From 6dcbef56e65a3d1ab720cc128fec130a589658c7 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Mon, 7 Jul 2025 10:04:39 +0200 Subject: [PATCH 01/22] postgres tf module --- postgres/main.tf | 33 +++++++++++++++++++++++++ postgres/outputs.tf | 11 +++++++++ postgres/providers.tf | 9 +++++++ postgres/variables.tf | 56 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 postgres/main.tf create mode 100644 postgres/outputs.tf create mode 100644 postgres/providers.tf create mode 100644 postgres/variables.tf diff --git a/postgres/main.tf b/postgres/main.tf new file mode 100644 index 0000000..0507717 --- /dev/null +++ b/postgres/main.tf @@ -0,0 +1,33 @@ +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 new file mode 100644 index 0000000..216884c --- /dev/null +++ b/postgres/outputs.tf @@ -0,0 +1,11 @@ +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 new file mode 100644 index 0000000..6e038c3 --- /dev/null +++ b/postgres/providers.tf @@ -0,0 +1,9 @@ +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 new file mode 100644 index 0000000..dbe1920 --- /dev/null +++ b/postgres/variables.tf @@ -0,0 +1,56 @@ +variable "project_id" { + type = string +} + +variable "name" { + type = string +} + +variable "ver" { + type = number +} + +variable "flavor" { + type = object({ + cpu = number, + ram = number + }) +} + +variable "storage" { + type = object({ + class = string, + size = number + }) +} + +variable "replicas" { + type = number +} + +variable "acl" { + type = list(string) +} + +variable "backup_schedule" { + type = string + +} + +variable "users" { + description = "List of users" + type = list(object({ + username = string + roles = set(string) + })) + default = [] +} + +variable "databases" { + description = "List of databases" + type = list(object({ + name = string + owner = string + })) + default = [] +} From 0f94aee91dae91f8a9feba6267a912549930cbc3 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Mon, 7 Jul 2025 11:12:30 +0200 Subject: [PATCH 02/22] network tf module --- network/main.tf | 23 ++++++++++++++++++++ network/output.tf | 19 +++++++++++++++++ network/providers.tf | 9 ++++++++ network/variables.tf | 50 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 network/main.tf create mode 100644 network/output.tf create mode 100644 network/providers.tf create mode 100644 network/variables.tf diff --git a/network/main.tf b/network/main.tf new file mode 100644 index 0000000..f9ca504 --- /dev/null +++ b/network/main.tf @@ -0,0 +1,23 @@ +resource "stackit_network" "this" { + project_id = var.project_id + name = var.name + + ipv4_nameservers = var.ipv4_nameservers + labels = var.labels + + routed = true +} + +resource "stackit_network_interface" "static" { + count = var.static_ipv4 == null ? 0 : 1 + + project_id = var.project_id + network_id = stackit_network.this.network_id + + ipv4 = var.static_ipv4 + labels = var.nic_labels + name = var.nic_name == null ? "${var.name}-nic" : var.nic_name + security = var.nic_security + security_group_ids = var.nic_security ? var.nic_security_group_ids : null + allowed_addresses = var.nic_security ? var.nic_allowed_addresses : null +} diff --git a/network/output.tf b/network/output.tf new file mode 100644 index 0000000..14a3f9c --- /dev/null +++ b/network/output.tf @@ -0,0 +1,19 @@ +output "network_id" { + description = "Network ID" + value = stackit_network.this.network_id +} + +output "network_name" { + description = "Network name" + value = stackit_network.this.name +} + +output "network_interface_id" { + description = "NIC ID" + value = try(stackit_network_interface.static[0].network_interface_id, null) +} + +output "static_ipv4" { + description = "IPv4 address assigned to NIC (null when not used)" + value = var.static_ipv4 +} diff --git a/network/providers.tf b/network/providers.tf new file mode 100644 index 0000000..dd742e3 --- /dev/null +++ b/network/providers.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.9.0" + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = "0.56.0" + } + } +} \ No newline at end of file diff --git a/network/variables.tf b/network/variables.tf new file mode 100644 index 0000000..5bbe8e6 --- /dev/null +++ b/network/variables.tf @@ -0,0 +1,50 @@ +variable "project_id" { + type = string +} + +variable "name" { + type = string +} + +variable "ipv4_nameservers" { + type = list(string) + default = [] +} + +variable "labels" { + type = map(string) + default = {} +} + +variable "static_ipv4" { + type = string + description = "If set, a NIC will be created with this IPv4." + default = null +} + +variable "nic_name" { + type = string + default = null +} + +variable "nic_allowed_addresses" { + type = list(string) + description = "Additional CIDR blocks for NIC" + default = [] +} + +variable "nic_labels" { + type = map(string) + default = {} +} + +variable "nic_security" { + type = bool + default = true +} + +variable "nic_security_group_ids" { + type = list(string) + description = "nic_security must be set to true" + default = [] +} From dcc8079e21be4242f8643f699f1c7b6800999a06 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Mon, 7 Jul 2025 14:51:41 +0200 Subject: [PATCH 03/22] ske tf module --- ske/main.tf | 12 ++++++++++++ ske/output.tf | 10 ++++++++++ ske/providers.tf | 9 +++++++++ ske/variables.tf | 22 ++++++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 ske/main.tf create mode 100644 ske/output.tf create mode 100644 ske/providers.tf create mode 100644 ske/variables.tf diff --git a/ske/main.tf b/ske/main.tf new file mode 100644 index 0000000..90124a0 --- /dev/null +++ b/ske/main.tf @@ -0,0 +1,12 @@ +resource "stackit_ske_cluster" "this" { + project_id = var.project_id + name = var.name + kubernetes_version_min = var.kubernetes_version_min + node_pools = var.node_pools +} + +resource "stackit_ske_kubeconfig" "admin" { + project_id = var.project_id + cluster_name = stackit_ske_cluster.this.name + refresh = true +} diff --git a/ske/output.tf b/ske/output.tf new file mode 100644 index 0000000..9abc2e4 --- /dev/null +++ b/ske/output.tf @@ -0,0 +1,10 @@ +output "name" { + description = "Name of SKE cluster" + value = stackit_ske_cluster.this.name +} + +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/providers.tf b/ske/providers.tf new file mode 100644 index 0000000..6e038c3 --- /dev/null +++ b/ske/providers.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.9.0" + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = "0.56.0" + } + } +} diff --git a/ske/variables.tf b/ske/variables.tf new file mode 100644 index 0000000..53533c0 --- /dev/null +++ b/ske/variables.tf @@ -0,0 +1,22 @@ +variable "project_id" { + type = string +} + +variable "name" { + type = string +} + +variable "kubernetes_version_min" { + type = string +} + +variable "node_pools" { + type = list(object({ + name = string + machine_type = string + availability_zones = list(string) + volume_size = number + minimum = number + maximum = number + })) +} From f13e94f5502b5996af447a13c5c04f2c99270893 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Tue, 8 Jul 2025 12:47:56 +0200 Subject: [PATCH 04/22] observability tf module --- observability/main.tf | 5 +++++ observability/output.tf | 0 observability/providers.tf | 10 ++++++++++ observability/variables.tf | 11 +++++++++++ 4 files changed, 26 insertions(+) create mode 100644 observability/main.tf create mode 100644 observability/output.tf create mode 100644 observability/providers.tf create mode 100644 observability/variables.tf diff --git a/observability/main.tf b/observability/main.tf new file mode 100644 index 0000000..1268066 --- /dev/null +++ b/observability/main.tf @@ -0,0 +1,5 @@ +resource "stackit_observability_instance" "this" { + project_id = var.project_id + name = var.name + plan_name = var.plan_name +} diff --git a/observability/output.tf b/observability/output.tf new file mode 100644 index 0000000..e69de29 diff --git a/observability/providers.tf b/observability/providers.tf new file mode 100644 index 0000000..8962cf6 --- /dev/null +++ b/observability/providers.tf @@ -0,0 +1,10 @@ + +terraform { + required_version = ">= 1.9.0" + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = "0.56.0" + } + } +} diff --git a/observability/variables.tf b/observability/variables.tf new file mode 100644 index 0000000..f3be80f --- /dev/null +++ b/observability/variables.tf @@ -0,0 +1,11 @@ +variable "project_id" { + type = string +} + +variable "name" { + type = string +} + +variable "plan_name" { + type = string +} From 4144912afab2258464ad2cddaa10d29f7f5e9ff2 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Tue, 8 Jul 2025 14:54:18 +0200 Subject: [PATCH 05/22] testing --- example/main.tf | 58 +++++++++++++++++++++- example/terraform.tfvars | 103 ++++++++++++++++++++++++++++++++++++--- example/variables.tf | 60 ++++++++++++++++++++++- 3 files changed, 212 insertions(+), 9 deletions(-) diff --git a/example/main.tf b/example/main.tf index 2d2fc0b..8ca31ba 100644 --- a/example/main.tf +++ b/example/main.tf @@ -7,4 +7,60 @@ module "security_groups" { name = each.value.name description = each.value.description rules = each.value.rules -} \ No newline at end of file +} + +# module "postgres" { +# source = "../postgres" + +# for_each = var.postgres_instances + +# project_id = var.project_id +# 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 "net" { +# source = "../network" + +# for_each = var.routed_networks + +# project_id = var.project_id +# name = each.value.name + +# ipv4_nameservers = each.value.ipv4_nameservers +# labels = each.value.labels + +# static_ipv4 = each.value.static_ipv4 +# nic_name = each.value.nic_name +# nic_allowed_addresses = each.value.nic_allowed_addresses +# nic_labels = each.value.nic_labels +# nic_security = each.value.nic_security +# nic_security_group_ids = each.value.nic_security_group_ids +# } + +# module "ske" { +# source = "../ske" + +# for_each = var.ske_clusters + +# project_id = var.project_id +# name = each.value.name +# kubernetes_version_min = each.value.kubernetes_version_min +# node_pools = each.value.node_pools +# } + +# module "observability" { +# source = "../observability" + +# for_each = var.observability_instances +# project_id = var.project_id +# name = each.value.name +# plan_name = each.value.plan_name +# } diff --git a/example/terraform.tfvars b/example/terraform.tfvars index 584af52..70d2beb 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -7,8 +7,7 @@ security_groups = { name = "ssh-ingress-group" description = "ALLOW SSH ingress" rules = [ - { - description = "SSH RULE 1" + { description = "SSH RULE 1" direction = "ingress" ether_type = "IPv4" ip_range = "0.0.0.0/0" @@ -27,8 +26,7 @@ security_groups = { name = "web-traffic-group" description = "ALLOW WEB TRAFFIC ingress" rules = [ - { - description = "ALLOW ALL 80" + { description = "ALLOW ALL 80" direction = "ingress" ether_type = "IPv4" ip_range = "0.0.0.0/0" @@ -40,8 +38,7 @@ security_groups = { max = 80 } }, - { - description = "ALLOW ALL 443" + { description = "ALLOW ALL 443" direction = "ingress" ether_type = "IPv4" ip_range = "0.0.0.0/0" @@ -56,4 +53,96 @@ security_groups = { ] }, -} \ No newline at end of file +} + +postgres_instances = { + dev = { + name = "pg-test-instance" + version = 17 + flavor = { + cpu = 2, + ram = 4 + } + storage = { + class = "premium-perf6-stackit", + size = 20 + } + replicas = 1 + acl = ["0.0.0.0/0"] + backup_schedule = "00 00 * * *" + + users = [ + { username = "admin", + roles = ["login", "createdb"] + }, + { username = "testusr", + roles = ["login"] + } + ] + + databases = [ + { + name = "test_db", + owner = "admin" + } + ] + } +} + +routed_networks = { + web = { + name = "web-net" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + labels = { + env = "prod" + } + } + + db = { + name = "db-net" + static_ipv4 = "10.0.2.120" + nic_security = false + } +} + +ske_clusters = { + dev = { + name = "dev-cluster" + kubernetes_version_min = "1.31" + node_pools = [ + { name = "default" + machine_type = "c2.1" + availability_zones = ["eu01-1", "eu01-2"] + volume_size = 40 + minimum = 1 + maximum = 3 + } + ] + } + + staging = { + name = "staging-cluster" + kubernetes_version_min = "1.31" + node_pools = [ + { name = "general" + machine_type = "c2.2" + availability_zones = ["eu03-1", "eu03-2"] + volume_size = 80 + minimum = 2 + maximum = 4 + } + ] + } +} + +observability_instances = { + starter = { + name = "Observability-1" + plan_name = "Observability-Starter-EU01" + } + + prod = { + name = "Observability-2" + plan_name = "Observability-Large-EU01" + } +} diff --git a/example/variables.tf b/example/variables.tf index 918e44e..2752f35 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -15,7 +15,6 @@ variable "service_account_token" { type = string } - variable "security_groups" { type = map(object({ name = optional(string) @@ -41,3 +40,62 @@ variable "security_groups" { })) })) } + +variable "postgres_instances" { + type = map(object({ + name = string + version = number + flavor = object({ cpu = number, ram = number }) + storage = object({ class = string, size = number }) + replicas = number + acl = list(string) + backup_schedule = string + users = list(object({ + username = string + roles = set(string) + })) + databases = list(object({ + name = string + owner = string + })) + })) +} + +variable "routed_networks" { + type = map(object({ + name = string + + ipv4_nameservers = optional(list(string)) + labels = optional(map(string)) + + static_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)) + })) +} + +variable "ske_clusters" { + type = map(object({ + name = string + kubernetes_version_min = string + node_pools = list(object({ + name = string + machine_type = string + availability_zones = list(string) + volume_size = number + minimum = number + maximum = number + })) + })) +} + +variable "observability_instances" { + type = map(object({ + name = string + plan_name = string + })) +} From c335e50effe20da48870f2dfb3003cd406eb96a8 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Wed, 9 Jul 2025 09:46:57 +0200 Subject: [PATCH 06/22] custom static ip nic --- network/main.tf | 24 +++++++++----- network/output.tf | 5 ++- network/variables.tf | 76 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 80 insertions(+), 25 deletions(-) diff --git a/network/main.tf b/network/main.tf index f9ca504..1eae91a 100644 --- a/network/main.tf +++ b/network/main.tf @@ -2,21 +2,29 @@ resource "stackit_network" "this" { project_id = var.project_id name = var.name - ipv4_nameservers = var.ipv4_nameservers - labels = var.labels - - routed = true + ipv4_gateway = var.routed == false ? var.ipv4_gateway : null + ipv4_nameservers = var.ipv4_nameservers + ipv4_prefix = var.ipv4_prefix + ipv4_prefix_length = var.ipv4_prefix_length + ipv6_gateway = var.routed == false ? var.ipv6_gateway : null + ipv6_nameservers = var.ipv6_nameservers + ipv6_prefix = var.ipv6_prefix + ipv6_prefix_length = var.ipv6_prefix_length + labels = var.labels + no_ipv4_gateway = var.no_ipv4_gateway + no_ipv6_gateway = var.no_ipv6_gateway + routed = var.routed } resource "stackit_network_interface" "static" { - count = var.static_ipv4 == null ? 0 : 1 + count = var.nic_ipv4 == null ? 0 : 1 - project_id = var.project_id network_id = stackit_network.this.network_id + project_id = var.project_id - ipv4 = var.static_ipv4 + ipv4 = var.nic_ipv4 labels = var.nic_labels - name = var.nic_name == null ? "${var.name}-nic" : var.nic_name + name = var.nic_name != null ? var.nic_name : "${var.name}-nic" security = var.nic_security security_group_ids = var.nic_security ? var.nic_security_group_ids : null allowed_addresses = var.nic_security ? var.nic_allowed_addresses : null diff --git a/network/output.tf b/network/output.tf index 14a3f9c..ddf472c 100644 --- a/network/output.tf +++ b/network/output.tf @@ -13,7 +13,6 @@ output "network_interface_id" { value = try(stackit_network_interface.static[0].network_interface_id, null) } -output "static_ipv4" { - description = "IPv4 address assigned to NIC (null when not used)" - value = var.static_ipv4 +output "nic_ipv4_list" { + value = try(stackit_network_interface.static[*].ipv4, null) } diff --git a/network/variables.tf b/network/variables.tf index 5bbe8e6..d41ef18 100644 --- a/network/variables.tf +++ b/network/variables.tf @@ -6,31 +6,74 @@ variable "name" { type = string } +variable "ipv4_gateway" { + type = string + default = null +} + variable "ipv4_nameservers" { type = list(string) default = [] } +variable "ipv4_prefix" { + type = string # CIDR, only for NON-routed nets + default = null +} + +variable "ipv4_prefix_length" { + type = number # e.g. 24 + default = null +} + +variable "ipv6_gateway" { + type = string + default = null +} + +variable "ipv6_nameservers" { + type = list(string) + default = [] +} + +variable "ipv6_prefix" { + type = string + default = null +} + +variable "ipv6_prefix_length" { + type = number + default = null +} + variable "labels" { type = map(string) default = {} } -variable "static_ipv4" { - type = string - description = "If set, a NIC will be created with this IPv4." - default = null +variable "no_ipv4_gateway" { + type = bool + default = false } -variable "nic_name" { - type = string - default = null +variable "no_ipv6_gateway" { + type = bool + default = false +} + +variable "routed" { + type = bool + default = true } variable "nic_allowed_addresses" { - type = list(string) - description = "Additional CIDR blocks for NIC" - default = [] + type = list(string) + default = [] +} + +variable "nic_ipv4" { + type = string + default = null } variable "nic_labels" { @@ -38,13 +81,18 @@ variable "nic_labels" { default = {} } +variable "nic_name" { + type = string + default = null +} + variable "nic_security" { type = bool - default = true + default = false + nullable = false } variable "nic_security_group_ids" { - type = list(string) - description = "nic_security must be set to true" - default = [] + type = list(string) + default = [] } From 93f2af55c729ffb38b8760e0617789f110c20b88 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Mon, 14 Jul 2025 13:55:16 +0200 Subject: [PATCH 07/22] update structure for nested resources in project --- security-group/main.tf | 2 +- security-group/variables.tf | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/security-group/main.tf b/security-group/main.tf index 17a4dba..3098cf0 100644 --- a/security-group/main.tf +++ b/security-group/main.tf @@ -13,7 +13,7 @@ resource "stackit_security_group_rule" "rule" { direction = var.rules[count.index].direction project_id = var.project_id - security_group_id = stackit_security_group.this.id + security_group_id = stackit_security_group.this.security_group_id description = var.rules[count.index].description ether_type = var.rules[count.index].ether_type diff --git a/security-group/variables.tf b/security-group/variables.tf index 4367b87..5ccff74 100644 --- a/security-group/variables.tf +++ b/security-group/variables.tf @@ -17,7 +17,7 @@ variable "description" { variable "rules" { description = "List of rules to attach to this security-group" type = list(object({ - direction = string + direction = string description = optional(string) ether_type = optional(string) icmp_parameters = optional(object({ @@ -30,12 +30,12 @@ variable "rules" { max = number })) protocol = optional(object({ - name = optional(string) + name = optional(string) })) remote_security_group_id = optional(string) })) default = [] - validation { + validation { condition = alltrue([ for rule in var.rules : contains(["ingress", "egress"], rule.direction) # ... need more validations From a495f53751dadd869e3ba1c3580c0778bbfb6b14 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Tue, 15 Jul 2025 10:16:40 +0200 Subject: [PATCH 08/22] revert --- example/main.tf | 86 ++++++++++++++++++++-------------------- example/providers.tf | 9 +++-- example/terraform.tfvars | 8 ++-- example/variables.tf | 9 ++++- network/output.tf | 18 --------- network/providers.tf | 3 +- 6 files changed, 61 insertions(+), 72 deletions(-) delete mode 100644 network/output.tf diff --git a/example/main.tf b/example/main.tf index 8ca31ba..c43cdf9 100644 --- a/example/main.tf +++ b/example/main.tf @@ -9,58 +9,58 @@ module "security_groups" { rules = each.value.rules } -# module "postgres" { -# source = "../postgres" +module "postgres" { + source = "../postgres" -# for_each = var.postgres_instances + for_each = var.postgres_instances -# project_id = var.project_id -# 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 -# } + project_id = var.project_id + 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 "net" { -# source = "../network" +module "net" { + source = "../network" -# for_each = var.routed_networks + for_each = var.networks -# project_id = var.project_id -# name = each.value.name + project_id = var.project_id + name = each.value.name -# ipv4_nameservers = each.value.ipv4_nameservers -# labels = each.value.labels + ipv4_nameservers = each.value.ipv4_nameservers + labels = each.value.labels -# static_ipv4 = each.value.static_ipv4 -# nic_name = each.value.nic_name -# nic_allowed_addresses = each.value.nic_allowed_addresses -# nic_labels = each.value.nic_labels -# nic_security = each.value.nic_security -# nic_security_group_ids = each.value.nic_security_group_ids -# } + nic_ipv4 = each.value.nic_ipv4 + nic_name = each.value.nic_name + nic_allowed_addresses = each.value.nic_allowed_addresses + nic_labels = each.value.nic_labels + nic_security = each.value.nic_security + nic_security_group_ids = each.value.nic_security_group_ids +} -# module "ske" { -# source = "../ske" +module "ske" { + source = "../ske" -# for_each = var.ske_clusters + for_each = var.ske_clusters -# project_id = var.project_id -# name = each.value.name -# kubernetes_version_min = each.value.kubernetes_version_min -# node_pools = each.value.node_pools -# } + project_id = var.project_id + name = each.value.name + kubernetes_version_min = each.value.kubernetes_version_min + node_pools = each.value.node_pools +} -# module "observability" { -# source = "../observability" +module "observability" { + source = "../observability" -# for_each = var.observability_instances -# project_id = var.project_id -# name = each.value.name -# plan_name = each.value.plan_name -# } + for_each = var.observability_instances + project_id = var.project_id + name = each.value.name + plan_name = each.value.plan_name +} diff --git a/example/providers.tf b/example/providers.tf index e5cfc8d..04db4e1 100644 --- a/example/providers.tf +++ b/example/providers.tf @@ -9,7 +9,8 @@ terraform { } provider "stackit" { - default_region = var.region - service_account_token = var.service_account_token - enable_beta_resources = true -} \ No newline at end of file + default_region = var.region + service_account_token = var.service_account_token != "" ? var.service_account_token : null + service_account_key_path = var.service_account_key_path != "" ? var.service_account_key_path : null + enable_beta_resources = true +} diff --git a/example/terraform.tfvars b/example/terraform.tfvars index 70d2beb..c5ac554 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -1,6 +1,7 @@ region = "eu01" service_account_token = "" -project_id = "" +# project_id = "b25685da-5954-4382-b654-62abd9f0ef77" +service_account_key_path = "/Users/schlenz/sa-key-dd5fa2c9-1651-4da7-8404-9ac4fe9bc3d5.json" security_groups = { ssh_ingress_group = { @@ -52,7 +53,6 @@ security_groups = { }, ] }, - } postgres_instances = { @@ -89,7 +89,7 @@ postgres_instances = { } } -routed_networks = { +networks = { web = { name = "web-net" ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] @@ -100,7 +100,7 @@ routed_networks = { db = { name = "db-net" - static_ipv4 = "10.0.2.120" + nic_ipv4 = "10.0.2.120" nic_security = false } } diff --git a/example/variables.tf b/example/variables.tf index 2752f35..4c9ea43 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -15,6 +15,11 @@ variable "service_account_token" { type = string } +variable "service_account_key_path" { + type = string + default = "" +} + variable "security_groups" { type = map(object({ name = optional(string) @@ -61,14 +66,14 @@ variable "postgres_instances" { })) } -variable "routed_networks" { +variable "networks" { type = map(object({ name = string ipv4_nameservers = optional(list(string)) labels = optional(map(string)) - static_ipv4 = optional(string) + nic_ipv4 = optional(string) nic_name = optional(string) nic_allowed_addresses = optional(list(string)) diff --git a/network/output.tf b/network/output.tf deleted file mode 100644 index ddf472c..0000000 --- a/network/output.tf +++ /dev/null @@ -1,18 +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 -} - -output "network_interface_id" { - description = "NIC ID" - value = try(stackit_network_interface.static[0].network_interface_id, null) -} - -output "nic_ipv4_list" { - value = try(stackit_network_interface.static[*].ipv4, null) -} diff --git a/network/providers.tf b/network/providers.tf index dd742e3..8962cf6 100644 --- a/network/providers.tf +++ b/network/providers.tf @@ -1,3 +1,4 @@ + terraform { required_version = ">= 1.9.0" required_providers { @@ -6,4 +7,4 @@ terraform { version = "0.56.0" } } -} \ No newline at end of file +} From bb841ad2a3ffe722cdd39da700f488de0508be3f Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Tue, 15 Jul 2025 12:04:25 +0200 Subject: [PATCH 09/22] revert to old structure --- example/main.tf | 88 ++++++----- example/terraform.tfvars | 226 ++++++++++++++------------- example/variables.tf | 91 ++++++----- network/main.tf | 24 +-- network/variables.tf | 9 +- project/main.tf | 38 +---- project/output.tf | 4 + project/providers.tf | 9 ++ project/variables.tf | 27 +++- project_old/main.tf | 34 ++++ {project => project_old}/provider.tf | 0 {project => project_old}/sna.tf | 0 project_old/variables.tf | 10 ++ security-group/main.tf | 2 +- security-group/output.tf | 2 +- 15 files changed, 321 insertions(+), 243 deletions(-) create mode 100644 project/output.tf create mode 100644 project/providers.tf create mode 100644 project_old/main.tf rename {project => project_old}/provider.tf (100%) rename {project => project_old}/sna.tf (100%) create mode 100644 project_old/variables.tf diff --git a/example/main.tf b/example/main.tf index c43cdf9..2d6c014 100644 --- a/example/main.tf +++ b/example/main.tf @@ -1,66 +1,78 @@ +module "project" { + source = "../project" + + name = "project-1" + organization_id = var.organization_id + owner_email = "maximilian.schlenz@stackit.cloud" +} + module "security_groups" { source = "../security-group" for_each = var.security_groups - project_id = var.project_id + project_id = module.project.project_id name = each.value.name description = each.value.description rules = each.value.rules } -module "postgres" { - source = "../postgres" +# module "postgres" { +# source = "../postgres" - for_each = var.postgres_instances +# for_each = var.postgres_instances - project_id = var.project_id - 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 -} +# project_id = module.project.project_id +# 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 "net" { - source = "../network" + depends_on = [module.security_groups] + source = "../network" for_each = var.networks - project_id = var.project_id + project_id = module.project.project_id name = each.value.name ipv4_nameservers = each.value.ipv4_nameservers labels = each.value.labels - nic_ipv4 = each.value.nic_ipv4 - nic_name = each.value.nic_name - nic_allowed_addresses = each.value.nic_allowed_addresses - nic_labels = each.value.nic_labels - nic_security = each.value.nic_security - nic_security_group_ids = each.value.nic_security_group_ids + nic_ipv4 = each.value.nic_ipv4 + nic_name = each.value.nic_name + nic_allowed_addresses = each.value.nic_allowed_addresses + nic_labels = each.value.nic_labels + nic_security = each.value.nic_security + + nic_security_group_ids = [ + module.security_groups["ssh_ingress_group"].security_group_id, + ] } -module "ske" { - source = "../ske" +# module "ske" { +# source = "../ske" - for_each = var.ske_clusters +# for_each = var.ske_clusters - project_id = var.project_id - name = each.value.name - kubernetes_version_min = each.value.kubernetes_version_min - node_pools = each.value.node_pools -} +# project_id = module.project.project_id +# name = each.value.name +# kubernetes_version_min = each.value.kubernetes_version_min +# node_pools = each.value.node_pools +# } -module "observability" { - source = "../observability" +# module "observability" { +# source = "../observability" - for_each = var.observability_instances - project_id = var.project_id - name = each.value.name - plan_name = each.value.plan_name -} +# for_each = var.observability_instances +# project_id = module.project.project_id +# name = each.value.name +# plan_name = each.value.plan_name +# } diff --git a/example/terraform.tfvars b/example/terraform.tfvars index c5ac554..ef8304b 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -1,6 +1,7 @@ -region = "eu01" -service_account_token = "" -# project_id = "b25685da-5954-4382-b654-62abd9f0ef77" +region = "eu01" +service_account_token = "" +project_id = "" +organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" service_account_key_path = "/Users/schlenz/sa-key-dd5fa2c9-1651-4da7-8404-9ac4fe9bc3d5.json" security_groups = { @@ -23,126 +24,129 @@ security_groups = { ] }, - web_traffic_group = { - name = "web-traffic-group" - 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 - } - }, - ] - }, + # web_traffic_group = { + # name = "web-traffic-group" + # 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 + # } + # }, + # ] + # }, } -postgres_instances = { - dev = { - name = "pg-test-instance" - version = 17 - flavor = { - cpu = 2, - ram = 4 - } - storage = { - class = "premium-perf6-stackit", - size = 20 - } - replicas = 1 - acl = ["0.0.0.0/0"] - backup_schedule = "00 00 * * *" +# postgres_instances = { +# dev = { +# name = "pg-test-instance" +# version = 17 +# flavor = { +# cpu = 2, +# ram = 4 +# } +# storage = { +# class = "premium-perf6-stackit", +# size = 20 +# } +# replicas = 1 +# acl = ["0.0.0.0/0"] +# backup_schedule = "00 00 * * *" - users = [ - { username = "admin", - roles = ["login", "createdb"] - }, - { username = "testusr", - roles = ["login"] - } - ] +# users = [ +# { username = "admin", +# roles = ["login", "createdb"] +# }, +# { username = "testusr", +# roles = ["login"] +# } +# ] - databases = [ - { - name = "test_db", - owner = "admin" - } - ] - } -} +# databases = [ +# { +# name = "test_db", +# owner = "admin" +# } +# ] +# } +# } networks = { - web = { - name = "web-net" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - labels = { - env = "prod" - } - } + # web = { + # name = "web-net" + # ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + # labels = { + # env = "prod" + # } + # } db = { name = "db-net" - nic_ipv4 = "10.0.2.120" - nic_security = false + nic_ipv4 = "10.0.0.126" + nic_security = true + security_groups = { + + } } } -ske_clusters = { - dev = { - name = "dev-cluster" - kubernetes_version_min = "1.31" - node_pools = [ - { name = "default" - machine_type = "c2.1" - availability_zones = ["eu01-1", "eu01-2"] - volume_size = 40 - minimum = 1 - maximum = 3 - } - ] - } +# ske_clusters = { +# dev = { +# name = "dev-cluster" +# kubernetes_version_min = "1.31" +# node_pools = [ +# { name = "default" +# machine_type = "c2.1" +# availability_zones = ["eu01-1", "eu01-2"] +# volume_size = 40 +# minimum = 1 +# maximum = 3 +# } +# ] +# } - staging = { - name = "staging-cluster" - kubernetes_version_min = "1.31" - node_pools = [ - { name = "general" - machine_type = "c2.2" - availability_zones = ["eu03-1", "eu03-2"] - volume_size = 80 - minimum = 2 - maximum = 4 - } - ] - } -} +# staging = { +# name = "staging-cluster" +# kubernetes_version_min = "1.31" +# node_pools = [ +# { name = "general" +# machine_type = "c2.2" +# availability_zones = ["eu03-1", "eu03-2"] +# volume_size = 80 +# minimum = 2 +# maximum = 4 +# } +# ] +# } +# } -observability_instances = { - starter = { - name = "Observability-1" - plan_name = "Observability-Starter-EU01" - } +# observability_instances = { +# starter = { +# name = "Observability-1" +# plan_name = "Observability-Starter-EU01" +# } - prod = { - name = "Observability-2" - plan_name = "Observability-Large-EU01" - } -} +# prod = { +# name = "Observability-2" +# plan_name = "Observability-Large-EU01" +# } +# } diff --git a/example/variables.tf b/example/variables.tf index 4c9ea43..be98dee 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -20,6 +20,17 @@ variable "service_account_key_path" { default = "" } +variable "organization_id" { + description = "Organization ID" + type = string +} + +variable "owner_email" { + description = "Email of the project owner" + type = string + default = null +} + variable "security_groups" { type = map(object({ name = optional(string) @@ -46,25 +57,25 @@ variable "security_groups" { })) } -variable "postgres_instances" { - type = map(object({ - name = string - version = number - flavor = object({ cpu = number, ram = number }) - storage = object({ class = string, size = number }) - replicas = number - acl = list(string) - backup_schedule = string - users = list(object({ - username = string - roles = set(string) - })) - databases = list(object({ - name = string - owner = string - })) - })) -} +# variable "postgres_instances" { +# type = map(object({ +# name = string +# version = number +# flavor = object({ cpu = number, ram = number }) +# storage = object({ class = string, size = number }) +# replicas = number +# acl = list(string) +# backup_schedule = string +# users = list(object({ +# username = string +# roles = set(string) +# })) +# databases = list(object({ +# name = string +# owner = string +# })) +# })) +# } variable "networks" { type = map(object({ @@ -74,7 +85,7 @@ variable "networks" { labels = optional(map(string)) nic_ipv4 = optional(string) - nic_name = optional(string) + nic_name = optional(string) nic_allowed_addresses = optional(list(string)) nic_labels = optional(map(string)) @@ -83,24 +94,24 @@ variable "networks" { })) } -variable "ske_clusters" { - type = map(object({ - name = string - kubernetes_version_min = string - node_pools = list(object({ - name = string - machine_type = string - availability_zones = list(string) - volume_size = number - minimum = number - maximum = number - })) - })) -} +# variable "ske_clusters" { +# type = map(object({ +# name = string +# kubernetes_version_min = string +# node_pools = list(object({ +# name = string +# machine_type = string +# availability_zones = list(string) +# volume_size = number +# minimum = number +# maximum = number +# })) +# })) +# } -variable "observability_instances" { - type = map(object({ - name = string - plan_name = string - })) -} +# variable "observability_instances" { +# type = map(object({ +# name = string +# plan_name = string +# })) +# } diff --git a/network/main.tf b/network/main.tf index 1eae91a..b010a34 100644 --- a/network/main.tf +++ b/network/main.tf @@ -2,18 +2,18 @@ resource "stackit_network" "this" { project_id = var.project_id name = var.name - ipv4_gateway = var.routed == false ? var.ipv4_gateway : null - ipv4_nameservers = var.ipv4_nameservers - ipv4_prefix = var.ipv4_prefix - ipv4_prefix_length = var.ipv4_prefix_length - ipv6_gateway = var.routed == false ? var.ipv6_gateway : null - ipv6_nameservers = var.ipv6_nameservers - ipv6_prefix = var.ipv6_prefix - ipv6_prefix_length = var.ipv6_prefix_length - labels = var.labels - no_ipv4_gateway = var.no_ipv4_gateway - no_ipv6_gateway = var.no_ipv6_gateway - routed = var.routed + ipv4_gateway = var.routed == false ? var.ipv4_gateway : null + ipv4_nameservers = var.ipv4_nameservers + ipv4_prefix = var.ipv4_prefix + ipv4_prefix_length = var.ipv4_prefix_length + ipv6_gateway = var.routed == false ? var.ipv6_gateway : null + ipv6_nameservers = var.ipv6_nameservers + ipv6_prefix = var.ipv6_prefix + ipv6_prefix_length = var.ipv6_prefix_length + labels = var.labels + no_ipv4_gateway = var.no_ipv4_gateway + no_ipv6_gateway = var.no_ipv6_gateway + routed = var.routed } resource "stackit_network_interface" "static" { diff --git a/network/variables.tf b/network/variables.tf index d41ef18..dd0dad5 100644 --- a/network/variables.tf +++ b/network/variables.tf @@ -87,8 +87,8 @@ variable "nic_name" { } variable "nic_security" { - type = bool - default = false + type = bool + default = false nullable = false } @@ -96,3 +96,8 @@ variable "nic_security_group_ids" { type = list(string) default = [] } + +variable "nic_security_group_names" { + type = list(string) + default = [] +} \ No newline at end of file diff --git a/project/main.tf b/project/main.tf index 58176f0..bc13502 100644 --- a/project/main.tf +++ b/project/main.tf @@ -1,34 +1,6 @@ -variable "projects" { - type = map(object({ - name = string - owner_email = string - })) - default = { - project1 = { - name = "project-alpha" - owner_email = "michael.sodan@stackit.cloud" - } - project2 = { - name = "project-beta" - owner_email = "michael.sodan@stackit.cloud" - } - } +resource "stackit_resourcemanager_project" "this" { + parent_container_id = var.organization_id + name = var.name + labels = var.labels + owner_email = var.owner_email } - -resource "stackit_resourcemanager_project" "projects" { - for_each = var.projects - parent_container_id = var.organization_id # Nutzt jetzt die übergebene Variable - name = each.value.name - owner_email = each.value.owner_email - # labels = { ... } # Vorerst entfernt, da stackit_network_area nicht definiert war -} - -output "project_info" { - value = { - for k, project in stackit_resourcemanager_project.projects : k => { - project_id = project.project_id - container_id = project.container_id - } - } -} - diff --git a/project/output.tf b/project/output.tf new file mode 100644 index 0000000..67fb6c5 --- /dev/null +++ b/project/output.tf @@ -0,0 +1,4 @@ +output "project_id" { + value = stackit_resourcemanager_project.this.id + description = "ID of the project" +} \ No newline at end of file diff --git a/project/providers.tf b/project/providers.tf new file mode 100644 index 0000000..6e038c3 --- /dev/null +++ b/project/providers.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.9.0" + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = "0.56.0" + } + } +} diff --git a/project/variables.tf b/project/variables.tf index 6a8400f..ff96a41 100644 --- a/project/variables.tf +++ b/project/variables.tf @@ -1,10 +1,27 @@ variable "organization_id" { - description = "Empfängt die Container-ID der Organisation vom Root-Modul." - type = string + type = string } -variable "sna_net" { - description = "SNA Transfer Network" - type = string +variable "name" { + type = string } +variable "description" { + type = string + default = null +} + +variable "labels" { + type = map(string) + default = {} +} + +variable "project_id" { + type = string + default = null +} + +variable "owner_email" { + type = string + default = null +} diff --git a/project_old/main.tf b/project_old/main.tf new file mode 100644 index 0000000..58176f0 --- /dev/null +++ b/project_old/main.tf @@ -0,0 +1,34 @@ +variable "projects" { + type = map(object({ + name = string + owner_email = string + })) + default = { + project1 = { + name = "project-alpha" + owner_email = "michael.sodan@stackit.cloud" + } + project2 = { + name = "project-beta" + owner_email = "michael.sodan@stackit.cloud" + } + } +} + +resource "stackit_resourcemanager_project" "projects" { + for_each = var.projects + parent_container_id = var.organization_id # Nutzt jetzt die übergebene Variable + name = each.value.name + owner_email = each.value.owner_email + # labels = { ... } # Vorerst entfernt, da stackit_network_area nicht definiert war +} + +output "project_info" { + value = { + for k, project in stackit_resourcemanager_project.projects : k => { + project_id = project.project_id + container_id = project.container_id + } + } +} + diff --git a/project/provider.tf b/project_old/provider.tf similarity index 100% rename from project/provider.tf rename to project_old/provider.tf diff --git a/project/sna.tf b/project_old/sna.tf similarity index 100% rename from project/sna.tf rename to project_old/sna.tf diff --git a/project_old/variables.tf b/project_old/variables.tf new file mode 100644 index 0000000..6a8400f --- /dev/null +++ b/project_old/variables.tf @@ -0,0 +1,10 @@ +variable "organization_id" { + description = "Empfängt die Container-ID der Organisation vom Root-Modul." + type = string +} + +variable "sna_net" { + description = "SNA Transfer Network" + type = string +} + diff --git a/security-group/main.tf b/security-group/main.tf index 17a4dba..3098cf0 100644 --- a/security-group/main.tf +++ b/security-group/main.tf @@ -13,7 +13,7 @@ resource "stackit_security_group_rule" "rule" { direction = var.rules[count.index].direction project_id = var.project_id - security_group_id = stackit_security_group.this.id + security_group_id = stackit_security_group.this.security_group_id description = var.rules[count.index].description ether_type = var.rules[count.index].ether_type diff --git a/security-group/output.tf b/security-group/output.tf index bf320d2..b172314 100644 --- a/security-group/output.tf +++ b/security-group/output.tf @@ -5,4 +5,4 @@ output "security_group_id" { output "rule_ids" { value = stackit_security_group_rule.rule[*].id -} \ No newline at end of file +} From 7345619f2306741415abf3880bbda52d0c4b73ce Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Tue, 15 Jul 2025 15:42:38 +0200 Subject: [PATCH 10/22] add logic for nic, nic w. custom ipv4, creation of and attachement of sec grps to nic --- example/main.tf | 69 ++++++++++++-------- example/providers.tf | 2 +- example/terraform.tfvars | 52 +++++++++++---- example/variables.tf | 38 ++++++++--- network/main.tf | 46 ++++++++------ network/output.tf | 9 +++ network/providers.tf | 3 +- network/variables.tf | 23 +++++-- project/output.tf | 2 +- project/providers.tf | 2 +- security-group/output.tf | 7 ++- security-group/providers.tf | 2 +- security-group/variables.tf | 122 +++++++++++++++++++++++++++--------- 13 files changed, 270 insertions(+), 107 deletions(-) create mode 100644 network/output.tf diff --git a/example/main.tf b/example/main.tf index 2d6c014..d185416 100644 --- a/example/main.tf +++ b/example/main.tf @@ -1,9 +1,12 @@ module "project" { source = "../project" - name = "project-1" + name = "project-123" + labels = { + "example" = "test" + } organization_id = var.organization_id - owner_email = "maximilian.schlenz@stackit.cloud" + owner_email = "maximilian.schlenz@stackit.cloud" } module "security_groups" { @@ -13,10 +16,47 @@ module "security_groups" { project_id = module.project.project_id name = each.value.name - description = each.value.description + 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 = module.project.project_id + name = each.value.name + + # IPv4 and IPv6 settings + 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 + + # NIC options + nics = each.value.nics + security_group_ids_by_name = local.security_group_ids_by_name +} + # module "postgres" { # source = "../postgres" @@ -34,29 +74,6 @@ module "security_groups" { # databases = each.value.databases # } -module "net" { - depends_on = [module.security_groups] - source = "../network" - - for_each = var.networks - - project_id = module.project.project_id - name = each.value.name - - ipv4_nameservers = each.value.ipv4_nameservers - labels = each.value.labels - - nic_ipv4 = each.value.nic_ipv4 - nic_name = each.value.nic_name - nic_allowed_addresses = each.value.nic_allowed_addresses - nic_labels = each.value.nic_labels - nic_security = each.value.nic_security - - nic_security_group_ids = [ - module.security_groups["ssh_ingress_group"].security_group_id, - ] -} - # module "ske" { # source = "../ske" diff --git a/example/providers.tf b/example/providers.tf index 04db4e1..21bfe9e 100644 --- a/example/providers.tf +++ b/example/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.56.0" + version = "0.54.0" } } } diff --git a/example/terraform.tfvars b/example/terraform.tfvars index ef8304b..d8c6bc8 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -1,7 +1,7 @@ region = "eu01" service_account_token = "" project_id = "" -organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" +organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" service_account_key_path = "/Users/schlenz/sa-key-dd5fa2c9-1651-4da7-8404-9ac4fe9bc3d5.json" security_groups = { @@ -91,21 +91,51 @@ security_groups = { # } networks = { - # web = { - # name = "web-net" - # ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - # labels = { - # env = "prod" - # } - # } + wan_network = { + name = "wan_network" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + ipv4_prefix_length = 24 + ipv4_prefix = "10.219.0.0/24" + routed = true + } + lan_network1 = { + name = "lan_network1" + ipv4_prefix_length = 24 + ipv4_prefix = "10.220.1.0/24" + routed = true + nics = { + p2_lan1 = { + nic_name = "P2LAN1" + nic_ipv4 = "10.220.1.32" + nic_security = true + nic_security_group_names = ["ssh-ingress-group"] + } + } + } + lan_network2 = { + name = "lan_network2" + ipv4_prefix_length = 24 + ipv4_prefix = "10.221.0.0/24" + routed = true + } + lan_network3 = { + name = "lan_network3" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + ipv4_prefix_length = 24 + ipv4_prefix = "10.223.3.0/24" + routed = true + } + wan = { + name = "MGMT" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + ipv4_prefix_length = 24 + nic_ipv4 = "10.224.0.254" + } db = { name = "db-net" nic_ipv4 = "10.0.0.126" nic_security = true - security_groups = { - - } } } diff --git a/example/variables.tf b/example/variables.tf index be98dee..496493e 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -77,23 +77,45 @@ variable "security_groups" { # })) # } +# Network definition map variable "networks" { type = map(object({ name = string - ipv4_nameservers = optional(list(string)) - labels = optional(map(string)) + # IPv4 settings + ipv4_gateway = optional(string) + ipv4_nameservers = optional(list(string)) + ipv4_prefix = optional(string) + ipv4_prefix_length = optional(number) - nic_ipv4 = optional(string) - nic_name = optional(string) + # IPv6 settings + ipv6_gateway = optional(string) + ipv6_nameservers = optional(list(string)) + ipv6_prefix = optional(string) + ipv6_prefix_length = optional(number) - nic_allowed_addresses = optional(list(string)) - nic_labels = optional(map(string)) - nic_security = optional(bool) - nic_security_group_ids = optional(list(string)) + # Flags & labels + labels = optional(map(string)) + no_ipv4_gateway = optional(bool) + no_ipv6_gateway = optional(bool) + routed = optional(bool) + + # NIC‑specific options + 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 = {} } + # variable "ske_clusters" { # type = map(object({ # name = string diff --git a/network/main.tf b/network/main.tf index b010a34..0f7b638 100644 --- a/network/main.tf +++ b/network/main.tf @@ -1,31 +1,41 @@ resource "stackit_network" "this" { - project_id = var.project_id - name = var.name + project_id = var.project_id + name = var.name + labels = var.labels - ipv4_gateway = var.routed == false ? var.ipv4_gateway : null + # 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_gateway = var.routed == false ? var.ipv6_gateway : null + + # IPv6 settings + ipv6_gateway = var.ipv6_gateway ipv6_nameservers = var.ipv6_nameservers ipv6_prefix = var.ipv6_prefix ipv6_prefix_length = var.ipv6_prefix_length - labels = var.labels - no_ipv4_gateway = var.no_ipv4_gateway - no_ipv6_gateway = var.no_ipv6_gateway - routed = var.routed + + no_ipv4_gateway = var.no_ipv4_gateway + no_ipv6_gateway = var.no_ipv6_gateway + routed = var.routed } -resource "stackit_network_interface" "static" { - count = var.nic_ipv4 == null ? 0 : 1 +resource "stackit_network_interface" "nics" { + for_each = var.nics != null ? var.nics : {} - network_id = stackit_network.this.network_id project_id = var.project_id - - ipv4 = var.nic_ipv4 - labels = var.nic_labels - name = var.nic_name != null ? var.nic_name : "${var.name}-nic" - security = var.nic_security - security_group_ids = var.nic_security ? var.nic_security_group_ids : null - allowed_addresses = var.nic_security ? var.nic_allowed_addresses : null + 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]] + : [] + ) } + diff --git a/network/output.tf b/network/output.tf new file mode 100644 index 0000000..fc6e82d --- /dev/null +++ b/network/output.tf @@ -0,0 +1,9 @@ +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 index 8962cf6..532c77d 100644 --- a/network/providers.tf +++ b/network/providers.tf @@ -1,10 +1,9 @@ - terraform { required_version = ">= 1.9.0" required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.56.0" + version = "0.54.0" } } } diff --git a/network/variables.tf b/network/variables.tf index dd0dad5..68eb3a6 100644 --- a/network/variables.tf +++ b/network/variables.tf @@ -63,7 +63,7 @@ variable "no_ipv6_gateway" { variable "routed" { type = bool - default = true + # default = true } variable "nic_allowed_addresses" { @@ -97,7 +97,20 @@ variable "nic_security_group_ids" { default = [] } -variable "nic_security_group_names" { - type = list(string) - default = [] -} \ No newline at end of file +variable "nics" { + 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 = "Map of security-group names -> IDs" + type = map(string) +} diff --git a/project/output.tf b/project/output.tf index 67fb6c5..09573a9 100644 --- a/project/output.tf +++ b/project/output.tf @@ -1,4 +1,4 @@ output "project_id" { - value = stackit_resourcemanager_project.this.id + value = stackit_resourcemanager_project.this.project_id description = "ID of the project" } \ No newline at end of file diff --git a/project/providers.tf b/project/providers.tf index 6e038c3..532c77d 100644 --- a/project/providers.tf +++ b/project/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.56.0" + version = "0.54.0" } } } diff --git a/security-group/output.tf b/security-group/output.tf index b172314..d28e44e 100644 --- a/security-group/output.tf +++ b/security-group/output.tf @@ -1,8 +1,9 @@ output "security_group_id" { - value = stackit_security_group.this.security_group_id description = "ID of the security group" + value = stackit_security_group.this.security_group_id } -output "rule_ids" { - value = stackit_security_group_rule.rule[*].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 index 6e038c3..532c77d 100644 --- a/security-group/providers.tf +++ b/security-group/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.56.0" + version = "0.54.0" } } } diff --git a/security-group/variables.tf b/security-group/variables.tf index 4367b87..053a240 100644 --- a/security-group/variables.tf +++ b/security-group/variables.tf @@ -1,45 +1,107 @@ variable "project_id" { + description = "STACKIT project ID in which to create resources." type = string - description = "The ID of the project where the security group will be created." } variable "name" { + description = "Name of the network." type = string - description = "Name of the security group." } variable "description" { type = string default = "" - description = "Description of the security group. If not provided, it defaults to an empty string." +} + +variable "ipv4_gateway" { + description = "IPv4 gateway for the network. If null, the first IP in the CIDR is used." + type = string + nullable = true + default = null +} + +variable "ipv4_nameservers" { + description = "List of IPv4 nameservers." + type = list(string) + nullable = true + default = null +} + +variable "ipv4_prefix" { + description = "IPv4 prefix (CIDR) for the network." + type = string + nullable = true + default = null +} + +variable "ipv4_prefix_length" { + description = "IPv4 prefix length for the network." + type = number + nullable = true + default = null +} + +variable "ipv6_gateway" { + description = "IPv6 gateway for the network. If null, the first IP in the CIDR is used." + type = string + nullable = true + default = null +} + +variable "ipv6_nameservers" { + description = "List of IPv6 nameservers." + type = list(string) + nullable = true + default = null +} + +variable "ipv6_prefix" { + description = "IPv6 prefix (CIDR) for the network." + type = string + nullable = true + default = null +} + +variable "ipv6_prefix_length" { + description = "IPv6 prefix length for the network." + type = number + nullable = true + default = null +} + +variable "labels" { + description = "Key/value labels to attach to the network." + type = map(string) + nullable = true + default = null +} + +variable "no_ipv4_gateway" { + description = "If true, suppress creation of an IPv4 gateway." + type = bool + default = false +} + +variable "no_ipv6_gateway" { + description = "If true, suppress creation of an IPv6 gateway." + type = bool + default = false +} + +variable "routed" { + description = "If true, the network is routed." + type = bool + default = false +} + +variable "routing_table_id" { + description = "Routing table ID to associate with this network (experimental)." + type = string + nullable = true + default = null } variable "rules" { - description = "List of rules to attach to this security-group" - type = list(object({ - direction = string - description = optional(string) - ether_type = optional(string) - icmp_parameters = optional(object({ - type = optional(number) - code = optional(number) - })) - ip_range = optional(string) - port_range = optional(object({ - min = number - max = number - })) - protocol = optional(object({ - name = optional(string) - })) - remote_security_group_id = optional(string) - })) - default = [] - validation { - condition = alltrue([ - for rule in var.rules : contains(["ingress", "egress"], rule.direction) - # ... need more validations - ]) - error_message = "Direction must be either \"ingress\" or \"egress\"." - } + description = "List of routing rules to apply to this network (experimental)." + type = any } From 370b15a3286318d1f2399041fe78edc333ab0d50 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Tue, 15 Jul 2025 16:13:14 +0200 Subject: [PATCH 11/22] add validation for postgres, db name requirements and catch reserved 'admin' user --- example/main.tf | 50 ++++++++++++++++++++------------ example/terraform.tfvars | 62 ++++++++++++++++++++-------------------- example/variables.tf | 38 ++++++++++++------------ postgres/providers.tf | 2 +- postgres/variables.tf | 34 ++++++++++++++++++++-- 5 files changed, 115 insertions(+), 71 deletions(-) diff --git a/example/main.tf b/example/main.tf index d185416..f5c620a 100644 --- a/example/main.tf +++ b/example/main.tf @@ -57,22 +57,22 @@ module "net" { security_group_ids_by_name = local.security_group_ids_by_name } -# module "postgres" { -# source = "../postgres" +module "postgres" { + source = "../postgres" -# for_each = var.postgres_instances + for_each = var.postgres_instances -# project_id = module.project.project_id -# 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 -# } + project_id = module.project.project_id + 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 "ske" { # source = "../ske" @@ -86,10 +86,24 @@ module "net" { # } # module "observability" { -# source = "../observability" - +# source = "../observability" # path to the new module # for_each = var.observability_instances + # project_id = module.project.project_id -# name = each.value.name -# plan_name = each.value.plan_name + +# # required +# name = each.value.name +# plan_name = each.value.plan_name + +# # optionals +# 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 # } diff --git a/example/terraform.tfvars b/example/terraform.tfvars index d8c6bc8..d4e2d8f 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -56,39 +56,39 @@ security_groups = { # }, } -# postgres_instances = { -# dev = { -# name = "pg-test-instance" -# version = 17 -# flavor = { -# cpu = 2, -# ram = 4 -# } -# storage = { -# class = "premium-perf6-stackit", -# size = 20 -# } -# replicas = 1 -# acl = ["0.0.0.0/0"] -# backup_schedule = "00 00 * * *" +postgres_instances = { + dev = { + name = "pg-test-instance" + version = 17 + flavor = { + cpu = 2, + ram = 4 + } + storage = { + class = "premium-perf6-stackit", + size = 20 + } + replicas = 1 + acl = ["0.0.0.0/0"] + backup_schedule = "00 00 * * *" -# users = [ -# { username = "admin", -# roles = ["login", "createdb"] -# }, -# { username = "testusr", -# roles = ["login"] -# } -# ] + users = [ + { username = "adminusr", + roles = ["login", "createdb"] + }, + { username = "testusr", + roles = ["login"] + } + ] -# databases = [ -# { -# name = "test_db", -# owner = "admin" -# } -# ] -# } -# } + databases = [ + { + name = "testdb", + owner = "admin" + } + ] + } +} networks = { wan_network = { diff --git a/example/variables.tf b/example/variables.tf index 496493e..d17e836 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -57,25 +57,25 @@ variable "security_groups" { })) } -# variable "postgres_instances" { -# type = map(object({ -# name = string -# version = number -# flavor = object({ cpu = number, ram = number }) -# storage = object({ class = string, size = number }) -# replicas = number -# acl = list(string) -# backup_schedule = string -# users = list(object({ -# username = string -# roles = set(string) -# })) -# databases = list(object({ -# name = string -# owner = string -# })) -# })) -# } +variable "postgres_instances" { + type = map(object({ + name = string + version = number + flavor = object({ cpu = number, ram = number }) + storage = object({ class = string, size = number }) + replicas = number + acl = list(string) + backup_schedule = string + users = list(object({ + username = string + roles = set(string) + })) + databases = list(object({ + name = string + owner = string + })) + })) +} # Network definition map variable "networks" { diff --git a/postgres/providers.tf b/postgres/providers.tf index 6e038c3..532c77d 100644 --- a/postgres/providers.tf +++ b/postgres/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.56.0" + version = "0.54.0" } } } diff --git a/postgres/variables.tf b/postgres/variables.tf index dbe1920..061dd3f 100644 --- a/postgres/variables.tf +++ b/postgres/variables.tf @@ -4,6 +4,21 @@ variable "project_id" { variable "name" { type = string + + validation { + condition = length(regexall("^[a-z]([-a-z0-9]*[a-z0-9])?$", var.name)) > 0 + error_message = < 0 + ]) + error_message = < Date: Wed, 16 Jul 2025 11:07:08 +0200 Subject: [PATCH 12/22] add remaining observability resources --- example/main.tf | 52 ++++-- example/terraform.tfvars | 364 ++++++++++++++++++++++++------------- example/variables.tf | 137 ++++++++++++-- network/main.tf | 28 +-- network/variables.tf | 6 +- observability/main.tf | 51 ++++++ observability/output.tf | 0 observability/outputs.tf | 50 +++++ observability/providers.tf | 2 +- observability/variables.tf | 113 +++++++++++- project/output.tf | 4 +- 11 files changed, 616 insertions(+), 191 deletions(-) delete mode 100644 observability/output.tf create mode 100644 observability/outputs.tf diff --git a/example/main.tf b/example/main.tf index f5c620a..526054e 100644 --- a/example/main.tf +++ b/example/main.tf @@ -1,7 +1,7 @@ module "project" { source = "../project" - name = "project-123" + name = "project-123" labels = { "example" = "test" } @@ -53,7 +53,7 @@ module "net" { labels = each.value.labels # NIC options - nics = each.value.nics + nics = each.value.nics security_group_ids_by_name = local.security_group_ids_by_name } @@ -85,25 +85,37 @@ module "postgres" { # node_pools = each.value.node_pools # } -# module "observability" { -# source = "../observability" # path to the new module -# for_each = var.observability_instances +module "observability" { + source = "../observability" + for_each = var.observability_instances -# project_id = module.project.project_id + project_id = module.project.project_id -# # required -# name = each.value.name -# plan_name = each.value.plan_name + name = each.value.name + plan_name = each.value.plan_name -# # optionals -# 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 + 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 -# } + # 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 + } +} \ No newline at end of file diff --git a/example/terraform.tfvars b/example/terraform.tfvars index d4e2d8f..718230f 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -5,24 +5,24 @@ organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" service_account_key_path = "/Users/schlenz/sa-key-dd5fa2c9-1651-4da7-8404-9ac4fe9bc3d5.json" security_groups = { - ssh_ingress_group = { - name = "ssh-ingress-group" - 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 - } - }, - ] - }, + # ssh_ingress_group = { + # name = "ssh-ingress-group" + # 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" @@ -57,126 +57,234 @@ security_groups = { } postgres_instances = { - dev = { - name = "pg-test-instance" - version = 17 - flavor = { - cpu = 2, - ram = 4 - } - storage = { - class = "premium-perf6-stackit", - size = 20 - } - replicas = 1 - acl = ["0.0.0.0/0"] - backup_schedule = "00 00 * * *" + # dev = { + # name = "pg-test-instance" + # version = 17 + # flavor = { + # cpu = 2, + # ram = 4 + # } + # storage = { + # class = "premium-perf6-stackit", + # size = 20 + # } + # replicas = 1 + # acl = ["0.0.0.0/0"] + # backup_schedule = "00 00 * * *" - users = [ - { username = "adminusr", - roles = ["login", "createdb"] - }, - { username = "testusr", - roles = ["login"] - } - ] + # users = [ + # { username = "adminusr", + # roles = ["login", "createdb"] + # }, + # { username = "testusr", + # roles = ["login"] + # } + # ] - databases = [ - { - name = "testdb", - owner = "admin" - } - ] - } + # databases = [ + # { + # name = "testdb", + # owner = "admin" + # } + # ] + # } } networks = { - wan_network = { - name = "wan_network" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - ipv4_prefix_length = 24 - ipv4_prefix = "10.219.0.0/24" - routed = true - } - lan_network1 = { - name = "lan_network1" - ipv4_prefix_length = 24 - ipv4_prefix = "10.220.1.0/24" - routed = true - nics = { - p2_lan1 = { - nic_name = "P2LAN1" - nic_ipv4 = "10.220.1.32" - nic_security = true - nic_security_group_names = ["ssh-ingress-group"] + # wan_network = { + # name = "wan_network" + # ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + # ipv4_prefix_length = 24 + # ipv4_prefix = "10.219.0.0/24" + # routed = true + # } + # lan_network1 = { + # name = "lan_network1" + # ipv4_prefix_length = 24 + # ipv4_prefix = "10.220.1.0/24" + # routed = true + # nics = { + # p2_lan1 = { + # nic_name = "P2LAN1" + # nic_ipv4 = "10.220.1.32" + # nic_security = true + # nic_security_group_names = ["ssh-ingress-group"] + # } + # } + # } + # lan_network2 = { + # name = "lan_network2" + # ipv4_prefix_length = 24 + # ipv4_prefix = "10.221.0.0/24" + # routed = true + # } + # lan_network3 = { + # name = "lan_network3" + # ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + # ipv4_prefix_length = 24 + # ipv4_prefix = "10.223.3.0/24" + # routed = true + # } + # wan = { + # name = "MGMT" + # ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + # ipv4_prefix_length = 24 + # nic_ipv4 = "10.224.0.254" + # } + + # db = { + # name = "db-net" + # nic_ipv4 = "10.0.0.126" + # nic_security = true + # } +} + +observability_instances = { + test = { + # Required + name = "test-observability" + plan_name = "Observability-Large-EU01" + + # Optional instance 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 + # parameters = { + # "custom_param" = "value" + # } + + # Credentials + create_credentials = true + credentials_count = 2 + + # alert‑groups + 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‑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" + } + }, + ] + } + } + + # scrapeconfigs + scrapeconfigs = { + example_job = { + name = "example-job" + metrics_path = "/my-metrics" + saml2 = { + enable_url_parameters = true + } + targets = [ + { + urls = ["url1", "urls2"] + labels = { + "url1" = "dev" + } + } + ] } } } - lan_network2 = { - name = "lan_network2" - ipv4_prefix_length = 24 - ipv4_prefix = "10.221.0.0/24" - routed = true - } - lan_network3 = { - name = "lan_network3" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - ipv4_prefix_length = 24 - ipv4_prefix = "10.223.3.0/24" - routed = true - } - wan = { - name = "MGMT" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - ipv4_prefix_length = 24 - nic_ipv4 = "10.224.0.254" - } - - db = { - name = "db-net" - nic_ipv4 = "10.0.0.126" - nic_security = true - } } -# ske_clusters = { -# dev = { -# name = "dev-cluster" -# kubernetes_version_min = "1.31" -# node_pools = [ -# { name = "default" -# machine_type = "c2.1" -# availability_zones = ["eu01-1", "eu01-2"] -# volume_size = 40 -# minimum = 1 -# maximum = 3 -# } -# ] -# } +ske_clusters = { + # dev = { + # name = "dev-cluster" + # kubernetes_version_min = "1.31" + # node_pools = [ + # { name = "default" + # machine_type = "c2.1" + # availability_zones = ["eu01-1", "eu01-2"] + # volume_size = 40 + # minimum = 1 + # maximum = 3 + # } + # ] + # } -# staging = { -# name = "staging-cluster" -# kubernetes_version_min = "1.31" -# node_pools = [ -# { name = "general" -# machine_type = "c2.2" -# availability_zones = ["eu03-1", "eu03-2"] -# volume_size = 80 -# minimum = 2 -# maximum = 4 -# } -# ] -# } -# } + # staging = { + # name = "staging-cluster" + # kubernetes_version_min = "1.31" + # node_pools = [ + # { name = "general" + # machine_type = "c2.2" + # availability_zones = ["eu03-1", "eu03-2"] + # volume_size = 80 + # minimum = 2 + # maximum = 4 + # } + # ] + # } + # } -# observability_instances = { -# starter = { -# name = "Observability-1" -# plan_name = "Observability-Starter-EU01" -# } + # observability_instances = { + # starter = { + # name = "Observability-1" + # plan_name = "Observability-Starter-EU01" + # } -# prod = { -# name = "Observability-2" -# plan_name = "Observability-Large-EU01" -# } -# } + # prod = { + # name = "Observability-2" + # plan_name = "Observability-Large-EU01" + # } +} \ No newline at end of file diff --git a/example/variables.tf b/example/variables.tf index d17e836..71ee2ea 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -116,24 +116,121 @@ variable "networks" { } -# variable "ske_clusters" { -# type = map(object({ -# name = string -# kubernetes_version_min = string -# node_pools = list(object({ -# name = string -# machine_type = string -# availability_zones = list(string) -# volume_size = number -# minimum = number -# maximum = number -# })) -# })) -# } +variable "ske_clusters" { + type = map(object({ + name = string + kubernetes_version_min = string + node_pools = list(object({ + name = string + machine_type = string + availability_zones = list(string) + volume_size = number + minimum = number + maximum = number + })) + })) +} -# variable "observability_instances" { -# type = map(object({ -# name = string -# plan_name = string -# })) -# } +variable "observability_instances" { + description = "Map of Observability instances to create" + type = map(object({ + # Required + name = string + plan_name = string + + # Optional instance 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)) + + # Control credential creation + create_credentials = optional(bool, true) + credentials_count = optional(number, 1) + + # alert‑groups + 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‑groups + 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‑configs + 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 the list of supported plans. Allowed values: + 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 + } +} diff --git a/network/main.tf b/network/main.tf index 0f7b638..fd6691d 100644 --- a/network/main.tf +++ b/network/main.tf @@ -1,7 +1,7 @@ resource "stackit_network" "this" { - project_id = var.project_id - name = var.name - labels = var.labels + project_id = var.project_id + name = var.name + labels = var.labels # IPv4 settings ipv4_gateway = var.ipv4_gateway @@ -15,9 +15,9 @@ resource "stackit_network" "this" { 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 + no_ipv4_gateway = var.no_ipv4_gateway + no_ipv6_gateway = var.no_ipv6_gateway + routed = var.routed } resource "stackit_network_interface" "nics" { @@ -25,16 +25,16 @@ resource "stackit_network_interface" "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 + + 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]] + each.value.nic_security_group_names != null ? + [for name in each.value.nic_security_group_names : var.security_group_ids_by_name[name]] : [] ) } diff --git a/network/variables.tf b/network/variables.tf index 68eb3a6..35787b4 100644 --- a/network/variables.tf +++ b/network/variables.tf @@ -17,12 +17,12 @@ variable "ipv4_nameservers" { } variable "ipv4_prefix" { - type = string # CIDR, only for NON-routed nets + type = string default = null } variable "ipv4_prefix_length" { - type = number # e.g. 24 + type = number default = null } @@ -62,7 +62,7 @@ variable "no_ipv6_gateway" { } variable "routed" { - type = bool + type = bool # default = true } diff --git a/observability/main.tf b/observability/main.tf index 1268066..080d9be 100644 --- a/observability/main.tf +++ b/observability/main.tf @@ -2,4 +2,55 @@ 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/output.tf b/observability/output.tf deleted file mode 100644 index e69de29..0000000 diff --git a/observability/outputs.tf b/observability/outputs.tf new file mode 100644 index 0000000..a097640 --- /dev/null +++ b/observability/outputs.tf @@ -0,0 +1,50 @@ +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 Thanos alert-group IDs" + value = { + for key, alertgrp in stackit_observability_alertgroup.this : + key => alertgrp.id + } +} + +output "observability_logalertgroups" { + description = "Map of created Loki 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/providers.tf b/observability/providers.tf index 8962cf6..a2af181 100644 --- a/observability/providers.tf +++ b/observability/providers.tf @@ -4,7 +4,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.56.0" + version = "0.54.0" } } } diff --git a/observability/variables.tf b/observability/variables.tf index f3be80f..fb14907 100644 --- a/observability/variables.tf +++ b/observability/variables.tf @@ -1,11 +1,118 @@ variable "project_id" { - type = string + description = "STACKIT project ID" + type = string } variable "name" { - type = string + description = "The name of the Observability instance." + type = string } variable "plan_name" { - type = string + description = "Specifies the Observability plan." + type = string +} + +variable "acl" { + description = "Access control list (CIDR blocks) permitted to access this instance." + type = list(string) + default = null +} + +variable "metrics_retention_days" { + description = "How many days raw metrics are kept." + type = number + default = null +} + +variable "metrics_retention_days_5m_downsampling" { + description = "How many days 5m-downsampled metrics are kept." + type = number + default = null +} + +variable "metrics_retention_days_1h_downsampling" { + description = "How many days 1h-downsampled metrics are kept." + type = number + default = null +} + +variable "alert_config" { + description = "Complex Alertmanager configuration." + type = any + default = null +} + +variable "parameters" { + description = "Additional key/value parameters for the instance." + type = map(string) + default = null +} + +variable "create_credentials" { + description = "Whether to create credentials for this instance." + type = bool + default = true +} + +variable "credentials_count" { + description = "How many credentials to create 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/project/output.tf b/project/output.tf index 09573a9..957559e 100644 --- a/project/output.tf +++ b/project/output.tf @@ -1,4 +1,4 @@ output "project_id" { value = stackit_resourcemanager_project.this.project_id - description = "ID of the project" -} \ No newline at end of file + description = "ID of the project" +} From 96325e4c4346f6cb65099f6efaecc193a3a4577a Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Wed, 16 Jul 2025 15:28:03 +0200 Subject: [PATCH 13/22] final testing --- example/main.tf | 61 ++++--- example/providers.tf | 4 +- example/terraform.tfvars | 383 ++++++++++++++++++++++----------------- example/variables.tf | 134 +++++++++++--- network/main.tf | 10 + project/main.tf | 16 +- project/output.tf | 8 +- project/variables.tf | 26 +-- security-group/main.tf | 24 ++- ske/main.tf | 13 +- ske/output.tf | 2 +- ske/providers.tf | 2 +- ske/variables.tf | 96 ++++++++-- 13 files changed, 505 insertions(+), 274 deletions(-) diff --git a/example/main.tf b/example/main.tf index 526054e..9265f10 100644 --- a/example/main.tf +++ b/example/main.tf @@ -1,12 +1,39 @@ -module "project" { +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" - name = "project-123" - labels = { - "example" = "test" - } + projects = var.Projects_map organization_id = var.organization_id - owner_email = "maximilian.schlenz@stackit.cloud" + sna_id = stackit_network_area.project_sna.network_area_id + labels = var.labels != null ? var.labels : {} +} + +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 + 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 } module "security_groups" { @@ -14,7 +41,7 @@ module "security_groups" { for_each = var.security_groups - project_id = module.project.project_id + 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 @@ -33,10 +60,9 @@ module "net" { for_each = var.networks - project_id = module.project.project_id + project_id = local.project_ids[each.value.project_key] name = each.value.name - # IPv4 and IPv6 settings ipv4_gateway = each.value.ipv4_gateway ipv4_nameservers = each.value.ipv4_nameservers ipv4_prefix = each.value.ipv4_prefix @@ -52,7 +78,6 @@ module "net" { routed = each.value.routed labels = each.value.labels - # NIC options nics = each.value.nics security_group_ids_by_name = local.security_group_ids_by_name } @@ -62,7 +87,7 @@ module "postgres" { for_each = var.postgres_instances - project_id = module.project.project_id + project_id = local.project_ids[each.value.project_key] name = each.value.name ver = each.value.version flavor = each.value.flavor @@ -74,22 +99,11 @@ module "postgres" { databases = each.value.databases } -# module "ske" { -# source = "../ske" - -# for_each = var.ske_clusters - -# project_id = module.project.project_id -# name = each.value.name -# kubernetes_version_min = each.value.kubernetes_version_min -# node_pools = each.value.node_pools -# } - module "observability" { source = "../observability" for_each = var.observability_instances - project_id = module.project.project_id + project_id = local.project_ids[each.value.project_key] name = each.value.name plan_name = each.value.plan_name @@ -112,7 +126,6 @@ module "observability" { scrapeconfigs = each.value.scrapeconfigs } - output "obs_url" { value = { for key, instance in module.observability : diff --git a/example/providers.tf b/example/providers.tf index 21bfe9e..502d800 100644 --- a/example/providers.tf +++ b/example/providers.tf @@ -10,7 +10,7 @@ terraform { provider "stackit" { default_region = var.region - service_account_token = var.service_account_token != "" ? var.service_account_token : null - service_account_key_path = var.service_account_key_path != "" ? var.service_account_key_path : null + service_account_token = var.service_account_token != null ? var.service_account_token : null + service_account_key_path = var.service_account_key_path != null ? var.service_account_key_path : null enable_beta_resources = true } diff --git a/example/terraform.tfvars b/example/terraform.tfvars index 718230f..9a27fb6 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -1,148 +1,176 @@ -region = "eu01" -service_account_token = "" -project_id = "" -organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" -service_account_key_path = "/Users/schlenz/sa-key-dd5fa2c9-1651-4da7-8404-9ac4fe9bc3d5.json" +organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" + +Projects_map = { + "projekt-alpha" = { + name = "tf_modules_test_3_max" + owner_email = "maximilian.schlenz@stackit.cloud" + }, + "projekt-beta" = { + name = "tf_modules_test_4_max" + owner_email = "maximilian.schlenz@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" security_groups = { - # ssh_ingress_group = { - # name = "ssh-ingress-group" - # 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 - # } - # }, - # ] - # }, + 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" - # 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 - # } - # }, - # ] - # }, + 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 + } + }, + ] + }, } postgres_instances = { - # dev = { - # name = "pg-test-instance" - # version = 17 - # flavor = { - # cpu = 2, - # ram = 4 - # } - # storage = { - # class = "premium-perf6-stackit", - # size = 20 - # } - # replicas = 1 - # acl = ["0.0.0.0/0"] - # backup_schedule = "00 00 * * *" + dev = { + name = "pg-test-instance" + project_key = "projekt-alpha" + version = 17 + flavor = { + cpu = 2, + ram = 4 + } + storage = { + class = "premium-perf6-stackit", + size = 20 + } + replicas = 1 + acl = ["0.0.0.0/0"] + backup_schedule = "00 00 * * *" - # users = [ - # { username = "adminusr", - # roles = ["login", "createdb"] - # }, - # { username = "testusr", - # roles = ["login"] - # } - # ] + users = [ + { username = "adminusr", + roles = ["login", "createdb"] + }, + { username = "testusr", + roles = ["login"] + } + ] - # databases = [ - # { - # name = "testdb", - # owner = "admin" - # } - # ] - # } + databases = [ + { + name = "testdb", + owner = "admin" + } + ] + } } networks = { - # wan_network = { - # name = "wan_network" - # ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - # ipv4_prefix_length = 24 - # ipv4_prefix = "10.219.0.0/24" - # routed = true - # } - # lan_network1 = { - # name = "lan_network1" - # ipv4_prefix_length = 24 - # ipv4_prefix = "10.220.1.0/24" - # routed = true - # nics = { - # p2_lan1 = { - # nic_name = "P2LAN1" - # nic_ipv4 = "10.220.1.32" - # nic_security = true - # nic_security_group_names = ["ssh-ingress-group"] - # } - # } - # } - # lan_network2 = { - # name = "lan_network2" - # ipv4_prefix_length = 24 - # ipv4_prefix = "10.221.0.0/24" - # routed = true - # } - # lan_network3 = { - # name = "lan_network3" - # ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - # ipv4_prefix_length = 24 - # ipv4_prefix = "10.223.3.0/24" - # routed = true - # } - # wan = { - # name = "MGMT" - # ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - # ipv4_prefix_length = 24 - # nic_ipv4 = "10.224.0.254" - # } + wan_network = { + name = "wan_network" + project_key = "projekt-alpha" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + ipv4_prefix_length = 24 + ipv4_prefix = "10.219.0.0/24" + routed = true + } + lan_network1 = { + name = "lan_network1" + project_key = "projekt-alpha" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + ipv4_prefix_length = 24 + ipv4_prefix = "10.220.1.0/24" + routed = true + nics = { + p2_lan1 = { + nic_name = "P2LAN1" + nic_ipv4 = "10.220.1.32" + nic_security = true + nic_security_group_names = ["ssh-ingress-group"] + } + } + } + lan_network2 = { + name = "lan_network2" + project_key = "projekt-alpha" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + ipv4_prefix_length = 24 + ipv4_prefix = "10.221.0.0/24" + routed = true + } + lan_network3 = { + name = "lan_network3" + project_key = "projekt-alpha" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + ipv4_prefix_length = 24 + ipv4_prefix = "10.223.3.0/24" + routed = true + } + wan = { + name = "MGMT" + project_key = "projekt-alpha" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + ipv4_prefix_length = 24 + nic_ipv4 = "10.224.0.254" + } - # db = { - # name = "db-net" - # nic_ipv4 = "10.0.0.126" - # nic_security = true - # } + db = { + name = "db-net" + project_key = "projekt-alpha" + ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] + nic_ipv4 = "10.0.0.126" + nic_security = true + } } observability_instances = { test = { # Required name = "test-observability" + project_key = "projekt-alpha" plan_name = "Observability-Large-EU01" # Optional instance settings @@ -248,43 +276,70 @@ observability_instances = { } ske_clusters = { - # dev = { - # name = "dev-cluster" - # kubernetes_version_min = "1.31" - # node_pools = [ - # { name = "default" - # machine_type = "c2.1" - # availability_zones = ["eu01-1", "eu01-2"] - # volume_size = 40 - # minimum = 1 - # maximum = 3 - # } - # ] - # } - # staging = { - # name = "staging-cluster" - # kubernetes_version_min = "1.31" - # node_pools = [ - # { name = "general" - # machine_type = "c2.2" - # availability_zones = ["eu03-1", "eu03-2"] - # volume_size = 80 - # minimum = 2 - # maximum = 4 - # } - # ] - # } - # } + "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" - # observability_instances = { - # starter = { - # name = "Observability-1" - # plan_name = "Observability-Starter-EU01" - # } + 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" + }] + } + ] - # prod = { - # name = "Observability-2" - # plan_name = "Observability-Large-EU01" - # } -} \ No newline at end of file + 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 index 71ee2ea..65b7661 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -7,33 +7,65 @@ variable "region" { variable "project_id" { description = "STACKIT Cloud project ID" type = string + default = null } variable "service_account_token" { description = "Service account token for authentication" sensitive = true type = string + default = null +} + +# SNA & Projects variables + +variable "organization_id" { + description = "Die Container-ID deiner STACKIT Organisation." + type = string } variable "service_account_key_path" { + type = string + default = "/users/schlenz/.stackit/sa.json" +} + +variable "default_region" { type = string - default = "" + default = "eu01" } -variable "organization_id" { - description = "Organization ID" +variable "SNA_name" { + description = "Name der zu erstellenden Service Network Area." type = string } -variable "owner_email" { - description = "Email of the project owner" +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 - default = null +} + +variable "Projects_map" { + description = "Eine Map von Projekten, die erstellt werden sollen." + type = map(object({ + name = string + owner_email = string + })) +} + +variable "labels" { + type = map(string) + default = {} } variable "security_groups" { type = map(object({ name = optional(string) + project_key = string description = optional(string) rules = list(object({ direction = string @@ -60,6 +92,7 @@ variable "security_groups" { variable "postgres_instances" { type = map(object({ name = string + project_key = string version = number flavor = object({ cpu = number, ram = number }) storage = object({ class = string, size = number }) @@ -81,7 +114,7 @@ variable "postgres_instances" { variable "networks" { type = map(object({ name = string - + project_key = string # IPv4 settings ipv4_gateway = optional(string) ipv4_nameservers = optional(list(string)) @@ -100,7 +133,7 @@ variable "networks" { no_ipv6_gateway = optional(bool) routed = optional(bool) - # NIC‑specific options + # NIC-specific options nics = optional(map(object({ nic_ipv4 = optional(string) nic_name = string @@ -115,20 +148,62 @@ variable "networks" { default = {} } - variable "ske_clusters" { + description = "Eine Map von SKE-Clustern" type = map(object({ - name = string - kubernetes_version_min = string + + 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) - volume_size = number 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 = {} } variable "observability_instances" { @@ -136,6 +211,7 @@ variable "observability_instances" { type = map(object({ # Required name = string + project_key = string plan_name = string # Optional instance settings @@ -150,7 +226,7 @@ variable "observability_instances" { create_credentials = optional(bool, true) credentials_count = optional(number, 1) - # alert‑groups + # alert-groups alertgroups = optional(map(object({ name = string interval = optional(string) @@ -163,7 +239,7 @@ variable "observability_instances" { })) })), {}) - # log‑alert‑groups + # log-alert-groups logalertgroups = optional(map(object({ name = string interval = optional(string) @@ -176,7 +252,7 @@ variable "observability_instances" { })) })), {}) - # scrape‑configs + # scrape-configs scrapeconfigs = optional(map(object({ name = string metrics_path = string @@ -217,20 +293,20 @@ variable "observability_instances" { ], v.plan_name) ]) error_message = <<-EOM -One or more observability_instances specify an invalid plan_name. -See the provider error output for the list of supported plans. Allowed values: - 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 + One or more observability_instances specify an invalid plan_name. + See the provider error output for the list of supported plans. Allowed values: + 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 } } diff --git a/network/main.tf b/network/main.tf index fd6691d..246cdcf 100644 --- a/network/main.tf +++ b/network/main.tf @@ -37,5 +37,15 @@ resource "stackit_network_interface" "nics" { [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/project/main.tf b/project/main.tf index bc13502..a00c15d 100644 --- a/project/main.tf +++ b/project/main.tf @@ -1,6 +1,14 @@ -resource "stackit_resourcemanager_project" "this" { +resource "stackit_resourcemanager_project" "project" { + for_each = var.projects + parent_container_id = var.organization_id - name = var.name - labels = var.labels - owner_email = var.owner_email + name = each.value.name + owner_email = each.value.owner_email + + labels = merge( + { + "networkArea" = var.sna_id + }, + var.labels + ) } diff --git a/project/output.tf b/project/output.tf index 957559e..6aac267 100644 --- a/project/output.tf +++ b/project/output.tf @@ -1,4 +1,4 @@ -output "project_id" { - value = stackit_resourcemanager_project.this.project_id - description = "ID of the project" -} +output "created_projects" { + description = "Eine Map aller erstellten STACKIT Projekte." + value = stackit_resourcemanager_project.project +} \ No newline at end of file diff --git a/project/variables.tf b/project/variables.tf index ff96a41..9be4103 100644 --- a/project/variables.tf +++ b/project/variables.tf @@ -1,27 +1,21 @@ variable "organization_id" { - type = string + description = "Empfängt die Container-ID der Organisation vom Root-Modul." + type = string } -variable "name" { - type = string +variable "projects" { + type = map(object({ + name = string + owner_email = string + })) } -variable "description" { - type = string - default = null +variable "sna_id" { + description = "Empfängt die ID der Network Area vom Root-Modul." + type = string } variable "labels" { type = map(string) default = {} } - -variable "project_id" { - type = string - default = null -} - -variable "owner_email" { - type = string - default = null -} diff --git a/security-group/main.tf b/security-group/main.tf index 3098cf0..73675ab 100644 --- a/security-group/main.tf +++ b/security-group/main.tf @@ -1,7 +1,3 @@ -locals { - rule_count = length(var.rules) -} - resource "stackit_security_group" "this" { project_id = var.project_id name = var.name @@ -9,17 +5,19 @@ resource "stackit_security_group" "this" { } resource "stackit_security_group_rule" "rule" { - count = local.rule_count + for_each = { + for idx, r in var.rules : idx => r + } - direction = var.rules[count.index].direction + direction = each.value.direction project_id = var.project_id security_group_id = stackit_security_group.this.security_group_id - description = var.rules[count.index].description - ether_type = var.rules[count.index].ether_type - icmp_parameters = var.rules[count.index].icmp_parameters - ip_range = var.rules[count.index].ip_range - port_range = var.rules[count.index].port_range - protocol = var.rules[count.index].protocol - remote_security_group_id = var.rules[count.index].remote_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/ske/main.tf b/ske/main.tf index 90124a0..1cda6b9 100644 --- a/ske/main.tf +++ b/ske/main.tf @@ -1,8 +1,13 @@ resource "stackit_ske_cluster" "this" { - project_id = var.project_id - name = var.name - kubernetes_version_min = var.kubernetes_version_min - node_pools = var.node_pools + project_id = var.project_id + name = var.name + node_pools = var.node_pools + kubernetes_version_min = var.kubernetes_version_min + hibernations = var.hibernations + maintenance = var.maintenance + extensions = var.extensions + network = var.network + region = var.default_region } resource "stackit_ske_kubeconfig" "admin" { diff --git a/ske/output.tf b/ske/output.tf index 9abc2e4..88f4e56 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/providers.tf b/ske/providers.tf index 6e038c3..532c77d 100644 --- a/ske/providers.tf +++ b/ske/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.56.0" + version = "0.54.0" } } } diff --git a/ske/variables.tf b/ske/variables.tf index 53533c0..ccae10c 100644 --- a/ske/variables.tf +++ b/ske/variables.tf @@ -1,22 +1,94 @@ variable "project_id" { - type = string + description = "STACKIT project ID to which the cluster is associated." + type = string } variable "name" { - type = string -} - -variable "kubernetes_version_min" { - type = string + description = "The cluster name." + type = string } variable "node_pools" { + description = "One or more node_pool blocks." type = list(object({ - name = string - machine_type = string - availability_zones = list(string) - volume_size = number - minimum = number - maximum = number + 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) })) } + +# Optionale Variablen +variable "kubernetes_version_min" { + description = "The minimum Kubernetes version." + type = string + default = null +} + +variable "hibernations" { + description = "A list of hibernation schedules for the cluster." + type = list(object({ + start = string + end = string + timezone = optional(string) + })) + default = null +} + +variable "maintenance" { + description = "A single maintenance block." + type = object({ + enable_kubernetes_version_updates = bool + enable_machine_image_version_updates = bool + start = string + end = string + }) + default = null +} +variable "extensions" { + description = "A single extensions block." + type = object({ + acl = optional(object({ + enabled = bool + allowed_cidrs = list(string) + })) + argus = optional(object({ + enabled = bool + argus_instance_id = string + })) + dns = optional(object({ + enabled = bool + zones = optional(list(string)) + })) + }) + default = null +} + +variable "network" { + description = "Network block." + type = object({ + id = string + }) + default = null +} + +variable "default_region" { + description = "The resource region." + type = string + default = null +} \ No newline at end of file From 85ae1a19188a6ffc148436cfb679f56cbd029dee Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Wed, 16 Jul 2025 15:57:30 +0200 Subject: [PATCH 14/22] remove old project files --- 01-network.tf | 106 ------------------------------------------- 06-security-group.tf | 51 --------------------- main.tf | 30 ------------ variables.tf | 27 ----------- 4 files changed, 214 deletions(-) delete mode 100644 01-network.tf delete mode 100644 06-security-group.tf delete mode 100644 main.tf delete mode 100644 variables.tf diff --git a/01-network.tf b/01-network.tf deleted file mode 100644 index 577a909..0000000 --- a/01-network.tf +++ /dev/null @@ -1,106 +0,0 @@ -// ------- 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 deleted file mode 100644 index 22958ff..0000000 --- a/06-security-group.tf +++ /dev/null @@ -1,51 +0,0 @@ - -// 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/main.tf b/main.tf deleted file mode 100644 index c702464..0000000 --- a/main.tf +++ /dev/null @@ -1,30 +0,0 @@ -# main.tf - -terraform { - required_providers { - stackit = { - source = "stackitcloud/stackit" - version = ">=0.54" - } - } -} - -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" - - # -- variables for project module - organization_id = var.organization_id - sna_net = var.sna_net - -} - - - diff --git a/variables.tf b/variables.tf deleted file mode 100644 index 0321640..0000000 --- a/variables.tf +++ /dev/null @@ -1,27 +0,0 @@ -variable "organization_id" { - type = string - description = "Die Container-ID Ihrer Organisation." - # Kein Default, wird per .tfvars gesetzt - default = "03a34540-3c1a-4794-b2c6-7111ecf824ef" -} - -variable "service_account_key_path" { - type = string - default = "/root/.stackit/credentials.json" -} - -variable "private_key_path" { - type = string - default = "/root/.stackit/private_key.pem" -} - -variable "default_region" { - type = string - default = "eu01" -} - -variable "sna_net" { - type = string - default = "172.16.9.0/24" - } - From f71eae3c63f351fe72d4630f7a12479722fcb079 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Wed, 16 Jul 2025 16:39:45 +0200 Subject: [PATCH 15/22] fix ip ranges --- example/terraform.tfvars | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/example/terraform.tfvars b/example/terraform.tfvars index 9a27fb6..1fd2f83 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -114,7 +114,7 @@ networks = { project_key = "projekt-alpha" ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] ipv4_prefix_length = 24 - ipv4_prefix = "10.219.0.0/24" + ipv4_prefix = "192.168.10.0/27" routed = true } lan_network1 = { @@ -122,12 +122,12 @@ networks = { project_key = "projekt-alpha" ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] ipv4_prefix_length = 24 - ipv4_prefix = "10.220.1.0/24" + ipv4_prefix = "192.168.10.32/27" routed = true nics = { p2_lan1 = { nic_name = "P2LAN1" - nic_ipv4 = "10.220.1.32" + nic_ipv4 = "192.168.10.33" nic_security = true nic_security_group_names = ["ssh-ingress-group"] } @@ -138,7 +138,7 @@ networks = { project_key = "projekt-alpha" ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] ipv4_prefix_length = 24 - ipv4_prefix = "10.221.0.0/24" + ipv4_prefix = "192.168.10.64/27" routed = true } lan_network3 = { @@ -146,7 +146,7 @@ networks = { project_key = "projekt-alpha" ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] ipv4_prefix_length = 24 - ipv4_prefix = "10.223.3.0/24" + ipv4_prefix = "192.168.10.96/27" routed = true } wan = { @@ -154,14 +154,15 @@ networks = { project_key = "projekt-alpha" ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] ipv4_prefix_length = 24 - nic_ipv4 = "10.224.0.254" + ipv4_prefix = "192.168.10.128/27" + nic_ipv4 = "192.168.10.254" } db = { name = "db-net" project_key = "projekt-alpha" ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - nic_ipv4 = "10.0.0.126" + nic_ipv4 = "192.168.10.161" nic_security = true } } From 63332e09be78dd9b5d6b4a4215d5d4dfb9f24f0b Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Wed, 16 Jul 2025 16:41:06 +0200 Subject: [PATCH 16/22] add ske dummy net --- ske/main.tf | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ske/main.tf b/ske/main.tf index 1cda6b9..c96784f 100644 --- a/ske/main.tf +++ b/ske/main.tf @@ -1,3 +1,14 @@ +resource "stackit_network" "ske_network" { + project_id = var.project_id + name = "ske_network" + ipv4_nameservers = ["1.1.1.1", "9.9.9.9"] + ipv4_prefix_length = 24 +} + +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 @@ -6,7 +17,7 @@ resource "stackit_ske_cluster" "this" { hibernations = var.hibernations maintenance = var.maintenance extensions = var.extensions - network = var.network + network = stackit_network.ske_network region = var.default_region } From b4e80ed22ed096abb8768b6a170d70cf5bc967e3 Mon Sep 17 00:00:00 2001 From: Janis Hahn Date: Thu, 17 Jul 2025 09:55:20 +0200 Subject: [PATCH 17/22] final Updates --- .gitignore | 3 +- example/main.tf | 6 +-- example/terraform.tfvars | 87 +++++++++------------------------------- example/variables.tf | 4 +- ske/main.tf | 5 ++- 5 files changed, 25 insertions(+), 80 deletions(-) diff --git a/.gitignore b/.gitignore index 65bfb30..a634978 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .terraform* terraform.tfstate* -.env \ No newline at end of file +.env +kubeconfig* \ No newline at end of file diff --git a/example/main.tf b/example/main.tf index 9265f10..1f66eb9 100644 --- a/example/main.tf +++ b/example/main.tf @@ -25,10 +25,6 @@ module "stackit_ske_cluster" { 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) @@ -131,4 +127,4 @@ output "obs_url" { for key, instance in module.observability : key => instance.observability_urls } -} \ No newline at end of file +} diff --git a/example/terraform.tfvars b/example/terraform.tfvars index 1fd2f83..9b09f84 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -2,16 +2,16 @@ organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" Projects_map = { "projekt-alpha" = { - name = "tf_modules_test_3_max" + name = "tf_modules_test_6_jh" owner_email = "maximilian.schlenz@stackit.cloud" }, "projekt-beta" = { - name = "tf_modules_test_4_max" + name = "tf_modules_test_7_jh" owner_email = "maximilian.schlenz@stackit.cloud" } } -SNA_name = "sna-tf_modules_test" +SNA_name = "sna-jh" SNA_network_ranges = [ { prefix = "192.168.10.0/24" } @@ -111,60 +111,12 @@ postgres_instances = { networks = { wan_network = { name = "wan_network" - project_key = "projekt-alpha" + project_key = "projekt-beta" ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - ipv4_prefix_length = 24 - ipv4_prefix = "192.168.10.0/27" + ipv4_prefix_length = 29 + ipv4_prefix = "192.168.10.248/29" routed = true } - lan_network1 = { - name = "lan_network1" - project_key = "projekt-alpha" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - ipv4_prefix_length = 24 - ipv4_prefix = "192.168.10.32/27" - routed = true - nics = { - p2_lan1 = { - nic_name = "P2LAN1" - nic_ipv4 = "192.168.10.33" - nic_security = true - nic_security_group_names = ["ssh-ingress-group"] - } - } - } - lan_network2 = { - name = "lan_network2" - project_key = "projekt-alpha" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - ipv4_prefix_length = 24 - ipv4_prefix = "192.168.10.64/27" - routed = true - } - lan_network3 = { - name = "lan_network3" - project_key = "projekt-alpha" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - ipv4_prefix_length = 24 - ipv4_prefix = "192.168.10.96/27" - routed = true - } - wan = { - name = "MGMT" - project_key = "projekt-alpha" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - ipv4_prefix_length = 24 - ipv4_prefix = "192.168.10.128/27" - nic_ipv4 = "192.168.10.254" - } - - db = { - name = "db-net" - project_key = "projekt-alpha" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - nic_ipv4 = "192.168.10.161" - nic_security = true - } } observability_instances = { @@ -277,24 +229,21 @@ observability_instances = { } 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" + name = "np" machine_type = "c1.2" - availability_zones = ["eu01-1"] - minimum = 1 - maximum = 2 - cri = "containerd" + availability_zones = ["eu01-3", "eu01-1"] + minimum = 2 + maximum = 3 volume_type = "storage_premium_perf1" - volume_size = 21 - labels = { "worker" = "default" } + volume_size = 64 taints = [{ effect = "NoSchedule" key = "app" @@ -325,17 +274,16 @@ ske_clusters = { } } }, - + */ "dev-cluster" = { - name = "clusterdev" + name = "cluster" kubernetes_version_min = "1.32.5" - project_key = "projekt-beta" - network_id = "bedfc709-9285-4078-93ab-8e8a1c0be6bd" # WICHTIG: Hier die Netzwerk-ID connecten + project_key = "projekt-alpha" node_pools = [ { - name = "devpool" - machine_type = "c1.2" + name = "np" + machine_type = "g1.4" availability_zones = ["eu01-2"] minimum = 1 maximum = 2 @@ -343,4 +291,5 @@ ske_clusters = { } ] } + } diff --git a/example/variables.tf b/example/variables.tf index 65b7661..ee292d9 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -26,7 +26,7 @@ variable "organization_id" { variable "service_account_key_path" { type = string - default = "/users/schlenz/.stackit/sa.json" + default = "/home/hahnjan/.stackit/sa.json" } variable "default_region" { @@ -154,8 +154,6 @@ variable "ske_clusters" { name = string project_key = string - network_id = string - kubernetes_version_min = optional(string) hibernations = optional(list(object({ start = string diff --git a/ske/main.tf b/ske/main.tf index c96784f..2252538 100644 --- a/ske/main.tf +++ b/ske/main.tf @@ -2,7 +2,6 @@ resource "stackit_network" "ske_network" { project_id = var.project_id name = "ske_network" ipv4_nameservers = ["1.1.1.1", "9.9.9.9"] - ipv4_prefix_length = 24 } output "ske-egress-ip" { @@ -17,7 +16,9 @@ resource "stackit_ske_cluster" "this" { hibernations = var.hibernations maintenance = var.maintenance extensions = var.extensions - network = stackit_network.ske_network + network = { + id = stackit_network.ske_network.network_id + } region = var.default_region } From df457fe625eaeebd70f0e387a1a54706781f744f Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Thu, 17 Jul 2025 11:33:42 +0200 Subject: [PATCH 18/22] tflint, cleanup, description of vars --- example/variables.tf | 115 +++++++++++++++++------------ network/variables.tf | 131 +++++++++++++++++++-------------- observability/outputs.tf | 4 +- observability/variables.tf | 26 +++---- postgres/variables.tf | 38 ++++++---- project/variables.tf | 17 ++++- security-group/variables.tf | 142 +++++++++++++----------------------- ske/variables.tf | 67 ++++++++--------- 8 files changed, 276 insertions(+), 264 deletions(-) diff --git a/example/variables.tf b/example/variables.tf index ee292d9..bfeab6e 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -1,15 +1,9 @@ variable "region" { - description = "Region for the STACKIT Cloud" + description = "Provider region for STACKIT Cloud" type = string default = "eu01" } -variable "project_id" { - description = "STACKIT Cloud project ID" - type = string - default = null -} - variable "service_account_token" { description = "Service account token for authentication" sensitive = true @@ -17,40 +11,44 @@ variable "service_account_token" { default = null } -# SNA & Projects variables +# -----------------------------------------------------------------------------# +# SNA & Projects +# -----------------------------------------------------------------------------# variable "organization_id" { - description = "Die Container-ID deiner STACKIT Organisation." + description = "STACKIT organization container ID" type = string } variable "service_account_key_path" { + description = "Path to service account JSON key" type = string - default = "/home/hahnjan/.stackit/sa.json" + default = "/Users/schlenz/.stackit/sa.json" } variable "default_region" { - type = string - default = "eu01" + description = "Default region fallback for created resources" + type = string + default = "eu01" } variable "SNA_name" { - description = "Name der zu erstellenden Service Network Area." + description = "Name of the Service Network Area to create" type = string } variable "SNA_network_ranges" { - description = "Liste der Netzwerk-CIDRs für die SNA." + description = "CIDR list for the Service Network Area" type = list(object({ prefix = string })) } variable "SNA_transfer_network" { - description = "Das Transfer-Netzwerk für die SNA (z.B. 172.16.9.0/24)." + description = "Transfer network CIDR for the SNA" type = string } variable "Projects_map" { - description = "Eine Map von Projekten, die erstellt werden sollen." + description = "Map of STACKIT projects to create" type = map(object({ name = string owner_email = string @@ -58,11 +56,17 @@ variable "Projects_map" { } variable "labels" { - type = map(string) - default = {} + description = "Default labels to apply where supported" + type = map(string) + default = {} } +# -----------------------------------------------------------------------------# +# Security Groups +# -----------------------------------------------------------------------------# + variable "security_groups" { + description = "Map of security group definitions" type = map(object({ name = optional(string) project_key = string @@ -89,15 +93,20 @@ variable "security_groups" { })) } +# -----------------------------------------------------------------------------# +# PostgreSQL +# -----------------------------------------------------------------------------# + variable "postgres_instances" { + description = "Map of PostgreSQL instances to create" type = map(object({ - name = string + name = string project_key = string - version = number - flavor = object({ cpu = number, ram = number }) - storage = object({ class = string, size = number }) - replicas = number - acl = list(string) + version = number + flavor = object({ cpu = number, ram = number }) + storage = object({ class = string, size = number }) + replicas = number + acl = list(string) backup_schedule = string users = list(object({ username = string @@ -110,18 +119,23 @@ variable "postgres_instances" { })) } -# Network definition map +# -----------------------------------------------------------------------------# +# Networks +# -----------------------------------------------------------------------------# + variable "networks" { + description = "Map of network definitions per project" type = map(object({ - name = string + name = string project_key = string - # IPv4 settings + + # IPv4 ipv4_gateway = optional(string) ipv4_nameservers = optional(list(string)) ipv4_prefix = optional(string) ipv4_prefix_length = optional(number) - # IPv6 settings + # IPv6 ipv6_gateway = optional(string) ipv6_nameservers = optional(list(string)) ipv6_prefix = optional(string) @@ -133,7 +147,7 @@ variable "networks" { no_ipv6_gateway = optional(bool) routed = optional(bool) - # NIC-specific options + # NICs nics = optional(map(object({ nic_ipv4 = optional(string) nic_name = string @@ -144,16 +158,18 @@ variable "networks" { nic_security_group_names = optional(list(string)) }))) })) - default = {} } -variable "ske_clusters" { - description = "Eine Map von SKE-Clustern" - type = map(object({ +# -----------------------------------------------------------------------------# +# SKE Clusters +# -----------------------------------------------------------------------------# - name = string - project_key = string +variable "ske_clusters" { + description = "Map of SKE cluster definitions" + type = map(object({ + name = string + project_key = string kubernetes_version_min = optional(string) hibernations = optional(list(object({ start = string @@ -161,10 +177,10 @@ variable "ske_clusters" { timezone = optional(string) }))) maintenance = optional(object({ - enable_kubernetes_version_updates = bool + enable_kubernetes_version_updates = bool enable_machine_image_version_updates = bool - start = string - end = string + start = string + end = string })) extensions = optional(object({ acl = optional(object({ @@ -178,7 +194,6 @@ variable "ske_clusters" { })) node_pools = list(object({ - name = string machine_type = string availability_zones = list(string) @@ -204,15 +219,18 @@ variable "ske_clusters" { default = {} } +# -----------------------------------------------------------------------------# +# Observability +# -----------------------------------------------------------------------------# + variable "observability_instances" { description = "Map of Observability instances to create" type = map(object({ - # Required - name = string + name = string project_key = string - plan_name = string + plan_name = string - # Optional instance settings + # Instance settings acl = optional(list(string)) metrics_retention_days = optional(number) metrics_retention_days_5m_downsampling = optional(number) @@ -220,11 +238,11 @@ variable "observability_instances" { alert_config = optional(any) parameters = optional(map(string)) - # Control credential creation + # Credentials create_credentials = optional(bool, true) credentials_count = optional(number, 1) - # alert-groups + # Alert-groups alertgroups = optional(map(object({ name = string interval = optional(string) @@ -237,7 +255,7 @@ variable "observability_instances" { })) })), {}) - # log-alert-groups + # Log-alert-groups logalertgroups = optional(map(object({ name = string interval = optional(string) @@ -250,7 +268,7 @@ variable "observability_instances" { })) })), {}) - # scrape-configs + # Scrape-configs scrapeconfigs = optional(map(object({ name = string metrics_path = string @@ -272,6 +290,7 @@ variable "observability_instances" { })), {}) })) default = {} + validation { condition = alltrue([ for k, v in var.observability_instances : @@ -292,7 +311,7 @@ variable "observability_instances" { ]) error_message = <<-EOM One or more observability_instances specify an invalid plan_name. - See the provider error output for the list of supported plans. Allowed values: + See the provider error output for supported plans. Allowed: Observability-Medium-EU01 Observability-Monitoring-XL-EU01 Observability-Large-EU01 diff --git a/network/variables.tf b/network/variables.tf index 35787b4..b5b2fc7 100644 --- a/network/variables.tf +++ b/network/variables.tf @@ -1,103 +1,123 @@ variable "project_id" { - type = string + description = "STACKIT project ID" + type = string } variable "name" { - type = string + description = "Network name" + type = string } +# ----------------------------- +# IPv4 +# ----------------------------- variable "ipv4_gateway" { - type = string - default = null + description = "IPv4 gateway address" + type = string + default = null } variable "ipv4_nameservers" { - type = list(string) - default = [] + description = "IPv4 nameserver list" + type = list(string) + default = [] } variable "ipv4_prefix" { - type = string - default = null + description = "IPv4 prefix CIDR" + type = string + default = null } variable "ipv4_prefix_length" { - type = number - default = null + description = "IPv4 prefix length" + type = number + default = null } +# ----------------------------- +# IPv6 +# ----------------------------- variable "ipv6_gateway" { - type = string - default = null + description = "IPv6 gateway address" + type = string + default = null } variable "ipv6_nameservers" { - type = list(string) - default = [] + description = "IPv6 nameserver list" + type = list(string) + default = [] } variable "ipv6_prefix" { - type = string - default = null + description = "IPv6 prefix CIDR" + type = string + default = null } variable "ipv6_prefix_length" { - type = number - default = null + description = "IPv6 prefix length" + type = number + default = null } +# ----------------------------- +# Deprecated legacy nameservers (provider still exposes) +# ----------------------------- +variable "nameservers" { + description = "Deprecated nameserver list (legacy field)" + type = list(string) + default = [] +} + +# ----------------------------- +# Labels & flags +# ----------------------------- variable "labels" { - type = map(string) - default = {} + description = "Labels map" + type = map(string) + default = {} } variable "no_ipv4_gateway" { - type = bool - default = false + description = "Disable IPv4 gateway" + type = bool + default = false } variable "no_ipv6_gateway" { - type = bool - default = false + description = "Disable IPv6 gateway" + type = bool + default = false } variable "routed" { - type = bool - # default = true + description = "Mark network routed" + type = bool + default = null } -variable "nic_allowed_addresses" { - type = list(string) - default = [] +# ----------------------------- +# Region override & routing +# ----------------------------- +variable "region" { + description = "Resource region override (defaults to provider region)" + type = string + default = null } -variable "nic_ipv4" { - type = string - default = null -} - -variable "nic_labels" { - type = map(string) - default = {} -} - -variable "nic_name" { - type = string - default = null -} - -variable "nic_security" { - type = bool - default = false - nullable = false -} - -variable "nic_security_group_ids" { - type = list(string) - default = [] +variable "routing_table_id" { + description = "Routing table ID" + type = string + default = null } +# ----------------------------- +# NIC map (zero or many) +# ----------------------------- variable "nics" { + description = "Map of NIC configs" type = map(object({ nic_ipv4 = optional(string) nic_name = optional(string) @@ -110,7 +130,10 @@ variable "nics" { default = {} } +# ----------------------------- +# Security group lookup map +# ----------------------------- variable "security_group_ids_by_name" { - description = "Map of security-group names -> IDs" + description = "Security group name→ID map" type = map(string) } diff --git a/observability/outputs.tf b/observability/outputs.tf index a097640..15f6ecb 100644 --- a/observability/outputs.tf +++ b/observability/outputs.tf @@ -26,7 +26,7 @@ output "observability_credentials" { } output "observability_alertgroups" { - description = "Map of created Thanos alert-group IDs" + description = "Map of created alert-group IDs" value = { for key, alertgrp in stackit_observability_alertgroup.this : key => alertgrp.id @@ -34,7 +34,7 @@ output "observability_alertgroups" { } output "observability_logalertgroups" { - description = "Map of created Loki log-alert-group IDs" + description = "Map of created log-alert-group IDs" value = { for key, logalertgrp in stackit_observability_logalertgroup.this : key => logalertgrp.id diff --git a/observability/variables.tf b/observability/variables.tf index fb14907..daee852 100644 --- a/observability/variables.tf +++ b/observability/variables.tf @@ -4,65 +4,65 @@ variable "project_id" { } variable "name" { - description = "The name of the Observability instance." + description = "Observability instance name" type = string } variable "plan_name" { - description = "Specifies the Observability plan." + description = "Observability plan name" type = string } variable "acl" { - description = "Access control list (CIDR blocks) permitted to access this instance." + description = "Allowed CIDR list" type = list(string) default = null } variable "metrics_retention_days" { - description = "How many days raw metrics are kept." + description = "Retention days raw metrics" type = number default = null } variable "metrics_retention_days_5m_downsampling" { - description = "How many days 5m-downsampled metrics are kept." + description = "Retention days 5m downsample" type = number default = null } variable "metrics_retention_days_1h_downsampling" { - description = "How many days 1h-downsampled metrics are kept." + description = "Retention days 1h downsample" type = number default = null } variable "alert_config" { - description = "Complex Alertmanager configuration." + description = "Alertmanager config object" type = any default = null } variable "parameters" { - description = "Additional key/value parameters for the instance." + description = "Extra key/value parameters" type = map(string) default = null } variable "create_credentials" { - description = "Whether to create credentials for this instance." + description = "Create credentials" type = bool default = true } variable "credentials_count" { - description = "How many credentials to create when enabled." + description = "Credential count when enabled" type = number default = 1 } variable "alertgroups" { - description = "Map of alert-groups to create." + description = "Map of alert-groups to create" type = map(object({ name = string interval = optional(string) @@ -78,7 +78,7 @@ variable "alertgroups" { } variable "logalertgroups" { - description = "Map of log-alert-groups to create." + description = "Map of log-alert-groups to create" type = map(object({ name = string interval = optional(string) @@ -94,7 +94,7 @@ variable "logalertgroups" { } variable "scrapeconfigs" { - description = "Map of scrape-configs to create." + description = "Map of scrape-configs to create" type = map(object({ name = string metrics_path = string diff --git a/postgres/variables.tf b/postgres/variables.tf index 061dd3f..620fea0 100644 --- a/postgres/variables.tf +++ b/postgres/variables.tf @@ -1,9 +1,11 @@ variable "project_id" { - type = string + description = "STACKIT project ID" + type = string } variable "name" { - type = string + description = "Instance name (DNS-1035 compliant)" + type = string validation { condition = length(regexall("^[a-z]([-a-z0-9]*[a-z0-9])?$", var.name)) > 0 @@ -16,50 +18,52 @@ variable "name" { } } -variable "instance_id" { - type = string - default = "" -} - variable "ver" { - type = number + description = "PostgreSQL version" + type = number } variable "flavor" { + description = "Compute flavor (cpu, ram GB)" type = object({ - cpu = number, + cpu = number ram = number }) } variable "storage" { + description = "Storage settings (class, size GB)" type = object({ - class = string, + class = string size = number }) } variable "replicas" { - type = number + description = "Number of instance replicas" + type = number } variable "acl" { - type = list(string) + description = "Allowed CIDR list for instance access" + type = list(string) } variable "backup_schedule" { - type = string - + description = "Backup schedule string" + type = string } variable "users" { + description = "Database users (username, roles)" type = list(object({ username = string roles = set(string) })) default = [] + validation { - condition = alltrue([ + condition = alltrue([ for user in var.users : user.username != "admin" ]) error_message = "The username 'admin' is reserved and cannot be used." @@ -67,12 +71,14 @@ variable "users" { } variable "databases" { + description = "Databases to create (name, owner)" type = list(object({ name = string owner = string })) default = [] - validation { + + validation { condition = alltrue([ for db in var.databases : length(regexall("^[a-z]([-a-z0-9]*[a-z0-9])?$", db.name)) > 0 ]) diff --git a/project/variables.tf b/project/variables.tf index 9be4103..b0eb6dd 100644 --- a/project/variables.tf +++ b/project/variables.tf @@ -1,9 +1,16 @@ variable "organization_id" { - description = "Empfängt die Container-ID der Organisation vom Root-Modul." + description = "Organization container ID (root parent)" type = string } +variable "parent_container_id" { + description = "Parent container ID to create projects under" + type = string + default = null +} + variable "projects" { + description = "Map of projects (name, owner_email)" type = map(object({ name = string owner_email = string @@ -11,11 +18,13 @@ variable "projects" { } variable "sna_id" { - description = "Empfängt die ID der Network Area vom Root-Modul." + description = "Network Area ID; adds label networkArea= when set" type = string + default = null } variable "labels" { - type = map(string) - default = {} + description = "Extra labels applied to all projects" + type = map(string) + default = {} } diff --git a/security-group/variables.tf b/security-group/variables.tf index 053a240..4ca3116 100644 --- a/security-group/variables.tf +++ b/security-group/variables.tf @@ -1,107 +1,65 @@ variable "project_id" { - description = "STACKIT project ID in which to create resources." + description = "STACKIT project ID" type = string } variable "name" { - description = "Name of the network." + description = "Security group name" type = string } variable "description" { + description = "Security group description" type = string default = "" } -variable "ipv4_gateway" { - description = "IPv4 gateway for the network. If null, the first IP in the CIDR is used." - type = string - nullable = true - default = null -} - -variable "ipv4_nameservers" { - description = "List of IPv4 nameservers." - type = list(string) - nullable = true - default = null -} - -variable "ipv4_prefix" { - description = "IPv4 prefix (CIDR) for the network." - type = string - nullable = true - default = null -} - -variable "ipv4_prefix_length" { - description = "IPv4 prefix length for the network." - type = number - nullable = true - default = null -} - -variable "ipv6_gateway" { - description = "IPv6 gateway for the network. If null, the first IP in the CIDR is used." - type = string - nullable = true - default = null -} - -variable "ipv6_nameservers" { - description = "List of IPv6 nameservers." - type = list(string) - nullable = true - default = null -} - -variable "ipv6_prefix" { - description = "IPv6 prefix (CIDR) for the network." - type = string - nullable = true - default = null -} - -variable "ipv6_prefix_length" { - description = "IPv6 prefix length for the network." - type = number - nullable = true - default = null -} - -variable "labels" { - description = "Key/value labels to attach to the network." - type = map(string) - nullable = true - default = null -} - -variable "no_ipv4_gateway" { - description = "If true, suppress creation of an IPv4 gateway." - type = bool - default = false -} - -variable "no_ipv6_gateway" { - description = "If true, suppress creation of an IPv6 gateway." - type = bool - default = false -} - -variable "routed" { - description = "If true, the network is routed." - type = bool - default = false -} - -variable "routing_table_id" { - description = "Routing table ID to associate with this network (experimental)." - type = string - nullable = true - default = null -} - +# rule schema variable "rules" { - description = "List of routing rules to apply to this network (experimental)." - type = any + 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." + } + + # port_range min <= max when provided + 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/variables.tf b/ske/variables.tf index ccae10c..6636f12 100644 --- a/ske/variables.tf +++ b/ske/variables.tf @@ -1,47 +1,51 @@ variable "project_id" { - description = "STACKIT project ID to which the cluster is associated." + description = "STACKIT project ID" type = string } variable "name" { - description = "The cluster name." + description = "Cluster name" type = string } variable "node_pools" { - description = "One or more node_pool blocks." + description = "List of node pool configs" 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 +# -----------------------------------------------------------------------------# +# Optional fields +# -----------------------------------------------------------------------------# + variable "kubernetes_version_min" { - description = "The minimum Kubernetes version." + description = "Minimum Kubernetes version" type = string default = null } variable "hibernations" { - description = "A list of hibernation schedules for the cluster." + description = "Hibernation schedules" type = list(object({ start = string end = string @@ -51,7 +55,7 @@ variable "hibernations" { } variable "maintenance" { - description = "A single maintenance block." + description = "Maintenance window settings" type = object({ enable_kubernetes_version_updates = bool enable_machine_image_version_updates = bool @@ -60,8 +64,9 @@ variable "maintenance" { }) default = null } + variable "extensions" { - description = "A single extensions block." + description = "Extensions config" type = object({ acl = optional(object({ enabled = bool @@ -72,23 +77,15 @@ 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 = "The resource region." + description = "Resource region override" type = string default = null -} \ No newline at end of file +} From 9695f5a95f5b7f878ec7b341c0f88e6b77966dde Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Thu, 17 Jul 2025 13:48:59 +0200 Subject: [PATCH 19/22] up provider version, cleanup --- example/.tflint.hcl | 16 ++ example/providers.tf | 2 +- example/variables.tf | 16 -- main.tf | 130 +++++++++++++ network/providers.tf | 2 +- network/variables.tf | 21 --- observability/providers.tf | 2 +- postgres/providers.tf | 2 +- project/providers.tf | 2 +- providers.tf | 16 ++ security-group/providers.tf | 2 +- security-group/variables.tf | 1 - ske/providers.tf | 2 +- ske/variables.tf | 4 - variables.tf | 351 ++++++++++++++++++++++++++++++++++++ 15 files changed, 520 insertions(+), 49 deletions(-) create mode 100644 example/.tflint.hcl create mode 100644 main.tf create mode 100644 providers.tf create mode 100644 variables.tf diff --git a/example/.tflint.hcl b/example/.tflint.hcl new file mode 100644 index 0000000..e927895 --- /dev/null +++ b/example/.tflint.hcl @@ -0,0 +1,16 @@ +plugin "terraform" { + enabled = true + preset = "recommended" +} + +rule "terraform_unused_declarations" { + enabled = true +} + +# rule "terraform_documented_outputs" { +# enabled = true +# } + +rule "terraform_documented_variables" { + enabled = true +} diff --git a/example/providers.tf b/example/providers.tf index 502d800..5873620 100644 --- a/example/providers.tf +++ b/example/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.54.0" + version = "0.56.0" } } } diff --git a/example/variables.tf b/example/variables.tf index bfeab6e..dff5a62 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -61,10 +61,6 @@ variable "labels" { default = {} } -# -----------------------------------------------------------------------------# -# Security Groups -# -----------------------------------------------------------------------------# - variable "security_groups" { description = "Map of security group definitions" type = map(object({ @@ -93,10 +89,6 @@ variable "security_groups" { })) } -# -----------------------------------------------------------------------------# -# PostgreSQL -# -----------------------------------------------------------------------------# - variable "postgres_instances" { description = "Map of PostgreSQL instances to create" type = map(object({ @@ -119,10 +111,6 @@ variable "postgres_instances" { })) } -# -----------------------------------------------------------------------------# -# Networks -# -----------------------------------------------------------------------------# - variable "networks" { description = "Map of network definitions per project" type = map(object({ @@ -219,10 +207,6 @@ variable "ske_clusters" { default = {} } -# -----------------------------------------------------------------------------# -# Observability -# -----------------------------------------------------------------------------# - variable "observability_instances" { description = "Map of Observability instances to create" type = map(object({ diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..93ef132 --- /dev/null +++ b/main.tf @@ -0,0 +1,130 @@ +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 + labels = var.labels != null ? var.labels : {} +} + +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/providers.tf b/network/providers.tf index 532c77d..6e038c3 100644 --- a/network/providers.tf +++ b/network/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.54.0" + version = "0.56.0" } } } diff --git a/network/variables.tf b/network/variables.tf index b5b2fc7..9c7f985 100644 --- a/network/variables.tf +++ b/network/variables.tf @@ -8,9 +8,6 @@ variable "name" { type = string } -# ----------------------------- -# IPv4 -# ----------------------------- variable "ipv4_gateway" { description = "IPv4 gateway address" type = string @@ -35,9 +32,6 @@ variable "ipv4_prefix_length" { default = null } -# ----------------------------- -# IPv6 -# ----------------------------- variable "ipv6_gateway" { description = "IPv6 gateway address" type = string @@ -62,18 +56,12 @@ variable "ipv6_prefix_length" { default = null } -# ----------------------------- -# Deprecated legacy nameservers (provider still exposes) -# ----------------------------- variable "nameservers" { description = "Deprecated nameserver list (legacy field)" type = list(string) default = [] } -# ----------------------------- -# Labels & flags -# ----------------------------- variable "labels" { description = "Labels map" type = map(string) @@ -98,9 +86,6 @@ variable "routed" { default = null } -# ----------------------------- -# Region override & routing -# ----------------------------- variable "region" { description = "Resource region override (defaults to provider region)" type = string @@ -113,9 +98,6 @@ variable "routing_table_id" { default = null } -# ----------------------------- -# NIC map (zero or many) -# ----------------------------- variable "nics" { description = "Map of NIC configs" type = map(object({ @@ -130,9 +112,6 @@ variable "nics" { default = {} } -# ----------------------------- -# Security group lookup map -# ----------------------------- variable "security_group_ids_by_name" { description = "Security group name→ID map" type = map(string) diff --git a/observability/providers.tf b/observability/providers.tf index a2af181..8962cf6 100644 --- a/observability/providers.tf +++ b/observability/providers.tf @@ -4,7 +4,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.54.0" + version = "0.56.0" } } } diff --git a/postgres/providers.tf b/postgres/providers.tf index 532c77d..6e038c3 100644 --- a/postgres/providers.tf +++ b/postgres/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.54.0" + version = "0.56.0" } } } diff --git a/project/providers.tf b/project/providers.tf index 532c77d..6e038c3 100644 --- a/project/providers.tf +++ b/project/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.54.0" + version = "0.56.0" } } } diff --git a/providers.tf b/providers.tf new file mode 100644 index 0000000..5873620 --- /dev/null +++ b/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.region + service_account_token = var.service_account_token != null ? var.service_account_token : null + service_account_key_path = var.service_account_key_path != null ? var.service_account_key_path : null + enable_beta_resources = true +} diff --git a/security-group/providers.tf b/security-group/providers.tf index 532c77d..6e038c3 100644 --- a/security-group/providers.tf +++ b/security-group/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.54.0" + version = "0.56.0" } } } diff --git a/security-group/variables.tf b/security-group/variables.tf index 4ca3116..97d6da7 100644 --- a/security-group/variables.tf +++ b/security-group/variables.tf @@ -52,7 +52,6 @@ variable "rules" { error_message = "Each rule.ether_type must be 'IPv4' or 'IPv6' when set." } - # port_range min <= max when provided validation { condition = alltrue([ for r in var.rules : diff --git a/ske/providers.tf b/ske/providers.tf index 532c77d..6e038c3 100644 --- a/ske/providers.tf +++ b/ske/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { stackit = { source = "stackitcloud/stackit" - version = "0.54.0" + version = "0.56.0" } } } diff --git a/ske/variables.tf b/ske/variables.tf index 6636f12..efa26e0 100644 --- a/ske/variables.tf +++ b/ske/variables.tf @@ -34,10 +34,6 @@ variable "node_pools" { })) } -# -----------------------------------------------------------------------------# -# Optional fields -# -----------------------------------------------------------------------------# - variable "kubernetes_version_min" { description = "Minimum Kubernetes version" type = string diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..54c97e1 --- /dev/null +++ b/variables.tf @@ -0,0 +1,351 @@ +# ----------------------------------------------------------------------------- +# 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 +} + +# 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" +} + +# Fallback region for resources if none specified +variable "default_region" { + description = "Default region fallback for created resources" + 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 + } +} From 938455bd7c04a95797aefc73ddcd62b75d1c1820 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Thu, 17 Jul 2025 13:50:05 +0200 Subject: [PATCH 20/22] rm testing parameters in tfvars --- terraform.tfvars | 285 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 terraform.tfvars diff --git a/terraform.tfvars b/terraform.tfvars new file mode 100644 index 0000000..7481295 --- /dev/null +++ b/terraform.tfvars @@ -0,0 +1,285 @@ +# 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 + } + ] + } +} From d62221db859d6d6c3eb2716ceecd025cf1225ab2 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Thu, 17 Jul 2025 13:53:32 +0200 Subject: [PATCH 21/22] rm example dir --- example/.tflint.hcl | 16 -- example/main.tf | 130 ---------------- example/providers.tf | 16 -- example/terraform.tfvars | 295 ------------------------------------ example/variables.tf | 313 --------------------------------------- 5 files changed, 770 deletions(-) delete mode 100644 example/.tflint.hcl delete mode 100644 example/main.tf delete mode 100644 example/providers.tf delete mode 100644 example/terraform.tfvars delete mode 100644 example/variables.tf diff --git a/example/.tflint.hcl b/example/.tflint.hcl deleted file mode 100644 index e927895..0000000 --- a/example/.tflint.hcl +++ /dev/null @@ -1,16 +0,0 @@ -plugin "terraform" { - enabled = true - preset = "recommended" -} - -rule "terraform_unused_declarations" { - enabled = true -} - -# rule "terraform_documented_outputs" { -# enabled = true -# } - -rule "terraform_documented_variables" { - enabled = true -} diff --git a/example/main.tf b/example/main.tf deleted file mode 100644 index 1f66eb9..0000000 --- a/example/main.tf +++ /dev/null @@ -1,130 +0,0 @@ -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 - labels = var.labels != null ? var.labels : {} -} - -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/example/providers.tf b/example/providers.tf deleted file mode 100644 index 5873620..0000000 --- a/example/providers.tf +++ /dev/null @@ -1,16 +0,0 @@ -terraform { - required_version = ">= 1.9.0" - required_providers { - stackit = { - source = "stackitcloud/stackit" - version = "0.56.0" - } - } -} - -provider "stackit" { - default_region = var.region - service_account_token = var.service_account_token != null ? var.service_account_token : null - service_account_key_path = var.service_account_key_path != null ? var.service_account_key_path : null - enable_beta_resources = true -} diff --git a/example/terraform.tfvars b/example/terraform.tfvars deleted file mode 100644 index 9b09f84..0000000 --- a/example/terraform.tfvars +++ /dev/null @@ -1,295 +0,0 @@ -organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" - -Projects_map = { - "projekt-alpha" = { - name = "tf_modules_test_6_jh" - owner_email = "maximilian.schlenz@stackit.cloud" - }, - "projekt-beta" = { - name = "tf_modules_test_7_jh" - owner_email = "maximilian.schlenz@stackit.cloud" - } -} - -SNA_name = "sna-jh" - -SNA_network_ranges = [ - { prefix = "192.168.10.0/24" } -] - -SNA_transfer_network = "172.16.0.0/24" - -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 - } - }, - ] - }, -} - -postgres_instances = { - dev = { - name = "pg-test-instance" - project_key = "projekt-alpha" - version = 17 - flavor = { - cpu = 2, - ram = 4 - } - storage = { - class = "premium-perf6-stackit", - size = 20 - } - replicas = 1 - acl = ["0.0.0.0/0"] - backup_schedule = "00 00 * * *" - - users = [ - { username = "adminusr", - roles = ["login", "createdb"] - }, - { username = "testusr", - roles = ["login"] - } - ] - - databases = [ - { - name = "testdb", - owner = "admin" - } - ] - } -} - -networks = { - wan_network = { - name = "wan_network" - project_key = "projekt-beta" - ipv4_nameservers = ["1.1.1.1", "8.8.8.8"] - ipv4_prefix_length = 29 - ipv4_prefix = "192.168.10.248/29" - routed = true - } -} - -observability_instances = { - test = { - # Required - name = "test-observability" - project_key = "projekt-alpha" - plan_name = "Observability-Large-EU01" - - # Optional instance 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 - # parameters = { - # "custom_param" = "value" - # } - - # Credentials - create_credentials = true - credentials_count = 2 - - # alert‑groups - 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‑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" - } - }, - ] - } - } - - # scrapeconfigs - scrapeconfigs = { - example_job = { - name = "example-job" - metrics_path = "/my-metrics" - saml2 = { - enable_url_parameters = true - } - targets = [ - { - urls = ["url1", "urls2"] - labels = { - "url1" = "dev" - } - } - ] - } - } - } -} - -ske_clusters = { - /* - "prod-cluster" = { - name = "clusterprod" - project_key = "projekt-alpha" - kubernetes_version_min = "1.32.5" - - node_pools = [ - { - name = "np" - machine_type = "c1.2" - availability_zones = ["eu01-3", "eu01-1"] - minimum = 2 - maximum = 3 - volume_type = "storage_premium_perf1" - volume_size = 64 - 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 = "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/example/variables.tf b/example/variables.tf deleted file mode 100644 index dff5a62..0000000 --- a/example/variables.tf +++ /dev/null @@ -1,313 +0,0 @@ -variable "region" { - description = "Provider region for STACKIT Cloud" - type = string - default = "eu01" -} - -variable "service_account_token" { - description = "Service account token for authentication" - sensitive = true - type = string - default = null -} - -# -----------------------------------------------------------------------------# -# SNA & Projects -# -----------------------------------------------------------------------------# - -variable "organization_id" { - description = "STACKIT organization container ID" - type = string -} - -variable "service_account_key_path" { - description = "Path to service account JSON key" - type = string - default = "/Users/schlenz/.stackit/sa.json" -} - -variable "default_region" { - description = "Default region fallback for created resources" - type = string - default = "eu01" -} - -variable "SNA_name" { - description = "Name of the Service Network Area to create" - type = string -} - -variable "SNA_network_ranges" { - description = "CIDR list for the Service Network Area" - type = list(object({ prefix = string })) -} - -variable "SNA_transfer_network" { - description = "Transfer network CIDR for the SNA" - type = string -} - -variable "Projects_map" { - description = "Map of STACKIT projects to create" - type = map(object({ - name = string - owner_email = string - })) -} - -variable "labels" { - description = "Default labels to apply where supported" - type = map(string) - default = {} -} - -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 - description = optional(string) - ether_type = optional(string) - icmp_parameters = optional(object({ - type = optional(number) - code = optional(number) - })) - ip_range = optional(string) - port_range = optional(object({ - min = number - max = number - })) - protocol = optional(object({ - name = optional(string) - number = optional(number) - })) - remote_security_group_id = optional(string) - })) - })) -} - -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) - backup_schedule = string - users = list(object({ - username = string - roles = set(string) - })) - databases = list(object({ - name = string - owner = string - })) - })) -} - -variable "networks" { - description = "Map of network definitions per project" - type = map(object({ - name = string - project_key = string - - # IPv4 - ipv4_gateway = optional(string) - ipv4_nameservers = optional(list(string)) - ipv4_prefix = optional(string) - ipv4_prefix_length = optional(number) - - # IPv6 - ipv6_gateway = optional(string) - ipv6_nameservers = optional(list(string)) - ipv6_prefix = optional(string) - ipv6_prefix_length = optional(number) - - # Flags & labels - labels = optional(map(string)) - no_ipv4_gateway = optional(bool) - no_ipv6_gateway = optional(bool) - routed = optional(bool) - - # NICs - 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 Clusters -# -----------------------------------------------------------------------------# - -variable "ske_clusters" { - description = "Map of SKE cluster definitions" - type = map(object({ - name = string - project_key = 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 = {} -} - -variable "observability_instances" { - description = "Map of Observability instances to create" - type = map(object({ - name = string - project_key = string - plan_name = string - - # Instance 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)) - - # Credentials - create_credentials = optional(bool, true) - credentials_count = optional(number, 1) - - # Alert-groups - 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-groups - 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-configs - 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 - } -} From 76a1c17bad0be6eeb4f485008135b74c39fe6d17 Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Thu, 17 Jul 2025 13:56:45 +0200 Subject: [PATCH 22/22] rm project_old dir --- project_old/main.tf | 34 ---------------------------------- project_old/provider.tf | 10 ---------- project_old/sna.tf | 27 --------------------------- project_old/variables.tf | 10 ---------- 4 files changed, 81 deletions(-) delete mode 100644 project_old/main.tf delete mode 100644 project_old/provider.tf delete mode 100644 project_old/sna.tf delete mode 100644 project_old/variables.tf diff --git a/project_old/main.tf b/project_old/main.tf deleted file mode 100644 index 58176f0..0000000 --- a/project_old/main.tf +++ /dev/null @@ -1,34 +0,0 @@ -variable "projects" { - type = map(object({ - name = string - owner_email = string - })) - default = { - project1 = { - name = "project-alpha" - owner_email = "michael.sodan@stackit.cloud" - } - project2 = { - name = "project-beta" - owner_email = "michael.sodan@stackit.cloud" - } - } -} - -resource "stackit_resourcemanager_project" "projects" { - for_each = var.projects - parent_container_id = var.organization_id # Nutzt jetzt die übergebene Variable - name = each.value.name - owner_email = each.value.owner_email - # labels = { ... } # Vorerst entfernt, da stackit_network_area nicht definiert war -} - -output "project_info" { - value = { - for k, project in stackit_resourcemanager_project.projects : k => { - project_id = project.project_id - container_id = project.container_id - } - } -} - diff --git a/project_old/provider.tf b/project_old/provider.tf deleted file mode 100644 index a89dd02..0000000 --- a/project_old/provider.tf +++ /dev/null @@ -1,10 +0,0 @@ - -terraform { - required_providers { - stackit = { - source = "stackitcloud/stackit" - version = ">= 0.54.0" # Diese Version passt zu Ihrer Anforderung - } - } -} - diff --git a/project_old/sna.tf b/project_old/sna.tf deleted file mode 100644 index 711c80d..0000000 --- a/project_old/sna.tf +++ /dev/null @@ -1,27 +0,0 @@ -/* resource "time_sleep" "wait_before_destroy" { - destroy_duration = "60s" -} -*/ - -resource "stackit_network_area" "sna" { - organization_id = var.organization_id - name = "bego_sna" - network_ranges = [ - { - prefix = "10.220.0.0/16" - } - ] - transfer_network = "var.sna_net" - //depends_on = [time_sleep.wait_before_destroy] -} - -/* resource "stackit_network_area_route" "sna_route1" { - organization_id = var.organization_id - network_area_id = stackit_network_area.sna.network_area_id - prefix = "10.220.99.0/24" - next_hop = "10.220.0.0" - labels = { - "key" = "value" - } -} -*/ diff --git a/project_old/variables.tf b/project_old/variables.tf deleted file mode 100644 index 6a8400f..0000000 --- a/project_old/variables.tf +++ /dev/null @@ -1,10 +0,0 @@ -variable "organization_id" { - description = "Empfängt die Container-ID der Organisation vom Root-Modul." - type = string -} - -variable "sna_net" { - description = "SNA Transfer Network" - type = string -} -