From 6a8fdfa1c286a3854f5625cb04a65f85a0d767d0 Mon Sep 17 00:00:00 2001 From: Steve Brasier Date: Tue, 8 Apr 2025 14:23:14 +0000 Subject: [PATCH 1/4] add cluster_nodename_template and compute/login.nodename_template --- .../{{cookiecutter.environment}}/tofu/compute.tf | 3 ++- .../{{cookiecutter.environment}}/tofu/control.tf | 4 ++-- .../{{cookiecutter.environment}}/tofu/login.tf | 1 + .../{{cookiecutter.environment}}/tofu/main.tf | 2 +- .../tofu/node_group/nodes.tf | 8 ++++---- .../tofu/node_group/variables.tf | 5 +++++ .../tofu/variables.tf | 16 ++++++++++++++++ 7 files changed, 31 insertions(+), 8 deletions(-) diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/compute.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/compute.tf index 7ab27d84f..22e8c7247 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/compute.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/compute.tf @@ -19,7 +19,8 @@ module "compute" { volume_backed_instances = lookup(each.value, "volume_backed_instances", var.volume_backed_instances) root_volume_size = lookup(each.value, "root_volume_size", var.root_volume_size) gateway_ip = lookup(each.value, "gateway_ip", var.gateway_ip) - + nodename_template = lookup(each.value, "nodename_template", var.cluster_nodename_template) + # optionally set for group: networks = concat(var.cluster_networks, lookup(each.value, "extra_networks", [])) extra_volumes = lookup(each.value, "extra_volumes", {}) diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf index b4308f93d..7267e7271 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf @@ -24,7 +24,7 @@ resource "openstack_networking_port_v2" "control" { resource "openstack_compute_instance_v2" "control" { - name = "${var.cluster_name}-control" + name = split(".", templatestring(var.cluster_nodename_template, {node="control", cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix}))[0] image_id = var.cluster_image_id flavor_name = var.control_node_flavor key_pair = var.key_pair @@ -65,7 +65,7 @@ resource "openstack_compute_instance_v2" "control" { user_data = <<-EOF #cloud-config - fqdn: ${var.cluster_name}-control.${var.cluster_name}.${var.cluster_domain_suffix} + fqdn: ${templatestring(var.cluster_nodename_template, {node="control", cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix})} bootcmd: %{for volume in local.control_volumes} diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/login.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/login.tf index c4a2c74b3..59035ba80 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/login.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/login.tf @@ -19,6 +19,7 @@ module "login" { volume_backed_instances = lookup(each.value, "volume_backed_instances", var.volume_backed_instances) root_volume_size = lookup(each.value, "root_volume_size", var.root_volume_size) gateway_ip = lookup(each.value, "gateway_ip", var.gateway_ip) + nodename_template = lookup(each.value, "nodename_template", var.cluster_nodename_template) # optionally set for group networks = concat(var.cluster_networks, lookup(each.value, "extra_networks", [])) diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/main.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/main.tf index f29828499..dc639f7ec 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/main.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/main.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 0.14" + required_version = ">= 1.7" # templatestring() function required_providers { openstack = { source = "terraform-provider-openstack/openstack" diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf index f08ec1ca3..622b45b02 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf @@ -57,7 +57,7 @@ resource "openstack_compute_instance_v2" "compute_fixed_image" { for_each = var.ignore_image_changes ? toset(var.nodes) : [] - name = "${var.cluster_name}-${each.key}" + name = split(".", templatestring(var.nodename_template, {node=each.key, cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix}))[0] image_id = var.image_id flavor_name = var.flavor key_pair = var.key_pair @@ -94,7 +94,7 @@ resource "openstack_compute_instance_v2" "compute_fixed_image" { user_data = <<-EOF #cloud-config - fqdn: ${var.cluster_name}-${each.key}.${var.cluster_name}.${var.cluster_domain_suffix} + fqdn: ${templatestring(var.nodename_template, {node=each.key, cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix})} EOF availability_zone = var.match_ironic_node ? "${var.availability_zone}::${var.baremetal_nodes[each.key]}" : null @@ -111,7 +111,7 @@ resource "openstack_compute_instance_v2" "compute" { for_each = var.ignore_image_changes ? [] : toset(var.nodes) - name = "${var.cluster_name}-${each.key}" + name = split(".", templatestring(var.nodename_template, {node=each.key, cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix}))[0] image_id = var.image_id flavor_name = var.flavor key_pair = var.key_pair @@ -148,7 +148,7 @@ resource "openstack_compute_instance_v2" "compute" { user_data = <<-EOF #cloud-config - fqdn: ${var.cluster_name}-${each.key}.${var.cluster_name}.${var.cluster_domain_suffix} + fqdn: ${templatestring(var.nodename_template, {node=each.key, cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix})} EOF availability_zone = var.match_ironic_node ? "${var.availability_zone}::${var.baremetal_nodes[each.key]}" : null diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/variables.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/variables.tf index 896a28a48..212af343a 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/variables.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/variables.tf @@ -127,3 +127,8 @@ variable "gateway_ip" { type = string default = "" } + +variable "nodename_template" { + type = string + default = "" +} diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/variables.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/variables.tf index 0f1bb33b0..cb600ca9a 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/variables.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/variables.tf @@ -61,6 +61,7 @@ variable "login" { match_ironic_node: Set true to launch instances on the Ironic node of the same name as each cluster node availability_zone: Name of availability zone - ignored unless match_ironic_node is true (default: "nova") gateway_ip: Address to add default route via + nodename_template: Overrides variable cluster_nodename_template EOF } @@ -97,6 +98,7 @@ variable "compute" { match_ironic_node: Set true to launch instances on the Ironic node of the same name as each cluster node availability_zone: Name of availability zone - ignored unless match_ironic_node is true (default: "nova") gateway_ip: Address to add default route via + nodename_template: Overrides variable cluster_nodename_template EOF } @@ -179,3 +181,17 @@ variable "gateway_ip" { type = string default = "" } + +variable "cluster_nodename_template" { + description = <<-EOT + Template for node fully-qualified names. The following interpolations + can be used: + $${cluster_name}: From var.cluster_name + $${cluster_domain_suffix}: From var.cluster_domain_suffix + $${node}: The current entry in the "nodes" parameter for nodes + defined by var.compute and var.login, or "control" for the control + node. + EOT + type = string + default = "$${cluster_name}-$${node}.$${cluster_name}.$${cluster_domain_suffix}" +} From 404ea659794d8036b85ab5ff378efa344b1663da Mon Sep 17 00:00:00 2001 From: Steve Brasier Date: Tue, 6 May 2025 12:06:26 +0000 Subject: [PATCH 2/4] refactor nodename templating for DRY --- .../tofu/control.tf | 12 +++++++++-- .../tofu/node_group/nodes.tf | 20 +++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf index 7267e7271..b42007e9a 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf @@ -1,5 +1,13 @@ locals { control_volumes = concat([openstack_blockstorage_volume_v3.state], var.home_volume_size > 0 ? [openstack_blockstorage_volume_v3.home][0] : []) + nodename = templatestring( + var.cluster_nodename_template, + { + node="control", + cluster_name=var.cluster_name, + cluster_domain_suffix=var.cluster_domain_suffix + } + ) } resource "openstack_networking_port_v2" "control" { @@ -24,7 +32,7 @@ resource "openstack_networking_port_v2" "control" { resource "openstack_compute_instance_v2" "control" { - name = split(".", templatestring(var.cluster_nodename_template, {node="control", cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix}))[0] + name = split(".", local.nodename)[0] image_id = var.cluster_image_id flavor_name = var.control_node_flavor key_pair = var.key_pair @@ -65,7 +73,7 @@ resource "openstack_compute_instance_v2" "control" { user_data = <<-EOF #cloud-config - fqdn: ${templatestring(var.cluster_nodename_template, {node="control", cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix})} + fqdn: ${local.nodename} bootcmd: %{for volume in local.control_volumes} diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf index 622b45b02..437355e70 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf @@ -12,6 +12,18 @@ locals { # Workaround for lifecycle meta-argument only taking static values compute_instances = var.ignore_image_changes ? openstack_compute_instance_v2.compute_fixed_image : openstack_compute_instance_v2.compute + + # Define nodenames here to avoid repetition + nodenames = { + for n in var.nodes: n => templatestring( + var.nodename_template, + { + node=n, + cluster_name=var.cluster_name, + cluster_domain_suffix=var.cluster_domain_suffix + } + ) + } } resource "openstack_blockstorage_volume_v3" "compute" { @@ -57,7 +69,7 @@ resource "openstack_compute_instance_v2" "compute_fixed_image" { for_each = var.ignore_image_changes ? toset(var.nodes) : [] - name = split(".", templatestring(var.nodename_template, {node=each.key, cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix}))[0] + name = split(".", local.nodenames[each.key])[0] image_id = var.image_id flavor_name = var.flavor key_pair = var.key_pair @@ -94,7 +106,7 @@ resource "openstack_compute_instance_v2" "compute_fixed_image" { user_data = <<-EOF #cloud-config - fqdn: ${templatestring(var.nodename_template, {node=each.key, cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix})} + fqdn: ${local.nodenames[each.key]} EOF availability_zone = var.match_ironic_node ? "${var.availability_zone}::${var.baremetal_nodes[each.key]}" : null @@ -111,7 +123,7 @@ resource "openstack_compute_instance_v2" "compute" { for_each = var.ignore_image_changes ? [] : toset(var.nodes) - name = split(".", templatestring(var.nodename_template, {node=each.key, cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix}))[0] + name = split(".", local.nodenames[each.key])[0] image_id = var.image_id flavor_name = var.flavor key_pair = var.key_pair @@ -148,7 +160,7 @@ resource "openstack_compute_instance_v2" "compute" { user_data = <<-EOF #cloud-config - fqdn: ${templatestring(var.nodename_template, {node=each.key, cluster_name=var.cluster_name,cluster_domain_suffix=var.cluster_domain_suffix})} + fqdn: ${local.nodenames[each.key]} EOF availability_zone = var.match_ironic_node ? "${var.availability_zone}::${var.baremetal_nodes[each.key]}" : null From ad86692169b86a34b3e0dc81a766b3e004f3fa6c Mon Sep 17 00:00:00 2001 From: Steve Brasier Date: Tue, 6 May 2025 13:24:33 +0000 Subject: [PATCH 3/4] add environment_name to nodename template --- .../skeleton/{{cookiecutter.environment}}/tofu/control.tf | 7 ++++--- .../{{cookiecutter.environment}}/tofu/node_group/nodes.tf | 7 ++++--- .../{{cookiecutter.environment}}/tofu/variables.tf | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf index b42007e9a..844e4dff7 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/control.tf @@ -3,9 +3,10 @@ locals { nodename = templatestring( var.cluster_nodename_template, { - node="control", - cluster_name=var.cluster_name, - cluster_domain_suffix=var.cluster_domain_suffix + node = "control", + cluster_name = var.cluster_name, + cluster_domain_suffix = var.cluster_domain_suffix, + environment_name = basename(var.environment_root) } ) } diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf index 437355e70..8c9716e58 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/node_group/nodes.tf @@ -18,9 +18,10 @@ locals { for n in var.nodes: n => templatestring( var.nodename_template, { - node=n, - cluster_name=var.cluster_name, - cluster_domain_suffix=var.cluster_domain_suffix + node = n, + cluster_name = var.cluster_name, + cluster_domain_suffix = var.cluster_domain_suffix, + environment_name = basename(var.environment_root) } ) } diff --git a/environments/skeleton/{{cookiecutter.environment}}/tofu/variables.tf b/environments/skeleton/{{cookiecutter.environment}}/tofu/variables.tf index cb600ca9a..52cc3a605 100644 --- a/environments/skeleton/{{cookiecutter.environment}}/tofu/variables.tf +++ b/environments/skeleton/{{cookiecutter.environment}}/tofu/variables.tf @@ -190,7 +190,8 @@ variable "cluster_nodename_template" { $${cluster_domain_suffix}: From var.cluster_domain_suffix $${node}: The current entry in the "nodes" parameter for nodes defined by var.compute and var.login, or "control" for the control - node. + node + $${environment_name}: The last element of the current environment's path EOT type = string default = "$${cluster_name}-$${node}.$${cluster_name}.$${cluster_domain_suffix}" From c42349ea3fd75dd022296cfa5335099e1b62c969 Mon Sep 17 00:00:00 2001 From: Steve Brasier Date: Wed, 7 May 2025 09:16:08 +0000 Subject: [PATCH 4/4] bump opentofu version in CI --- .github/workflows/stackhpc.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stackhpc.yml b/.github/workflows/stackhpc.yml index 9d8de76d7..0d8846501 100644 --- a/.github/workflows/stackhpc.yml +++ b/.github/workflows/stackhpc.yml @@ -91,9 +91,9 @@ jobs: run: dev/setup-env.sh - name: Install OpenTofu - uses: opentofu/setup-opentofu@v1 + uses: opentofu/setup-opentofu@v1.0.5 with: - tofu_version: 1.6.2 + tofu_version: 1.9.0 - name: Initialise tofu run: tofu init