OpenTofu modules
Every module under opentofu/, generated by terraform-docs
(CI fails when stale), consumed from
oci://ghcr.io/do-now-io/socle/opentofu-modules//opentofu/<module>?tag=<socle_version>.
VPC, EKS with no CNI, bootstrap nodes, identities, Crossplane’s role. AWS.
Requirements
Section titled “Requirements”| Name | Version |
|---|---|
| terraform | >= 1.13 |
| aws | >= 6.0, < 7.0 |
| time | >= 0.13, < 1.0 |
Modules
Section titled “Modules”No modules.
Resources
Section titled “Resources”Inputs
Section titled “Inputs”| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| availability_zones | AZs the VPC's public and private subnets are spread across. Every VPC gets at least one public and one private subnet per AZ — never a flat, all-public layout — to satisfy ISO 27001 A.8.22 and SOC 2 CC6 network segregation. There is no all-public escape hatch: the private tier is structural, whether or not a client's workloads use it. | list(string) | n/a | yes |
| cluster_endpoint_public_access_cidrs | CIDRs allowed to reach the public EKS API endpoint. Required, no default: the endpoint is restricted by CIDR rather than left open or made fully private-only (AWS's own recommended pattern for this case), and there is no globally correct default to authorize on a client's behalf. | list(string) | n/a | yes |
| cluster_name | Name shared by the VPC, the EKS cluster and every resource this module creates around them. | string | n/a | yes |
| environment | Stamped on every billable resource. Also what the factory's upgrade rings (dev/staging/prod) key off. | string | n/a | yes |
| kubernetes_version | EKS control plane version. Required, no default: the module accepts whatever version it is given rather than enforcing the policy ceiling itself. The n-1 policy ceiling / n-2 compatibility floor is decided and bumped by the socle Kargo pipelines, not by this module — a validationblock cannot call the AWS API to know what "current" is, and the decoupled socle-release/Kubernetes-version pipelines are the actual owners of that decision. | string | n/a | yes |
| owner | Stamped on every billable resource so cost can be attributed and orphans can be found. | string | n/a | yes |
| additional_tags | Extra tags merged onto every resource this module creates, on top of owner/environment/socle-version. | map(string) | {} | no |
| bootstrap_node_capacity_type | SPOT by default: the several instance types spread the two nodes over independent pools, and EKS replaces a node at risk before draining it. ON_DEMAND for a cluster that must not lose a bootstrap node to a reclaim, at about two and a half times the price. | string | "SPOT" | no |
| bootstrap_node_count | How many bootstrap nodes, spread over the private subnets' AZs. Two by default: when one is reclaimed or lost the other carries the whole socle until it is replaced, CoreDNS keeps a replica, and Karpenter's chart places its two replicas on different nodes in different zones. One is accepted on a cluster that can live with neither. Nothing scales this group, so it is one number rather than min, max and desired. | number | 2 | no |
| bootstrap_node_instance_types | Instance types of the bootstrap node group, which carries Cilium's operator, CoreDNS, Flux and later Karpenter — not the client's workloads, which Karpenter's nodes carry. Several on Spot, so the nodes come from independent capacity pools; on demand, the first is used. The default is six Graviton families of 4 vCPU and 8 to 32 GiB: each one alone carries the whole socle, Karpenter included, with half its CPU left, so losing a node to a reclaim is routine. All must share an architecture, which the AMI follows. | list(string) | [ | no |
| cluster_log_types | Control plane log types shipped to CloudWatch Logs. None by default: ingestion is billed by the gigabyte, and the audit stream records every request to the API server — one controller writing in a loop made it about $40 a day on an idle cluster (#80). A client whose audit expects the API server's record of who did what (ISO 27001 A.8.15, SOC 2 CC7) turns on at least audit and authenticator; the log group, its retention and its key exist either way, so the first line is already covered. | list(string) | [] | no |
| create_nat_gateway | Create one NAT Gateway per AZ. One per AZ, never a single shared one, to avoid cross-AZ data transfer charges — not a toggle for disabling NAT outright, which the private-subnet decision above rules out. Exists only for the create_vpc = false case, where the consumer's existing VPC already manages its own NAT. | bool | true | no |
| create_vpc | Create the VPC, or attach to one the consumer already manages. | bool | true | no |
| crossplane | Give the catalog's crossplane module its AWS identity — the one the socle cannot make for itself: an IAM role, bound through EKS Pod Identity to crossplane-system/provider-aws, allowed to create roles under /socle/<cluster_name>/ only, and only carrying the permissions boundary this module writes. allowed_services is that boundary: the AWS services (IAM action prefixes, such as route53 or s3) any module's role may be granted. Empty grants nothing; iam, sts, organizations, account, sso and identitystore are refused. Which resources of those services a module reaches is its own role's policy. Null, the default, creates nothing. The client root passes the boundary's ARN into kube.crossplane. | object({ | null | no |
| force_update_version | Force the control plane version update even if Upgrade Insights reports blocking findings. Default false: Upgrade Insights is a mandatory pre-check, never sufficient alone (it only sees the client's own removed-API usage, over a rolling 30-day audit-log window that both misses infrequent calls and over-reports fixed ones) — but AWS's own blocking of update-cluster-version on ERROR findings is currentlyrolled back, so this module does not assume AWS enforces the check either. | bool | false | no |
| gateway_certificate | The ACM certificate the socle's two Gateways terminate TLS with, at the load balancer: domain and *.domain, validated by DNS in the publicRoute 53 zone named domain — found by name, no zone ID to copy. zonenames that zone instead when domain is a subdomain of it, such asdomain = "sbx.acme.example" in zone = "acme.example". Every route published through a Gateway — ArgoCD's included — is then <name>.<domain>. Null, the default, creates nothing, and the bootstrapmodule creates no Gateway: the socle never serves a route in clear text. | object({ | null | no |
| log_retention_days | Retention for the log groups this module creates — the control plane's and the VPC flow logs'. Set explicitly because a log group left to AWS never expires. | number | 90 | no |
| private_subnet_ids | Existing private subnet IDs, one per AZ in availability_zones. Required when create_vpc is false — this module carves its own subnets out of vpc_cidr only when it also creates the VPC. | list(string) | [] | no |
| public_subnet_ids | Existing public subnet IDs, one per AZ in availability_zones. Required when create_vpc is false — same reasoning as private_subnet_ids. | list(string) | [] | no |
| secrets_encryption_enabled | Envelope-encrypt Kubernetes Secrets via KMS. On by default: essentially free (~$1/month per key, negligible per-request cost), and standard on Kubernetes 1.28+ already. | bool | true | no |
| secrets_encryption_kms_key_arn | Existing KMS key for Secrets envelope encryption. Leave unset and the module creates its own key. Ignored when secrets_encryption_enabled is false. | string | null | no |
| vpc_cidr | CIDR for the VPC when this module creates it. Arbitrary default (not a research decision) — a /16 large enough for any socle estate. | string | "10.0.0.0/16" | no |
| vpc_flow_logs_enabled | Record accepted and rejected traffic on the VPC this module creates. On by default, aggregated over ten-minute windows to keep the volume down: it is the only record of who talked to whom, and the segmentation this VPC is built around is unauditable without it. | bool | true | no |
| vpc_id | Existing VPC to attach to. Required when create_vpc is false, and incoherent to set when create_vpc is true — this module cannot both create a VPC and attach to a different one. | string | null | no |
Outputs
Section titled “Outputs”| Name | Description |
|---|---|
| bootstrap_node_group | The bootstrap node group, once its nodes have joined. node_count is what the bootstrap module checks before it installs anything that needs a node; referencing it is also what orders those releases after the group. |
| cilium_operator_policy_json | IAM policy the Cilium operator needs in ENI mode — the bootstrap module installs Cilium on this cluster before Flux. The bootstrap nodes' role already carries it; any other node role the operator may be scheduled on needs it too. |
| cluster_ca_certificate | Base64-encoded cluster CA certificate, for building a kubeconfig. |
| cluster_endpoint | The control plane's API endpoint — the access path the socle and its automation use. |
| cluster_name | Name of the EKS cluster. |
| crossplane_permissions_boundary_arn | ARN of the permissions boundary every role Crossplane creates must carry — what kube.crossplane.permissions_boundary takes, and what the client root passes for you. Null when crossplane is not set. |
| crossplane_role_arn | ARN of the IAM role the catalog's crossplane module's AWS providers run as, through Pod Identity. Null when crossplane is not set. |
| gateway_certificate_arn | ARN of the issued ACM certificate the socle's Gateways terminate TLS with — what the bootstrap module's gateway_certificate_arn takes, and what the client root passes for you. Null when gateway_certificate is not set. |
| helm_kubernetes | Drop-in value for the helm provider's kubernetes attribute, so a root configures it in one line. Carries no credential: the exec plugin obtains a short-lived token from the caller's ambient AWS credentials at call time, exactly as the aws provider itself authenticates. |
| oidc_issuer_url | The cluster's OIDC issuer. Checklist requirement, not this module's identity mechanism — Pod Identity is, IRSA is absent, and nothing here provisions an OIDC trust relationship against it. Null on an emulated cluster that reports no identity (floci), so an apply there still converges. |
| private_subnet_ids | Private subnet IDs, one per AZ. |
| public_subnet_ids | Public subnet IDs, one per AZ. |
| region | Region the cluster and VPC were created in, as resolved from the provider. |
| service_cidr | The Kubernetes service range EKS chose for this cluster (172.20.0.0/16 or 10.100.0.0/16, by VPC CIDR). The bootstrap module gives CoreDNS its .10 address, the one every node's kubelet is told to use. Null on an emulated cluster that reports none (floci). |
| tags | The standard tag set applied to every billable resource this module creates. |
| vpc_id | ID of the VPC the cluster is attached to, whether this module created it or not. |
A GKE Autopilot cluster in its own network, Crossplane’s bounded grants, the Gateways’ certificates. GCP.
Requirements
Section titled “Requirements”| Name | Version |
|---|---|
| terraform | >= 1.13 |
| >= 8.0, < 9.0 |
Modules
Section titled “Modules”No modules.
Resources
Section titled “Resources”Inputs
Section titled “Inputs”| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| cluster_name | Name of the GKE cluster. Also prefixes the network resources the module creates. | string | n/a | yes |
| environment | Environment this cluster serves. Stamped as a label, and the axis the upgrade ring order follows. | string | n/a | yes |
| maintenance_window | When GKE may touch this cluster. Required on purpose — a silent default would mean nobody decided when production gets upgraded, and the day of the week is what orders a dev/staging/prod ring. start_time and end_time are RFC3339 timestamps whose difference is the window length; recurrence is an RFC5545 RRULE. At least 48 hours of maintenance availability must remain in any 92-day rolling window, and only contiguous blocks of four hours or more count. | object({ | n/a | yes |
| owner | Team accountable for the cluster. Stamped as a label on every billable resource. | string | n/a | yes |
| project_id | Google Cloud project that holds the cluster and its network. | string | n/a | yes |
| region | Region of the cluster and its subnetwork. The cluster is regional; zonal clusters are not offered. | string | n/a | yes |
| additional_labels | Extra labels merged onto the standard set. Cannot override owner, environment or socle-version. | map(string) | {} | no |
| backup_agent_enabled | Install the Backup for GKE agent. Off by default: $9 per protected namespace per month, where Velero covers a Persistent-Disk-backed socle for a third of that. | bool | false | no |
| billing_export_dataset_id | When set, create a BigQuery dataset to receive the detailed billing export. Linking the billing account to it stays a Console step — Google exposes no API for it. | string | null | no |
| billing_export_dataset_location | Location of the billing export dataset. Ignored when billing_export_dataset_id is null. | string | "EU" | no |
| control_plane_dns_allow_external_traffic | Allow user traffic to the DNS-based control plane endpoint. True means the control plane is reachable wherever Google Cloud APIs are, gated by IAM; VPC Service Controls is the network boundary and is set outside this module. | bool | true | no |
| control_plane_ip_endpoints_enabled | Expose the control plane on IP endpoints. Off: the DNS-based endpoint replaces them, and with it the authorized-networks maintenance problem. | bool | false | no |
| cost_allocation_enabled | Add cluster, namespace and workload labels to the detailed billing export. On from day one because it does not backfill. | bool | true | no |
| create_nat | Create a Cloud Router and Cloud NAT for egress. A cluster with private nodes and no NAT cannot pull an image from outside Google Cloud. | bool | true | no |
| create_network | Create the VPC instead of using an existing one. The common case is a network the consumer already owns. | bool | false | no |
| create_proxy_only_subnet | Create the proxy-only subnetwork. Set to false when another cluster in the same region and VPC already created it — the pool is shared. | bool | true | no |
| create_subnetwork | Create the cluster subnetwork. Set to false in a Shared VPC where the network team owns subnets, and supply subnetwork_name and pod_range_name instead. | bool | true | no |
| crossplane | Give the catalog's crossplane module its Google Cloud identity — the one the socle cannot make for itself: grants to the federated principal of crossplane-system/provider-gcp, no Google service account. allowed_roles is the boundary: the roles (predefined, or custom by full name) Crossplane may grant any module's principal on the project or on a bucket, through Project IAM Admin under a modifiedGrantsByRole condition. Empty grants nothing but the socle's own DNS records role; owner, editor, viewer, iam.* and resourcemanager.* are refused, and Google caps the list at nine. Predefined admin and owner roles (roles/storage.admin, roles/bigquery.dataOwner, …) are refused too, roles/storage.objectAdmin excepted: they grant roles on their resources, and Crossplane could give one to itself. A custom role that carries a setIamPolicy permission must not be listed, for the same reason. Buckets are reachable under the <cluster_name>- prefix only, and never deletable. Nothing of Cloud DNS: external-dns writes records through the socle's DNS records role, granted on the project. Null, the default, creates nothing. | object({ | null | no |
| deletion_protection | Refuse to destroy the cluster. On by default; test fixtures turn it off. | bool | true | no |
| enable_private_nodes | Nodes get no external address. Flips the Autopilot default, which is public. | bool | true | no |
| enable_upgrade_notifications | Create a Pub/Sub topic and publish cluster upgrade notifications to it, so automation can react instead of polling. | bool | true | no |
| gateway_api_enabled | Run GKE's Gateway API controller and let GKE install and upgrade the standard-channel Gateway API CRDs. On by default and stated rather than assumed: the socle installs nothing for Gateway API on GKE because of it, and its templates target GKE's classes. Off leaves the cluster without Gateway API at all. | bool | true | no |
| gateway_certificate | The Certificate Manager certificates the socle's two Gateways terminate TLS with, at the load balancer: every name in domains (wildcardsincluded, such as ["acme.example", "*.acme.example"]), authorised by DNS in the Cloud DNS managed zone dns_zone (its name, in this project).A global certificate in a certificate map serves the public Gateway; a regional one serves the internal Gateway. Every route published through a Gateway — ArgoCD's included — is then <name>.<domain>. The zone mustnot already hold an _acme-challenge.<domain> record (one another ACMEclient left behind): the global authorization writes that name. Null, the default, creates nothing, and the bootstrap module creates no Gateway: the socle never serves a route in clear text. | object({ | null | no |
| kubernetes_min_version | Floor for the control plane version. Raise-only escape hatch for promoting a minor deliberately; leave null in steady state and let the channel decide. | string | null | no |
| logging_components | GKE log sources to send to Cloud Logging. SYSTEM_COMPONENTS cannot be removed; drop WORKLOADS when application logs are collected in-cluster. | list(string) | [ | no |
| maintenance_exclusions | Windows during which GKE must not upgrade the cluster. The brake, not the routine: empty by default. | list(object({ | [] | no |
| monitoring_components | GKE metric sources. SYSTEM_COMPONENTS is free and mandatory; every other component is billed per sample, so none is defaulted on. | list(string) | [ | no |
| network_name | Name of an existing custom-mode VPC to attach the cluster to. Mutually exclusive with create_network. | string | null | no |
| node_range_cidr | Primary range of the cluster subnetwork, used by nodes and by internal load balancers. A /22 carries 1020 nodes, which is what the Pod range allows. | string | "10.0.0.0/22" | no |
| observability_reader_members | Principals granted read-only access to this project's metrics — the central observability cluster's federated identity, never a key. | list(string) | [] | no |
| pod_range_cidr | Secondary range for Pod addresses. Autopilot fixes 32 Pods per node, so a /26 is consumed per node: a /16 carries 1024 nodes. Sized generously on purpose — a cluster's Pod range cannot be changed after creation, while the primary range can be expanded in place. | string | "10.4.0.0/16" | no |
| pod_range_name | Name of the secondary range that carries Pod addresses. Defaults to <cluster_name>-pods, which is what the module creates; set it when attaching to a subnetwork someone else owns. | string | null | no |
| project_number | The project's number, which every Workload Identity Federation principal names the project by. Null, the default, reads it from the project; set it only where that read cannot happen — the Cloud Billing call the provider makes alongside it is what an emulator lacks. | string | null | no |
| proxy_only_range_cidr | Range of the REGIONAL_MANAGED_PROXY subnetwork. Regional Application Load Balancers, and therefore Gateways, cannot exist without it. | string | "10.8.0.0/23" | no |
| release_channel | GKE release channel. REGULAR is Google's recommendation and the estate-wide default; RAPID is outside the GKE SLA and belongs in pre-production only. | string | "REGULAR" | no |
| subnet_flow_logs_enabled | Enable VPC flow logs on the cluster subnetwork, at half sampling over ten-minute windows. Vended network logs are billed at $0.25/GiB, which is a dollar or so a month at that sampling for a socle cluster. | bool | true | no |
| subnetwork_name | Name of an existing subnetwork in var.region to place the cluster in. Required when create_subnetwork is false, ignored otherwise. | string | null | no |
Outputs
Section titled “Outputs”| Name | Description |
|---|---|
| billing_export_dataset | Reference of the BigQuery dataset waiting for the detailed billing export. Null when none was requested. The billing account still has to be linked to it by hand. |
| cluster_ca_certificate | Base64-encoded cluster CA certificate, for building a kubeconfig. |
| cluster_dns_endpoint | The control plane's DNS endpoint — the access path the socle and its automation use. Stable for the life of the cluster and authorised by IAM. |
| cluster_endpoint | IP endpoint of the control plane. Empty when IP endpoints are disabled, which is the default. |
| cluster_location | Region of the cluster. Regional by default; there is no zonal option. |
| cluster_name | Name of the GKE cluster. |
| crossplane_principal | The federated principal the catalog's crossplane module's GCP providers run as (crossplane-system/provider-gcp), read off its grants: whatever consumes it is applied after them and destroyed before them. Null when crossplane is not set. |
| dns_records_role | Full name of the custom role external-dns writes DNS records with: find the project's managed zones, read and change their record sets. Project-level, because a zone's IAM policy is never honoured when granted on the zone itself (measured 2026-10-07), so Crossplane binds it on the project, and --domain-filter bounds what external-dns writes. Always among the roles Crossplane may grant. Built from its ID, so known on the first plan. Empty when crossplane is not set. |
| gateway_certificate_map | Name of the Certificate Manager map the public Gateway's networking.gke.io/certmap annotation takes — what the bootstrap module's gateway_certificate_map takes. Empty when gateway_certificate is not set. |
| gateway_regional_certificate | Name of the regional Certificate Manager certificate the internal Gateway's HTTPS listener takes, in its networking.gke.io/cert-manager-certs TLS option — what the bootstrap module's gateway_regional_certificate takes. Empty when gateway_certificate is not set. |
| helm_kubernetes | Drop-in value for the helm provider's kubernetes attribute, so a root configures it in one line. Uses the DNS endpoint, the only one enabled by default, which serves a publicly trusted certificate: no cluster CA is carried (use cluster_ca_certificate with the IP endpoint). Carries no credential: gke-gcloud-auth-plugin obtains a short-lived token from the caller's ambient gcloud credentials at call time. |
| labels | The standard label set applied to every billable resource this module creates. |
| network_name | Name of the VPC the cluster is attached to, whether the module created it or not. |
| oidc_issuer_url | The cluster's OIDC issuer, for federating an external identity provider against this cluster. |
| pod_range_name | Name of the secondary range carrying Pod addresses. |
| project_id | The project the cluster lives in — half of every workload's principal, with project_number. |
| project_number | The project's number, which a Workload Identity Federation principal names the project by. |
| proxy_only_subnetwork_name | The REGIONAL_MANAGED_PROXY subnetwork regional Gateways draw their proxies from. Null when the module did not create it. |
| region | Region of the cluster, and of the internal Gateway's regional certificate. |
| subnetwork_name | Name of the cluster's subnetwork. |
| upgrade_notifications_topic | Pub/Sub topic carrying GKE upgrade and security bulletin notifications. Null when notifications are disabled. |
| workload_identity_pool | The Workload Identity Federation pool. Autopilot enforces it, so this is derived rather than configured. Grant IAM roles to principals in this pool to give a catalog workload direct resource access. |
| workload_identity_principal_prefix | Prefix of a workload's IAM principal identifier, naming the project by its number as Workload Identity Federation requires. Append /ns/NAMESPACE/sa/SERVICEACCOUNT. Note that two clusters in one project produce identical principals for the same namespace and service account. |
A VNet and an AKS cluster with no CNI. Azure.
Requirements
Section titled “Requirements”| Name | Version |
|---|---|
| terraform | >= 1.13 |
| azurerm | >= 4.0, < 5.0 |
Modules
Section titled “Modules”No modules.
Resources
Section titled “Resources”Inputs
Section titled “Inputs”| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| cluster_name | Name shared by the resource group (when created), the VNet, the AKS cluster and every resource this module creates around them. | string | n/a | yes |
| environment | Stamped on every billable resource. Also what the factory's upgrade rings (dev/staging/prod) key off. | string | n/a | yes |
| kubernetes_version | AKS control plane version. Required, no default: the module accepts whatever version it is given rather than enforcing a version policy itself — that policy is decided and bumped by the socle Kargo pipelines, not by this module. | string | n/a | yes |
| location | Azure region for every resource this module creates. Required, no default — there is no globally correct region to pick on a client's behalf. | string | n/a | yes |
| maintenance_window_auto_upgrade | Window Kubernetes version auto-upgrades (stable channel) are allowed to run in. At least 4 hours, per AKS's own constraint. | object({ | n/a | yes |
| maintenance_window_node_os | Window node OS security patches are allowed to run in. Separate schedule from maintenance_window_auto_upgrade, so node patching and Kubernetes upgrades never have to share a window. | object({ | n/a | yes |
| owner | Stamped on every billable resource so cost can be attributed and orphans can be found. | string | n/a | yes |
| resource_group_name | Name of the resource group. Used as the name to create when create_resource_group is true, or the name of an existing one to attach to when false. | string | n/a | yes |
| additional_tags | Extra tags merged onto every resource this module creates, on top of owner/environment/socle-version. | map(string) | {} | no |
| create_nat_gateway | Create one NAT Gateway for the VNet's node subnet. Not a toggle for disabling egress outright — the node subnet has no public IP of its own, so without this its nodes reach nothing. Exists only for the create_vnet = false case, where the consumer's existing VNet already manages its own NAT or an alternate egress path. | bool | true | no |
| create_resource_group | Create the resource group, or attach to one the consumer already manages. | bool | true | no |
| create_vnet | Create the VNet and its node subnet, or attach to a subnet the consumer already manages. | bool | true | no |
| dns_service_ip | IP address within service_cidr used for cluster service discovery (kube-dns). | string | "10.1.0.10" | no |
| log_retention_days | Retention for the Container Insights Log Analytics workspace this module creates. | number | 90 | no |
| node_subnet_id | Existing node subnet ID to attach to. Required when create_vnet is false — this module carves its own subnet out of vnet_cidr only when it also creates the VNet. | string | null | no |
| pod_cidr | Range Cilium allocates pod addresses from, as the cluster pool of the Cilium the bootstrap module installs (docs/architecture/cilium-before-flux.md). Not set on the cluster: azurerm refuses pod_cidr under network_plugin = "none" (see cluster.tf), so this module only carries the value to the bootstrap through its output. Must not overlap the VNet, service_cidr or any connected network. The default is AKS's own pod range, which the chart's default (10.0.0.0/8) would not be: that one contains the VNet. | string | "10.244.0.0/16" | no |
| service_cidr | CIDR for Kubernetes service IPs. Must not overlap the VNet or any connected network, and be smaller than /12 — an AKS constraint independent of the BYO CNI choice below. | string | "10.1.0.0/16" | no |
| system_node_pool_node_count | Node count for the mandatory system node pool. Small and fixed rather than autoscaled: this pool exists to satisfy AKS's structural minimum, not to run workloads. | number | 2 | no |
| system_node_pool_vm_size | VM size for the mandatory system node pool. This is a structural AKS requirement, not a Karpenter/NAP-managed pool — kept small and tainted for-system-only by default (only_critical_addons_enabled), since NAP provisions everything workload-shaped. | string | "Standard_D2s_v5" | no |
| vnet_cidr | CIDR for the VNet — and its single node subnet, which covers the whole range — when this module creates it. Arbitrary default (not a research decision), sized generously since it only ever needs to fit nodes: Cilium's own IPAM owns pod addressing entirely, decoupled from the VNet. | string | "10.0.0.0/16" | no |
| vnet_name | Existing VNet name to attach to. Required when create_vnet is false, and incoherent to set when create_vnet is true — this module cannot both create a VNet and attach to a different one. | string | null | no |
| zones | Availability zones the default system node pool spreads across. Azure subnets aren't zone-scoped — zone placement happens on the node pool itself. | list(string) | [ | no |
Outputs
Section titled “Outputs”| Name | Description |
|---|---|
| cluster_ca_certificate | Base64-encoded cluster CA certificate, for building a kubeconfig. |
| cluster_endpoint | The control plane's private FQDN — the only reachable endpoint, since this module always disables the public one. |
| cluster_name | Name of the AKS cluster. |
| helm_kubernetes | Drop-in value for the helm provider's kubernetes attribute, so a root configures it in one line. Carries no credential: kubelogin obtains a short-lived Entra token from the caller's Azure CLI login at call time; the server ID is AKS's well-known Entra application. PRECONDITION NOT YET MET BY THIS MODULE: the exec only authenticates against a cluster with Entra ID authentication enabled (azure_active_directory_role_based_access_control), which this module does not configure yet — local accounts remain its auth path. Until it is enabled, this output is the shape a root will consume, not a working login (docs/clouds/azure/limits.md). |
| location | Region the cluster and its resources were created in. |
| node_subnet_id | ID of the node subnet. |
| oidc_issuer_url | The cluster's OIDC issuer — what a workload identity federation binding built by the layer above (Crossplane's provider, or anything else) will need. |
| pod_cidr | Range the bootstrap module hands Cilium as its cluster pool. Passed through, never set on the cluster: azurerm refuses pod_cidr under BYO CNI. |
| resource_group_name | Name of the resource group the cluster and its resources live in, whether this module created it or not. |
| tags | The standard tag set applied to every billable resource this module creates. |
| vnet_name | Name of the VNet the cluster is attached to, whether this module created it or not. |
scaleway
Section titled “scaleway”A private network and a Kapsule cluster. Scaleway.
Requirements
Section titled “Requirements”| Name | Version |
|---|---|
| terraform | >= 1.13 |
| scaleway | >= 2.82, < 3.0 |
Modules
Section titled “Modules”No modules.
Resources
Section titled “Resources”| Name | Type |
|---|---|
| scaleway_cockpit_token.observability | resource |
| scaleway_iam_api_key.crossplane | resource |
| scaleway_iam_application.crossplane | resource |
| scaleway_iam_policy.crossplane | resource |
| scaleway_instance_placement_group.socle | resource |
| scaleway_instance_security_group.socle | resource |
| scaleway_ipam_ip.gateway | resource |
| scaleway_k8s_acl.socle | resource |
| scaleway_k8s_cluster.socle | resource |
| scaleway_k8s_pool.socle | resource |
| scaleway_vpc.socle | resource |
| scaleway_vpc_gateway_network.socle | resource |
| scaleway_vpc_private_network.socle | resource |
| scaleway_vpc_public_gateway.socle | resource |
| scaleway_vpc_public_gateway_ip.socle | resource |
Inputs
Section titled “Inputs”| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| cluster_endpoint_public_access_cidrs | CIDRs allowed to reach the Kubernetes API server. Required with no default: the control plane cannot be made private on Kapsule, so this list is the only boundary there is, and Kapsule ships 0.0.0.0/0. | list(string) | n/a | yes |
| cluster_name | Name of the Kapsule cluster. Also names the network resources the module creates. | string | n/a | yes |
| crossplane_permission_sets | Permission sets granted to the in-cluster Crossplane identity, scoped to this Project. Required with no default: what Crossplane may provision is a per-client decision, and a default would either be uselessly narrow or dangerously wide. | list(string) | n/a | yes |
| environment | Environment this cluster serves. Stamped as a tag, decides the default control plane offer, and is the axis the upgrade ring order follows. | string | n/a | yes |
| kubernetes_version | Kubernetes minor or patch version. Required with no default: Scaleway has no release channel, auto-upgrade covers patches only, and a floating version would let the pipeline lose track of which minor is deployed. | string | n/a | yes |
| maintenance_window | When patch auto-upgrades may run. Required with no default: a silent default means nobody decided when production gets upgraded, and the window is what orders the upgrade rings across environments. | object({ | n/a | yes |
| owner | Team accountable for the cluster. Stamped as a tag on every resource that takes tags. | string | n/a | yes |
| project_id | Scaleway Project that holds the cluster and its network. One Project per environment: it is the only boundary Scaleway offers for both IAM and cost attribution. | string | n/a | yes |
| additional_tags | Extra tags merged onto the standard set, rendered as key=value. Cannot override owner, environment, cluster or socle-version. | map(string) | {} | no |
| autoscaler_expander | How the cluster-autoscaler picks which pool to grow. least_waste strands the least capacity; Scaleway's own default is random, which is a coin flip once there is more than one pool. | string | "least_waste" | no |
| availability_zones | Zones the node pools span, one pool per zone. Two is the default because the current instance generation exists in only two zones of fr-par and nl-ams; only pl-waw offers three. | list(string) | [ | no |
| cockpit_token_enabled | Create a query-only Cockpit token so the central observability cluster can federate Scaleway's own metrics and logs. Reading is what the supervision plane does; pushing into Cockpit is billed per sample and is refused. | bool | true | no |
| control_plane_type | Control plane offer. Null derives it from environment — dedicated 4 in production for the SLA and the audit log, mutualized elsewhere. Kosmos offers are absent by decision. | string | null | no |
| create_vpc | Create the VPC instead of attaching to an existing one. Routing is VPC-wide: by default each cluster gets its own VPC; pass an existing one to share it. | bool | true | no |
| crossplane_allowed_cidrs | Source addresses the Crossplane key may be used from, as an IAM policy condition. Empty derives it from the Public Gateways' egress addresses, which is the only stable source a fully isolated node presents. | list(string) | [] | no |
| crossplane_key_expires_at | RFC 3339 expiry for the Crossplane API key. Null means no expiry. Scaleway has no workload identity federation, so this key is the credential — an expiry is what forces the rotation the factory owns. | string | null | no |
| delete_additional_resources | On cluster deletion, also delete the Load Balancers and Block volumes Kubernetes created. False keeps client data when a cluster is torn down, at the price of orphaned billable resources someone has to clean up. | bool | false | no |
| node_type | Commercial type of the pool nodes. COMPUTE3-X is the current generation: dedicated vCPU at 1 vCPU per 2 GiB. BASIC3-X is refused for nodes — shared vCPU and a 99% SLO. | string | "COMPUTE3-X8C-16G" | no |
| pool_max_size | Maximum nodes per pool, and therefore per zone. | number | 5 | no |
| pool_min_size | Minimum nodes per pool, and therefore per zone. Billed whether anything schedules on them or not, because the autoscaler never consolidates. | number | 2 | no |
| private_network_cidr | IPv4 subnet of the cluster's Private Network. Kapsule consumes a /22 per cluster, so anything larger is wasted and anything smaller is refused. | string | "10.10.0.0/22" | no |
| public_gateway_type | Offer of the Public Gateways that carry node egress. VPC-GW-S handles 100 Mbps, which is ample for image pulls and API calls. | string | "VPC-GW-S" | no |
| region | Scaleway region for the cluster, its network and its pools. | string | "fr-par" | no |
| root_volume_size_in_gb | System volume of each node. Scaleway's own guidance is 20 GB minimum and 100 GB to hold images and system logs comfortably. | number | 100 | no |
| scale_down_unneeded_time | How long a node must sit below the utilisation threshold before the autoscaler removes it. | string | "10m" | no |
| scale_down_utilization_threshold | Requested resources over allocatable capacity, below which a node becomes a scale-down candidate. | number | 0.5 | no |
| vpc_id | ID of an existing VPC to attach the cluster's Private Network to. Mutually exclusive with create_vpc. | string | null | no |
Outputs
Section titled “Outputs”| Name | Description |
|---|---|
| cluster_ca_certificate | Base64-encoded cluster CA certificate, for building a kubeconfig. |
| cluster_endpoint | URL of the Kubernetes API server. Always public on Kapsule — a fully private control plane does not exist — and reachable only from cluster_endpoint_public_access_cidrs. |
| cluster_id | ID of the Kapsule cluster, in region/uuid form. |
| cluster_name | Name of the Kapsule cluster. |
| cluster_region | Region of the cluster. A Kapsule cluster lives in exactly one. |
| cluster_type | The control plane offer in force. Derived from environment unless control_plane_type overrides it: production gets a dedicated offer for the SLA and the audit log. |
| cockpit_token_secret | Query-only Cockpit token for the central observability cluster to federate Scaleway's metrics and logs. Null when cockpit_token_enabled is false. |
| crossplane_access_key | Access key of the Crossplane API key. Not secret on its own, but pair it with crossplane_secret_key. |
| crossplane_application_id | ID of the IAM application the in-cluster Crossplane provider authenticates as. |
| crossplane_secret_key | Secret key for the in-cluster Crossplane provider. This is a long-lived credential because Scaleway offers no alternative; it is bound to the source addresses in crossplane_allowed_cidrs and expires at crossplane_key_expires_at. |
| gateway_egress_cidrs | Public addresses the cluster's nodes egress from, one per zone, as /32 CIDRs. This is the estate's stable source address: allow-list it wherever a client needs to admit the cluster. |
| helm_kubernetes | Drop-in value for the helm provider's kubernetes attribute, so a root configures it in one line. Kapsule has no exec credential plugin and accepts the IAM secret key as a bearer token, so the exec emits an ExecCredential from SCW_SECRET_KEY — the variable the scaleway provider already reads — at call time. No token is stored in state. |
| kubeconfig | Raw kubeconfig for the cluster. Sensitive: it carries a bearer token. |
| oidc_issuer_url | Always null. Kapsule exposes no OIDC issuer for workload identity, so nothing can federate against this cluster's ServiceAccount tokens. |
| private_network_id | ID of the cluster's Private Network. |
| security_group_ids | The cluster's own node security groups, keyed by zone. Not the shared Kapsule default, which is common to every cluster in the Project. One per zone because an Instance security group is a zoned resource. |
| tags | The standard tag set applied to every resource this module creates that accepts tags. |
| vpc_id | ID of the VPC the cluster's Private Network sits in, whether the module created it or not. |
| wildcard_dns | DNS wildcard resolving to every ready node. Useful for reaching a NodePort before an ingress path exists. |
| workload_identity_pool | Always null. Scaleway has no workload identity federation — the in-cluster provider authenticates with the API key below instead. |
bootstrap
Section titled “bootstrap”What runs before the catalog, then Flux and the inputs. Its kube schema: Inputs.
Requirements
Section titled “Requirements”| Name | Version |
|---|---|
| terraform | >= 1.13 |
| aws | >= 6.0, < 7.0 |
| helm | >= 3.0, < 4.0 |
Modules
Section titled “Modules”No modules.
Resources
Section titled “Resources”| Name | Type |
|---|---|
| aws_eks_addon.ebs_csi | resource |
| aws_eks_addon.efs_csi | resource |
| aws_eks_addon.pod_identity_agent | resource |
| aws_eks_addon.snapshot_controller | resource |
| aws_iam_role.ebs_csi | resource |
| aws_iam_role.efs_csi | resource |
| aws_iam_role_policy_attachment.ebs_csi | resource |
| aws_iam_role_policy_attachment.efs_csi | resource |
| helm_release.cilium | resource |
| helm_release.coredns | resource |
| helm_release.instance | resource |
| helm_release.operator | resource |
| helm_release.socle | resource |
| helm_release.storage_class | resource |
| aws_caller_identity.current | data source |
Inputs
Section titled “Inputs”| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| cloud | Which cloud this cluster runs on. Selects the artifact's clusters/ | string | n/a | yes |
| cluster_name | Cluster this socle serves. Stamped on every object the operator creates, and exposed to the catalog as inputs.cluster.name. | string | n/a | yes |
| environment | Environment this cluster serves. Stamped as a label, exposed as inputs.cluster.environment, and the axis the upgrade rings follow. | string | n/a | yes |
| owner | Team accountable for the cluster. Stamped as a label on every object. | string | n/a | yes |
| artifact_pull_secret | Name of an existing kubernetes.io/dockerconfigjson Secret in flux-system that Flux uses to pull the artifact from a private registry. Empty for a public registry. The Secret is created outside this module — a credential never enters OpenTofu. | string | "" | no |
| artifact_url | OCI repository the socle artifact is pulled from. Override for a mirror; the tag is socle_version. | string | "oci://ghcr.io/do-now-io/socle/flux-modules" | no |
| cilium | The socle's Cilium, on the clouds whose foundations create a cluster with no CNI — aws and azure — as { enabled, hubble, gateway_api }, every keyoptional: enabled (true) installs it before Flux; false means thecluster brings its own CNI and DNS, which only a test double does. hubble (false) adds Hubble Relay and UI. gateway_api (true) makesCilium serve the cilium GatewayClass. values ({}) is any Cilium chartvalue, merged over the socle's so the client wins; private keys are refused there, and the chart's existingSecret fields name a Secretinstead. Refused on gcp and scaleway, where the cloud operates Cilium. Typed any and validated like kube, so a misspelt key is an error atplan. Chart versions are pinned in cilium.tf. | any | {} | no |
| cluster_network | What Cilium needs to know about the cluster, from the foundations' outputs, never from the client: api_endpoint, the API server as EKSreturns it (https://host) or AKS does (a bare FQDN), for kube-proxy replacement; service_cidr, the service range, whose .10 is CoreDNS'saddress on aws; pod_cidr, Cilium's pool on azure, where the VNet holdsnodes only. Required wherever the socle installs Cilium, ignored elsewhere. | object({ | null | no |
| coredns | The CoreDNS the socle installs on aws, right after Cilium, as{ values }: values ({}) is any CoreDNS chart value, merged over thesocle's so the client wins — extra zones, forwarders, plugins. The chart has no value that takes secret material inline; a Secret is mounted by name through extraSecrets, or read through env[].valueFrom. Refusedwhere the socle installs no CoreDNS: every cloud but aws, and aws with cilium.enabled = false. Chart version pinned in cilium.tf. | any | {} | no |
| cosign_identity | Keyless identity the artifact's signature must match, as issuer and subject regexes. Defaults to the socle's release workflow on main, so production never consumes a branch build by accident. Override on a dev cluster testing a branch. Null means this default. Verification cannot be disabled. | object({ | { | no |
| eks_addons | The EKS-managed add-ons the socle installs on aws once the nodes run, as{ pod_identity_agent, ebs_csi, efs_csi, snapshot_controller }, everykey optional: pod_identity_agent (true) is what hands every Pod Identity associationits credentials — Crossplane's AWS providers included — and flux-operator waits for it; ebs_csi (true) is the block-storage driver, with its ownrole; efs_csi (false) the RWX one, with its own role. Both drivers needthe agent. snapshot_controller (true) is the CSI snapshot controllerand its CRDs, what the velero module's EBS snapshots need. Refused on every cloud but aws. Versions pinned in eks_addons.tf. | any | {} | no |
| flux_components | Flux controllers to install. The image automation pair is absent by default: the socle's version moves through a reviewed tfvars change, not through a controller rewriting tags. | list(string) | [ | no |
| flux_version | Flux version the operator installs and keeps converged. 2.x tracks the latest 2 series the operator ships (its embedded distribution, so operator_version bounds it); 2.y.x the latest patch of 2.y; an exact 2.y.z pins it. | string | "2.x" | no |
| gateway_certificate_arn | On aws, the ACM certificate the shared Gateways' load balancers terminate TLS with — the foundations' gateway_certificate_arn output, never the client's. Null or empty on aws means no shared Gateway, and no route attached to one. Unknown at plan on the apply that issues it, which is why nothing validates it here. Ignored elsewhere. | string | null | no |
| gateway_certificate_map | On gcp, the Certificate Manager map the public shared Gateway's global load balancer terminates TLS with — the foundations' gateway_certificate_map output, never the client's. Null or empty on gcp means no shared Gateway, and no route attached to one. Unknown at plan on the apply that creates it, which is why nothing validates it here. Ignored elsewhere. | string | null | no |
| gateway_regional_certificate | On gcp, the regional Certificate Manager certificate the private shared Gateway's internal load balancer terminates TLS with — the foundations' gateway_regional_certificate output, never the client's. Null or empty on gcp means no shared Gateway either: a private listener without it would never be programmed. Unknown at plan on the apply that creates it, which is why nothing validates it here. Ignored elsewhere. | string | null | no |
| helm_timeout_seconds | How long to wait for each release to become ready. The instance release is the slow one: its health check waits for the operator to converge the controllers. | number | 600 | no |
| instance_size | Resource profile the operator applies to the controllers. Empty is the operator's own default; small, medium and large scale requests and limits together. | string | "" | no |
| kube | The catalog modules this cluster enables and their values, as{ <module> = { <attribute> = <value> } }. List only what differs fromthe catalog's defaults; an absent module is at its default. Module names are snake_case. Typed any on purpose: a map(any) refuses two modules withdifferent attributes, and an object type silently drops a misspelt attribute — the validations below are what makes a typo an error at plan. The schema is catalog.tf; docs/reference/inputs.md lists it module by module. | any | {} | no |
| network_policy | Let the operator install network policies isolating the Flux namespace. On by default; Cilium enforces them on every cloud we ship. | bool | true | no |
| operator_version | Chart version of flux-operator, which is also the operator's own version. Pinned exactly: the operator is pre-1.0 and its minors are not a stable contract. | string | "0.60.0" | no |
| project | On gcp, the project the cluster runs in, as { id, number } — thefoundations' project_id and project_number outputs, never the client's. Exposed to the catalog as inputs.cluster.projectId and projectNumber: a module's Workload Identity principal names the project number, and the pool named after the project id. Required on gcp, refused elsewhere. | object({ | null | no |
| region | Region the cluster runs in, exposed to the catalog as inputs.cluster.region. Regional cloud APIs need it — on AWS the Pod Identity associations the crossplane module creates. Empty when the caller does not know it; a module that needs it says so. | string | "" | no |
| schedulable_nodes | How many nodes the foundations give the cluster before this module starts — on aws, the bootstrap node group's size. Everything but Cilium waits for it: Cilium's DaemonSet is what makes those nodes Ready, so it is installed beside them, and CoreDNS and the Flux operator, the first releases that need a scheduled pod, come after. Zero fails the plan with that reason, instead of Helm waiting helm_timeout_seconds for a node. Null skips the check, on a cluster whose compute this module cannot see. | number | null | no |
| socle_version | Tag of the socle artifact to pull. Null means this module's own version, so that one bump of the module tag moves module and artifact together. Set it only on a dev cluster testing a branch build, together with cosign_identity. | string | null | no |
| storage_class | Storage class for the source-controller's artifact cache. Empty uses the cluster default. | string | "" | no |
Outputs
Section titled “Outputs”| Name | Description |
|---|---|
| artifact | The socle artifact, as OCI URL and tag. |
| cilium | Whether this module installed Cilium (aws, azure: the clouds whose foundations create a cluster with no CNI), with the chart versions it pinned. installed is false where the cloud operates Cilium, or when cilium.enabled is false. |
| cosign_identity | Keyless identity the artifact's signature is verified against, on every reconciliation. |
| eks_addons | The EKS-managed add-ons this module installed (aws only), each as its pinned version, and for the two storage drivers the ARN of the role their controller runs as. Null for an add-on not installed. |
| flux_version | Flux version the operator converges the controllers to. |
| inputs | What this module ships into the cluster as the ResourceSetInputProvider's defaultValues, after normalisation against the catalog. The catalog's templates read exactly these paths. |
| namespace | Namespace holding the operator, the Flux controllers and the socle's inputs. |
| operator_version | Version of flux-operator installed, which is also its chart version. |
| socle_version | Tag of the socle artifact the cluster pulls. |
clusters/aws
Section titled “clusters/aws”The AWS root your main.tf calls: foundations and bootstrap in one apply.
Requirements
Section titled “Requirements”| Name | Version |
|---|---|
| terraform | >= 1.13 |
| aws | >= 6.0, < 7.0 |
| helm | >= 3.0, < 4.0 |
Modules
Section titled “Modules”| Name | Source | Version |
|---|---|---|
| foundations | ../../aws | n/a |
| socle | ../../bootstrap | n/a |
Resources
Section titled “Resources”No resources.
Inputs
Section titled “Inputs”| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| aws | The foundations module's inputs, grouped, plus the region for the aws provider. Required keys are the ones the module leaves without a default; every other key is optional and passes through as-is. | object({ | n/a | yes |
| socle_version | The socle release this cluster runs. In a client's copy this variable is also in both module sources (?tag=), so this one line moves foundations, bootstrap and the artifact together. | string | n/a | yes |
| artifact_pull_secret | Name of an existing dockerconfigjson Secret in flux-system for a private registry. Empty for a public one; the Secret is created outside OpenTofu. | string | "" | no |
| artifact_url | Override of the OCI repository the artifact is pulled from, for a mirror. Null keeps the socle registry. | string | null | no |
| cilium | The socle's Cilium, installed before Flux because EKS is created with no CNI: { enabled = true, hubble = false, gateway_api = true, values = {} }, every key optional. values is any Cilium chart value, the client's winning; private keys are refused, name a Secret instead. Validated by the bootstrap module. enabled = false is for a cluster that brings its own CNI and DNS — the e2e test double, never a real EKS. | any | {} | no |
| coredns | The CoreDNS installed right after Cilium: { values = {} }. values is any CoreDNS chart value, the client's winning. Validated by the bootstrap module. | any | {} | no |
| cosign_identity | Override of the signature identity the cluster trusts. Null keeps the bootstrap module's default, the release workflow on main. Set it only on a dev cluster testing a branch build. | object({ | null | no |
| eks_addons | The EKS-managed add-ons installed once the nodes run: { pod_identity_agent = true, ebs_csi = true, efs_csi = false, snapshot_controller = true }, every key optional. The Pod Identity Agent is what every catalog module's AWS identity, Crossplane's included, gets its credentials from; the two storage drivers need it. The snapshot controller is what the velero module's EBS snapshots need. Versions pinned by the bootstrap module, which validates this. | any | {} | no |
| kube | Catalog modules and their values, as { | any | {} | no |
Outputs
Section titled “Outputs”| Name | Description |
|---|---|
| artifact | The socle artifact this cluster pulls, as URL and tag. |
| cluster_endpoint | The control plane's API endpoint. |
| cluster_name | Name of the EKS cluster. |
| inputs | What the catalog renders from, after normalisation. Compare with kubectl -n flux-system get resourcesetinputprovider socle -o yaml. |
clusters/gcp
Section titled “clusters/gcp”The GCP root your main.tf calls: foundations and bootstrap in one apply.
Requirements
Section titled “Requirements”| Name | Version |
|---|---|
| terraform | >= 1.13 |
| aws | >= 6.0, < 7.0 |
| >= 8.0, < 9.0 | |
| helm | >= 3.0, < 4.0 |
Modules
Section titled “Modules”| Name | Source | Version |
|---|---|---|
| foundations | ../../gcp | n/a |
| socle | ../../bootstrap | n/a |
Resources
Section titled “Resources”No resources.
Inputs
Section titled “Inputs”| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| gcp | The foundations module's inputs, grouped; project_id and region also configure the google provider. Required keys are the ones the module leaves without a default; every other key is optional and passes through as-is. | object({ | n/a | yes |
| socle_version | The socle release this cluster runs. In a client's copy this variable is also in both module sources (?tag=), so this one line moves foundations, bootstrap and the artifact together. | string | n/a | yes |
| artifact_pull_secret | Name of an existing dockerconfigjson Secret in flux-system for a private registry. Empty for a public one; the Secret is created outside OpenTofu. | string | "" | no |
| artifact_url | Override of the OCI repository the artifact is pulled from, for a mirror. Null keeps the socle registry. | string | null | no |
| cosign_identity | Override of the signature identity the cluster trusts. Null keeps the bootstrap module's default, the release workflow on main. Set it only on a dev cluster testing a branch build. | object({ | null | no |
| kube | Catalog modules and their values, as { | any | {} | no |
Outputs
Section titled “Outputs”| Name | Description |
|---|---|
| artifact | The socle artifact this cluster pulls, as URL and tag. |
| cluster_dns_endpoint | The control plane's DNS endpoint, the access path the socle and its automation use. |
| cluster_name | Name of the GKE cluster. |
| inputs | What the catalog renders from, after normalisation. Compare with kubectl -n flux-system get resourcesetinputprovider socle -o yaml. |