Skip to content

Commit

Permalink
DBP-817-ionos-basic-vm and ionos-datacenter
Browse files Browse the repository at this point in the history
  • Loading branch information
sahassou committed May 31, 2024
1 parent 14ffa7c commit f187c9b
Show file tree
Hide file tree
Showing 17 changed files with 937 additions and 0 deletions.
76 changes: 76 additions & 0 deletions modules/ionos-basic-vm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<!-- BEGIN_TF_DOCS -->

## Providers

| Name | Version |
|------|---------|
| <a name="provider_ionoscloud"></a> [ionoscloud](#provider\_ionoscloud) | 6.3.6 |
| <a name="provider_opentelekomcloud"></a> [opentelekomcloud](#provider\_opentelekomcloud) | n/a |
## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_conventions_coordinates"></a> [conventions\_coordinates](#module\_conventions\_coordinates) | ../conventions-coordinates | n/a |
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_basic_vm_server_cpu"></a> [basic\_vm\_server\_cpu](#input\_basic\_vm\_server\_cpu) | cpu of the basic vm servers | `number` | n/a | yes |
| <a name="input_basic_vm_server_memory"></a> [basic\_vm\_server\_memory](#input\_basic\_vm\_server\_memory) | memory of the basic vm servers | `number` | n/a | yes |
| <a name="input_basic_vm_volume_size"></a> [basic\_vm\_volume\_size](#input\_basic\_vm\_volume\_size) | volume size for vm | `number` | n/a | yes |
| <a name="input_coordinates"></a> [coordinates](#input\_coordinates) | n/a | `map(any)` | n/a | yes |
| <a name="input_cpu_family"></a> [cpu\_family](#input\_cpu\_family) | n/a | `string` | n/a | yes |
| <a name="input_datacenter"></a> [datacenter](#input\_datacenter) | n/a | `string` | n/a | yes |
| <a name="input_datacenter_location"></a> [datacenter\_location](#input\_datacenter\_location) | n/a | `string` | n/a | yes |
| <a name="input_domain_without_top_level"></a> [domain\_without\_top\_level](#input\_domain\_without\_top\_level) | domain without top level | `string` | n/a | yes |
| <a name="input_fulldomainname"></a> [fulldomainname](#input\_fulldomainname) | Domain under which the basic vm server will be available | `string` | n/a | yes |
| <a name="input_image"></a> [image](#input\_image) | image of the vm | `string` | n/a | yes |
| <a name="input_server_name"></a> [server\_name](#input\_server\_name) | name of the vm | `string` | n/a | yes |
| <a name="input_top_level_domain"></a> [top\_level\_domain](#input\_top\_level\_domain) | Top-level domain mapping for environments | `map(any)` | n/a | yes |
| <a name="input_additional_ips"></a> [additional\_ips](#input\_additional\_ips) | Additional IPs for the VM (optional) | `list(string)` | `[]` | no |
| <a name="input_availability_zone"></a> [availability\_zone](#input\_availability\_zone) | Possible Zones: AUTO, ZONE\_1, ZONE\_2 | `string` | `"AUTO"` | no |
| <a name="input_basic_vm_create_second_volume"></a> [basic\_vm\_create\_second\_volume](#input\_basic\_vm\_create\_second\_volume) | n/a | `bool` | `true` | no |
| <a name="input_basic_vm_second_volume_disk_type"></a> [basic\_vm\_second\_volume\_disk\_type](#input\_basic\_vm\_second\_volume\_disk\_type) | n/a | `string` | `"HDD"` | no |
| <a name="input_basic_vm_second_volume_size"></a> [basic\_vm\_second\_volume\_size](#input\_basic\_vm\_second\_volume\_size) | size of the second volume | `string` | `100` | no |
| <a name="input_create_ip_pool"></a> [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 |
| <a name="input_create_lan"></a> [create\_lan](#input\_create\_lan) | If true a LAN will be created, if false a LAN ID must be provided | `bool` | `true` | no |
| <a name="input_dns_zone_name_override"></a> [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 |
| <a name="input_initial_public_key"></a> [initial\_public\_key](#input\_initial\_public\_key) | The public key of the initial user created via the cloud init script. | `string` | `""` | no |
| <a name="input_initial_uid"></a> [initial\_uid](#input\_initial\_uid) | The uid of the initial user created via the cloud init script. | `string` | `""` | no |
| <a name="input_initial_user"></a> [initial\_user](#input\_initial\_user) | The initial user to be created via the cloud init script. | `string` | `""` | no |
| <a name="input_ip_pool_name"></a> [ip\_pool\_name](#input\_ip\_pool\_name) | Name of the ip pools | `string` | `""` | no |
| <a name="input_lan_id"></a> [lan\_id](#input\_lan\_id) | Id of the LAN to use (only necessary if create\_lan is false) | `number` | `null` | no |
| <a name="input_permanent_vm"></a> [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 |
| <a name="input_port_ranges"></a> [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 |
| <a name="input_ports"></a> [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 |
| <a name="input_public_ip"></a> [public\_ip](#input\_public\_ip) | n/a | `string` | `""` | no |
| <a name="input_user_data_script"></a> [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 |
|------|-------------|
| <a name="output_basic_vm_server_dns"></a> [basic\_vm\_server\_dns](#output\_basic\_vm\_server\_dns) | n/a |
| <a name="output_basic_vm_server_id"></a> [basic\_vm\_server\_id](#output\_basic\_vm\_server\_id) | n/a |
| <a name="output_basic_vm_server_nicuuid"></a> [basic\_vm\_server\_nicuuid](#output\_basic\_vm\_server\_nicuuid) | n/a |
| <a name="output_basic_vm_server_public_ip"></a> [basic\_vm\_server\_public\_ip](#output\_basic\_vm\_server\_public\_ip) | n/a |
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13 |
| <a name="requirement_ionoscloud"></a> [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 |
<!-- END_TF_DOCS -->
7 changes: 7 additions & 0 deletions modules/ionos-basic-vm/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
data "opentelekomcloud_dns_zone_v2" "dns_zone" {
name = local.dns_zone_name
}

data "ionoscloud_datacenter" "datacenter" {
id = var.datacenter
}
13 changes: 13 additions & 0 deletions modules/ionos-basic-vm/locals.tf
Original file line number Diff line number Diff line change
@@ -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))
}
73 changes: 73 additions & 0 deletions modules/ionos-basic-vm/main.tf
Original file line number Diff line number Diff line change
@@ -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
}
}
15 changes: 15 additions & 0 deletions modules/ionos-basic-vm/outputs.tf
Original file line number Diff line number Diff line change
@@ -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
}
74 changes: 74 additions & 0 deletions modules/ionos-basic-vm/server.tf
Original file line number Diff line number Diff line change
@@ -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
]
}
}
12 changes: 12 additions & 0 deletions modules/ionos-basic-vm/user-data-cloud-init.tpl
Original file line number Diff line number Diff line change
@@ -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}
4 changes: 4 additions & 0 deletions modules/ionos-basic-vm/user-data-lvm.sh
Original file line number Diff line number Diff line change
@@ -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)
3 changes: 3 additions & 0 deletions modules/ionos-basic-vm/user-data.sh
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit f187c9b

Please sign in to comment.