From f187c9b4bf5086aa6af400c6607ce49158da3c14 Mon Sep 17 00:00:00 2001 From: Salima Hassouni Date: Fri, 31 May 2024 14:18:46 +0000 Subject: [PATCH] DBP-817-ionos-basic-vm and ionos-datacenter --- modules/ionos-basic-vm/README.md | 76 +++++++++ modules/ionos-basic-vm/data.tf | 7 + modules/ionos-basic-vm/locals.tf | 13 ++ modules/ionos-basic-vm/main.tf | 73 ++++++++ modules/ionos-basic-vm/outputs.tf | 15 ++ modules/ionos-basic-vm/server.tf | 74 ++++++++ .../ionos-basic-vm/user-data-cloud-init.tpl | 12 ++ modules/ionos-basic-vm/user-data-lvm.sh | 4 + modules/ionos-basic-vm/user-data.sh | 3 + modules/ionos-basic-vm/variables.tf | 160 ++++++++++++++++++ modules/ionos-basic-vm/versions.tf | 12 ++ modules/ionos-datacenter/README.md | 91 ++++++++++ modules/ionos-datacenter/locals.tf | 43 +++++ modules/ionos-datacenter/main.tf | 134 +++++++++++++++ modules/ionos-datacenter/output.tf | 96 +++++++++++ modules/ionos-datacenter/variables.tf | 115 +++++++++++++ modules/ionos-datacenter/versions.tf | 9 + 17 files changed, 937 insertions(+) create mode 100644 modules/ionos-basic-vm/README.md create mode 100644 modules/ionos-basic-vm/data.tf create mode 100644 modules/ionos-basic-vm/locals.tf create mode 100644 modules/ionos-basic-vm/main.tf create mode 100644 modules/ionos-basic-vm/outputs.tf create mode 100644 modules/ionos-basic-vm/server.tf create mode 100644 modules/ionos-basic-vm/user-data-cloud-init.tpl create mode 100644 modules/ionos-basic-vm/user-data-lvm.sh create mode 100644 modules/ionos-basic-vm/user-data.sh create mode 100644 modules/ionos-basic-vm/variables.tf create mode 100644 modules/ionos-basic-vm/versions.tf create mode 100644 modules/ionos-datacenter/README.md create mode 100644 modules/ionos-datacenter/locals.tf create mode 100644 modules/ionos-datacenter/main.tf create mode 100644 modules/ionos-datacenter/output.tf create mode 100644 modules/ionos-datacenter/variables.tf create mode 100644 modules/ionos-datacenter/versions.tf diff --git a/modules/ionos-basic-vm/README.md b/modules/ionos-basic-vm/README.md new file mode 100644 index 0000000..c794667 --- /dev/null +++ b/modules/ionos-basic-vm/README.md @@ -0,0 +1,76 @@ + + +## Providers + +| Name | Version | +|------|---------| +| [ionoscloud](#provider\_ionoscloud) | 6.3.6 | +| [opentelekomcloud](#provider\_opentelekomcloud) | n/a | +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [conventions\_coordinates](#module\_conventions\_coordinates) | ../conventions-coordinates | n/a | +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [basic\_vm\_server\_cpu](#input\_basic\_vm\_server\_cpu) | cpu of the basic vm servers | `number` | n/a | yes | +| [basic\_vm\_server\_memory](#input\_basic\_vm\_server\_memory) | memory of the basic vm servers | `number` | n/a | yes | +| [basic\_vm\_volume\_size](#input\_basic\_vm\_volume\_size) | volume size for vm | `number` | n/a | yes | +| [coordinates](#input\_coordinates) | n/a | `map(any)` | n/a | yes | +| [cpu\_family](#input\_cpu\_family) | n/a | `string` | n/a | yes | +| [datacenter](#input\_datacenter) | n/a | `string` | n/a | yes | +| [datacenter\_location](#input\_datacenter\_location) | n/a | `string` | n/a | yes | +| [domain\_without\_top\_level](#input\_domain\_without\_top\_level) | domain without top level | `string` | n/a | yes | +| [fulldomainname](#input\_fulldomainname) | Domain under which the basic vm server will be available | `string` | n/a | yes | +| [image](#input\_image) | image of the vm | `string` | n/a | yes | +| [server\_name](#input\_server\_name) | name of the vm | `string` | n/a | yes | +| [top\_level\_domain](#input\_top\_level\_domain) | Top-level domain mapping for environments | `map(any)` | n/a | yes | +| [additional\_ips](#input\_additional\_ips) | Additional IPs for the VM (optional) | `list(string)` | `[]` | no | +| [availability\_zone](#input\_availability\_zone) | Possible Zones: AUTO, ZONE\_1, ZONE\_2 | `string` | `"AUTO"` | no | +| [basic\_vm\_create\_second\_volume](#input\_basic\_vm\_create\_second\_volume) | n/a | `bool` | `true` | no | +| [basic\_vm\_second\_volume\_disk\_type](#input\_basic\_vm\_second\_volume\_disk\_type) | n/a | `string` | `"HDD"` | no | +| [basic\_vm\_second\_volume\_size](#input\_basic\_vm\_second\_volume\_size) | size of the second volume | `string` | `100` | no | +| [create\_ip\_pool](#input\_create\_ip\_pool) | If true an IP pool of size 1 will be created, if false a public IP must be provided | `bool` | `true` | no | +| [create\_lan](#input\_create\_lan) | If true a LAN will be created, if false a LAN ID must be provided | `bool` | `true` | no | +| [dns\_zone\_name\_override](#input\_dns\_zone\_name\_override) | Name of the DNS zone if it doesn't follow the naming convention (i.e. messenger.schule) | `string` | `""` | no | +| [initial\_public\_key](#input\_initial\_public\_key) | The public key of the initial user created via the cloud init script. | `string` | `""` | no | +| [initial\_uid](#input\_initial\_uid) | The uid of the initial user created via the cloud init script. | `string` | `""` | no | +| [initial\_user](#input\_initial\_user) | The initial user to be created via the cloud init script. | `string` | `""` | no | +| [ip\_pool\_name](#input\_ip\_pool\_name) | Name of the ip pools | `string` | `""` | no | +| [lan\_id](#input\_lan\_id) | Id of the LAN to use (only necessary if create\_lan is false) | `number` | `null` | no | +| [permanent\_vm](#input\_permanent\_vm) | Create a permanent VM that mustn't be deleted, if false then a VM that can be deleted and that ignores changes to ram and cpu is created | `bool` | `true` | no | +| [port\_ranges](#input\_port\_ranges) | port rangs to open in the IONOS firewall provided as objects in a list [{protocol = ???, name = ???, port\_start = ???, port\_end = ???, source\_ip = ???}], source\_ip is optional. | `list` | `[]` | no | +| [ports](#input\_ports) | ports to open in the IONOS firewall provided as objects in a list [{protocol = ???, name = ???, port = ???, source\_ip = ???}], source\_ip is optional. | `list` | `[]` | no | +| [public\_ip](#input\_public\_ip) | n/a | `string` | `""` | no | +| [user\_data\_script](#input\_user\_data\_script) | Decide which user-data.sh script to use | `string` | `"user-data-cloud-init.tpl"` | no | +## Outputs + +| Name | Description | +|------|-------------| +| [basic\_vm\_server\_dns](#output\_basic\_vm\_server\_dns) | n/a | +| [basic\_vm\_server\_id](#output\_basic\_vm\_server\_id) | n/a | +| [basic\_vm\_server\_nicuuid](#output\_basic\_vm\_server\_nicuuid) | n/a | +| [basic\_vm\_server\_public\_ip](#output\_basic\_vm\_server\_public\_ip) | n/a | +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.13 | +| [ionoscloud](#requirement\_ionoscloud) | 6.3.6 | +## Resources + +| Name | Type | +|------|------| +| [ionoscloud_firewall.range_rule](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/firewall) | resource | +| [ionoscloud_firewall.rule](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/firewall) | resource | +| [ionoscloud_ipblock.public_ip](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/ipblock) | resource | +| [ionoscloud_lan.basic_vm_server_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_server.basic_vm_server](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/server) | resource | +| [ionoscloud_server.basic_vm_server_not_permanent](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/server) | resource | +| [ionoscloud_volume.second_volume](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/volume) | resource | +| [opentelekomcloud_dns_recordset_v2.a_records](https://registry.terraform.io/providers/opentelekomcloud/opentelekomcloud/latest/docs/resources/dns_recordset_v2) | resource | +| [ionoscloud_datacenter.datacenter](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/data-sources/datacenter) | data source | +| [opentelekomcloud_dns_zone_v2.dns_zone](https://registry.terraform.io/providers/opentelekomcloud/opentelekomcloud/latest/docs/data-sources/dns_zone_v2) | data source | + \ No newline at end of file diff --git a/modules/ionos-basic-vm/data.tf b/modules/ionos-basic-vm/data.tf new file mode 100644 index 0000000..d9075f7 --- /dev/null +++ b/modules/ionos-basic-vm/data.tf @@ -0,0 +1,7 @@ +data "opentelekomcloud_dns_zone_v2" "dns_zone" { + name = local.dns_zone_name +} + +data "ionoscloud_datacenter" "datacenter" { + id = var.datacenter +} \ No newline at end of file diff --git a/modules/ionos-basic-vm/locals.tf b/modules/ionos-basic-vm/locals.tf new file mode 100644 index 0000000..cbb570d --- /dev/null +++ b/modules/ionos-basic-vm/locals.tf @@ -0,0 +1,13 @@ +locals { + technicaluser_key_path = var.initial_public_key + public_ip = var.create_ip_pool ? ionoscloud_ipblock.public_ip[0].ips[0] : var.public_ip + dns_zone_name = var.dns_zone_name_override == "" ? module.conventions_coordinates.dns_zone_name : var.dns_zone_name_override + basic_vm_server = var.permanent_vm ? ionoscloud_server.basic_vm_server[0] : ionoscloud_server.basic_vm_server_not_permanent[0] + + user_data_vars = { + "initial_user" = var.initial_user + "initial_uid" = var.initial_uid + "initial_public_key" = file(var.initial_public_key) + } + user_data = base64encode(templatefile("${path.module}/${var.user_data_script}", local.user_data_vars)) +} diff --git a/modules/ionos-basic-vm/main.tf b/modules/ionos-basic-vm/main.tf new file mode 100644 index 0000000..efce938 --- /dev/null +++ b/modules/ionos-basic-vm/main.tf @@ -0,0 +1,73 @@ +resource "ionoscloud_ipblock" "public_ip" { + count = var.create_ip_pool ? 1 : 0 + name = var.ip_pool_name + location = var.datacenter_location + size = 1 +} + +resource "ionoscloud_lan" "basic_vm_server_lan" { + count = var.create_lan ? 1 : 0 + datacenter_id = var.datacenter + public = true + name = "${var.server_name}-vm-public" +} + +resource "opentelekomcloud_dns_recordset_v2" "a_records" { + zone_id = data.opentelekomcloud_dns_zone_v2.dns_zone.id + name = "${var.fulldomainname}" + ttl = 3600 + type = "A" + records = [local.public_ip] + + lifecycle { + ignore_changes = [zone_id] + } +} + +resource "ionoscloud_firewall" "rule" { + count = length(var.ports) + datacenter_id = var.datacenter + server_id = local.basic_vm_server.id + nic_id = local.basic_vm_server.primary_nic + protocol = var.ports[count.index]["protocol"] + name = var.ports[count.index]["name"] + port_range_start = var.ports[count.index]["port"] + port_range_end = var.ports[count.index]["port"] + source_ip = lookup(var.ports[count.index], "source_ip", null) +} + +resource "ionoscloud_firewall" "range_rule" { + count = length(var.port_ranges) + datacenter_id = var.datacenter + server_id = local.basic_vm_server.id + nic_id = local.basic_vm_server.primary_nic + protocol = var.port_ranges[count.index]["protocol"] + name = var.port_ranges[count.index]["name"] + port_range_start = var.port_ranges[count.index]["port_start"] + port_range_end = var.port_ranges[count.index]["port_end"] + source_ip = lookup(var.port_ranges[count.index], "source_ip", null) +} + +module "conventions_coordinates" { + source = "../conventions-coordinates" + coordinates = var.coordinates + domain_without_top_level = var.domain_without_top_level + top_level_domain = var.top_level_domain +} + +# Extra Volume +# /dev/vdb +resource "ionoscloud_volume" "second_volume" { + count = var.basic_vm_create_second_volume ? 1 : 0 + datacenter_id = var.datacenter + server_id = local.basic_vm_server.id + name = "second-volume-${var.basic_vm_second_volume_disk_type}" + size = var.basic_vm_second_volume_size + disk_type = var.basic_vm_second_volume_disk_type + bus = "VIRTIO" + licence_type = "UNKNOWN" + + lifecycle { + prevent_destroy = true + } +} diff --git a/modules/ionos-basic-vm/outputs.tf b/modules/ionos-basic-vm/outputs.tf new file mode 100644 index 0000000..85c8ed0 --- /dev/null +++ b/modules/ionos-basic-vm/outputs.tf @@ -0,0 +1,15 @@ +output "basic_vm_server_id" { + value = local.basic_vm_server.id +} + +output "basic_vm_server_dns" { + value = trim(opentelekomcloud_dns_recordset_v2.a_records.name, ".") +} + +output "basic_vm_server_public_ip" { + value = local.basic_vm_server.primary_ip +} + +output "basic_vm_server_nicuuid" { + value = local.basic_vm_server.nic[*].id +} \ No newline at end of file diff --git a/modules/ionos-basic-vm/server.tf b/modules/ionos-basic-vm/server.tf new file mode 100644 index 0000000..6a289f5 --- /dev/null +++ b/modules/ionos-basic-vm/server.tf @@ -0,0 +1,74 @@ +# Terraform can't handle variables in resource lifecycles (https://github.com/hashicorp/terraform/issues/3116) so this workaround is necessary +resource "ionoscloud_server" "basic_vm_server" { + count = var.permanent_vm ? 1 : 0 + name = var.server_name + datacenter_id = var.datacenter + cores = var.basic_vm_server_cpu + ram = var.basic_vm_server_memory + image_name = var.image + cpu_family = var.cpu_family + availability_zone = var.availability_zone + ssh_keys = [ local.technicaluser_key_path ] + + # /dev/vda1 + volume { + name = "root-volume-ssd" + size = var.basic_vm_volume_size + disk_type = "SSD Standard" + user_data = local.user_data + } + + nic { + lan = var.create_lan ? ionoscloud_lan.basic_vm_server_lan[0].id : var.lan_id + dhcp = true + ips = concat([local.public_ip], var.additional_ips) + firewall_active = true + name = "public" + } + # will cause Terraform to reject with an error any plan that would destroy the infrastructure object associated with the resource, + # as long as the argument remains present in the configuration + lifecycle { + prevent_destroy = true + ignore_changes = [ + volume[0].user_data, + ssh_keys + ] + } +} + +resource "ionoscloud_server" "basic_vm_server_not_permanent" { + count = var.permanent_vm ? 0 : 1 + name = var.server_name + datacenter_id = var.datacenter + cores = var.basic_vm_server_cpu + ram = var.basic_vm_server_memory + image_name = var.image + cpu_family = var.cpu_family + availability_zone = var.availability_zone + ssh_keys = [ local.technicaluser_key_path ] + + # /dev/vda1 + volume { + name = "root-volume-ssd" + size = var.basic_vm_volume_size + disk_type = "SSD Standard" + user_data = local.user_data + } + + nic { + lan = var.create_lan ? ionoscloud_lan.basic_vm_server_lan[0].id : var.lan_id + dhcp = true + ips = concat([local.public_ip], var.additional_ips) + firewall_active = true + name = "public" + } + + lifecycle { + ignore_changes = [ + volume[0].user_data, + cores, + ram, + ssh_keys + ] + } +} diff --git a/modules/ionos-basic-vm/user-data-cloud-init.tpl b/modules/ionos-basic-vm/user-data-cloud-init.tpl new file mode 100644 index 0000000..942678e --- /dev/null +++ b/modules/ionos-basic-vm/user-data-cloud-init.tpl @@ -0,0 +1,12 @@ +#cloud-config +runcmd: + - sed -i 's/HISTSIZE=1000/HISTSIZE=10000/g' /root/.bashrc + - sed -i 's/HISTFILESIZE=2000/HISTFILESIZE=20000/g' /root/.bashrc + +users: + - name: ${initial_user} + sudo: ALL=(ALL:ALL) NOPASSWD:ALL + # uid must match the uid of the technical user in infra-schulcloud/ansible/group_vars/all/users.yml variable present_users + uid: ${initial_uid} + ssh_authorized_keys: + - ${initial_public_key} diff --git a/modules/ionos-basic-vm/user-data-lvm.sh b/modules/ionos-basic-vm/user-data-lvm.sh new file mode 100644 index 0000000..6a692b3 --- /dev/null +++ b/modules/ionos-basic-vm/user-data-lvm.sh @@ -0,0 +1,4 @@ +#!/bin/bash +sed -i 's/HISTSIZE=1000/HISTSIZE=10000/g' ~/.bashrc +sed -i 's/HISTFILESIZE=2000/HISTFILESIZE=20000/g' ~/.bashrc +# wait for the volume to be created (normal duration: 30 seconds) diff --git a/modules/ionos-basic-vm/user-data.sh b/modules/ionos-basic-vm/user-data.sh new file mode 100644 index 0000000..68c2377 --- /dev/null +++ b/modules/ionos-basic-vm/user-data.sh @@ -0,0 +1,3 @@ +#!/bin/bash +sed -i 's/HISTSIZE=1000/HISTSIZE=10000/g' /root/.bashrc +sed -i 's/HISTFILESIZE=2000/HISTFILESIZE=20000/g' /root/.bashrc \ No newline at end of file diff --git a/modules/ionos-basic-vm/variables.tf b/modules/ionos-basic-vm/variables.tf new file mode 100644 index 0000000..7fccab0 --- /dev/null +++ b/modules/ionos-basic-vm/variables.tf @@ -0,0 +1,160 @@ +variable "datacenter" { + type = string +} + +variable "datacenter_location" { + type = string +} + +variable "fulldomainname" { + type = string + description = "Domain under which the basic vm server will be available" +} + +variable "create_ip_pool" { + type = bool + description = "If true an IP pool of size 1 will be created, if false a public IP must be provided" + default = true +} + +variable "public_ip" { + type = string + default = "" +} + +variable "ip_pool_name" { + type = string + description = "Name of the ip pools" + default = "" +} + +variable "basic_vm_server_memory" { + type = number + description = "memory of the basic vm servers" +} + +variable "basic_vm_server_cpu" { + type = number + description = "cpu of the basic vm servers" +} + +variable "basic_vm_volume_size" { + type = number + description = "volume size for vm" +} + +variable "basic_vm_create_second_volume" { + type = bool + default = true +} + +variable "basic_vm_second_volume_disk_type" { + type = string + default = "HDD" +} + +variable "cpu_family" { + type = string +} + +variable "coordinates" { + type = map(any) +} + +variable "top_level_domain" { + type = map(any) + description = "Top-level domain mapping for environments" +} + +variable "domain_without_top_level" { + type = string + description = "domain without top level" +} + +variable "dns_zone_name_override" { + type = string + description = "Name of the DNS zone if it doesn't follow the naming convention (i.e. messenger.schule)" + default = "" +} + +variable "image" { + type = string + description = "image of the vm" +} + +variable "server_name" { + type = string + description = "name of the vm" +} + +variable "basic_vm_second_volume_size" { + type = string + description = "size of the second volume" + default = 100 +} + +variable "ports" { + type = list + description = "ports to open in the IONOS firewall provided as objects in a list [{protocol = ???, name = ???, port = ???, source_ip = ???}], source_ip is optional." + default = [] +} + +variable "port_ranges" { + type = list + description = "port rangs to open in the IONOS firewall provided as objects in a list [{protocol = ???, name = ???, port_start = ???, port_end = ???, source_ip = ???}], source_ip is optional." + default = [] +} + +variable "permanent_vm" { + type = bool + description = "Create a permanent VM that mustn't be deleted, if false then a VM that can be deleted and that ignores changes to ram and cpu is created" + default = true +} + +variable "user_data_script" { + type = string + description = "Decide which user-data.sh script to use" + default = "user-data-cloud-init.tpl" +} + +variable "initial_user" { + type = string + description = "The initial user to be created via the cloud init script." + default = "" +} + +variable "initial_uid" { + type = string + description = "The uid of the initial user created via the cloud init script." + default = "" +} + +variable "initial_public_key" { + type = string + description = "The public key of the initial user created via the cloud init script." + default = "" +} + +variable "availability_zone" { + type = string + description = "Possible Zones: AUTO, ZONE_1, ZONE_2" + default = "AUTO" +} + +variable "create_lan" { + type = bool + description = "If true a LAN will be created, if false a LAN ID must be provided" + default = true +} + +variable "lan_id" { + type = number + description = "Id of the LAN to use (only necessary if create_lan is false)" + default = null +} + +variable "additional_ips" { + type = list(string) + description = "Additional IPs for the VM (optional)" + default = [] +} \ No newline at end of file diff --git a/modules/ionos-basic-vm/versions.tf b/modules/ionos-basic-vm/versions.tf new file mode 100644 index 0000000..5040039 --- /dev/null +++ b/modules/ionos-basic-vm/versions.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + ionoscloud = { + source = "ionos-cloud/ionoscloud" + version = "6.3.6" + } + opentelekomcloud = { + source = "opentelekomcloud/opentelekomcloud" + } + } + required_version = ">= 0.13" +} diff --git a/modules/ionos-datacenter/README.md b/modules/ionos-datacenter/README.md new file mode 100644 index 0000000..24e5916 --- /dev/null +++ b/modules/ionos-datacenter/README.md @@ -0,0 +1,91 @@ + + +## Providers + +| Name | Version | +|------|---------| +| [ionoscloud](#provider\_ionoscloud) | 6.3.6 | +## Modules + +No modules. +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [datacenter\_name](#input\_datacenter\_name) | n/a | `string` | n/a | yes | +| [associated\_backend\_crossconnect\_id](#input\_associated\_backend\_crossconnect\_id) | Specifies whether an existing crossconnect shall be associated. | `string` | `""` | no | +| [associated\_frontend\_crossconnect\_id](#input\_associated\_frontend\_crossconnect\_id) | Specifies whether an existing crossconnect shall be associated. | `string` | `""` | no | +| [associated\_service\_crossconnect\_id](#input\_associated\_service\_crossconnect\_id) | Specifies whether an existing crossconnect shall be associated. | `string` | `""` | no | +| [create\_alb\_target\_lan](#input\_create\_alb\_target\_lan) | Specifies whether a private target for the Application Load Balancer shall be created. | `bool` | `false` | no | +| [create\_backend\_crossconnect](#input\_create\_backend\_crossconnect) | Specifies whether crossconnect shall be created. Default: false. | `bool` | `false` | no | +| [create\_frontend\_crossconnect](#input\_create\_frontend\_crossconnect) | Specifies whether crossconnect shall be created. Default: false. | `bool` | `false` | no | +| [create\_mariadb\_lan](#input\_create\_mariadb\_lan) | Specifies whether a private lan to connect Mariadb shall be created. | `bool` | `false` | no | +| [create\_nat\_lan](#input\_create\_nat\_lan) | Specifies whether a private lan to connect a NAT gateway shall be created. | `bool` | `false` | no | +| [create\_nfs\_server\_lan](#input\_create\_nfs\_server\_lan) | Specifies whether a private lan to connect an NFS server shall be created. | `bool` | `false` | no | +| [create\_nlb\_target\_lan](#input\_create\_nlb\_target\_lan) | Specifies whether a private target for the Network Load Balancer shall be created. | `bool` | `false` | no | +| [create\_postgres\_lan](#input\_create\_postgres\_lan) | Specifies whether a private lan to connect Postgres shall be created. | `bool` | `false` | no | +| [create\_public\_lan](#input\_create\_public\_lan) | Specifies whether a public lan shall be created. Default: false. | `bool` | `false` | no | +| [create\_service\_crossconnect](#input\_create\_service\_crossconnect) | Specifies whether crossconnect shall be created. Default: false. | `bool` | `false` | no | +| [crossconnect\_shared\_group\_ids](#input\_crossconnect\_shared\_group\_ids) | Specifies which groups crossconnect shall be shared with. Default: []. | `list(string)` | `[]` | no | +| [custom\_lans\_to\_create](#input\_custom\_lans\_to\_create) | Map of for private LANs to be created. The key is used for the output. The value is used for the name: - | `map(string)` | `{}` | no | +| [datacenter\_location](#input\_datacenter\_location) | n/a | `string` | `"de/txl"` | no | +| [datacenter\_shares](#input\_datacenter\_shares) | Which groups have access to the datacenter |
list(object({
group = string
edit = optional(bool, false)
share = optional(bool, false)
}))
| `[]` | no | +| [routes\_map](#input\_routes\_map) | map which links based on the lan id to a list in which the routes in form of an object ('network'='###' and 'gateway\_ip'='###') are saved | `any` | `{}` | no | +## Outputs + +| Name | Description | +|------|-------------| +| [alb\_target\_lan\_id](#output\_alb\_target\_lan\_id) | n/a | +| [backend\_crossconnect\_id](#output\_backend\_crossconnect\_id) | n/a | +| [custom\_lans\_id](#output\_custom\_lans\_id) | n/a | +| [datacenter\_id](#output\_datacenter\_id) | n/a | +| [datacenter\_location](#output\_datacenter\_location) | n/a | +| [datacenter\_name](#output\_datacenter\_name) | n/a | +| [frontend\_crossconnect\_id](#output\_frontend\_crossconnect\_id) | n/a | +| [frontend\_lan\_id](#output\_frontend\_lan\_id) | n/a | +| [lan\_alb\_target](#output\_lan\_alb\_target) | n/a | +| [lan\_backend](#output\_lan\_backend) | n/a | +| [lan\_frontend](#output\_lan\_frontend) | n/a | +| [lan\_mariadb](#output\_lan\_mariadb) | n/a | +| [lan\_nat](#output\_lan\_nat) | n/a | +| [lan\_nfs\_server](#output\_lan\_nfs\_server) | n/a | +| [lan\_nlb\_target](#output\_lan\_nlb\_target) | n/a | +| [lan\_postgres](#output\_lan\_postgres) | n/a | +| [lan\_service](#output\_lan\_service) | n/a | +| [lans\_custom](#output\_lans\_custom) | n/a | +| [mariadb\_lan\_id](#output\_mariadb\_lan\_id) | n/a | +| [nat\_lan\_id](#output\_nat\_lan\_id) | n/a | +| [nfs\_server\_lan\_id](#output\_nfs\_server\_lan\_id) | n/a | +| [nlb\_target\_lan\_id](#output\_nlb\_target\_lan\_id) | n/a | +| [postgres\_lan\_id](#output\_postgres\_lan\_id) | n/a | +| [service\_crossconnect\_id](#output\_service\_crossconnect\_id) | n/a | +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.13 | +| [ionoscloud](#requirement\_ionoscloud) | 6.3.6 | +## Resources + +| Name | Type | +|------|------| +| [ionoscloud_datacenter.datacenter](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/datacenter) | resource | +| [ionoscloud_lan.alb_target_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_lan.backend_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_lan.custom_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_lan.frontend_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_lan.mariadb_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_lan.nat_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_lan.nfs_server_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_lan.nlb_target_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_lan.postgres_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_lan.public_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_lan.service_lan](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/lan) | resource | +| [ionoscloud_private_crossconnect.backend_cc](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/private_crossconnect) | resource | +| [ionoscloud_private_crossconnect.frontend_cc](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/private_crossconnect) | resource | +| [ionoscloud_private_crossconnect.service_cc](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/private_crossconnect) | resource | +| [ionoscloud_share.backend_cc](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/share) | resource | +| [ionoscloud_share.datacenter_permissions](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/share) | resource | +| [ionoscloud_share.frontend_cc](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/share) | resource | +| [ionoscloud_share.service_cc](https://registry.terraform.io/providers/ionos-cloud/ionoscloud/6.3.6/docs/resources/share) | resource | + \ No newline at end of file diff --git a/modules/ionos-datacenter/locals.tf b/modules/ionos-datacenter/locals.tf new file mode 100644 index 0000000..1e77e64 --- /dev/null +++ b/modules/ionos-datacenter/locals.tf @@ -0,0 +1,43 @@ +locals { + create_frontend_crossconnect = var.create_frontend_crossconnect + create_frontend_lan = (local.create_frontend_crossconnect == true || var.associated_frontend_crossconnect_id != "") ? true : false + create_backend_crossconnect = var.create_backend_crossconnect + create_backend_lan = (local.create_backend_crossconnect == true || var.associated_backend_crossconnect_id != "") ? true : false + create_service_crossconnect = var.create_service_crossconnect + create_service_lan = (local.create_service_crossconnect == true || var.associated_service_crossconnect_id != "") ? true : false + create_public_lan = var.create_public_lan + create_nfs_server_lan = var.create_nfs_server_lan + create_alb_target_lan = var.create_alb_target_lan + create_nlb_target_lan = var.create_nlb_target_lan + create_nat_lan = var.create_nat_lan + frontend_crossconnect_shared_group_ids = (length(var.crossconnect_shared_group_ids) > 0 && local.create_frontend_crossconnect == true) ? var.crossconnect_shared_group_ids : [] + backend_crossconnect_shared_group_ids = (length(var.crossconnect_shared_group_ids) > 0 && local.create_backend_crossconnect == true) ? var.crossconnect_shared_group_ids : [] + service_crossconnect_shared_group_ids = (length(var.crossconnect_shared_group_ids) > 0 && local.create_frontend_crossconnect == true) ? var.crossconnect_shared_group_ids : [] + routes_map = var.routes_map + create_postgres_lan = var.create_postgres_lan + create_mariadb_lan = var.create_mariadb_lan + custom_lans_to_create = var.custom_lans_to_create + # this saves the service/backend/frontend lans as an object in a list + # Example of an object: + # > type({"id" = "id", "routes_list" = [{"network" = "10.0.0.0/24", gateway_ip="10.0.0.0"}]}) + # object({ + # id: string, + # routes_list: tuple([ + # object({ + # gateway_ip: string, + # network: string, + # }), + # ]), + # }) + # if no routes_map is provided, a default value of [{}] is given (just empty), to comply with type requirements in further processing + lan_service = flatten([ for id in ionoscloud_lan.service_lan.*.id: { id = id, routes_list = [{}] }]) + lan_backend = flatten([ for id in ionoscloud_lan.backend_lan.*.id: { id = id, routes_list = lookup(local.routes_map, id , [{}]) }]) + lan_frontend = flatten([ for id in ionoscloud_lan.frontend_lan.*.id: { id = id, routes_list = lookup(local.routes_map, id , [{}]) }]) + lan_nfs_server = flatten([ for id in ionoscloud_lan.nfs_server_lan.*.id: { id = id, routes_list = [{}] }]) + lan_postgres = flatten([ for id in ionoscloud_lan.postgres_lan.*.id: { id = id, routes_list = [{}] }]) + lan_mariadb = flatten([ for id in ionoscloud_lan.mariadb_lan.*.id: { id = id, routes_list = [{}] }]) + lan_alb_target = flatten([ for id in ionoscloud_lan.alb_target_lan.*.id: { id = id, routes_list =[{}] }]) + lan_nlb_target = flatten([ for id in ionoscloud_lan.nlb_target_lan.*.id: { id = id, routes_list =[{}] }]) + lan_nat = flatten([ for id in ionoscloud_lan.nat_lan.*.id: { id = id, routes_list = [{}] }]) + lans_custom = { for name, lan in ionoscloud_lan.custom_lan: name => { id = lan.id, routes_list = [{}] }} +} diff --git a/modules/ionos-datacenter/main.tf b/modules/ionos-datacenter/main.tf new file mode 100644 index 0000000..8d78f00 --- /dev/null +++ b/modules/ionos-datacenter/main.tf @@ -0,0 +1,134 @@ +resource "ionoscloud_datacenter" "datacenter" { + name = var.datacenter_name + location = var.datacenter_location + description = "" +} + +resource "ionoscloud_share" "datacenter_permissions" { + for_each = { for share in var.datacenter_shares : share.group => share} + group_id = each.key + resource_id = ionoscloud_datacenter.datacenter.id + edit_privilege = each.value.edit + share_privilege = each.value.share +} + +resource "ionoscloud_private_crossconnect" "frontend_cc" { + count = local.create_frontend_crossconnect ? 1 : 0 + name = "${var.datacenter_name}-frontend-lan-cc" +} + +resource "ionoscloud_share" "frontend_cc" { + for_each = toset(local.frontend_crossconnect_shared_group_ids) + group_id = each.key + resource_id = ionoscloud_private_crossconnect.frontend_cc[0].id + edit_privilege = false + share_privilege = false +} + +resource "ionoscloud_private_crossconnect" "service_cc" { + count = local.create_service_crossconnect ? 1 : 0 + name = "${var.datacenter_name}-service-lan-cc" +} + +# Share is not removed when Terraform resource is destroyed! I.e. a share created by Terraform can only be removed manually. +resource "ionoscloud_share" "service_cc" { + for_each = toset(local.service_crossconnect_shared_group_ids) + group_id = each.key + resource_id = ionoscloud_private_crossconnect.service_cc[0].id + edit_privilege = false + share_privilege = false +} + +resource "ionoscloud_private_crossconnect" "backend_cc" { + count = local.create_backend_crossconnect ? 1 : 0 + name = "${var.datacenter_name}-backend-lan-cc" +} + +resource "ionoscloud_share" "backend_cc" { + for_each = toset(local.backend_crossconnect_shared_group_ids) + group_id = each.key + resource_id = ionoscloud_private_crossconnect.backend_cc[0].id + edit_privilege = false + share_privilege = false +} + +resource "ionoscloud_lan" "frontend_lan" { + count = local.create_frontend_lan ? 1 : 0 + name = "${var.datacenter_name}-frontend-lan" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = false + pcc = var.associated_frontend_crossconnect_id != "" ? var.associated_frontend_crossconnect_id : ionoscloud_private_crossconnect.frontend_cc[0].id +} + +resource "ionoscloud_lan" "service_lan" { + count = local.create_service_lan ? 1 : 0 + name = "${var.datacenter_name}-service-lan" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = false + pcc = var.associated_service_crossconnect_id != "" ? var.associated_service_crossconnect_id : ionoscloud_private_crossconnect.service_cc[0].id +} + +resource "ionoscloud_lan" "backend_lan" { + count = local.create_backend_lan ? 1 : 0 + name = "${var.datacenter_name}-backend-lan" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = false + pcc = var.associated_backend_crossconnect_id != "" ? var.associated_backend_crossconnect_id : ionoscloud_private_crossconnect.backend_cc[0].id + +} + +resource "ionoscloud_lan" "public_lan" { + count = local.create_public_lan ? 1 : 0 + name = "${var.datacenter_name}-public-lan" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = true +} + +resource "ionoscloud_lan" "nfs_server_lan" { + count = local.create_nfs_server_lan ? 1 : 0 + name = "${var.datacenter_name}-nfs-lan" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = false +} + +resource "ionoscloud_lan" "postgres_lan" { + count = local.create_postgres_lan ? 1 : 0 + name = "${var.datacenter_name}-postgres-lan" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = false +} + +resource "ionoscloud_lan" "mariadb_lan" { + count = local.create_mariadb_lan ? 1 : 0 + name = "${var.datacenter_name}-mariadb-lan" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = false +} + +resource "ionoscloud_lan" "alb_target_lan" { + count = local.create_alb_target_lan ? 1 : 0 + name = "${var.datacenter_name}-alb-target-lan" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = false +} + +resource "ionoscloud_lan" "nlb_target_lan" { + count = local.create_nlb_target_lan ? 1 : 0 + name = "${var.datacenter_name}-nlb-target-lan" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = false +} + +resource "ionoscloud_lan" "nat_lan" { + count = local.create_nat_lan ? 1 : 0 + name = "${var.datacenter_name}-nat-lan" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = false +} + +resource "ionoscloud_lan" "custom_lan" { + for_each = local.custom_lans_to_create + name = "${var.datacenter_name}-${each.value}" + datacenter_id = ionoscloud_datacenter.datacenter.id + public = false +} \ No newline at end of file diff --git a/modules/ionos-datacenter/output.tf b/modules/ionos-datacenter/output.tf new file mode 100644 index 0000000..e416230 --- /dev/null +++ b/modules/ionos-datacenter/output.tf @@ -0,0 +1,96 @@ + +output "datacenter_id" { + value = ionoscloud_datacenter.datacenter.id +} + +output "datacenter_name" { + value = ionoscloud_datacenter.datacenter.name +} + +output "datacenter_location" { + value = ionoscloud_datacenter.datacenter.location +} + +output "frontend_crossconnect_id" { + value = join("", ionoscloud_private_crossconnect.frontend_cc.*.id) +} + +output "frontend_lan_id" { + value = join("", ionoscloud_lan.frontend_lan.*.id) +} + +output "lan_frontend" { + value = local.lan_frontend +} + +output "backend_crossconnect_id" { + value = join("", ionoscloud_private_crossconnect.backend_cc.*.id) +} + +output "lan_backend" { + value = local.lan_backend +} + +output "service_crossconnect_id" { + value = join("", ionoscloud_private_crossconnect.service_cc.*.id) +} + +output "lan_service" { + value = local.lan_service +} + +output "nfs_server_lan_id" { + value = join("", ionoscloud_lan.nfs_server_lan.*.id) +} + +output "lan_nfs_server" { + value = local.lan_nfs_server +} + +output "postgres_lan_id" { + value = join("", ionoscloud_lan.postgres_lan.*.id) +} + +output "lan_postgres" { + value = local.lan_postgres +} + +output "mariadb_lan_id" { + value = join("", ionoscloud_lan.mariadb_lan.*.id) +} + +output "lan_mariadb" { + value = local.lan_mariadb +} + +output "alb_target_lan_id" { + value = join("", ionoscloud_lan.alb_target_lan.*.id) +} + +output "lan_alb_target" { + value = local.lan_alb_target +} + +output "nlb_target_lan_id" { + value = join("", ionoscloud_lan.nlb_target_lan.*.id) +} + +output "lan_nlb_target" { + value = local.lan_nlb_target +} + +output "nat_lan_id" { + value = join("", ionoscloud_lan.nat_lan.*.id) +} + +output "lan_nat" { + value = local.lan_nat +} + +output "custom_lans_id" { + value = { for name, lan in ionoscloud_lan.custom_lan: name => lan.id } +} + +output "lans_custom" { + value = local.lans_custom +} \ No newline at end of file diff --git a/modules/ionos-datacenter/variables.tf b/modules/ionos-datacenter/variables.tf new file mode 100644 index 0000000..095e03c --- /dev/null +++ b/modules/ionos-datacenter/variables.tf @@ -0,0 +1,115 @@ +variable "datacenter_name" { + type = string + description = "" +} + +variable "datacenter_location" { + type = string + description = "" + default = "de/txl" +} + +variable "datacenter_shares" { + type = list(object({ + group = string + edit = optional(bool, false) + share = optional(bool, false) + })) + description = "Which groups have access to the datacenter" + default = [] +} + +variable "create_frontend_crossconnect" { + type = bool + description = "Specifies whether crossconnect shall be created. Default: false." + default = false +} + +variable "associated_frontend_crossconnect_id" { + type = string + description = "Specifies whether an existing crossconnect shall be associated." + default = "" +} + +variable "create_backend_crossconnect" { + type = bool + description = "Specifies whether crossconnect shall be created. Default: false." + default = false +} + +variable "associated_backend_crossconnect_id" { + type = string + description = "Specifies whether an existing crossconnect shall be associated." + default = "" +} + +variable "create_service_crossconnect" { + type = bool + description = "Specifies whether crossconnect shall be created. Default: false." + default = false +} + +variable "associated_service_crossconnect_id" { + type = string + description = "Specifies whether an existing crossconnect shall be associated." + default = "" +} + +variable "create_public_lan" { + type = bool + description = "Specifies whether a public lan shall be created. Default: false." + default = false +} + +variable "crossconnect_shared_group_ids" { + type = list(string) + description = "Specifies which groups crossconnect shall be shared with. Default: []." + default = [] +} + +variable "routes_map" { + type = any + description = "map which links based on the lan id to a list in which the routes in form of an object ('network'='###' and 'gateway_ip'='###') are saved" + default = {} +} + +variable "create_nfs_server_lan" { + type = bool + description = "Specifies whether a private lan to connect an NFS server shall be created." + default = false +} + +variable "create_postgres_lan" { + description = "Specifies whether a private lan to connect Postgres shall be created." + type = bool + default = false +} +variable "create_mariadb_lan" { + description = "Specifies whether a private lan to connect Mariadb shall be created." + type = bool + default = false +} + +variable "create_alb_target_lan" { + type = bool + description = "Specifies whether a private target for the Application Load Balancer shall be created." + default = false +} + +variable "create_nlb_target_lan" { + type = bool + description = "Specifies whether a private target for the Network Load Balancer shall be created." + default = false +} + +variable "create_nat_lan" { + type = bool + description = "Specifies whether a private lan to connect a NAT gateway shall be created." + default = false +} + +variable "custom_lans_to_create" { + description = "Map of for private LANs to be created. The key is used for the output. The value is used for the name: -" + type = map(string) + default = {} +} diff --git a/modules/ionos-datacenter/versions.tf b/modules/ionos-datacenter/versions.tf new file mode 100644 index 0000000..d0372ea --- /dev/null +++ b/modules/ionos-datacenter/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + ionoscloud = { + source = "ionos-cloud/ionoscloud" + version = "6.3.6" + } + } + required_version = ">= 0.13" +}