diff --git a/.gitignore b/.gitignore index a634978..278cec6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ .terraform* terraform.tfstate* -.env -kubeconfig* \ No newline at end of file +kubeconfig-clusterdev.yaml \ No newline at end of file diff --git a/01-network.tf b/01-network.tf new file mode 100644 index 0000000..577a909 --- /dev/null +++ b/01-network.tf @@ -0,0 +1,106 @@ +// ------- project 1 - landingzone ------------ +// This file defines the network setup for the first project landingzone. +resource "stackit_network" "wan_network" { + project_id = module.project.project_info["project1"].project_id + name = "wan_network" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + ipv4_prefix_length = 24 + ipv4_prefix = "10.220.0.0/24" + routed = true +} + +resource "stackit_network" "lan_network1" { + project_id = module.project.project_info["project1"].project_id + name = "lan_network1" + ipv4_prefix_length = 24 + ipv4_prefix = "10.220.1.0/24" + routed = true +} + +resource "stackit_network" "lan_network2" { + project_id = module.project.project_info["project1"].project_id + name = "lan_network2" + ipv4_prefix_length = 24 + ipv4_prefix = "10.220.2.0/24" + routed = true +} + +resource "stackit_network" "lan_network3" { + project_id = module.project.project_info["project1"].project_id + name = "lan_network3" + ipv4_prefix_length = 24 + ipv4_prefix = "10.220.3.0/24" + routed = false +} + +resource "stackit_network_interface" "wan" { + project_id = module.project.project_info["project1"].project_id + network_id = stackit_network.wan_network.network_id + security = false + name = "MGMT" + ipv4 = "10.220.0.254" + +} + +resource "stackit_network_interface" "lan1" { + project_id = module.project.project_info["project1"].project_id + network_id = stackit_network.lan_network1.network_id + security = false + name = "LAN1" +} + +resource "stackit_network_interface" "lan2" { + project_id = module.project.project_info["project1"].project_id + network_id = stackit_network.lan_network2.network_id + security = false + name = "LAN2" +} + +resource "stackit_network_interface" "lan3" { + project_id = module.project.project_info["project1"].project_id + network_id = stackit_network.lan_network3.network_id + security = false + name = "LAN3" +} + +# ---------- project 2 core ------------------ +// This file defines the network setup for the second project (core). + +resource "stackit_network" "p2_lan_network1" { + project_id = module.project.project_info["project2"].project_id + name = "p2_lan_network" + ipv4_prefix_length = 24 + ipv4_prefix = "10.220.5.0/24" + routed = true +} + +resource "stackit_network_interface" "p2_lan1" { + project_id = module.project.project_info["project2"].project_id + network_id = stackit_network.p2_lan_network1.network_id + security = true + name = "P2LAN1" + security_group_ids = [ stackit_security_group.example.security_group_id ] +} + + +// ---------- public IPs ------------------ +// This file defines the public IPs for the projects. +resource "stackit_public_ip" "wan_ip" { + project_id = module.project.project_info["project1"].project_id + network_interface_id = stackit_network_interface.wan.network_interface_id +} + +/*resource "stackit_public_ip" "wan_server" { + project_id = module.project.project_info["project2"].project_id + network_interface_id = stackit_network_interface.p2_wan_interface1.network_interface_id +} +*/ + +// Output the public IPs for both projects +output "public_ips" { + value = { + "wan_ip" = stackit_public_ip.wan_ip.ip + //"wan_server" = stackit_public_ip.wan_server.ip + } +} + diff --git a/06-security-group.tf b/06-security-group.tf new file mode 100644 index 0000000..22958ff --- /dev/null +++ b/06-security-group.tf @@ -0,0 +1,51 @@ + +// Security Group and Security Group Rules +resource "stackit_security_group" "example" { + project_id = module.project.project_info["project2"].project_id + name = "test" + labels = { + "key" = "example" + } +} + +resource "stackit_security_group_rule" "icmp_ingress" { + security_group_id = stackit_security_group.example.security_group_id + project_id = module.project.project_info["project2"].project_id + direction = "ingress" + icmp_parameters = { + code = 0 + type = 8 + } + protocol = { + name = "icmp" + } +} +resource "stackit_security_group_rule" "icmp_egress" { + project_id = module.project.project_info["project2"].project_id + security_group_id = stackit_security_group.example.security_group_id + direction = "egress" + icmp_parameters = { + code = 0 + type = 8 + } + protocol = { + name = "icmp" + } +} + +resource "stackit_security_group_rule" "ssh_ingress" { + security_group_id = stackit_security_group.example.security_group_id + project_id = module.project.project_info["project2"].project_id + direction = "ingress" + + protocol = { + name = "tcp" + } + port_range = { + max = 22 + min = 22 + } +} + + + diff --git a/example/main.tf b/example/main.tf new file mode 100644 index 0000000..6d42b65 --- /dev/null +++ b/example/main.tf @@ -0,0 +1,36 @@ +resource "stackit_network_area" "project_sna" { + organization_id = var.organization_id + name = var.SNA_name + network_ranges = var.SNA_network_ranges + transfer_network = var.SNA_transfer_network +} + +module "projects" { + source = "../project" + + projects = var.Projects_map + organization_id = var.organization_id + sna_id = stackit_network_area.project_sna.network_area_id +} + +locals { + project_ids = { for k, v in module.projects.created_projects : k => v.project_id } +} + +module "stackit_ske_cluster" { + for_each = var.ske_clusters + source = "../ske" + project_id = local.project_ids[each.value.project_key] + name = each.value.name + node_pools = each.value.node_pools + network = { + id = each.value.network_id + } + + kubernetes_version_min = lookup(each.value, "kubernetes_version_min", null) + hibernations = lookup(each.value, "hibernations", null) + maintenance = lookup(each.value, "maintenance", null) + extensions = lookup(each.value, "extensions", null) + default_region = var.default_region +} + diff --git a/example/providers.tf b/example/providers.tf new file mode 100644 index 0000000..ba2ffb3 --- /dev/null +++ b/example/providers.tf @@ -0,0 +1,16 @@ +terraform { + required_version = ">= 1.9.0" + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = "0.56.0" + } + } +} + +provider "stackit" { + default_region = var.default_region + service_account_key_path = var.service_account_key_path + enable_beta_resources = true +} + diff --git a/example/test.tfvars b/example/test.tfvars new file mode 100644 index 0000000..b0d5467 --- /dev/null +++ b/example/test.tfvars @@ -0,0 +1,89 @@ +organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" + +Projects_map = { + "projekt-alpha" = { + name = "tf_modules_test_3" + owner_email = "janis.hahn@stackit.cloud" + }, + "projekt-beta" = { + name = "tf_modules_test_4" + owner_email = "janis.hahn@stackit.cloud" + } +} + +SNA_name = "sna-tf_modules_test" + +SNA_network_ranges = [ + { prefix = "192.168.10.0/24" } +] + +SNA_transfer_network = "172.16.0.0/24" + +ske_clusters = { + + "prod-cluster" = { + name = "clusterprod" + project_key = "projekt-alpha" + network_id = "53917a75-0014-49b0-a4d6-e62934ab479f" # WICHTIG: Hier die Netzwerk-ID connecten + kubernetes_version_min = "1.32.5" + + node_pools = [ + { + name = "defaulpool" + machine_type = "c1.2" + availability_zones = ["eu01-1"] + minimum = 1 + maximum = 2 + cri = "containerd" + volume_type = "storage_premium_perf1" + volume_size = 21 + labels = { "worker" = "default" } + taints = [{ + effect = "NoSchedule" + key = "app" + value = "database" + }] + } + ] + + hibernations = [ + { + start = "00 18 * * 1-5" # Mo-Fr um 18:00 Uhr + end = "00 08 * * 1-5" # Mo-Fr um 08:00 Uhr + timezone = "Europe/Berlin" + } + ] + + maintenance = { + enable_kubernetes_version_updates = true + enable_machine_image_version_updates = true + start = "01:00:00Z" + end = "03:00:00Z" + } + + extensions = { + acl = { + enabled = true + allowed_cidrs = ["0.0.0.0/0"] + } + } + }, + + "dev-cluster" = { + name = "clusterdev" + kubernetes_version_min = "1.32.5" + project_key = "projekt-beta" + network_id = "bedfc709-9285-4078-93ab-8e8a1c0be6bd" # WICHTIG: Hier die Netzwerk-ID connecten + + node_pools = [ + { + name = "devpool" + machine_type = "c1.2" + availability_zones = ["eu01-2"] + minimum = 1 + maximum = 2 + volume_size = 21 + } + ] + } +} diff --git a/example/variables.tf b/example/variables.tf new file mode 100644 index 0000000..3665f68 --- /dev/null +++ b/example/variables.tf @@ -0,0 +1,100 @@ +# SNA & Projects variables + +variable "organization_id" { + description = "Die Container-ID deiner STACKIT Organisation." + type = string +} + +variable "service_account_key_path" { + type = string + default = "/home/hahnjan/.stackit/sa.json" +} + +variable "default_region" { + type = string + default = "eu01" +} + +variable "SNA_name" { + description = "Name der zu erstellenden Service Network Area." + type = string +} + +variable "SNA_network_ranges" { + description = "Liste der Netzwerk-CIDRs für die SNA." + type = list(object({ prefix = string })) +} + +variable "SNA_transfer_network" { + description = "Das Transfer-Netzwerk für die SNA (z.B. 172.16.9.0/24)." + type = string +} + +variable "Projects_map" { + description = "Eine Map von Projekten, die erstellt werden sollen." + type = map(object({ + name = string + owner_email = string + })) +} + + +# SKE variables + +variable "ske_clusters" { + description = "Eine Map von SKE-Clustern" + type = map(object({ + + name = string + project_key = string + network_id = string + + kubernetes_version_min = optional(string) + hibernations = optional(list(object({ + start = string + end = string + timezone = optional(string) + }))) + maintenance = optional(object({ + enable_kubernetes_version_updates = bool + enable_machine_image_version_updates = bool + start = string + end = string + })) + extensions = optional(object({ + acl = optional(object({ + enabled = bool + allowed_cidrs = list(string) + })) + argus = optional(object({ + enabled = bool + argus_instance_id = string + })) + })) + + node_pools = list(object({ + + name = string + machine_type = string + availability_zones = list(string) + minimum = number + maximum = number + + allow_system_components = optional(bool) + cri = optional(string) + labels = optional(map(string)) + max_surge = optional(number) + max_unavailable = optional(number) + os_name = optional(string) + os_version_min = optional(string) + volume_size = optional(number) + volume_type = optional(string) + taints = optional(list(object({ + effect = string + key = string + value = optional(string) + }))) + })) + })) + default = {} +} diff --git a/main.tf b/main.tf index 93ef132..ecb00bb 100644 --- a/main.tf +++ b/main.tf @@ -1,130 +1,32 @@ -resource "stackit_network_area" "project_sna" { - organization_id = var.organization_id - name = var.SNA_name - network_ranges = var.SNA_network_ranges - transfer_network = var.SNA_transfer_network +# main.tf + +terraform { + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = ">=0.54" + } + } } -module "projects" { +provider "stackit" { + default_region = var.default_region + service_account_key_path = var.service_account_key_path + private_key_path = var.private_key_path + enable_beta_resources = true +} + + +module "project" { source = "./project" - projects = var.Projects_map - organization_id = var.organization_id - sna_id = stackit_network_area.project_sna.network_area_id - labels = var.labels != null ? var.labels : {} + # -- variables for project module + organization_id = var.organization_id + sna_net = var.sna_net + } -locals { - project_ids = { for k, v in module.projects.created_projects : k => v.project_id } -} -module "stackit_ske_cluster" { - source = "./ske" - for_each = var.ske_clusters - project_id = local.project_ids[each.value.project_key] - name = each.value.name - node_pools = each.value.node_pools - kubernetes_version_min = lookup(each.value, "kubernetes_version_min", null) - hibernations = lookup(each.value, "hibernations", null) - maintenance = lookup(each.value, "maintenance", null) - extensions = lookup(each.value, "extensions", null) - default_region = var.default_region -} -module "security_groups" { - source = "./security-group" - for_each = var.security_groups - - project_id = local.project_ids[each.value.project_key] - name = each.value.name - description = each.value.description != null ? each.value.description : "" - rules = each.value.rules -} - -locals { - security_group_ids_by_name = { - for key, m in module.security_groups : - m.name => m.security_group_id - } -} - -module "net" { - depends_on = [module.security_groups] - source = "./network" - - for_each = var.networks - - project_id = local.project_ids[each.value.project_key] - name = each.value.name - - ipv4_gateway = each.value.ipv4_gateway - ipv4_nameservers = each.value.ipv4_nameservers - ipv4_prefix = each.value.ipv4_prefix - ipv4_prefix_length = each.value.ipv4_prefix_length - - ipv6_gateway = each.value.ipv6_gateway - ipv6_nameservers = each.value.ipv6_nameservers - ipv6_prefix = each.value.ipv6_prefix - ipv6_prefix_length = each.value.ipv6_prefix_length - - no_ipv4_gateway = each.value.no_ipv4_gateway - no_ipv6_gateway = each.value.no_ipv6_gateway - routed = each.value.routed - labels = each.value.labels - - nics = each.value.nics - security_group_ids_by_name = local.security_group_ids_by_name -} - -module "postgres" { - source = "./postgres" - - for_each = var.postgres_instances - - project_id = local.project_ids[each.value.project_key] - name = each.value.name - ver = each.value.version - flavor = each.value.flavor - storage = each.value.storage - replicas = each.value.replicas - acl = each.value.acl - backup_schedule = each.value.backup_schedule - users = each.value.users - databases = each.value.databases -} - -module "observability" { - source = "./observability" - for_each = var.observability_instances - - project_id = local.project_ids[each.value.project_key] - - name = each.value.name - plan_name = each.value.plan_name - - acl = each.value.acl - metrics_retention_days = each.value.metrics_retention_days - metrics_retention_days_5m_downsampling = each.value.metrics_retention_days_5m_downsampling - metrics_retention_days_1h_downsampling = each.value.metrics_retention_days_1h_downsampling - alert_config = each.value.alert_config - parameters = each.value.parameters - - # Credentials - create_credentials = each.value.create_credentials - credentials_count = each.value.credentials_count - - alertgroups = each.value.alertgroups - - logalertgroups = each.value.logalertgroups - - scrapeconfigs = each.value.scrapeconfigs -} - -output "obs_url" { - value = { - for key, instance in module.observability : - key => instance.observability_urls - } -} diff --git a/network/main.tf b/network/main.tf deleted file mode 100644 index 246cdcf..0000000 --- a/network/main.tf +++ /dev/null @@ -1,51 +0,0 @@ -resource "stackit_network" "this" { - project_id = var.project_id - name = var.name - labels = var.labels - - # IPv4 settings - ipv4_gateway = var.ipv4_gateway - ipv4_nameservers = var.ipv4_nameservers - ipv4_prefix = var.ipv4_prefix - ipv4_prefix_length = var.ipv4_prefix_length - - # IPv6 settings - ipv6_gateway = var.ipv6_gateway - ipv6_nameservers = var.ipv6_nameservers - ipv6_prefix = var.ipv6_prefix - ipv6_prefix_length = var.ipv6_prefix_length - - no_ipv4_gateway = var.no_ipv4_gateway - no_ipv6_gateway = var.no_ipv6_gateway - routed = var.routed -} - -resource "stackit_network_interface" "nics" { - for_each = var.nics != null ? var.nics : {} - - project_id = var.project_id - network_id = stackit_network.this.network_id - - name = each.value.nic_name - ipv4 = each.value.nic_ipv4 - allowed_addresses = each.value.nic_allowed_addresses - labels = each.value.nic_labels - security = each.value.nic_security - security_group_ids = ( - each.value.nic_security_group_ids != null ? each.value.nic_security_group_ids : - each.value.nic_security_group_names != null ? - [for name in each.value.nic_security_group_names : var.security_group_ids_by_name[name]] - : [] - ) - - lifecycle { - precondition { - condition = alltrue([ - for sg_name in try(each.value.nic_security_group_names, []) : - contains(keys(var.security_group_ids_by_name), sg_name) - ]) - error_message = "NIC '${each.key}' references unknown security group name(s)." - } - } -} - diff --git a/network/output.tf b/network/output.tf deleted file mode 100644 index fc6e82d..0000000 --- a/network/output.tf +++ /dev/null @@ -1,9 +0,0 @@ -output "network_id" { - description = "Network ID" - value = stackit_network.this.network_id -} - -output "network_name" { - description = "Network name" - value = stackit_network.this.name -} diff --git a/network/providers.tf b/network/providers.tf deleted file mode 100644 index 6e038c3..0000000 --- a/network/providers.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_version = ">= 1.9.0" - required_providers { - stackit = { - source = "stackitcloud/stackit" - version = "0.56.0" - } - } -} diff --git a/network/variables.tf b/network/variables.tf deleted file mode 100644 index 9c7f985..0000000 --- a/network/variables.tf +++ /dev/null @@ -1,118 +0,0 @@ -variable "project_id" { - description = "STACKIT project ID" - type = string -} - -variable "name" { - description = "Network name" - type = string -} - -variable "ipv4_gateway" { - description = "IPv4 gateway address" - type = string - default = null -} - -variable "ipv4_nameservers" { - description = "IPv4 nameserver list" - type = list(string) - default = [] -} - -variable "ipv4_prefix" { - description = "IPv4 prefix CIDR" - type = string - default = null -} - -variable "ipv4_prefix_length" { - description = "IPv4 prefix length" - type = number - default = null -} - -variable "ipv6_gateway" { - description = "IPv6 gateway address" - type = string - default = null -} - -variable "ipv6_nameservers" { - description = "IPv6 nameserver list" - type = list(string) - default = [] -} - -variable "ipv6_prefix" { - description = "IPv6 prefix CIDR" - type = string - default = null -} - -variable "ipv6_prefix_length" { - description = "IPv6 prefix length" - type = number - default = null -} - -variable "nameservers" { - description = "Deprecated nameserver list (legacy field)" - type = list(string) - default = [] -} - -variable "labels" { - description = "Labels map" - type = map(string) - default = {} -} - -variable "no_ipv4_gateway" { - description = "Disable IPv4 gateway" - type = bool - default = false -} - -variable "no_ipv6_gateway" { - description = "Disable IPv6 gateway" - type = bool - default = false -} - -variable "routed" { - description = "Mark network routed" - type = bool - default = null -} - -variable "region" { - description = "Resource region override (defaults to provider region)" - type = string - default = null -} - -variable "routing_table_id" { - description = "Routing table ID" - type = string - default = null -} - -variable "nics" { - description = "Map of NIC configs" - type = map(object({ - nic_ipv4 = optional(string) - nic_name = optional(string) - nic_allowed_addresses = optional(list(string)) - nic_labels = optional(map(string)) - nic_security = optional(bool) - nic_security_group_ids = optional(list(string)) - nic_security_group_names = optional(list(string)) - })) - default = {} -} - -variable "security_group_ids_by_name" { - description = "Security group name→ID map" - type = map(string) -} diff --git a/observability/main.tf b/observability/main.tf deleted file mode 100644 index 080d9be..0000000 --- a/observability/main.tf +++ /dev/null @@ -1,56 +0,0 @@ -resource "stackit_observability_instance" "this" { - project_id = var.project_id - name = var.name - plan_name = var.plan_name - - acl = var.acl - metrics_retention_days = var.metrics_retention_days - metrics_retention_days_5m_downsampling = var.metrics_retention_days_5m_downsampling - metrics_retention_days_1h_downsampling = var.metrics_retention_days_1h_downsampling - alert_config = var.alert_config - parameters = var.parameters -} - -resource "stackit_observability_credential" "this" { - count = var.create_credentials ? var.credentials_count : 0 - project_id = var.project_id - instance_id = stackit_observability_instance.this.instance_id -} - -resource "stackit_observability_alertgroup" "this" { - for_each = var.alertgroups - project_id = var.project_id - instance_id = stackit_observability_instance.this.instance_id - - name = each.value.name - interval = each.value.interval - rules = each.value.rules -} - -resource "stackit_observability_logalertgroup" "this" { - for_each = var.logalertgroups - project_id = var.project_id - instance_id = stackit_observability_instance.this.instance_id - - name = each.value.name - interval = each.value.interval - rules = each.value.rules -} - -resource "stackit_observability_scrapeconfig" "this" { - for_each = var.scrapeconfigs - project_id = var.project_id - instance_id = stackit_observability_instance.this.instance_id - name = each.value.name - metrics_path = each.value.metrics_path - - targets = each.value.targets - - basic_auth = each.value.basic_auth - saml2 = each.value.saml2 - - sample_limit = each.value.sample_limit - scheme = each.value.scheme - scrape_interval = each.value.scrape_interval - scrape_timeout = each.value.scrape_timeout -} diff --git a/observability/outputs.tf b/observability/outputs.tf deleted file mode 100644 index 15f6ecb..0000000 --- a/observability/outputs.tf +++ /dev/null @@ -1,50 +0,0 @@ -output "observability_id" { - description = "Observability instance ID" - value = stackit_observability_instance.this.instance_id -} - -output "observability_urls" { - description = "Key Observability URLs" - value = { - grafana = stackit_observability_instance.this.grafana_url - dashboard = stackit_observability_instance.this.dashboard_url - metrics = stackit_observability_instance.this.metrics_url - logs = stackit_observability_instance.this.logs_url - } -} - -output "observability_credentials" { - description = "List of credential objects (username & password)" - value = [ - for cred in stackit_observability_credential.this : - { - username = cred.username - password = cred.password - } - ] - sensitive = true -} - -output "observability_alertgroups" { - description = "Map of created alert-group IDs" - value = { - for key, alertgrp in stackit_observability_alertgroup.this : - key => alertgrp.id - } -} - -output "observability_logalertgroups" { - description = "Map of created log-alert-group IDs" - value = { - for key, logalertgrp in stackit_observability_logalertgroup.this : - key => logalertgrp.id - } -} - -output "observability_scrapeconfigs" { - description = "Map of created scrape-config IDs" - value = { - for key, sconfig in stackit_observability_scrapeconfig.this : - key => sconfig.id - } -} diff --git a/observability/variables.tf b/observability/variables.tf deleted file mode 100644 index daee852..0000000 --- a/observability/variables.tf +++ /dev/null @@ -1,118 +0,0 @@ -variable "project_id" { - description = "STACKIT project ID" - type = string -} - -variable "name" { - description = "Observability instance name" - type = string -} - -variable "plan_name" { - description = "Observability plan name" - type = string -} - -variable "acl" { - description = "Allowed CIDR list" - type = list(string) - default = null -} - -variable "metrics_retention_days" { - description = "Retention days raw metrics" - type = number - default = null -} - -variable "metrics_retention_days_5m_downsampling" { - description = "Retention days 5m downsample" - type = number - default = null -} - -variable "metrics_retention_days_1h_downsampling" { - description = "Retention days 1h downsample" - type = number - default = null -} - -variable "alert_config" { - description = "Alertmanager config object" - type = any - default = null -} - -variable "parameters" { - description = "Extra key/value parameters" - type = map(string) - default = null -} - -variable "create_credentials" { - description = "Create credentials" - type = bool - default = true -} - -variable "credentials_count" { - description = "Credential count when enabled" - type = number - default = 1 -} - -variable "alertgroups" { - description = "Map of alert-groups to create" - type = map(object({ - name = string - interval = optional(string) - rules = list(object({ - alert = string - expression = string - for = optional(string) - labels = optional(map(string)) - annotations = optional(map(string)) - })) - })) - default = {} -} - -variable "logalertgroups" { - description = "Map of log-alert-groups to create" - type = map(object({ - name = string - interval = optional(string) - rules = list(object({ - alert = string - expression = string - for = optional(string) - labels = optional(map(string)) - annotations = optional(map(string)) - })) - })) - default = {} -} - -variable "scrapeconfigs" { - description = "Map of scrape-configs to create" - type = map(object({ - name = string - metrics_path = string - targets = list(object({ - urls = list(string) - labels = optional(map(string)) - })) - basic_auth = optional(object({ - username = string - password = string - })) - saml2 = optional(object({ - enable_url_parameters = optional(bool) - })) - sample_limit = optional(number) - scheme = optional(string) - scrape_interval = optional(string) - scrape_timeout = optional(string) - })) - default = {} -} diff --git a/postgres/main.tf b/postgres/main.tf deleted file mode 100644 index 0507717..0000000 --- a/postgres/main.tf +++ /dev/null @@ -1,33 +0,0 @@ -locals { - user_count = length(var.users) - db_count = length(var.databases) -} - -resource "stackit_postgresflex_instance" "this" { - project_id = var.project_id - name = var.name - version = var.ver - flavor = var.flavor - storage = var.storage - replicas = var.replicas - acl = var.acl - backup_schedule = var.backup_schedule -} - -resource "stackit_postgresflex_user" "user" { - count = local.user_count - - project_id = var.project_id - instance_id = stackit_postgresflex_instance.this.instance_id - username = var.users[count.index].username - roles = var.users[count.index].roles -} - -resource "stackit_postgresflex_database" "db" { - count = local.db_count - - project_id = var.project_id - instance_id = stackit_postgresflex_instance.this.instance_id - name = var.databases[count.index].name - owner = var.databases[count.index].owner -} diff --git a/postgres/outputs.tf b/postgres/outputs.tf deleted file mode 100644 index 216884c..0000000 --- a/postgres/outputs.tf +++ /dev/null @@ -1,11 +0,0 @@ -output "instance_id" { - value = stackit_postgresflex_instance.this.instance_id -} - -output "user_ids" { - value = stackit_postgresflex_user.user[*].user_id -} - -output "database_ids" { - value = stackit_postgresflex_database.db[*].database_id -} diff --git a/postgres/providers.tf b/postgres/providers.tf deleted file mode 100644 index 6e038c3..0000000 --- a/postgres/providers.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_version = ">= 1.9.0" - required_providers { - stackit = { - source = "stackitcloud/stackit" - version = "0.56.0" - } - } -} diff --git a/postgres/variables.tf b/postgres/variables.tf deleted file mode 100644 index 620fea0..0000000 --- a/postgres/variables.tf +++ /dev/null @@ -1,92 +0,0 @@ -variable "project_id" { - description = "STACKIT project ID" - type = string -} - -variable "name" { - description = "Instance name (DNS-1035 compliant)" - type = string - - validation { - condition = length(regexall("^[a-z]([-a-z0-9]*[a-z0-9])?$", var.name)) > 0 - error_message = < 0 - ]) - error_message = < r - } - - direction = each.value.direction - project_id = var.project_id - security_group_id = stackit_security_group.this.security_group_id - - description = each.value.description - ether_type = each.value.ether_type - icmp_parameters = each.value.icmp_parameters - ip_range = each.value.ip_range - port_range = each.value.port_range - protocol = each.value.protocol - remote_security_group_id = each.value.remote_security_group_id -} diff --git a/security-group/output.tf b/security-group/output.tf deleted file mode 100644 index d28e44e..0000000 --- a/security-group/output.tf +++ /dev/null @@ -1,9 +0,0 @@ -output "security_group_id" { - description = "ID of the security group" - value = stackit_security_group.this.security_group_id -} - -output "name" { - description = "Name of the security group" - value = stackit_security_group.this.name -} diff --git a/security-group/providers.tf b/security-group/providers.tf deleted file mode 100644 index 6e038c3..0000000 --- a/security-group/providers.tf +++ /dev/null @@ -1,9 +0,0 @@ -terraform { - required_version = ">= 1.9.0" - required_providers { - stackit = { - source = "stackitcloud/stackit" - version = "0.56.0" - } - } -} diff --git a/security-group/variables.tf b/security-group/variables.tf deleted file mode 100644 index 97d6da7..0000000 --- a/security-group/variables.tf +++ /dev/null @@ -1,64 +0,0 @@ -variable "project_id" { - description = "STACKIT project ID" - type = string -} - -variable "name" { - description = "Security group name" - type = string -} - -variable "description" { - description = "Security group description" - type = string - default = "" -} - -# rule schema -variable "rules" { - description = "List of security group rules" - type = list(object({ - direction = string # ingress | egress - description = optional(string) - ether_type = optional(string) # IPv4 | IPv6 - icmp_parameters = optional(object({ - type = optional(number) - code = optional(number) - })) - ip_range = optional(string) # CIDR - port_range = optional(object({ - min = number - max = number - })) - protocol = optional(object({ - name = optional(string) # tcp | udp | icmp - number = optional(number) # OR protocol number - })) - remote_security_group_id = optional(string) - })) - - validation { - condition = alltrue([ - for r in var.rules : contains(["ingress", "egress"], lower(r.direction)) - ]) - error_message = "Each rule.direction must be 'ingress' or 'egress'." - } - - validation { - condition = alltrue([ - for r in var.rules : - r.ether_type == null ? true : contains(["IPv4", "IPv6"], r.ether_type) - ]) - error_message = "Each rule.ether_type must be 'IPv4' or 'IPv6' when set." - } - - validation { - condition = alltrue([ - for r in var.rules : - ( - r.port_range == null ? true : (r.port_range.min <= r.port_range.max) - ) - ]) - error_message = "Each rule.port_range.min must be <= rule.port_range.max." - } -} diff --git a/ske/main.tf b/ske/main.tf index 2252538..1cda6b9 100644 --- a/ske/main.tf +++ b/ske/main.tf @@ -1,13 +1,3 @@ -resource "stackit_network" "ske_network" { - project_id = var.project_id - name = "ske_network" - ipv4_nameservers = ["1.1.1.1", "9.9.9.9"] -} - -output "ske-egress-ip" { - value = stackit_ske_cluster.this.egress_address_ranges -} - resource "stackit_ske_cluster" "this" { project_id = var.project_id name = var.name @@ -16,9 +6,7 @@ resource "stackit_ske_cluster" "this" { hibernations = var.hibernations maintenance = var.maintenance extensions = var.extensions - network = { - id = stackit_network.ske_network.network_id - } + network = var.network region = var.default_region } diff --git a/ske/output.tf b/ske/output.tf index 88f4e56..9abc2e4 100644 --- a/ske/output.tf +++ b/ske/output.tf @@ -7,4 +7,4 @@ output "kubeconfig" { description = "Kubeconfig of SKE cluster" value = stackit_ske_kubeconfig.admin.kube_config sensitive = true -} +} \ No newline at end of file diff --git a/ske/variables.tf b/ske/variables.tf index efa26e0..ccae10c 100644 --- a/ske/variables.tf +++ b/ske/variables.tf @@ -1,47 +1,47 @@ variable "project_id" { - description = "STACKIT project ID" + description = "STACKIT project ID to which the cluster is associated." type = string } variable "name" { - description = "Cluster name" + description = "The cluster name." type = string } variable "node_pools" { - description = "List of node pool configs" + description = "One or more node_pool blocks." type = list(object({ - name = string - machine_type = string - availability_zones = list(string) - minimum = number - maximum = number - - allow_system_components = optional(bool) - cri = optional(string) - labels = optional(map(string)) - max_surge = optional(number) - max_unavailable = optional(number) - os_name = optional(string) - os_version_min = optional(string) - taints = optional(list(object({ + name = string + machine_type = string + availability_zones = list(string) + minimum = number + maximum = number + allow_system_components = optional(bool) + cri = optional(string) + labels = optional(map(string)) + max_surge = optional(number) + max_unavailable = optional(number) + os_name = optional(string) + os_version_min = optional(string) + taints = optional(list(object({ effect = string key = string value = optional(string) }))) - volume_size = optional(number) - volume_type = optional(string) + volume_size = optional(number) + volume_type = optional(string) })) } +# Optionale Variablen variable "kubernetes_version_min" { - description = "Minimum Kubernetes version" + description = "The minimum Kubernetes version." type = string default = null } variable "hibernations" { - description = "Hibernation schedules" + description = "A list of hibernation schedules for the cluster." type = list(object({ start = string end = string @@ -51,7 +51,7 @@ variable "hibernations" { } variable "maintenance" { - description = "Maintenance window settings" + description = "A single maintenance block." type = object({ enable_kubernetes_version_updates = bool enable_machine_image_version_updates = bool @@ -60,9 +60,8 @@ variable "maintenance" { }) default = null } - variable "extensions" { - description = "Extensions config" + description = "A single extensions block." type = object({ acl = optional(object({ enabled = bool @@ -73,15 +72,23 @@ variable "extensions" { argus_instance_id = string })) dns = optional(object({ - enabled = bool - zones = optional(list(string)) + enabled = bool + zones = optional(list(string)) })) }) default = null } +variable "network" { + description = "Network block." + type = object({ + id = string + }) + default = null +} + variable "default_region" { - description = "Resource region override" + description = "The resource region." type = string default = null -} +} \ No newline at end of file diff --git a/terraform.tfvars b/terraform.tfvars deleted file mode 100644 index 7481295..0000000 --- a/terraform.tfvars +++ /dev/null @@ -1,285 +0,0 @@ -# Your STACKIT organization container ID (must be provided) -organization_id = "" - - -# ----------------------------------------------------------------------------- -# Projects to Create -# ----------------------------------------------------------------------------- -Projects_map = { - "projekt-alpha" = { - name = "" - owner_email = "" - }, - - "projekt-beta" = { - name = "" - owner_email = "" - } -} - - -# ----------------------------------------------------------------------------- -# Service Network Area (SNA) Settings -# ----------------------------------------------------------------------------- -# Name to assign to the Service Network Area -SNA_name = "" - -# List of CIDR blocks to include in the SNA -SNA_network_ranges = [ - { prefix = "192.168.10.0/24" } -] -# Dedicated transfer network CIDR for internal traffic -SNA_transfer_network = "172.16.0.0/24" - - -# ----------------------------------------------------------------------------- -# Security Groups Definitions -# ----------------------------------------------------------------------------- -security_groups = { - ssh_ingress_group = { - name = "ssh-ingress-group" - project_key = "projekt-alpha" - description = "ALLOW SSH ingress" - rules = [ - { - description = "SSH RULE 1" - direction = "ingress" - ether_type = "IPv4" - ip_range = "0.0.0.0/0" - protocol = { - name = "tcp" - } - port_range = { - min = 22 - max = 22 - } - }, - ] - }, - - web_traffic_group = { - name = "web-traffic-group" - project_key = "projekt-alpha" - description = "ALLOW WEB TRAFFIC ingress" - rules = [ - { - description = "ALLOW ALL 80" - direction = "ingress" - ether_type = "IPv4" - ip_range = "0.0.0.0/0" - protocol = { - name = "tcp" - } - port_range = { - min = 80 - max = 80 - } - }, - { - description = "ALLOW ALL 443" - direction = "ingress" - ether_type = "IPv4" - ip_range = "0.0.0.0/0" - protocol = { - name = "tcp" - } - port_range = { - min = 443 - max = 443 - } - }, - ] - }, -} - - -# ----------------------------------------------------------------------------- -# PostgreSQL Instances -# ----------------------------------------------------------------------------- -postgres_instances = { - # Development instance “dev” - dev = { - name = "pg-test-instance" # Instance name - project_key = "projekt-alpha" # Owning project - version = 17 # PostgreSQL major version - flavor = { - cpu = 2 # vCPU count - ram = 4 # RAM in GB - } - storage = { - class = "premium-perf6-stackit" # Storage performance class - size = 20 # Size in GB - } - replicas = 1 # Number of read replicas - acl = ["0.0.0.0/0"] # CIDR(s) allowed to connect - backup_schedule = "00 00 * * *" # Daily at midnight (cron syntax) - - # Database users to create - users = [ - { - username = "adminusr" - roles = ["login", "createdb"] # Permissions granted - }, - { - username = "testusr" - roles = ["login"] - } - ] - - # Databases to provision - databases = [ - { - name = "testdb" - owner = "admin" # Owner user of the database - } - ] - } -} - - -# ----------------------------------------------------------------------------- -# Network Definitions -# ----------------------------------------------------------------------------- -networks = { - wan_network = { - name = "wan_network" - project_key = "projekt-beta" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] # DNS resolvers - ipv4_prefix_length = 29 - ipv4_prefix = "192.168.10.248/29" # Subnet CIDR - routed = true - } -} - - -# ----------------------------------------------------------------------------- -# Observability (Metrics & Logs) Instances -# ----------------------------------------------------------------------------- -observability_instances = { - test = { - # Required instance settings - name = "test-observability" - project_key = "projekt-alpha" - plan_name = "Observability-Large-EU01" # Choose from allowed plan list - - # Optional network & retention settings - acl = ["192.168.100.10/32", "203.0.113.5/32"] - metrics_retention_days = 30 - metrics_retention_days_5m_downsampling = 10 - metrics_retention_days_1h_downsampling = 5 - - # Credentials management - create_credentials = true - credentials_count = 2 - - # Alert groups for metrics - alertgroups = { - test_group = { - name = "example-alert-group" - interval = "60s" - rules = [ - { - alert = "example-alert-name" - expression = "kube_node_status_condition{condition=\"Ready\", status=\"false\"} > 0" - for = "60s" - labels = { - severity = "critical" - } - annotations = { - summary = "example summary" - description = "example description" - } - }, - { - alert = "example-alert-name-2" - expression = "kube_node_status_condition{condition=\"Ready\", status=\"false\"} > 0" - for = "1m" - labels = { - severity = "critical" - } - annotations = { - summary = "example summary" - description = "example description" - } - }, - ] - } - } - - # Log-based alert groups - logalertgroups = { - example_log = { - name = "example-log-alert-group" - interval = "60m" - rules = [ - { - alert = "example-log-alert-name" - expression = "sum(rate({namespace=\"example\", pod=\"logger\"} |= \"Simulated error message\" [1m])) > 0" - for = "60s" - labels = { - severity = "critical" - } - annotations = { - summary = "example summary" - description = "example description" - } - }, - { - alert = "example-log-alert-name-2" - expression = "sum(rate({namespace=\"example\", pod=\"logger\"} |= \"Another error message\" [1m])) > 0" - for = "60s" - labels = { - severity = "critical" - } - annotations = { - summary = "example summary" - description = "example description" - } - }, - ] - } - } - - # Scrape configurations for Prometheus-style scraping - scrapeconfigs = { - example_job = { - name = "example-job" - metrics_path = "/my-metrics" - saml2 = { - enable_url_parameters = true - } - targets = [ - { - urls = ["url1", "urls2"] - labels = { - "url1" = "dev" - } - } - ] - } - } - } -} - - -# ----------------------------------------------------------------------------- -# SKE (Kubernetes) Clusters -# ----------------------------------------------------------------------------- -ske_clusters = { - "dev-cluster" = { - name = "cluster" - kubernetes_version_min = "1.32.5" - project_key = "projekt-alpha" - - node_pools = [ - { - name = "np" - machine_type = "g1.4" - availability_zones = ["eu01-2"] - minimum = 1 - maximum = 2 - volume_size = 21 - } - ] - } -} diff --git a/variables.tf b/variables.tf index 54c97e1..0321640 100644 --- a/variables.tf +++ b/variables.tf @@ -1,351 +1,27 @@ -# ----------------------------------------------------------------------------- -# STACKIT Cloud: Core Configuration Variables -# ----------------------------------------------------------------------------- - -# Provider region where STACKIT services will be deployed -variable "region" { - description = "Provider region for STACKIT Cloud" - type = string - default = "eu01" -} - -# Token for service account authentication (sensitive) -variable "service_account_token" { - description = "Service account token for authentication" - sensitive = true - type = string - default = null -} - -# ----------------------------------------------------------------------------- -# Subscriber Network Area (SNA) & Project Settings -# ----------------------------------------------------------------------------- - -# ID of the STACKIT organization container variable "organization_id" { - description = "STACKIT organization container ID" type = string + description = "Die Container-ID Ihrer Organisation." + # Kein Default, wird per .tfvars gesetzt + default = "03a34540-3c1a-4794-b2c6-7111ecf824ef" } -# Local path to the JSON key for the service account variable "service_account_key_path" { - description = "Path to service account JSON key" type = string - default = "/Users/schlenz/.stackit/sa.json" + default = "/root/.stackit/credentials.json" +} + +variable "private_key_path" { + type = string + default = "/root/.stackit/private_key.pem" } -# Fallback region for resources if none specified variable "default_region" { - description = "Default region fallback for created resources" - type = string - default = "eu01" + type = string + default = "eu01" } -# Name for the Service Network Area (SNA) -variable "SNA_name" { - description = "Name of the Service Network Area to create" - type = string -} - -# List of CIDR prefixes for the Service Network Area network ranges -variable "SNA_network_ranges" { - description = "CIDR list for the Service Network Area" - type = list(object({ prefix = string })) -} - -# CIDR block used for transfer network within the SNA -variable "SNA_transfer_network" { - description = "Transfer network CIDR for the SNA" - type = string -} - -# Map of project keys to project definitions (name and owner email) -variable "Projects_map" { - description = "Map of STACKIT projects to create" - type = map(object({ - name = string - owner_email = string - })) -} - -# Default labels applied to resources where supported -variable "labels" { - description = "Default labels to apply where supported" - type = map(string) - default = {} -} - -# Security group definitions, including rules and associations -variable "security_groups" { - description = "Map of security group definitions" - type = map(object({ - name = optional(string) - project_key = string - description = optional(string) - rules = list(object({ - direction = string # e.g., ingress or egress - description = optional(string) # description of the rule - ether_type = optional(string) # IPv4 or IPv6 - icmp_parameters = optional(object({ # ICMP type/code when applicable - type = optional(number) - code = optional(number) - })) - ip_range = optional(string) # source/destination IP range - port_range = optional(object({ # TCP/UDP port range - min = number - max = number - })) - protocol = optional(object({ # protocol name/number - name = optional(string) - number = optional(number) - })) - remote_security_group_id = optional(string) # reference another group - })) - })) -} - -# ----------------------------------------------------------------------------- -# PostgreSQL Database Instances -# ----------------------------------------------------------------------------- - -# Definitions for PostgreSQL instances (name, sizing, ACLs, users, and databases) -variable "postgres_instances" { - description = "Map of PostgreSQL instances to create" - type = map(object({ - name = string - project_key = string - version = number - flavor = object({ cpu = number, ram = number }) - storage = object({ class = string, size = number }) - replicas = number - acl = list(string) # allowed IP CIDRs - backup_schedule = string # cron-like schedule - users = list(object({ # DB users and their roles - username = string - roles = set(string) - })) - databases = list(object({ # databases to create - name = string - owner = string - })) - })) -} - -# ----------------------------------------------------------------------------- -# Virtual Networks per Project -# ----------------------------------------------------------------------------- - -# Network definitions, including IPv4/IPv6 settings, labels, and NICs -variable "networks" { - description = "Map of network definitions per project" - type = map(object({ - name = string - project_key = string - - # IPv4 configuration - ipv4_gateway = optional(string) - ipv4_nameservers = optional(list(string)) - ipv4_prefix = optional(string) - ipv4_prefix_length = optional(number) - - # IPv6 configuration - ipv6_gateway = optional(string) - ipv6_nameservers = optional(list(string)) - ipv6_prefix = optional(string) - ipv6_prefix_length = optional(number) - - # Additional flags and resource labels - labels = optional(map(string)) - no_ipv4_gateway = optional(bool) - no_ipv6_gateway = optional(bool) - routed = optional(bool) - - # Network interface cards (NICs) definitions - nics = optional(map(object({ - nic_ipv4 = optional(string) - nic_name = string - nic_allowed_addresses = optional(list(string)) - nic_labels = optional(map(string)) - nic_security = optional(bool) - nic_security_group_ids = optional(list(string)) - nic_security_group_names = optional(list(string)) - }))) - })) - default = {} -} - -# ----------------------------------------------------------------------------- -# SKE Kubernetes Clusters -# ----------------------------------------------------------------------------- - -# Configuration for SKE clusters, node pools, and optional extensions -variable "ske_clusters" { - description = "Map of SKE cluster definitions" - type = map(object({ - name = string - project_key = string - kubernetes_version_min = optional(string) - - # Scheduled cluster hibernations - hibernations = optional(list(object({ - start = string # local time window start - end = string # local time window end - timezone = optional(string) # timezone of the schedule - }))) - - # Maintenance window settings - maintenance = optional(object({ - enable_kubernetes_version_updates = bool - enable_machine_image_version_updates = bool - start = string - end = string - })) - - # Cluster extensions (ACL, Argus monitoring) - extensions = optional(object({ - acl = optional(object({ - enabled = bool - allowed_cidrs = list(string) - })) - argus = optional(object({ - enabled = bool - argus_instance_id = string - })) - })) - - # Node pool definitions (machine types, scaling, labels, taints) - node_pools = list(object({ - name = string - machine_type = string - availability_zones = list(string) - minimum = number - maximum = number - - allow_system_components = optional(bool) - cri = optional(string) - labels = optional(map(string)) - max_surge = optional(number) - max_unavailable = optional(number) - os_name = optional(string) - os_version_min = optional(string) - volume_size = optional(number) - volume_type = optional(string) - taints = optional(list(object({ - effect = string - key = string - value = optional(string) - }))) - })) - })) - default = {} -} - -# ----------------------------------------------------------------------------- -# Observability Instances (Monitoring & Alerting) -# ----------------------------------------------------------------------------- - -# Definitions for Observability service instances and alert configurations -variable "observability_instances" { - description = "Map of Observability instances to create" - type = map(object({ - name = string - project_key = string - plan_name = string # e.g., Observability-Medium-EU01 - - # Retention and ACL settings - acl = optional(list(string)) - metrics_retention_days = optional(number) - metrics_retention_days_5m_downsampling = optional(number) - metrics_retention_days_1h_downsampling = optional(number) - alert_config = optional(any) - parameters = optional(map(string)) - - # Credential generation settings - create_credentials = optional(bool, true) - credentials_count = optional(number, 1) - - # Alert group definitions - alertgroups = optional(map(object({ - name = string - interval = optional(string) - rules = list(object({ - alert = string - expression = string - for = optional(string) - labels = optional(map(string)) - annotations = optional(map(string)) - })) - })), {}) - - # Log alert group definitions - logalertgroups = optional(map(object({ - name = string - interval = optional(string) - rules = list(object({ - alert = string - expression = string - for = optional(string) - labels = optional(map(string)) - annotations = optional(map(string)) - })) - })), {}) - - # Scrape configuration for metrics collection - scrapeconfigs = optional(map(object({ - name = string - metrics_path = string - targets = list(object({ - urls = list(string) - labels = optional(map(string)) - })) - basic_auth = optional(object({ - username = string - password = string - })) - saml2 = optional(object({ - enable_url_parameters = optional(bool) - })) - sample_limit = optional(number) - scheme = optional(string) - scrape_interval = optional(string) - scrape_timeout = optional(string) - })), {}) - })) - default = {} - - validation { - condition = alltrue([ - for k, v in var.observability_instances : - contains([ - "Observability-Medium-EU01", - "Observability-Monitoring-XL-EU01", - "Observability-Large-EU01", - "Observability-Monitoring-Basic-EU01", - "Observability-Monitoring-Large-EU01", - "Observability-Basic-EU01", - "Observability-Monitoring-Medium-EU01", - "Observability-Monitoring-XXL-EU01", - "Observability-Metrics-Endpoint-100k-EU01", - "Observability-Frontend-Starter-EU01", - "Observability-Monitoring-Starter-EU01", - "Observability-Starter-EU01", - ], v.plan_name) - ]) - error_message = <<-EOM -One or more observability_instances specify an invalid plan_name. -See the provider error output for supported plans. Allowed: - Observability-Medium-EU01 - Observability-Monitoring-XL-EU01 - Observability-Large-EU01 - Observability-Monitoring-Basic-EU01 - Observability-Monitoring-Large-EU01 - Observability-Basic-EU01 - Observability-Monitoring-Medium-EU01 - Observability-Monitoring-XXL-EU01 - Observability-Metrics-Endpoint-100k-EU01 - Observability-Frontend-Starter-EU01 - Observability-Monitoring-Starter-EU01 - Observability-Starter-EU01 -EOM +variable "sna_net" { + type = string + default = "172.16.9.0/24" } -} +