sync-modules: mirrored modules of release 3.3.0-F-feature-simpl-33565.773.825d7dcb

+++ hpc/README.md
+++ hpc/ovh/credentials.tf
+++ hpc/ovh/main.tf
+++ hpc/ovh/versions.tf
This commit is contained in:
gitops_test 2026-10-08 16:15:41 +00:00
parent 53339e50a8
commit 09cc7b38e0
4 changed files with 36 additions and 14 deletions

View File

@ -16,7 +16,7 @@ Provisions an HPC cluster and generates the consumer access credentials. One sub
| `credentials_version` | Opaque rotation marker for the consumer credential, defaults to `1`. Changing the value regenerates the consumer password, applies it on the head node over SSH and republishes the fresh credential to Vault in the same apply, without touching any instance. Managed by the credential renewal workflow, not by the deployment script author | | `credentials_version` | Opaque rotation marker for the consumer credential, defaults to `1`. Changing the value regenerates the consumer password, applies it on the head node over SSH and republishes the fresh credential to Vault in the same apply, without touching any instance. Managed by the credential renewal workflow, not by the deployment script author |
| `name_prefix` | Prefix for resource names, defaults to `simpl` | | `name_prefix` | Prefix for resource names, defaults to `simpl` |
| `region` | OVH region for the instances and the private network, for example SBG5 | | `region` | OVH region for the instances and the private network, for example SBG5 |
| `project_id` | Optional override of the OVH project; by default the provider resolves it from the `OVH_CLOUD_PROJECT_SERVICE` variable of the runner environment, which the provisioner derives from the `OVH_PROJECT_ID` key of the cloud account configuration | | `project_id` | OVH project id. Unlike the other catalog modules this one effectively needs it: its flavors/images/floatingips data sources require an explicit service_name (no `OVH_CLOUD_PROJECT_SERVICE` fallback for an explicit null). When omitted, the module falls back to resolving the project from the credential (`ovh_cloud_projects`), which only works if the account API key is granted `GET /cloud/project`; the current platform account keys are not, so either pass the value in the deployment script or add that read grant when creating account keys |
| `compute_node_count` | Number of compute nodes, defaults to 2 | | `compute_node_count` | Number of compute nodes, defaults to 2 |
| `head_flavor`, `compute_flavor` | Instance flavors per role, default `b3-8` | | `head_flavor`, `compute_flavor` | Instance flavors per role, default `b3-8` |
| `compute_cpus` | Schedulable CPUs per compute node declared to the Slurm controller, must not exceed the vCPUs of `compute_flavor`, defaults to 2 | | `compute_cpus` | Schedulable CPUs per compute node declared to the Slurm controller, must not exceed the vCPUs of `compute_flavor`, defaults to 2 |

View File

