From 494ecba5118bb9673a24eb3d49fb01ccee80ae19 Mon Sep 17 00:00:00 2001 From: Simone Ruffilli Date: Mon, 9 Feb 2026 11:51:43 +0100 Subject: [PATCH] Refactor subnets mgmt in net-vpc-factory (#3715) Refactor subnets mgmt in net-vpc-factory This commit removes the ability to define subnets inline within the VPC `.config.yaml` across `net-vpc-factory` and enforces file-based subnet definitions using the `subnets/` subdirectory pattern. Key changes include: - **Module Updates:** Removed standard and non-standard inline subnet arguments (`subnets`, `subnets_private_nat`, `subnets_proxy_only`, `subnets_psc`) from the factory module's internal `vpcs` instantiation. - **Schema & Docs:** Renamed `vpc.schema.json` to `vpc-factory.schema.json`, stripping inline subnet definitions from the JSON schema, and updated the module `README.md` to reflect the new file-based only approach. - **Stage 2 Networking Configs:** Refactored datasets to migrate inline `subnets_proxy_only` definitions into standalone files like `subnets/prod-proxy.yaml`. Added a new exported output `subnet_ips` for downstream usage. --- fast/stages/2-networking/README.md | 13 ++- .../hub-and-spokes-ncc/vpcs/prod/.config.yaml | 5 - .../vpcs/prod/subnets/prod-proxy.yaml | 9 ++ .../vpcs/prod/subnets/prod-proxy.yaml | 9 ++ .../vpcs/prod/.config.yaml | 5 - .../vpcs/prod/subnets/prod-proxy.yaml | 9 ++ .../vpcs/prod/subnets/prod-proxy.yaml | 9 ++ fast/stages/2-networking/outputs.tf | 8 ++ modules/net-vpc-factory/README.md | 22 ++-- .../net-vpc-factory/data/example/.config.yaml | 2 +- modules/net-vpc-factory/main.tf | 4 - ...pc.schema.json => vpc-factory.schema.json} | 104 ------------------ .../schemas/vpc-factory.schema.md | 91 +++++++++++++++ tests/fast/stages/s2_networking/nva.yaml | 4 +- tests/fast/stages/s2_networking/vpns.yaml | 4 +- .../net_vpc_factory/examples/example.yaml | 12 +- 16 files changed, 164 insertions(+), 146 deletions(-) create mode 100644 fast/stages/2-networking/datasets/hub-and-spokes-ncc/vpcs/prod/subnets/prod-proxy.yaml create mode 100644 fast/stages/2-networking/datasets/hub-and-spokes-nva/vpcs/prod/subnets/prod-proxy.yaml create mode 100644 fast/stages/2-networking/datasets/hub-and-spokes-peerings/vpcs/prod/subnets/prod-proxy.yaml create mode 100644 fast/stages/2-networking/datasets/hub-and-spokes-vpns/vpcs/prod/subnets/prod-proxy.yaml rename modules/net-vpc-factory/schemas/{vpc.schema.json => vpc-factory.schema.json} (75%) create mode 100644 modules/net-vpc-factory/schemas/vpc-factory.schema.md diff --git a/fast/stages/2-networking/README.md b/fast/stages/2-networking/README.md index 88820d6eb..c738ce36b 100644 --- a/fast/stages/2-networking/README.md +++ b/fast/stages/2-networking/README.md @@ -334,10 +334,11 @@ Internally created resources are mapped to context namespaces, and use specific | name | description | sensitive | |---|---|:---:| -| [host_project_ids](outputs.tf#L70) | Project IDs. | | -| [host_project_numbers](outputs.tf#L75) | Project numbers. | | -| [subnet_proxy_only_self_links](outputs.tf#L80) | Subnet proxy-only self-links. | | -| [subnet_psc_self_links](outputs.tf#L85) | Subnet PSC self-links. | | -| [subnet_self_links](outputs.tf#L90) | Subnet self-links. | | -| [vpc_self_links](outputs.tf#L95) | VPC self-links. | | +| [host_project_ids](outputs.tf#L73) | Project IDs. | | +| [host_project_numbers](outputs.tf#L78) | Project numbers. | | +| [subnet_ips](outputs.tf#L83) | Subnet IP ranges. | | +| [subnet_proxy_only_self_links](outputs.tf#L88) | Subnet proxy-only self-links. | | +| [subnet_psc_self_links](outputs.tf#L93) | Subnet PSC self-links. | | +| [subnet_self_links](outputs.tf#L98) | Subnet self-links. | | +| [vpc_self_links](outputs.tf#L103) | VPC self-links. | | diff --git a/fast/stages/2-networking/datasets/hub-and-spokes-ncc/vpcs/prod/.config.yaml b/fast/stages/2-networking/datasets/hub-and-spokes-ncc/vpcs/prod/.config.yaml index 736e05ff4..f31af526e 100644 --- a/fast/stages/2-networking/datasets/hub-and-spokes-ncc/vpcs/prod/.config.yaml +++ b/fast/stages/2-networking/datasets/hub-and-spokes-ncc/vpcs/prod/.config.yaml @@ -26,8 +26,3 @@ routes: dest_range: 0.0.0.0/0 next_hop_type: "gateway" next_hop: "default-internet-gateway" -subnets_proxy_only: - - ip_cidr_range: 10.72.240.0/24 - region: $locations:primary - name: primary-region-proxy-only - active: true diff --git a/fast/stages/2-networking/datasets/hub-and-spokes-ncc/vpcs/prod/subnets/prod-proxy.yaml b/fast/stages/2-networking/datasets/hub-and-spokes-ncc/vpcs/prod/subnets/prod-proxy.yaml new file mode 100644 index 000000000..cf688d346 --- /dev/null +++ b/fast/stages/2-networking/datasets/hub-and-spokes-ncc/vpcs/prod/subnets/prod-proxy.yaml @@ -0,0 +1,9 @@ +# skip boilerplate check + +# yaml-language-server: $schema=../../../../../schemas/subnet.schema.json + +name: prod-proxy +region: $locations:primary +ip_cidr_range: 10.72.240.0/24 +description: Primary-region proxy-only subnet for prod +proxy_only: true diff --git a/fast/stages/2-networking/datasets/hub-and-spokes-nva/vpcs/prod/subnets/prod-proxy.yaml b/fast/stages/2-networking/datasets/hub-and-spokes-nva/vpcs/prod/subnets/prod-proxy.yaml new file mode 100644 index 000000000..cf688d346 --- /dev/null +++ b/fast/stages/2-networking/datasets/hub-and-spokes-nva/vpcs/prod/subnets/prod-proxy.yaml @@ -0,0 +1,9 @@ +# skip boilerplate check + +# yaml-language-server: $schema=../../../../../schemas/subnet.schema.json + +name: prod-proxy +region: $locations:primary +ip_cidr_range: 10.72.240.0/24 +description: Primary-region proxy-only subnet for prod +proxy_only: true diff --git a/fast/stages/2-networking/datasets/hub-and-spokes-peerings/vpcs/prod/.config.yaml b/fast/stages/2-networking/datasets/hub-and-spokes-peerings/vpcs/prod/.config.yaml index 276180569..20bb1e4b8 100644 --- a/fast/stages/2-networking/datasets/hub-and-spokes-peerings/vpcs/prod/.config.yaml +++ b/fast/stages/2-networking/datasets/hub-and-spokes-peerings/vpcs/prod/.config.yaml @@ -26,10 +26,5 @@ routes: dest_range: 0.0.0.0/0 next_hop_type: "gateway" next_hop: "default-internet-gateway" -subnets_proxy_only: - - ip_cidr_range: 10.72.240.0/24 - region: $locations:primary - name: primary-region-proxy-only - active: true # dns_policy: # logging: true diff --git a/fast/stages/2-networking/datasets/hub-and-spokes-peerings/vpcs/prod/subnets/prod-proxy.yaml b/fast/stages/2-networking/datasets/hub-and-spokes-peerings/vpcs/prod/subnets/prod-proxy.yaml new file mode 100644 index 000000000..cf688d346 --- /dev/null +++ b/fast/stages/2-networking/datasets/hub-and-spokes-peerings/vpcs/prod/subnets/prod-proxy.yaml @@ -0,0 +1,9 @@ +# skip boilerplate check + +# yaml-language-server: $schema=../../../../../schemas/subnet.schema.json + +name: prod-proxy +region: $locations:primary +ip_cidr_range: 10.72.240.0/24 +description: Primary-region proxy-only subnet for prod +proxy_only: true diff --git a/fast/stages/2-networking/datasets/hub-and-spokes-vpns/vpcs/prod/subnets/prod-proxy.yaml b/fast/stages/2-networking/datasets/hub-and-spokes-vpns/vpcs/prod/subnets/prod-proxy.yaml new file mode 100644 index 000000000..cf688d346 --- /dev/null +++ b/fast/stages/2-networking/datasets/hub-and-spokes-vpns/vpcs/prod/subnets/prod-proxy.yaml @@ -0,0 +1,9 @@ +# skip boilerplate check + +# yaml-language-server: $schema=../../../../../schemas/subnet.schema.json + +name: prod-proxy +region: $locations:primary +ip_cidr_range: 10.72.240.0/24 +description: Primary-region proxy-only subnet for prod +proxy_only: true diff --git a/fast/stages/2-networking/outputs.tf b/fast/stages/2-networking/outputs.tf index 28026f382..8359d1201 100644 --- a/fast/stages/2-networking/outputs.tf +++ b/fast/stages/2-networking/outputs.tf @@ -18,6 +18,9 @@ locals { tfvars = { host_project_ids = module.projects.project_ids host_project_numbers = module.projects.project_numbers + subnet_ips = { + for vpc_key, vpc in module.vpc-factory.vpcs : vpc_key => vpc.subnet_ips + } subnet_self_links = { for vpc_key, vpc in module.vpc-factory.vpcs : vpc_key => vpc.subnet_ids } @@ -77,6 +80,11 @@ output "host_project_numbers" { value = local.tfvars.host_project_numbers } +output "subnet_ips" { + description = "Subnet IP ranges." + value = local.tfvars.subnet_ips +} + output "subnet_proxy_only_self_links" { description = "Subnet proxy-only self-links." value = local.tfvars.subnet_proxy_only_self_links diff --git a/modules/net-vpc-factory/README.md b/modules/net-vpc-factory/README.md index 59918598b..ca6e2cd39 100644 --- a/modules/net-vpc-factory/README.md +++ b/modules/net-vpc-factory/README.md @@ -43,10 +43,6 @@ Each VPC directory contains a `.config.yaml` file. The structure of the YAML fil project_id: $project_ids:my-project # Or use the project id directly description: "My VPC" routing_mode: GLOBAL -subnets: - - name: subnet-a - region: europe-west1 - ip_cidr_range: 10.0.0.0/24 ``` ### Defaults @@ -71,7 +67,7 @@ module "net-vpc-factory" { ### Subnets -Subnets can be defined inline in the VPC `.config.yaml` file (as shown above) or in separate files within a `subnets` subdirectory in the VPC's folder. The factory automatically scans the `subnets` folder if it exists. +Subnets can be defined in separate files within a `subnets` subdirectory in the VPC's folder. ```text data/vpcs/ @@ -150,18 +146,22 @@ module "net-vpc-factory" { vpcs = "data/vpcs" } } -# tftest files=vpc,fw modules=3 inventory=example.yaml +# tftest files=vpc,fw,subnet modules=3 inventory=example.yaml ``` **data/vpcs/shared-vpc/.config.yaml** ```yaml project_id: $project_ids:net-project name: data-vpc-0 -subnets: - - name: primary-subnet - region: $locations:primary - ip_cidr_range: 10.10.0.0/24 -# tftest-file id=vpc path=data/vpcs/data-vpc-0/.config.yaml schema=vpc.schema.json +# 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 +name: primary-subnet +region: $locations:primary +ip_cidr_range: 10.10.0.0/24 +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** diff --git a/modules/net-vpc-factory/data/example/.config.yaml b/modules/net-vpc-factory/data/example/.config.yaml index c23ea6046..00db87f58 100644 --- a/modules/net-vpc-factory/data/example/.config.yaml +++ b/modules/net-vpc-factory/data/example/.config.yaml @@ -2,7 +2,7 @@ --- # start of document (---) avoids errors if the file only contains comments -# yaml-language-server: $schema=../../../schemas/vpc.schema.json +# yaml-language-server: $schema=../../../schemas/vpc-factory.schema.json name: example project_id: $project_ids:net diff --git a/modules/net-vpc-factory/main.tf b/modules/net-vpc-factory/main.tf index 621fe50f0..8224c94b0 100644 --- a/modules/net-vpc-factory/main.tf +++ b/modules/net-vpc-factory/main.tf @@ -79,10 +79,6 @@ module "vpcs" { network_attachments = try(each.value.network_attachments, {}) psa_configs = try(each.value.psa_configs, []) routing_mode = try(each.value.routing_mode, "GLOBAL") - subnets = try(each.value.subnets, []) - subnets_private_nat = try(each.value.subnets_private_nat, []) - subnets_proxy_only = try(each.value.subnets_proxy_only, []) - subnets_psc = try(each.value.subnets_psc, []) context = local.context } diff --git a/modules/net-vpc-factory/schemas/vpc.schema.json b/modules/net-vpc-factory/schemas/vpc-factory.schema.json similarity index 75% rename from modules/net-vpc-factory/schemas/vpc.schema.json rename to modules/net-vpc-factory/schemas/vpc-factory.schema.json index 3d42a1a60..6ba88bff1 100644 --- a/modules/net-vpc-factory/schemas/vpc.schema.json +++ b/modules/net-vpc-factory/schemas/vpc-factory.schema.json @@ -65,30 +65,6 @@ "$ref": "#/$defs/psa_config" } }, - "subnets": { - "type": "array", - "items": { - "$ref": "#/$defs/subnet" - } - }, - "subnets_private_nat": { - "type": "array", - "items": { - "$ref": "#/$defs/simple_subnet" - } - }, - "subnets_proxy_only": { - "type": "array", - "items": { - "$ref": "#/$defs/proxy_only_subnet" - } - }, - "subnets_psc": { - "type": "array", - "items": { - "$ref": "#/$defs/simple_subnet" - } - }, "nat_config": { "$ref": "#/$defs/nat_config" }, @@ -317,86 +293,6 @@ } } } - }, - "simple_subnet": { - "type": "object", - "required": [ - "name", - "ip_cidr_range", - "region" - ], - "properties": { - "name": { - "type": "string" - }, - "ip_cidr_range": { - "type": "string" - }, - "region": { - "type": "string" - }, - "description": { - "type": "string" - } - } - }, - "subnet": { - "type": "object", - "required": [ - "name", - "region" - ], - "properties": { - "name": { - "type": "string" - }, - "ip_cidr_range": { - "type": "string" - }, - "region": { - "type": "string" - }, - "description": { - "type": "string" - }, - "enable_private_access": { - "type": "boolean" - }, - "allow_subnet_cidr_routes_overlap": { - "type": "boolean" - }, - "reserved_internal_range": { - "type": "string" - } - } - }, - "proxy_only_subnet": { - "type": "object", - "required": [ - "name", - "ip_cidr_range", - "region" - ], - "properties": { - "name": { - "type": "string" - }, - "ip_cidr_range": { - "type": "string" - }, - "region": { - "type": "string" - }, - "description": { - "type": "string" - }, - "active": { - "type": "boolean" - }, - "global": { - "type": "boolean" - } - } } } } \ No newline at end of file diff --git a/modules/net-vpc-factory/schemas/vpc-factory.schema.md b/modules/net-vpc-factory/schemas/vpc-factory.schema.md new file mode 100644 index 000000000..1e60c09d2 --- /dev/null +++ b/modules/net-vpc-factory/schemas/vpc-factory.schema.md @@ -0,0 +1,91 @@ +# VPC Configuration + + + +## Properties + +*additional properties: false* + +- ⁺**project_id**: *string* +- ⁺**name**: *string* +- **description**: *string* +- **auto_create_subnetworks**: *boolean* +- **delete_default_routes_on_create**: *boolean* +- **mtu**: *number* +- **routing_mode**: *string* +
*enum: ['GLOBAL', 'REGIONAL']* +- **firewall_policy_enforcement_order**: *string* +
*enum: ['BEFORE_CLASSIC_FIREWALL', 'AFTER_CLASSIC_FIREWALL']* +- **create_googleapis_routes**: *reference([create_googleapis_routes](#refs-create_googleapis_routes))* +- **dns_policy**: *reference([dns_policy](#refs-dns_policy))* +- **ipv6_config**: *reference([ipv6_config](#refs-ipv6_config))* +- **network_attachments**: *reference([network_attachments](#refs-network_attachments))* +- **routers**: *reference([routers](#refs-routers))* +- **peering_config**: *reference([peering_config](#refs-peering_config))* +- **psa_configs**: *array* + - items: *reference([psa_config](#refs-psa_config))* +- **nat_config**: *reference([nat_config](#refs-nat_config))* +- **ncc_config**: *reference([ncc_config](#refs-ncc_config))* +- **routes**: *object* +- **policy_based_routes**: *object* +- **vpn_config**: *object* + +## Definitions + +- **create_googleapis_routes**: *object* + - **directpath**: *boolean* + - **directpath-6**: *boolean* + - **private**: *boolean* + - **private-6**: *boolean* + - **restricted**: *boolean* + - **restricted-6**: *boolean* +- **dns_policy**: *object* + - **inbound**: *boolean* + - **logging**: *boolean* + - **outbound**: *object* + - **private_ns**: *array* + - items: *string* + - **public_ns**: *array* + - items: *string* +- **ipv6_config**: *object* + - **enable_ula_internal**: *boolean* + - **internal_range**: *string* +- **nat_config**: *object* + - **`^[a-z0-9-]+$`**: *object* + - ⁺**region**: *string* +- **ncc_config**: *object* + - ⁺**hub**: *string* + - **group**: *string* +- **network_attachments**: *object* + - **`^[a-z0-9-]+$`**: *object* + - **subnet**: *string* + - **automatic_connection**: *boolean* + - **description**: *string* + - **producer_accept_lists**: *array* + - items: *string* + - **producer_reject_lists**: *array* + - items: *string* +- **peering_config**: *object* + - **peer_vpc_self_link**: *string* + - **create_remote_peer**: *boolean* + - **export_routes**: *boolean* + - **import_routes**: *boolean* +- **psa_config**: *object* + - **deletion_policy**: *string* + - **ranges**: *object* + - **`^[a-z0-9-]+$`**: *string* + - **export_routes**: *boolean* + - **import_routes**: *boolean* + - **peered_domains**: *array* + - items: *string* + - **range_prefix**: *string* + - **service_producer**: *string* +- **routers**: *object* + - **`^[a-z0-9-]+$`**: *object* +
*additional properties: false* + - ⁺**region**: *string* + - ⁺**asn**: *number* + - **custom_advertise**: *object* + - **all_subnets**: *boolean* + - **ip_ranges**: *object* + - **`.*`**: *string* diff --git a/tests/fast/stages/s2_networking/nva.yaml b/tests/fast/stages/s2_networking/nva.yaml index a17f6f35f..4b3a3dabe 100644 --- a/tests/fast/stages/s2_networking/nva.yaml +++ b/tests/fast/stages/s2_networking/nva.yaml @@ -31,7 +31,7 @@ counts: google_compute_router_nat: 1 google_compute_router_peer: 2 google_compute_shared_vpc_host_project: 3 - google_compute_subnetwork: 4 + google_compute_subnetwork: 5 google_compute_vpn_tunnel: 2 google_dns_managed_zone: 5 google_dns_record_set: 3 @@ -44,5 +44,5 @@ counts: google_storage_bucket_object: 2 modules: 36 random_id: 3 - resources: 199 + resources: 200 terraform_data: 2 diff --git a/tests/fast/stages/s2_networking/vpns.yaml b/tests/fast/stages/s2_networking/vpns.yaml index 08dc9463c..f4731500f 100644 --- a/tests/fast/stages/s2_networking/vpns.yaml +++ b/tests/fast/stages/s2_networking/vpns.yaml @@ -26,7 +26,7 @@ counts: google_compute_router_nat: 1 google_compute_router_peer: 10 google_compute_shared_vpc_host_project: 3 - google_compute_subnetwork: 3 + google_compute_subnetwork: 4 google_compute_vpn_tunnel: 10 google_dns_managed_zone: 5 google_dns_record_set: 3 @@ -39,5 +39,5 @@ counts: google_storage_bucket_object: 2 modules: 30 random_id: 15 - resources: 214 + resources: 215 terraform_data: 2 diff --git a/tests/modules/net_vpc_factory/examples/example.yaml b/tests/modules/net_vpc_factory/examples/example.yaml index 3de086ee7..6335ed804 100644 --- a/tests/modules/net_vpc_factory/examples/example.yaml +++ b/tests/modules/net_vpc_factory/examples/example.yaml @@ -15,9 +15,9 @@ values: module.net-vpc-factory.module.firewall["data-vpc-0"].google_compute_firewall.custom-rules["allow-iap"]: allow: - - ports: - - '22' - protocol: tcp + - ports: + - "22" + protocol: tcp deny: [] description: Allow IAP for SSH direction: INGRESS @@ -29,12 +29,12 @@ values: priority: 1000 project: my-host-project-id source_ranges: - - 35.235.240.0/20 + - 35.235.240.0/20 source_service_accounts: null source_tags: null target_service_accounts: null target_tags: - - ssh + - ssh timeouts: null module.net-vpc-factory.module.vpcs["data-vpc-0"].google_compute_network.network[0]: auto_create_subnetworks: true @@ -92,7 +92,7 @@ values: tags: null timeouts: null module.net-vpc-factory.module.vpcs["data-vpc-0"].google_compute_subnetwork.subnetwork["europe-west1/primary-subnet"]: - description: Terraform-managed. + description: Primary subnet for data-vpc-0 ip_cidr_range: 10.10.0.0/24 ip_collection: null ipv6_access_type: null