From 1e34ae3bc8231c4de288d861dc412c06f18c0f0c Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 10 Apr 2026 19:21:21 +0200 Subject: [PATCH] align vpc factory module factories_config to project factory (#3855) --- fast/stages/2-networking/factory-projects.tf | 4 +-- fast/stages/2-networking/factory-vpcs.tf | 7 +++-- modules/net-vpc-factory/README.md | 31 ++++++++++---------- modules/net-vpc-factory/main.tf | 26 ++++++++++------ modules/net-vpc-factory/variables.tf | 8 +++-- 5 files changed, 43 insertions(+), 33 deletions(-) diff --git a/fast/stages/2-networking/factory-projects.tf b/fast/stages/2-networking/factory-projects.tf index 70d02f7c2..397b3f820 100644 --- a/fast/stages/2-networking/factory-projects.tf +++ b/fast/stages/2-networking/factory-projects.tf @@ -34,9 +34,7 @@ module "projects" { source = "../../../modules/project-factory" data_defaults = local.project_defaults.defaults data_overrides = merge( - { - universe = var.universe - }, + { universe = var.universe }, local.project_defaults.overrides ) context = local.ctx diff --git a/fast/stages/2-networking/factory-vpcs.tf b/fast/stages/2-networking/factory-vpcs.tf index 1afb641d0..2274ee97b 100644 --- a/fast/stages/2-networking/factory-vpcs.tf +++ b/fast/stages/2-networking/factory-vpcs.tf @@ -98,8 +98,11 @@ moved { } module "vpc-factory" { - source = "../../../modules/net-vpc-factory" - factories_config = local.paths + source = "../../../modules/net-vpc-factory" + factories_config = { + basepath = var.factories_config.dataset + paths = var.factories_config.paths + } context = { project_ids = local.ctx_projects.project_ids locations = local.ctx.locations diff --git a/modules/net-vpc-factory/README.md b/modules/net-vpc-factory/README.md index cfc3baab3..03d39c2cf 100644 --- a/modules/net-vpc-factory/README.md +++ b/modules/net-vpc-factory/README.md @@ -4,9 +4,9 @@ This module implements the creation of VPCs, subnets, and firewall rules via YAM It supports: -- **VPCs** and **Subnets** leveraging the [net-vpc](../net-vpc/) module. -- **Firewall rules** leveraging the [net-vpc-firewall](../net-vpc-firewall/) module. -- **Context-based interpolation** for referring to resources dynamically (e.g., project IDs, IAM principals, Locations). +- **VPCs** and **Subnets** leveraging the [net-vpc](../net-vpc/) module. +- **Firewall rules** leveraging the [net-vpc-firewall](../net-vpc-firewall/) module. +- **Context-based interpolation** for referring to resources dynamically (e.g., project IDs, IAM principals, Locations). The factory is implemented as a thin data translation layer over the underlying modules, ensuring transparency and ease of debugging. @@ -49,9 +49,9 @@ routing_mode: GLOBAL In addition to the YAML-based VPC configurations, the factory accepts three additional sets of inputs via Terraform variables to control defaults: -- `data_defaults`: defaults for specific VPC attributes, used if not present in YAML. -- `data_overrides`: overrides that take precedence over YAML values. -- `factories_config.defaults`: path to a YAML file containing global context and VPC defaults. +- `data_defaults`: defaults for specific VPC attributes, used if not present in YAML. +- `data_overrides`: overrides that take precedence over YAML values. +- `factories_config.paths.defaults`: path to a YAML file containing global context and VPC defaults (defaults to `defaults.yaml` in the path set by `factories_config.basepath`) ```hcl module "net-vpc-factory" { @@ -60,7 +60,7 @@ module "net-vpc-factory" { routing_mode = "REGIONAL" } factories_config = { - vpcs = "data/vpcs" + basepath = "data" } } ``` @@ -124,15 +124,14 @@ module "net-vpc-factory" { Other contexts can be defined freely. Common uses include: -- `$locations:` for GCP regions. -- `$iam_principals:` for IAM principals. +- `$locations:` for GCP regions. +- `$iam_principals:` for IAM principals. ## Example ```hcl module "net-vpc-factory" { source = "./fabric/modules/net-vpc-factory" - context = { project_ids = { net-project = "my-host-project-id" @@ -141,22 +140,22 @@ module "net-vpc-factory" { primary = "europe-west1" } } - factories_config = { - vpcs = "data/vpcs" + basepath = "data" } } # tftest files=vpc,fw,subnet modules=3 inventory=example.yaml ``` -**data/vpcs/shared-vpc/.config.yaml** ```yaml +# data/vpcs/shared-vpc/.config.yaml project_id: $project_ids:net-project name: data-vpc-0 # tftest-file id=vpc path=data/vpcs/data-vpc-0/.config.yaml schema=vpc-factory.schema.json ``` -**data/vpcs/data-vpc-0/subnets/primary-subnet.yaml** + ```yaml +# data/vpcs/data-vpc-0/subnets/primary-subnet.yaml name: primary-subnet region: $locations:primary ip_cidr_range: 10.10.0.0/24 @@ -164,8 +163,8 @@ description: Primary subnet for data-vpc-0 # tftest-file id=subnet path=data/vpcs/data-vpc-0/subnets/primary-subnet.yaml schema=subnet.schema.json ``` -**data/vpcs/data-vpc-0/firewall-rules/allow-iap.yaml** ```yaml +# data/vpcs/data-vpc-0/firewall-rules/allow-iap.yaml ingress: allow-iap: description: Allow IAP for SSH @@ -182,10 +181,10 @@ ingress: | name | description | type | required | default | |---|---|:---:|:---:|:---:| +| [factories_config](variables.tf#L97) | Path to folder with YAML resource description data files. | object({…}) | ✓ | | | [context](variables.tf#L17) | Context-specific interpolations. | object({…}) | | {} | | [data_defaults](variables.tf#L27) | Optional default values used when corresponding vpc data from files are missing. | object({…}) | | {} | | [data_overrides](variables.tf#L62) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | -| [factories_config](variables.tf#L97) | Path to folder with YAML resource description data files. | object({…}) | | {} | ## Outputs diff --git a/modules/net-vpc-factory/main.tf b/modules/net-vpc-factory/main.tf index 0b2e7fd67..f6c29226a 100644 --- a/modules/net-vpc-factory/main.tf +++ b/modules/net-vpc-factory/main.tf @@ -15,28 +15,29 @@ */ locals { - _vpcs_path = try( - pathexpand(var.factories_config.vpcs), null - ) _vpcs_files = try( - fileset(local._vpcs_path, "**/.config.yaml"), + fileset(local.paths.vpcs, "**/.config.yaml"), [] ) _defaults = try( - yamldecode(file(var.factories_config.defaults)), {} + yamldecode(file(local.paths.defaults)), {} ) context = { - locations = merge(var.context.locations, try(local._defaults.context.locations, {})) - project_ids = merge(var.context.project_ids, try(local._defaults.context.project_ids, {})) + locations = merge( + var.context.locations, try(local._defaults.context.locations, {}) + ) + project_ids = merge( + var.context.project_ids, try(local._defaults.context.project_ids, {}) + ) cidr_ranges_sets = try(local._defaults.context.cidr_ranges_sets, {}) iam_principals = try(local._defaults.context.iam_principals, {}) } _vpcs_preprocess = [ for f in local._vpcs_files : merge( - yamldecode(file("${coalesce(local._vpcs_path, "-")}/${f}")), + yamldecode(file("${coalesce(local.paths.vpcs, "-")}/${f}")), { factory_dirname = dirname(f) - factory_basepath = "${local._vpcs_path}/${dirname(f)}" + factory_basepath = "${local.paths.vpcs}/${dirname(f)}" } ) if f != "defaults.yaml" @@ -44,6 +45,13 @@ locals { _vpcs = { for v in local._vpcs_preprocess : v.factory_dirname => v } + paths = { + for k, v in var.factories_config.paths : k => try(pathexpand( + var.factories_config.basepath == null || startswith(v, "/") || startswith(v, ".") + ? v : + "${var.factories_config.basepath}/${v}" + ), null) + } vpcs = { for k, v in local._vpcs : k => merge( try(local._defaults.vpcs, {}), diff --git a/modules/net-vpc-factory/variables.tf b/modules/net-vpc-factory/variables.tf index 2ce00f819..9bd65b20c 100644 --- a/modules/net-vpc-factory/variables.tf +++ b/modules/net-vpc-factory/variables.tf @@ -97,9 +97,11 @@ variable "data_overrides" { variable "factories_config" { description = "Path to folder with YAML resource description data files." type = object({ - vpcs = optional(string) - defaults = optional(string) + basepath = string + paths = optional(object({ + defaults = optional(string, "defaults.yaml") + vpcs = optional(string, "vpcs") + }), {}) }) - default = {} nullable = false }