@ -31,11 +31,16 @@ resource "random_password" "consumer" {
// never touches the instances: this resource is replaced (triggered by the // never touches the instances: this resource is replaced (triggered by the
// rotation marker), re-runs chpasswd over SSH with the management key, and // rotation marker), re-runs chpasswd over SSH with the management key, and
// the Vault entry below is updated in the same apply. // the Vault entry below is updated in the same apply.
resource "terraform_data" "consumer_password" { // null_resource instead of terraform_data: the tofu-controller runner ships a
// Terraform older than 1.4, which has no terraform_data built-in.
resource "null_resource" "consumer_password" {
// Re-applied on rotation AND whenever the head node is recreated: a fresh // Re-applied on rotation AND whenever the head node is recreated: a fresh
// instance boots without the consumer password (it never travels through // instance boots without the consumer password (it never travels through
// user data). // user data).
triggers_replace = [var.credentials_version, ovh_cloud_project_instance.head.id] triggers = {
rotation = var.credentials_version
head_node = ovh_cloud_project_instance.head.id
}
connection { connection {
type = "ssh" type = "ssh"
@ -65,7 +70,7 @@ resource "vault_kv_secret_v2" "consumer" {
port = 22 port = 22
}) })
depends_on = [terraform_data.consumer_password] depends_on = [null_resource.consumer_password]
} }
resource "vault_kv_secret_v2" "admin" { resource "vault_kv_secret_v2" "admin" {

View File

@ -4,20 +4,33 @@
// credentials and the project (OVH_CLOUD_PROJECT_SERVICE) reach the provider // credentials and the project (OVH_CLOUD_PROJECT_SERVICE) reach the provider
// from the runner environment, never from module inputs. // from the runner environment, never from module inputs.
// The flavors/images data sources require an explicit service_name (unlike
// the resources, they do not fall back to the OVH_CLOUD_PROJECT_SERVICE
// runner variable when the attribute is an explicit null), so the project is
// resolved from the credential itself when no override is given: the
// per-account API keys of the platform are scoped to a single project.
data "ovh_cloud_projects" "all" {
count = var.project_id == null ? 1 : 0
}
locals {
service_name = var.project_id != null ? var.project_id : one(data.ovh_cloud_projects.all[0].projects[*].project_id)
}
data "ovh_cloud_project_flavors" "head" { data "ovh_cloud_project_flavors" "head" {
service_name = var.project_id service_name = local.service_name
name_filter = var.head_flavor name_filter = var.head_flavor
region = var.region region = var.region
} }
data "ovh_cloud_project_flavors" "compute" { data "ovh_cloud_project_flavors" "compute" {
service_name = var.project_id service_name = local.service_name
name_filter = var.compute_flavor name_filter = var.compute_flavor
region = var.region region = var.region
} }
data "ovh_cloud_project_images" "all" { data "ovh_cloud_project_images" "all" {
service_name = var.project_id service_name = local.service_name
region = var.region region = var.region
} }
@ -37,14 +50,14 @@ locals {
// assigned outside the DHCP pool; DHCP stays enabled so the instances // assigned outside the DHCP pool; DHCP stays enabled so the instances
// configure their private interface from the OpenStack metadata. // configure their private interface from the OpenStack metadata.
resource "ovh_cloud_project_network_private" "cluster" { resource "ovh_cloud_project_network_private" "cluster" {
service_name = var.project_id service_name = local.service_name
name = "${var.name_prefix}-hpc-${var.deployment_id}" name = "${var.name_prefix}-hpc-${var.deployment_id}"
regions = [var.region] regions = [var.region]
vlan_id = var.vlan_id vlan_id = var.vlan_id
} }
resource "ovh_cloud_project_network_private_subnet" "cluster" { resource "ovh_cloud_project_network_private_subnet" "cluster" {
service_name = var.project_id service_name = local.service_name
network_id = ovh_cloud_project_network_private.cluster.id network_id = ovh_cloud_project_network_private.cluster.id
region = var.region region = var.region
network = var.cluster_cidr network = var.cluster_cidr
@ -69,7 +82,7 @@ locals {
// through a dual-homed head node is not an option: the cloud's port // through a dual-homed head node is not an option: the cloud's port
// anti-spoofing silently drops the forwarded return traffic. // anti-spoofing silently drops the forwarded return traffic.
resource "ovh_cloud_project_gateway" "egress" { resource "ovh_cloud_project_gateway" "egress" {
service_name = var.project_id service_name = local.service_name
name = "${var.name_prefix}-hpc-gw-${var.deployment_id}" name = "${var.name_prefix}-hpc-gw-${var.deployment_id}"
model = var.gateway_model model = var.gateway_model
region = var.region region = var.region
@ -81,13 +94,13 @@ resource "ovh_cloud_project_gateway" "egress" {
// on destroy. The instance level ssh_key_create is avoided on purpose: keys it // on destroy. The instance level ssh_key_create is avoided on purpose: keys it
// creates outlive the instance and collide on the next deployment. // creates outlive the instance and collide on the next deployment.
resource "ovh_cloud_project_ssh_key" "admin" { resource "ovh_cloud_project_ssh_key" "admin" {
service_name = var.project_id service_name = local.service_name
name = "${var.name_prefix}-${var.deployment_id}-key" name = "${var.name_prefix}-${var.deployment_id}-key"
public_key = trimspace(tls_private_key.admin.public_key_openssh) public_key = trimspace(tls_private_key.admin.public_key_openssh)
} }
resource "ovh_cloud_project_instance" "head" { resource "ovh_cloud_project_instance" "head" {
service_name = var.project_id service_name = local.service_name
region = var.region region = var.region
billing_period = "hourly" billing_period = "hourly"
name = local.head_hostname name = local.head_hostname
@ -133,7 +146,7 @@ resource "ovh_cloud_project_instance" "head" {
// addresses only carry the fixed private ip, the floating ip is matched // addresses only carry the fixed private ip, the floating ip is matched
// through the port it is associated with. // through the port it is associated with.
data "ovh_cloud_project_floatingips" "all" { data "ovh_cloud_project_floatingips" "all" {
service_name = var.project_id service_name = local.service_name
region_name = var.region region_name = var.region
depends_on = [ovh_cloud_project_instance.head] depends_on = [ovh_cloud_project_instance.head]
@ -141,7 +154,7 @@ data "ovh_cloud_project_floatingips" "all" {
resource "ovh_cloud_project_instance" "compute" { resource "ovh_cloud_project_instance" "compute" {
count = var.compute_node_count count = var.compute_node_count
service_name = var.project_id service_name = local.service_name
region = var.region region = var.region
billing_period = "hourly" billing_period = "hourly"
name = local.compute_hostnames[count.index] name = local.compute_hostnames[count.index]

View File

@ -16,6 +16,10 @@ terraform {
source = "hashicorp/tls" source = "hashicorp/tls"
version = "4.0.6" version = "4.0.6"
} }
null = {
source = "hashicorp/null"
version = "3.2.4"
}
cloudinit = { cloudinit = {
source = "hashicorp/cloudinit" source = "hashicorp/cloudinit"
version = "2.3.7" version = "2.3.7"