Add net-vpc-factory and starter-gcd dataset to 0-org-setup, fix context in net-vpc-factory (#3860)

* feat(fast/0-org-setup): integrate net-vpc-factory into stage 0

* initial starter dataset

* starter pack

* fix(fast/0-org-setup): correct factory vpcs paths definition and update test inventory

* feat(fast/0-org-setup): add VPC and subnet outputs and update stage tfvars

* test(fast/0-org-setup): update gcd starter defaults and regenerate inventory

* fix(modules/net-vpc-factory): remove internal defaults logic and pass context correctly

* fix typo in dataset fw rule, add missing boilerplate, set sane defaults for net vpc factory

* terraform fmt

* tfdoc, copyright year

* schema docs

* yamllint
This commit is contained in:
Ludovico Magnocavallo
2026-04-13 09:42:03 +02:00
committed by GitHub
parent 6847fae28d
commit 85b0871085
55 changed files with 3754 additions and 131 deletions

View File

@@ -1081,6 +1081,26 @@ tests:
A good example of tests showing different ways of leveraging our framework is in the [`tests/modules/organization`](./tests/modules/organization) folder.
### Debugging Terraform Context & Locals
When troubleshooting how variables, context, or locals are being evaluated during a `plan` (especially within factories or FAST stages), do not rely solely on `pytest` failure outputs or `grep`.
**ALWAYS** use a fast-failing `terraform_data` precondition to dump the exact runtime state of the data structure. Inject this snippet temporarily into the module being debugged:
```hcl
resource "terraform_data" "debug_dump" {
lifecycle {
precondition {
# The condition is intentionally designed to fail to trigger the error_message
condition = local.target_variable == null
error_message = yamlencode(local.target_variable)
}
}
}
```
Run the specific `pytest` plan test. The test will fail, and the captured output will contain the fully evaluated YAML representation of your target variable, making context resolution issues immediately obvious.
#### Generating the inventory for `tftest`-based tests
Just as you can generate an initial inventory for example-based tests, you can do the same for `tftest`-based tests. Currently the process relies on an additional tool (`tools/plan_summary.py`) but but we have plans to unify both cases in the future.

View File

@@ -224,9 +224,31 @@ Modify one existing README example (do not add a new one) to demonstrate context
* **Locals Separation:** Use module-level locals for values referenced directly by resources/outputs. Use block-level "private" locals prefixed with an underscore (`_`) for intermediate transformations.
* **Complex Transformations:** Move complex data transformations in `for` or `for_each` loops to `locals` to keep resource blocks clean.
## Debugging Terraform Context & Locals
When troubleshooting how variables, context, or locals are being evaluated during a `plan` (especially within factories or FAST stages), do not rely solely on `pytest` failure outputs or `grep`.
**ALWAYS** use a fast-failing `terraform_data` precondition to dump the exact runtime state of the data structure. Inject this snippet temporarily into the module being debugged:
```hcl
resource "terraform_data" "debug_dump" {
lifecycle {
precondition {
# The condition is intentionally designed to fail to trigger the error_message
condition = local.target_variable == null
error_message = yamlencode(local.target_variable)
}
}
}
```
Run the specific `pytest` plan test. The test will fail, and the captured output will contain the fully evaluated YAML representation of your target variable, making context resolution issues immediately obvious.
## File Modification Rules
- **CRITICAL:** NEVER use shell redirection (`cat << EOF`, `echo "..." >`, `>>`, `tee`) to create, overwrite, or append to files.
- For creating files, ALWAYS use the native `write_file` tool.
- For targeted edits or appending to a single file, ALWAYS use the native `replace` tool. (To append, match the last few lines of the file and replace them with the same lines plus your new content).
- **EXCEPTION (Pattern/Bulk Edits):** You MAY use shell commands (like `sed -i`, `perl -pi`, or `find ... xargs sed`) ONLY for regex-based or pattern-based replacements, particularly across multiple files, where the exact-match `replace` tool is not feasible.
- **Ambiguity & Paths:** When encountering unfamiliar or unexpected repository structures, paths, or tool executions, always pause and offer the user the choice to either explain or authorize further independent investigation, rather than making assumptions or guessing paths.
To run specific FAST stage tests, use the syntax `pytest tests/fast/stages/s<stage_num>_<stage_name>/tftest.yaml::<test_name>`. For example: `pytest tests/fast/stages/s0_org_setup/tftest.yaml::starter-gcd`.

View File

@@ -899,7 +899,7 @@ Define values for the `var.environments` variable in a tfvars file.
| [billing.tf](./billing.tf) | None | <code>billing-account</code> | |
| [cicd-workflows-preconditions.tf](./cicd-workflows-preconditions.tf) | None | | <code>terraform_data</code> |
| [cicd-workflows.tf](./cicd-workflows.tf) | None | <code>iam-service-account</code> | <code>google_storage_bucket_object</code> · <code>local_file</code> |
| [factory.tf](./factory.tf) | None | <code>project-factory</code> | |
| [factory.tf](./factory.tf) | None | <code>net-vpc-factory</code> · <code>project-factory</code> | |
| [identity-providers-defs.tf](./identity-providers-defs.tf) | None | | |
| [imports.tf](./imports.tf) | None | | |
| [main.tf](./main.tf) | Module-level locals and resources. | | <code>terraform_data</code> |
@@ -914,8 +914,8 @@ Define values for the `var.environments` variable in a tfvars file.
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [context](variables.tf#L17) | Context-specific interpolations. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [factories_config](variables.tf#L40) | Configuration for the resource factories or external data. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [org_policies_imports](variables.tf#L59) | List of org policies to import. These need to also be defined in data files. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [factories_config](variables.tf#L41) | Configuration for the resource factories or external data. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [org_policies_imports](variables.tf#L61) | List of org policies to import. These need to also be defined in data files. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
## Outputs
@@ -923,5 +923,8 @@ Define values for the `var.environments` variable in a tfvars file.
|---|---|:---:|
| [iam_principals](outputs.tf#L17) | IAM principals. | |
| [projects](outputs.tf#L22) | Attributes for managed projects. | |
| [tfvars](outputs.tf#L27) | Stage tfvars. | |
| [subnet_ips](outputs.tf#L27) | Map of subnet address ranges keyed by VPC and subnet name. | |
| [subnet_self_links](outputs.tf#L34) | Map of subnet self links keyed by VPC and subnet name. | |
| [tfvars](outputs.tf#L41) | Stage tfvars. | ✓ |
| [vpc_self_links](outputs.tf#L47) | Map of VPC self links keyed by VPC name. | |
<!-- END TFDOC -->

View File

@@ -0,0 +1,61 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../schemas/defaults.schema.json
global:
# use `gcloud beta billing accounts list` to populate
billing_account: ABCDEF-0123456-ABCDEF
organization:
# use `gcloud organizations list`` to populate
domain: fast-test-00.example.com
id: 1234567890
projects:
defaults:
# prefix must be unique and less than 9 characters
prefix: test00
locations:
bigquery: $locations:primary
logging: $locations:primary
storage: $locations:primary
overrides:
universe:
# Replace with values from the Configuration Reference table in ../../README-GCD.md
domain: <UNIVERSE_API_DOMAIN>
prefix: <UNIVERSE_PREFIX>
forced_jit_service_identities:
- compute.googleapis.com
unavailable_service_identities:
- dns.googleapis.com
- monitoring.googleapis.com
- networksecurity.googleapis.com
context:
# you can populate context variables here for use in YAML replacements
iam_principals:
# this is the default group used in bootstrap, initial user must be a member
gcp-organization-admins: group:gcp-organization-admins@example.com
locations:
# Replace with values from the Configuration Reference table
primary: <UNIVERSE_REGION>
output_files:
# local path is optional but recommended when starting
local_path: ~/fast-config/fast-test-00
storage_bucket: $storage_buckets:iac-0/iac-outputs
providers:
0-org-setup:
bucket: $storage_buckets:iac-0/iac-org-state
service_account: $iam_principals:service_accounts/iac-0/iac-org-rw
0-org-setup-ro:
bucket: $storage_buckets:iac-0/iac-org-state
service_account: $iam_principals:service_accounts/iac-0/iac-org-ro

View File

@@ -0,0 +1,19 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../schemas/folder.schema.json
name: Development
tag_bindings:
environment: $tag_values:environment/development

View File

@@ -0,0 +1,19 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../schemas/folder.schema.json
name: Production
tag_bindings:
environment: $tag_values:environment/production

View File

@@ -0,0 +1,59 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# TODO: data access logs
# yaml-language-server: $schema=../../../schemas/organization.schema.json
id: $defaults:organization/id
iam_by_principals:
$iam_principals:gcp-organization-admins:
- roles/cloudasset.owner
- roles/cloudsupport.admin
- roles/cloudsupport.techSupportEditor
- roles/compute.osAdminLogin
- roles/compute.osLoginExternalUser
- roles/compute.xpnAdmin
- roles/orgpolicy.policyAdmin
- roles/owner
- roles/resourcemanager.folderAdmin
- roles/resourcemanager.organizationAdmin
- roles/resourcemanager.projectCreator
- roles/resourcemanager.tagAdmin
- roles/iam.workforcePoolAdmin
$iam_principals:service_accounts/iac-0/iac-org-rw:
- roles/accesscontextmanager.policyAdmin
- roles/cloudasset.viewer
- roles/essentialcontacts.admin
- roles/iam.organizationRoleAdmin
- roles/iam.workforcePoolAdmin
- roles/logging.admin
- roles/orgpolicy.policyAdmin
- roles/resourcemanager.folderAdmin
- roles/resourcemanager.organizationAdmin
- roles/resourcemanager.projectCreator
- roles/resourcemanager.projectMover
- roles/resourcemanager.tagAdmin
- roles/resourcemanager.tagUser
logging:
sinks:
audit-logs:
destination: $log_buckets:iac-0/audit-logs
filter: |
log_id("cloudaudit.googleapis.com/activity") OR
log_id("cloudaudit.googleapis.com/system_event") OR
log_id("cloudaudit.googleapis.com/policy") OR
log_id("cloudaudit.googleapis.com/access_transparency")
iam:
roles/billing.creator: []

View File

@@ -0,0 +1,43 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../schemas/tags.schema.json
description: "Organization-level environments."
# iam:
# "roles/resourcemanager.tagViewer":
# - "group:finance-team@example.com"
values:
development:
description: "Development."
iam:
"roles/resourcemanager.tagUser":
- $iam_principals:service_accounts/iac-0/iac-networking-rw
- $iam_principals:service_accounts/iac-0/iac-security-rw
- $iam_principals:service_accounts/iac-0/iac-pf-rw
"roles/resourcemanager.tagViewer":
- $iam_principals:service_accounts/iac-0/iac-networking-ro
- $iam_principals:service_accounts/iac-0/iac-security-ro
- $iam_principals:service_accounts/iac-0/iac-pf-ro
production:
description: "Production."
iam:
"roles/resourcemanager.tagUser":
- $iam_principals:service_accounts/iac-0/iac-networking-rw
- $iam_principals:service_accounts/iac-0/iac-security-rw
- $iam_principals:service_accounts/iac-0/iac-pf-rw
"roles/resourcemanager.tagViewer":
- $iam_principals:service_accounts/iac-0/iac-networking-ro
- $iam_principals:service_accounts/iac-0/iac-security-ro
- $iam_principals:service_accounts/iac-0/iac-pf-ro

View File

@@ -0,0 +1,26 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../schemas/project.schema.json
name: dev-app-example-0
parent: $folder_ids:dev
services:
- bigquery.googleapis.com
- compute.googleapis.com
- logging.googleapis.com
- monitoring.googleapis.com
- storage.googleapis.com
shared_vpc_service_config:
host_project: $project_ids:dev-net-0

View File

@@ -0,0 +1,26 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../schemas/project.schema.json
name: prod-app-example-0
parent: $folder_ids:prod
services:
- bigquery.googleapis.com
- compute.googleapis.com
- logging.googleapis.com
- monitoring.googleapis.com
- storage.googleapis.com
shared_vpc_service_config:
host_project: $project_ids:prod-net-0

View File

@@ -0,0 +1,73 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../schemas/project.schema.json
name: prod-iac-core-0
iam_by_principals:
$iam_principals:gcp-organization-admins:
- roles/iam.serviceAccountTokenCreator
- roles/iam.workloadIdentityPoolAdmin
$iam_principals:service_accounts/iac-0/iac-org-rw:
- roles/cloudbuild.builds.editor
- roles/iam.serviceAccountAdmin
- roles/iam.workloadIdentityPoolAdmin
- roles/owner
- roles/storage.admin
services:
- accesscontextmanager.googleapis.com
- bigquery.googleapis.com
- bigquerystorage.googleapis.com
- cloudbilling.googleapis.com
- cloudkms.googleapis.com
- cloudresourcemanager.googleapis.com
- compute.googleapis.com
- container.googleapis.com
- essentialcontacts.googleapis.com
- iam.googleapis.com
- iamcredentials.googleapis.com
- logging.googleapis.com
- monitoring.googleapis.com
- orgpolicy.googleapis.com
- pubsub.googleapis.com
- serviceusage.googleapis.com
- storage-component.googleapis.com
- storage.googleapis.com
- sts.googleapis.com
buckets:
iac-org-state:
description: Terraform state for the org-level automation.
versioning: true
iam:
roles/storage.admin:
- $iam_principals:service_accounts/iac-0/iac-org-rw
$custom_roles:storage_viewer:
- $iam_principals:service_accounts/iac-0/iac-org-ro
iac-outputs:
description: Terraform state for the org-level automation.
versioning: true
iam:
roles/storage.admin:
- $iam_principals:service_accounts/iac-0/iac-org-rw
service_accounts:
iac-org-rw:
display_name: IaC service account for org setup (read-write).
datasets:
billing_export:
friendly_name: Billing export
log_buckets:
audit-logs:
log_analytics:
enable: true
retention: 31

View File

@@ -0,0 +1,27 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../schemas/project.schema.json
name: dev-net-shared-0
parent: $folder_ids:dev
services:
- container.googleapis.com
- compute.googleapis.com
- dns.googleapis.com
- iap.googleapis.com
- logging.googleapis.com
- monitoring.googleapis.com
shared_vpc_host_config:
enabled: true

View File

@@ -0,0 +1,27 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../schemas/project.schema.json
name: prod-net-shared-0
parent: $folder_ids:prod
services:
- container.googleapis.com
- compute.googleapis.com
- dns.googleapis.com
- iap.googleapis.com
- logging.googleapis.com
- monitoring.googleapis.com
shared_vpc_host_config:
enabled: true

View File

@@ -0,0 +1,19 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../schemas/vpc-factory.schema.json
name: dev-shared-0
project_id: $project_ids:dev-net-0
auto_create_subnetworks: false

View File

@@ -1,4 +1,4 @@
# Copyright 2025 Google LLC
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,24 +12,31 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../schemas/defaults.schema.json
# yaml-language-server: $schema=../../../../../schemas/firewall-rules.schema.json
context:
cidr_ranges_sets:
healthchecks:
ingress:
ingress-default-allow-iap:
description: Allow IAP.
source_ranges:
- 35.235.240.0/20
rules:
- protocol: all
ports: []
ingress-default-allow-healthchecks:
description: Allow GCP Healthcheck Ranges.
source_ranges:
- 35.191.0.0/16
- 130.211.0.0/22
- 209.85.152.0/22
- 209.85.204.0/22
rfc1918:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
locations:
primary: europe-west1
secondary: europe-west3
iam_principals: {}
vpcs:
auto_create_subnetworks: false
delete_default_route_on_create: true
mtu: 1500
rules:
- protocol: all
ports: []
ingress-default-allow-icmp:
description: Allow ICMP.
rules:
- protocol: icmp
ports: []

View File

@@ -0,0 +1,20 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../../schemas/subnet.schema.json
name: default
region: $locations:primary
ip_cidr_range: 10.0.0.0/24
description: Default primary-region subnet for dev

View File

@@ -0,0 +1,19 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../schemas/vpc-factory.schema.json
name: prod-shared-0
project_id: $project_ids:prod-net-0
auto_create_subnetworks: false

View File

@@ -0,0 +1,42 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../../schemas/firewall-rules.schema.json
ingress:
ingress-default-allow-iap:
description: Allow IAP.
source_ranges:
- 35.235.240.0/20
rules:
- protocol: all
ports: []
ingress-default-allow-healthchecks:
description: Allow GCP Healthcheck Ranges.
source_ranges:
- 35.191.0.0/16
- 130.211.0.0/22
- 209.85.152.0/22
- 209.85.204.0/22
rules:
- protocol: all
ports: []
ingress-default-allow-icmp:
description: Allow ICMP.
rules:
- protocol: icmp
ports: []

View File

@@ -0,0 +1,20 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../../schemas/subnet.schema.json
name: default
region: $locations:primary
ip_cidr_range: 10.0.0.0/24
description: Default primary-region subnet for prod

View File

@@ -68,3 +68,18 @@ module "factory" {
paths = var.factories_config.paths
}
}
module "vpcs" {
source = "../../../modules/net-vpc-factory"
context = merge(local.ctx, {
project_ids = local.of_ctx.project_ids
})
data_defaults = local.vpc_defaults.defaults
data_overrides = local.vpc_defaults.overrides
factories_config = {
basepath = var.factories_config.dataset
paths = {
vpcs = var.factories_config.paths.vpcs
}
}
}

View File

@@ -61,6 +61,10 @@ locals {
defaults = try(local._defaults.projects.defaults, {})
overrides = try(local._defaults.projects.overrides, {})
}
vpc_defaults = {
defaults = try(local._defaults.vpcs.defaults, {})
overrides = try(local._defaults.vpcs.overrides, {})
}
workload_identity_pools = merge([
for k, v in module.factory.projects : {
for wk, wv in v.workload_identity_pools :

View File

@@ -111,15 +111,24 @@ locals {
automation = {
outputs_bucket = local.of_outputs_bucket
}
custom_roles = local.of_ctx.custom_roles
folder_ids = local.of_ctx.folder_ids
iam_principals = local.of_ctx.iam_principals
logging_sinks = local.of_logging_sinks
project_ids = local.of_ctx.project_ids,
project_numbers = module.factory.project_numbers
service_accounts = module.factory.service_account_emails
storage_buckets = module.factory.storage_buckets
tag_values = local.of_ctx.tag_values
custom_roles = local.of_ctx.custom_roles
folder_ids = local.of_ctx.folder_ids
iam_principals = local.of_ctx.iam_principals
logging_sinks = local.of_logging_sinks
project_ids = local.of_ctx.project_ids,
project_numbers = module.factory.project_numbers
service_accounts = module.factory.service_account_emails
storage_buckets = module.factory.storage_buckets
subnet_ips = {
for k, v in module.vpcs.vpcs : k => v.subnet_ips
}
subnet_self_links = {
for k, v in module.vpcs.vpcs : k => v.subnet_ids
}
tag_values = local.of_ctx.tag_values
vpc_self_links = {
for k, v in module.vpcs.vpcs : k => v.id
}
workload_identity_providers = local.workload_identity_providers
workforce_identity_providers = module.organization[0].workforce_identity_providers
}

View File

@@ -24,8 +24,30 @@ output "projects" {
value = module.factory.projects
}
output "subnet_ips" {
description = "Map of subnet address ranges keyed by VPC and subnet name."
value = {
for k, v in module.vpcs.vpcs : k => v.subnet_ips
}
}
output "subnet_self_links" {
description = "Map of subnet self links keyed by VPC and subnet name."
value = {
for k, v in module.vpcs.vpcs : k => v.subnet_ids
}
}
output "tfvars" {
description = "Stage tfvars."
value = local.of_tfvars
sensitive = true
}
output "vpc_self_links" {
description = "Map of VPC self links keyed by VPC name."
value = {
for k, v in module.vpcs.vpcs : k => v.id
}
}

View File

@@ -460,10 +460,231 @@
}
}
},
"vpcs": {
"type": "object",
"additionalProperties": false,
"properties": {
"defaults": {
"type": "object",
"additionalProperties": false,
"properties": {
"project_id": {
"type": "string"
},
"description": {
"type": "string"
},
"auto_create_subnetworks": {
"type": "boolean"
},
"delete_default_routes_on_create": {
"type": "boolean"
},
"mtu": {
"type": "number",
"minimum": 1460,
"maximum": 1500
},
"routing_mode": {
"type": "string",
"enum": [
"GLOBAL",
"REGIONAL"
]
},
"firewall_policy_enforcement_order": {
"type": "string",
"enum": [
"BEFORE_CLASSIC_FIREWALL",
"AFTER_CLASSIC_FIREWALL"
]
},
"create_googleapis_routes": {
"type": "object",
"additionalProperties": false,
"properties": {
"directpath": {
"type": "boolean"
},
"directpath-6": {
"type": "boolean"
},
"private": {
"type": "boolean"
},
"private-6": {
"type": "boolean"
},
"restricted": {
"type": "boolean"
},
"restricted-6": {
"type": "boolean"
}
}
},
"dns_policy": {
"type": "object",
"additionalProperties": false,
"properties": {
"inbound": {
"type": "boolean"
},
"logging": {
"type": "boolean"
},
"outbound": {
"type": "object",
"additionalProperties": false,
"properties": {
"private_ns": {
"type": "array",
"items": {
"type": "string"
}
},
"public_ns": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"ipv6_config": {
"type": "object",
"additionalProperties": false,
"properties": {
"enable_ula_internal": {
"type": "boolean"
},
"internal_range": {
"type": "string"
}
}
}
}
},
"overrides": {
"type": "object",
"additionalProperties": false,
"properties": {
"project_id": {
"type": "string"
},
"description": {
"type": "string"
},
"auto_create_subnetworks": {
"type": "boolean"
},
"delete_default_routes_on_create": {
"type": "boolean"
},
"mtu": {
"type": "number",
"minimum": 1460,
"maximum": 1500
},
"routing_mode": {
"type": "string",
"enum": [
"GLOBAL",
"REGIONAL"
]
},
"firewall_policy_enforcement_order": {
"type": "string",
"enum": [
"BEFORE_CLASSIC_FIREWALL",
"AFTER_CLASSIC_FIREWALL"
]
},
"create_googleapis_routes": {
"type": "object",
"additionalProperties": false,
"properties": {
"directpath": {
"type": "boolean"
},
"directpath-6": {
"type": "boolean"
},
"private": {
"type": "boolean"
},
"private-6": {
"type": "boolean"
},
"restricted": {
"type": "boolean"
},
"restricted-6": {
"type": "boolean"
}
}
},
"dns_policy": {
"type": "object",
"additionalProperties": false,
"properties": {
"inbound": {
"type": "boolean"
},
"logging": {
"type": "boolean"
},
"outbound": {
"type": "object",
"additionalProperties": false,
"properties": {
"private_ns": {
"type": "array",
"items": {
"type": "string"
}
},
"public_ns": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"ipv6_config": {
"type": "object",
"additionalProperties": false,
"properties": {
"enable_ula_internal": {
"type": "boolean"
},
"internal_range": {
"type": "string"
}
}
}
}
}
}
},
"context": {
"type": "object",
"additionalProperties": false,
"properties": {
"cidr_ranges_sets": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"custom_roles": {
"type": "object",
"additionalProperties": {

View File

@@ -127,8 +127,78 @@
- **vpc_sc**: *object*
- ⁺**perimeter_name**: *string*
- **is_dry_run**: *boolean*
- **vpcs**: *object*
<br>*additional properties: false*
- **defaults**: *object*
<br>*additional properties: false*
- **project_id**: *string*
- **description**: *string*
- **auto_create_subnetworks**: *boolean*
- **delete_default_routes_on_create**: *boolean*
- **mtu**: *number*
- **routing_mode**: *string*
<br>*enum: ['GLOBAL', 'REGIONAL']*
- **firewall_policy_enforcement_order**: *string*
<br>*enum: ['BEFORE_CLASSIC_FIREWALL', 'AFTER_CLASSIC_FIREWALL']*
- **create_googleapis_routes**: *object*
<br>*additional properties: false*
- **directpath**: *boolean*
- **directpath-6**: *boolean*
- **private**: *boolean*
- **private-6**: *boolean*
- **restricted**: *boolean*
- **restricted-6**: *boolean*
- **dns_policy**: *object*
<br>*additional properties: false*
- **inbound**: *boolean*
- **logging**: *boolean*
- **outbound**: *object*
<br>*additional properties: false*
- **private_ns**: *array*
- items: *string*
- **public_ns**: *array*
- items: *string*
- **ipv6_config**: *object*
<br>*additional properties: false*
- **enable_ula_internal**: *boolean*
- **internal_range**: *string*
- **overrides**: *object*
<br>*additional properties: false*
- **project_id**: *string*
- **description**: *string*
- **auto_create_subnetworks**: *boolean*
- **delete_default_routes_on_create**: *boolean*
- **mtu**: *number*
- **routing_mode**: *string*
<br>*enum: ['GLOBAL', 'REGIONAL']*
- **firewall_policy_enforcement_order**: *string*
<br>*enum: ['BEFORE_CLASSIC_FIREWALL', 'AFTER_CLASSIC_FIREWALL']*
- **create_googleapis_routes**: *object*
<br>*additional properties: false*
- **directpath**: *boolean*
- **directpath-6**: *boolean*
- **private**: *boolean*
- **private-6**: *boolean*
- **restricted**: *boolean*
- **restricted-6**: *boolean*
- **dns_policy**: *object*
<br>*additional properties: false*
- **inbound**: *boolean*
- **logging**: *boolean*
- **outbound**: *object*
<br>*additional properties: false*
- **private_ns**: *array*
- items: *string*
- **public_ns**: *array*
- items: *string*
- **ipv6_config**: *object*
<br>*additional properties: false*
- **enable_ula_internal**: *boolean*
- **internal_range**: *string*
- **context**: *object*
<br>*additional properties: false*
- **cidr_ranges_sets**: *object*
<br>*additional properties: array*
- **custom_roles**: *object*
<br>*additional properties: string*
- **email_addresses**: *object*

View File

@@ -0,0 +1,104 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Firewall Rules",
"type": "object",
"additionalProperties": false,
"properties": {
"egress": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-z0-9_-]+$": {
"$ref": "#/$defs/rule"
}
}
},
"ingress": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-z0-9_-]+$": {
"$ref": "#/$defs/rule"
}
}
}
},
"$defs": {
"rule": {
"type": "object",
"additionalProperties": false,
"properties": {
"deny": {
"type": "boolean"
},
"description": {
"type": "string"
},
"destination_ranges": {
"type": "array",
"items": {
"type": "string"
}
},
"disabled": {
"type": "boolean"
},
"enable_logging": {
"type": "object",
"additionalProperties": false,
"properties": {
"include_metadata": {
"type": "boolean"
}
}
},
"priority": {
"type": "number"
},
"source_ranges": {
"type": "array",
"items": {
"type": "string"
}
},
"sources": {
"type": "array",
"items": {
"type": "string"
}
},
"targets": {
"type": "array",
"items": {
"type": "string"
}
},
"use_service_accounts": {
"type": "boolean"
},
"rules": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"protocol": {
"type": "string"
},
"ports": {
"type": "array",
"items": {
"type": [
"integer",
"string"
],
"pattern": "^[0-9]+(?:-[0-9]+)?$"
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,42 @@
# Firewall Rules
<!-- markdownlint-disable MD036 -->
## Properties
*additional properties: false*
- **egress**: *object*
<br>*additional properties: false*
- **`^[a-z0-9_-]+$`**: *reference([rule](#refs-rule))*
- **ingress**: *object*
<br>*additional properties: false*
- **`^[a-z0-9_-]+$`**: *reference([rule](#refs-rule))*
## Definitions
- **rule**<a name="refs-rule"></a>: *object*
<br>*additional properties: false*
- **deny**: *boolean*
- **description**: *string*
- **destination_ranges**: *array*
- items: *string*
- **disabled**: *boolean*
- **enable_logging**: *object*
<br>*additional properties: false*
- **include_metadata**: *boolean*
- **priority**: *number*
- **source_ranges**: *array*
- items: *string*
- **sources**: *array*
- items: *string*
- **targets**: *array*
- items: *string*
- **use_service_accounts**: *boolean*
- **rules**: *array*
- items: *object*
<br>*additional properties: false*
- **protocol**: *string*
- **ports**: *array*
- items: *(integer|string)*
<br>*pattern: `^[0-9]+(?:-[0-9]+)?$`*

View File

@@ -0,0 +1,231 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Subnet",
"type": "object",
"additionalProperties": false,
"required": [
"region"
],
"anyOf": [
{"required": ["ip_cidr_range"]},
{"required": ["reserved_internal_range"]},
{"required": ["ip_collection"]},
{
"allOf": [
{"not": {"required": ["ip_cidr_range"]}},
{"not": {"required": ["reserved_internal_range"]}},
{"not": {"required": ["ip_collection"]}},
{"properties": {"ipv6": {"properties": {"ipv6_only": {"const": true}}}}, "required": ["ipv6"]}
]
}
],
"properties": {
"active": {
"type": "boolean"
},
"description": {
"type": "string"
},
"enable_private_access": {
"type": "boolean"
},
"allow_subnet_cidr_routes_overlap": {
"type": "boolean"
},
"flow_logs_config": {
"type": "object",
"additionalProperties": false,
"properties": {
"aggregation_interval": {
"type": "string"
},
"filter_expression": {
"type": "string"
},
"flow_sampling": {
"type": "number"
},
"metadata": {
"type": "string"
},
"metadata_fields": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"global": {
"type": "boolean"
},
"ip_cidr_range": {
"type": "string"
},
"reserved_internal_range": {
"type": "string",
"description": "Name of the internal range to use for this subnet. Mutually exclusive with ip_cidr_range and ip_collection."
},
"ipv6": {
"type": "object",
"additionalProperties": false,
"properties": {
"access_type": {
"type": "string"
},
"ipv6_only": {
"type": "boolean"
}
}
},
"ip_collection": {
"type": "string"
},
"name": {
"type": "string"
},
"region": {
"type": "string"
},
"psc": {
"type": "boolean"
},
"proxy_only": {
"type": "boolean"
},
"secondary_ip_ranges": {
"type": "object",
"additionalProperties": {
"oneOf": [
{
"type": "string",
"description": "IP CIDR range for backward compatibility"
},
{
"type": "object",
"additionalProperties": false,
"anyOf": [
{"required": ["ip_cidr_range"]},
{"required": ["reserved_internal_range"]}
],
"properties": {
"ip_cidr_range": {
"type": "string",
"description": "IP CIDR range for this secondary range"
},
"reserved_internal_range": {
"type": "string",
"description": "Name of the internal range to use for this secondary range"
}
}
}
]
}
},
"iam": {
"$ref": "#/$defs/iam"
},
"iam_bindings": {
"$ref": "#/$defs/iam_bindings"
},
"iam_bindings_additive": {
"$ref": "#/$defs/iam_bindings_additive"
}
},
"$defs": {
"iam": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^roles/": {
"type": "array",
"items": {
"type": "string",
"pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|ro|rw)"
}
}
}
},
"iam_bindings": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-z0-9_-]+$": {
"type": "object",
"additionalProperties": false,
"properties": {
"members": {
"type": "array",
"items": {
"type": "string",
"pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|ro|rw)"
}
},
"role": {
"type": "string",
"pattern": "^roles/"
},
"condition": {
"type": "object",
"additionalProperties": false,
"required": [
"expression",
"title"
],
"properties": {
"expression": {
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
}
}
}
}
}
}
},
"iam_bindings_additive": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-z0-9_-]+$": {
"type": "object",
"additionalProperties": false,
"properties": {
"member": {
"type": "string",
"pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|ro|rw)"
},
"role": {
"type": "string",
"pattern": "^roles/"
},
"condition": {
"type": "object",
"additionalProperties": false,
"required": [
"expression",
"title"
],
"properties": {
"expression": {
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,77 @@
# Subnet
<!-- markdownlint-disable MD036 -->
## Properties
*additional properties: false*
- **active**: *boolean*
- **description**: *string*
- **enable_private_access**: *boolean*
- **allow_subnet_cidr_routes_overlap**: *boolean*
- **flow_logs_config**: *object*
<br>*additional properties: false*
- **aggregation_interval**: *string*
- **filter_expression**: *string*
- **flow_sampling**: *number*
- **metadata**: *string*
- **metadata_fields**: *array*
- items: *string*
- **global**: *boolean*
- **ip_cidr_range**: *string*
- **reserved_internal_range**: *string*
- **ipv6**: *object*
<br>*additional properties: false*
- **access_type**: *string*
- **ipv6_only**: *boolean*
- **ip_collection**: *string*
- **name**: *string*
- ⁺**region**: *string*
- **psc**: *boolean*
- **proxy_only**: *boolean*
- **secondary_ip_ranges**: *object*
<br>*additional properties: oneof*
- *string*
- *object*
<br>*additional properties: false*
- **ip_cidr_range**: *string*
- **reserved_internal_range**: *string*
- **iam**: *reference([iam](#refs-iam))*
- **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))*
- **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))*
## Definitions
- **iam**<a name="refs-iam"></a>: *object*
<br>*additional properties: false*
- **`^roles/`**: *array*
- items: *string*
<br>*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|ro|rw)*
- **iam_bindings**<a name="refs-iam_bindings"></a>: *object*
<br>*additional properties: false*
- **`^[a-z0-9_-]+$`**: *object*
<br>*additional properties: false*
- **members**: *array*
- items: *string*
<br>*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|ro|rw)*
- **role**: *string*
<br>*pattern: ^roles/*
- **condition**: *object*
<br>*additional properties: false*
- ⁺**expression**: *string*
- ⁺**title**: *string*
- **description**: *string*
- **iam_bindings_additive**<a name="refs-iam_bindings_additive"></a>: *object*
<br>*additional properties: false*
- **`^[a-z0-9_-]+$`**: *object*
<br>*additional properties: false*
- **member**: *string*
<br>*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|ro|rw)*
- **role**: *string*
<br>*pattern: ^roles/*
- **condition**: *object*
<br>*additional properties: false*
- ⁺**expression**: *string*
- ⁺**title**: *string*
- **description**: *string*

View File

@@ -0,0 +1,298 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "VPC Configuration",
"description": "Schema for a VPC .config.yaml file.",
"type": "object",
"additionalProperties": false,
"required": [
"name",
"project_id"
],
"properties": {
"project_id": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"auto_create_subnetworks": {
"type": "boolean"
},
"delete_default_routes_on_create": {
"type": "boolean"
},
"mtu": {
"type": "number"
},
"routing_mode": {
"type": "string",
"enum": [
"GLOBAL",
"REGIONAL"
]
},
"firewall_policy_enforcement_order": {
"type": "string",
"enum": [
"BEFORE_CLASSIC_FIREWALL",
"AFTER_CLASSIC_FIREWALL"
]
},
"create_googleapis_routes": {
"$ref": "#/$defs/create_googleapis_routes"
},
"dns_policy": {
"$ref": "#/$defs/dns_policy"
},
"ipv6_config": {
"$ref": "#/$defs/ipv6_config"
},
"network_attachments": {
"$ref": "#/$defs/network_attachments"
},
"routers": {
"$ref": "#/$defs/routers"
},
"peering_config": {
"$ref": "#/$defs/peering_config"
},
"psa_configs": {
"type": "array",
"items": {
"$ref": "#/$defs/psa_config"
}
},
"nat_config": {
"$ref": "#/$defs/nat_config"
},
"ncc_config": {
"$ref": "#/$defs/ncc_config"
},
"routes": {
"type": "object"
},
"policy_based_routes": {
"type": "object"
},
"vpn_config": {
"type": "object"
}
},
"$defs": {
"create_googleapis_routes": {
"type": "object",
"properties": {
"directpath": {
"type": "boolean"
},
"directpath-6": {
"type": "boolean"
},
"private": {
"type": "boolean"
},
"private-6": {
"type": "boolean"
},
"restricted": {
"type": "boolean"
},
"restricted-6": {
"type": "boolean"
}
}
},
"dns_policy": {
"type": "object",
"properties": {
"inbound": {
"type": "boolean"
},
"logging": {
"type": "boolean"
},
"outbound": {
"type": "object",
"properties": {
"private_ns": {
"type": "array",
"items": {
"type": "string"
}
},
"public_ns": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"ipv6_config": {
"type": "object",
"properties": {
"enable_ula_internal": {
"type": "boolean"
},
"internal_range": {
"type": "string"
}
}
},
"nat_config": {
"type": "object",
"patternProperties": {
"^[a-z0-9-]+$": {
"type": "object",
"required": [
"region"
],
"properties": {
"region": {
"type": "string"
}
}
}
}
},
"ncc_config": {
"type": "object",
"required": [
"hub"
],
"properties": {
"hub": {
"type": "string"
},
"group": {
"type": "string"
}
}
},
"network_attachments": {
"type": "object",
"patternProperties": {
"^[a-z0-9-]+$": {
"type": "object",
"properties": {
"subnet": {
"type": "string"
},
"automatic_connection": {
"type": "boolean"
},
"description": {
"type": "string"
},
"producer_accept_lists": {
"type": "array",
"items": {
"type": "string"
}
},
"producer_reject_lists": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"peering_config": {
"type": "object",
"properties": {
"peer_vpc_self_link": {
"type": "string"
},
"create_remote_peer": {
"type": "boolean"
},
"export_routes": {
"type": "boolean"
},
"import_routes": {
"type": "boolean"
}
}
},
"psa_config": {
"type": "object",
"properties": {
"deletion_policy": {
"type": "string"
},
"ranges": {
"type": "object",
"patternProperties": {
"^[a-z0-9-]+$": {
"type": "string"
}
}
},
"export_routes": {
"type": "boolean"
},
"import_routes": {
"type": "boolean"
},
"peered_domains": {
"type": "array",
"items": {
"type": "string"
}
},
"range_prefix": {
"type": "string"
},
"service_producer": {
"type": "string"
}
}
},
"routers": {
"type": "object",
"description": "A map of Cloud Routers to create in this VPC.",
"patternProperties": {
"^[a-z0-9-]+$": {
"type": "object",
"additionalProperties": false,
"required": [
"region",
"asn"
],
"properties": {
"region": {
"type": "string"
},
"asn": {
"type": "number"
},
"custom_advertise": {
"type": "object",
"properties": {
"all_subnets": {
"type": "boolean"
},
"ip_ranges": {
"type": "object",
"patternProperties": {
".*": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,91 @@
# VPC Configuration
<!-- markdownlint-disable MD036 -->
## 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*
<br>*enum: ['GLOBAL', 'REGIONAL']*
- **firewall_policy_enforcement_order**: *string*
<br>*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**<a name="refs-create_googleapis_routes"></a>: *object*
- **directpath**: *boolean*
- **directpath-6**: *boolean*
- **private**: *boolean*
- **private-6**: *boolean*
- **restricted**: *boolean*
- **restricted-6**: *boolean*
- **dns_policy**<a name="refs-dns_policy"></a>: *object*
- **inbound**: *boolean*
- **logging**: *boolean*
- **outbound**: *object*
- **private_ns**: *array*
- items: *string*
- **public_ns**: *array*
- items: *string*
- **ipv6_config**<a name="refs-ipv6_config"></a>: *object*
- **enable_ula_internal**: *boolean*
- **internal_range**: *string*
- **nat_config**<a name="refs-nat_config"></a>: *object*
- **`^[a-z0-9-]+$`**: *object*
- ⁺**region**: *string*
- **ncc_config**<a name="refs-ncc_config"></a>: *object*
- ⁺**hub**: *string*
- **group**: *string*
- **network_attachments**<a name="refs-network_attachments"></a>: *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**<a name="refs-peering_config"></a>: *object*
- **peer_vpc_self_link**: *string*
- **create_remote_peer**: *boolean*
- **export_routes**: *boolean*
- **import_routes**: *boolean*
- **psa_config**<a name="refs-psa_config"></a>: *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**<a name="refs-routers"></a>: *object*
- **`^[a-z0-9-]+$`**: *object*
<br>*additional properties: false*
- ⁺**region**: *string*
- ⁺**asn**: *number*
- **custom_advertise**: *object*
- **all_subnets**: *boolean*
- **ip_ranges**: *object*
- **`.*`**: *string*

View File

@@ -17,6 +17,7 @@
variable "context" {
description = "Context-specific interpolations."
type = object({
cidr_ranges_sets = optional(map(list(string)), {})
custom_roles = optional(map(string), {})
email_addresses = optional(map(string), {})
folder_ids = optional(map(string), {})
@@ -50,6 +51,7 @@ variable "factories_config" {
organization = optional(string, "organization")
project_templates = optional(string, "templates")
projects = optional(string, "projects")
vpcs = optional(string, "vpcs")
}), {})
})
nullable = false

View File

@@ -39,9 +39,10 @@ projects:
# perimeter_name: $vpc_sc_perimeters:default
# is_dry_run: true
vpcs:
auto_create_subnetworks: false
delete_default_route_on_create: true
mtu: 1500
defaults:
auto_create_subnetworks: false
delete_default_routes_on_create: true
mtu: 1500
output_files:
# local path is optional but recommended when starting
# local_path: ~/fast-config/fast-test-00

View File

@@ -39,9 +39,10 @@ projects:
# perimeter_name: $vpc_sc_perimeters:default
# is_dry_run: true
vpcs:
auto_create_subnetworks: false
delete_default_route_on_create: true
mtu: 1500
defaults:
auto_create_subnetworks: false
delete_default_routes_on_create: true
mtu: 1500
output_files:
# local path is optional but recommended when starting
# local_path: ~/fast-config/fast-test-00

View File

@@ -39,9 +39,10 @@ projects:
# perimeter_name: $vpc_sc_perimeters:default
# is_dry_run: true
vpcs:
auto_create_subnetworks: false
delete_default_route_on_create: true
mtu: 1500
defaults:
auto_create_subnetworks: false
delete_default_routes_on_create: true
mtu: 1500
output_files:
# local path is optional but recommended when starting
# local_path: ~/fast-config/fast-test-00

View File

@@ -39,9 +39,10 @@ projects:
# perimeter_name: $vpc_sc_perimeters:default
# is_dry_run: true
vpcs:
auto_create_subnetworks: false
delete_default_route_on_create: true
mtu: 1500
defaults:
auto_create_subnetworks: false
delete_default_routes_on_create: true
mtu: 1500
output_files:
# local path is optional but recommended when starting
# local_path: ~/fast-config/fast-test-00

View File

@@ -35,7 +35,8 @@ locals {
}
vpcs = {
for k, v in local._vpcs : k => merge(
local.vpc_defaults, v,
local.vpc_defaults.defaults,
v,
{
project_id = v.project_id
description = try(v.description, "Terraform managed")
@@ -71,7 +72,8 @@ locals {
factories_config = try(v.factories_config, {})
peering_config = try(v.peering_config, {})
vpn_config = try(v.vpn_config, {})
}
},
local.vpc_defaults.overrides
)
}
ctx_vpcs = {
@@ -98,7 +100,9 @@ moved {
}
module "vpc-factory" {
source = "../../../modules/net-vpc-factory"
source = "../../../modules/net-vpc-factory"
data_defaults = local.vpc_defaults.defaults
data_overrides = local.vpc_defaults.overrides
factories_config = {
basepath = var.factories_config.dataset
paths = var.factories_config.paths

View File

@@ -25,6 +25,12 @@ locals {
}
# fail if we have no valid defaults
_defaults = yamldecode(file(local.paths.defaults))
# provide sane VPC defaults
_vpc_defaults = {
auto_create_subnetworks = false
delete_default_route_on_create = true
mtu = 1500
}
ctx = merge(local._ctx, {
custom_roles = merge(var.custom_roles, local._ctx.custom_roles)
folder_ids = merge(var.folder_ids, var.context.folder_ids)
@@ -76,12 +82,10 @@ locals {
)
overrides = try(local._defaults.projects.overrides, {})
}
vpc_defaults = merge(
{
auto_create_subnetworks = false
delete_default_route_on_create = true
mtu = 1500
},
try(local._defaults.vpcs, {})
)
vpc_defaults = {
defaults = merge(
local._vpc_defaults, try(local._defaults.vpcs.defaults, {})
)
overrides = try(local._defaults.vpcs.overrides, {})
}
}

View File

@@ -432,17 +432,211 @@
"type": "object",
"additionalProperties": false,
"properties": {
"auto_create_subnetworks": {
"type": "boolean",
"default": false
"defaults": {
"type": "object",
"additionalProperties": false,
"properties": {
"project_id": {
"type": "string"
},
"description": {
"type": "string"
},
"auto_create_subnetworks": {
"type": "boolean"
},
"delete_default_routes_on_create": {
"type": "boolean"
},
"mtu": {
"type": "number",
"minimum": 1460,
"maximum": 1500
},
"routing_mode": {
"type": "string",
"enum": [
"GLOBAL",
"REGIONAL"
]
},
"firewall_policy_enforcement_order": {
"type": "string",
"enum": [
"BEFORE_CLASSIC_FIREWALL",
"AFTER_CLASSIC_FIREWALL"
]
},
"create_googleapis_routes": {
"type": "object",
"additionalProperties": false,
"properties": {
"directpath": {
"type": "boolean"
},
"directpath-6": {
"type": "boolean"
},
"private": {
"type": "boolean"
},
"private-6": {
"type": "boolean"
},
"restricted": {
"type": "boolean"
},
"restricted-6": {
"type": "boolean"
}
}
},
"dns_policy": {
"type": "object",
"additionalProperties": false,
"properties": {
"inbound": {
"type": "boolean"
},
"logging": {
"type": "boolean"
},
"outbound": {
"type": "object",
"additionalProperties": false,
"properties": {
"private_ns": {
"type": "array",
"items": {
"type": "string"
}
},
"public_ns": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"ipv6_config": {
"type": "object",
"additionalProperties": false,
"properties": {
"enable_ula_internal": {
"type": "boolean"
},
"internal_range": {
"type": "string"
}
}
}
}
},
"delete_default_route_on_create": {
"type": "boolean",
"default": true
},
"mtu": {
"type": "number",
"default": 1500
"overrides": {
"type": "object",
"additionalProperties": false,
"properties": {
"project_id": {
"type": "string"
},
"description": {
"type": "string"
},
"auto_create_subnetworks": {
"type": "boolean"
},
"delete_default_routes_on_create": {
"type": "boolean"
},
"mtu": {
"type": "number",
"minimum": 1460,
"maximum": 1500
},
"routing_mode": {
"type": "string",
"enum": [
"GLOBAL",
"REGIONAL"
]
},
"firewall_policy_enforcement_order": {
"type": "string",
"enum": [
"BEFORE_CLASSIC_FIREWALL",
"AFTER_CLASSIC_FIREWALL"
]
},
"create_googleapis_routes": {
"type": "object",
"additionalProperties": false,
"properties": {
"directpath": {
"type": "boolean"
},
"directpath-6": {
"type": "boolean"
},
"private": {
"type": "boolean"
},
"private-6": {
"type": "boolean"
},
"restricted": {
"type": "boolean"
},
"restricted-6": {
"type": "boolean"
}
}
},
"dns_policy": {
"type": "object",
"additionalProperties": false,
"properties": {
"inbound": {
"type": "boolean"
},
"logging": {
"type": "boolean"
},
"outbound": {
"type": "object",
"additionalProperties": false,
"properties": {
"private_ns": {
"type": "array",
"items": {
"type": "string"
}
},
"public_ns": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"ipv6_config": {
"type": "object",
"additionalProperties": false,
"properties": {
"enable_ula_internal": {
"type": "boolean"
},
"internal_range": {
"type": "string"
}
}
}
}
}
}
},

View File

@@ -123,10 +123,72 @@
- **is_dry_run**: *boolean*
- **vpcs**: *object*
<br>*additional properties: false*
- **auto_create_subnetworks**: *boolean*
- **delete_default_route_on_create**: *boolean*
- **mtu**: *number*
<br>*default: 1500*
- **defaults**: *object*
<br>*additional properties: false*
- **project_id**: *string*
- **description**: *string*
- **auto_create_subnetworks**: *boolean*
- **delete_default_routes_on_create**: *boolean*
- **mtu**: *number*
- **routing_mode**: *string*
<br>*enum: ['GLOBAL', 'REGIONAL']*
- **firewall_policy_enforcement_order**: *string*
<br>*enum: ['BEFORE_CLASSIC_FIREWALL', 'AFTER_CLASSIC_FIREWALL']*
- **create_googleapis_routes**: *object*
<br>*additional properties: false*
- **directpath**: *boolean*
- **directpath-6**: *boolean*
- **private**: *boolean*
- **private-6**: *boolean*
- **restricted**: *boolean*
- **restricted-6**: *boolean*
- **dns_policy**: *object*
<br>*additional properties: false*
- **inbound**: *boolean*
- **logging**: *boolean*
- **outbound**: *object*
<br>*additional properties: false*
- **private_ns**: *array*
- items: *string*
- **public_ns**: *array*
- items: *string*
- **ipv6_config**: *object*
<br>*additional properties: false*
- **enable_ula_internal**: *boolean*
- **internal_range**: *string*
- **overrides**: *object*
<br>*additional properties: false*
- **project_id**: *string*
- **description**: *string*
- **auto_create_subnetworks**: *boolean*
- **delete_default_routes_on_create**: *boolean*
- **mtu**: *number*
- **routing_mode**: *string*
<br>*enum: ['GLOBAL', 'REGIONAL']*
- **firewall_policy_enforcement_order**: *string*
<br>*enum: ['BEFORE_CLASSIC_FIREWALL', 'AFTER_CLASSIC_FIREWALL']*
- **create_googleapis_routes**: *object*
<br>*additional properties: false*
- **directpath**: *boolean*
- **directpath-6**: *boolean*
- **private**: *boolean*
- **private-6**: *boolean*
- **restricted**: *boolean*
- **restricted-6**: *boolean*
- **dns_policy**: *object*
<br>*additional properties: false*
- **inbound**: *boolean*
- **logging**: *boolean*
- **outbound**: *object*
<br>*additional properties: false*
- **private_ns**: *array*
- items: *string*
- **public_ns**: *array*
- items: *string*
- **ipv6_config**: *object*
<br>*additional properties: false*
- **enable_ula_internal**: *boolean*
- **internal_range**: *string*
- **context**: *object*
<br>*additional properties: false*
- **cidr_ranges_sets**: *object*

View File

@@ -1 +0,0 @@
../../../../modules/billing-account/schemas/budget.schema.json

View File

@@ -0,0 +1,179 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Budget",
"type": "object",
"additionalProperties": false,
"required": [
"amount"
],
"properties": {
"amount": {
"type": "object",
"additionalProperties": false,
"properties": {
"currency_code": {
"type": "string"
},
"nanos": {
"type": "number"
},
"units": {
"type": "number"
},
"use_last_period": {
"type": "boolean"
}
}
},
"display_name": {
"type": "string"
},
"filter": {
"type": "object",
"additionalProperties": false,
"properties": {
"credit_types_treatment": {
"type": "object",
"additionalProperties": false,
"properties": {
"exclude_all": {
"type": "boolean"
},
"include_specified": {
"type": "array",
"items": {
"type": "string",
"enum": [
"COMMITTED_USAGE_DISCOUNT",
"COMMITTED_USAGE_DISCOUNT_DOLLAR_BASE",
"DISCOUNT",
"FREE_TIER",
"PROMOTION",
"RESELLER_MARGIN",
"SUBSCRIPTION_BENEFIT",
"SUSTAINED_USAGE_DISCOUNT"
]
}
}
}
},
"label": {
"type": "object",
"additionalProperties": false,
"properties": {
"key": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"period": {
"type": "object",
"additionalProperties": false,
"properties": {
"calendar": {
"type": "string"
},
"custom": {
"type": "object",
"additionalProperties": false,
"properties": {
"start_date": {
"$ref": "#/$defs/date"
},
"end_date": {
"$ref": "#/$defs/date"
}
}
}
}
},
"projects": {
"type": "array",
"items": {
"type": "string"
}
},
"resource_ancestors": {
"type": "array",
"items": {
"type": "string"
}
},
"services": {
"type": "array",
"items": {
"type": "string"
}
},
"subaccounts": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"threshold_rules": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"percent"
],
"properties": {
"percent": {
"type": "number"
},
"forecasted_spend": {
"type": "boolean"
}
}
}
},
"update_rules": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-z0-9_-]+$": {
"type": "object",
"additionalProperties": false,
"properties": {
"disable_default_iam_recipients": {
"type": "boolean"
},
"monitoring_notification_channels": {
"type": "array",
"items": {
"type": "string"
}
},
"pubsub_topic": {
"type": "string"
}
}
}
}
}
},
"$defs": {
"date": {
"type": "object",
"additionalProperties": false,
"properties": {
"day": {
"type": "number"
},
"month": {
"type": "number"
},
"year": {
"type": "number"
}
}
}
}
}

View File

@@ -181,10 +181,10 @@ ingress:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [factories_config](variables.tf#L97) | Path to folder with YAML resource description data files. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [factories_config](variables.tf#L99) | Path to folder with YAML resource description data files. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [context](variables.tf#L17) | Context-specific interpolations. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [data_defaults](variables.tf#L27) | Optional default values used when corresponding vpc data from files are missing. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [data_overrides](variables.tf#L62) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [data_defaults](variables.tf#L29) | Optional default values used when corresponding vpc data from files are missing. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [data_overrides](variables.tf#L64) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
## Outputs

View File

@@ -15,23 +15,11 @@
*/
locals {
ctx = var.context
_vpcs_files = try(
fileset(local.paths.vpcs, "**/.config.yaml"),
[]
)
_defaults = try(
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, {})
)
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.paths.vpcs, "-")}/${f}")),
@@ -54,7 +42,6 @@ locals {
}
vpcs = {
for k, v in local._vpcs : k => merge(
try(local._defaults.vpcs, {}),
{ for k, v in var.data_defaults : k => v if v != null },
v,
{ for k, v in var.data_overrides : k => v if v != null },
@@ -81,6 +68,7 @@ locals {
module "vpcs" {
source = "../net-vpc"
for_each = local.vpcs
context = local.ctx
project_id = try(each.value.project_id, null)
name = try(each.value.name, null)
auto_create_subnetworks = try(each.value.auto_create_subnetworks, null)
@@ -95,7 +83,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")
context = local.context
}
module "firewall" {
@@ -103,12 +90,10 @@ module "firewall" {
for_each = {
for k, v in local.vpcs : k => v if v.firewall_factory_config != null
}
context = local.ctx
project_id = each.value.project_id
network = each.value.name
factories_config = each.value.firewall_factory_config
default_rules_config = { disabled = true }
context = {
project_ids = local.context.project_ids
}
depends_on = [module.vpcs]
depends_on = [module.vpcs]
}

View File

@@ -17,8 +17,10 @@
variable "context" {
description = "Context-specific interpolations."
type = object({
locations = optional(map(string), {})
project_ids = optional(map(string), {})
cidr_ranges_sets = optional(map(list(string)), {})
iam_principals = optional(map(string), {})
locations = optional(map(string), {})
project_ids = optional(map(string), {})
})
default = {}
nullable = false
@@ -29,9 +31,9 @@ variable "data_defaults" {
type = object({
project_id = optional(string)
description = optional(string, "Terraform managed")
auto_create_subnetworks = optional(bool)
auto_create_subnetworks = optional(bool, false)
delete_default_routes_on_create = optional(bool, true)
mtu = optional(number)
mtu = optional(number, 1500)
routing_mode = optional(string, "GLOBAL")
firewall_policy_enforcement_order = optional(string, "AFTER_CLASSIC_FIREWALL")
create_googleapis_routes = optional(object({
@@ -99,8 +101,7 @@ variable "factories_config" {
type = object({
basepath = string
paths = optional(object({
defaults = optional(string, "defaults.yaml")
vpcs = optional(string, "vpcs")
vpcs = optional(string, "vpcs")
}), {})
})
nullable = false

View File

@@ -960,8 +960,8 @@ secondary_ip_ranges:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L184) | The name of the network being created. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L261) | The ID of the project where this VPC will be created. | <code>string</code> | ✓ | |
| [name](variables.tf#L183) | The name of the network being created. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L260) | The ID of the project where this VPC will be created. | <code>string</code> | ✓ | |
| [auto_create_subnetworks](variables.tf#L17) | Set to true to create an auto mode subnet, defaults to custom mode. | <code>bool</code> | | <code>false</code> |
| [context](variables.tf#L23) | Context-specific interpolations. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [create_googleapis_routes](variables.tf#L45) | Toggle creation of googleapis private/restricted routes. Disabled when vpc creation is turned off, or when set to null. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
@@ -970,23 +970,23 @@ secondary_ip_ranges:
| [dns_policy](variables.tf#L70) | DNS policy setup for the VPC. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [factories_config](variables.tf#L83) | Paths to data files and folders that enable factory functionality. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [firewall_policy_enforcement_order](variables.tf#L92) | Order that Firewall Rules and Firewall Policies are evaluated. Can be either 'BEFORE_CLASSIC_FIREWALL' or 'AFTER_CLASSIC_FIREWALL'. | <code>string</code> | | <code>&#34;AFTER_CLASSIC_FIREWALL&#34;</code> |
| [internal_ranges](variables.tf#L104) | Internal range configuration for IPAM operations within the VPC network. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [ipv6_config](variables.tf#L168) | Optional IPv6 configuration for this network. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [mtu](variables.tf#L178) | Maximum Transmission Unit in bytes. The minimum value for this field is 1460 (the default) and the maximum value is 1500 bytes. | <code>number</code> | | <code>null</code> |
| [network_attachments](variables.tf#L189) | PSC network attachments, names as keys. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [peering_config](variables.tf#L202) | VPC peering configuration. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [policy_based_routes](variables.tf#L213) | Policy based routes, keyed by name. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [psa_configs](variables.tf#L266) | The Private Service Access configuration. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [routes](variables.tf#L298) | Network routes, keyed by name. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [routing_mode](variables.tf#L319) | The network routing mode (default 'GLOBAL'). | <code>string</code> | | <code>&#34;GLOBAL&#34;</code> |
| [service_connection_policies](variables.tf#L329) | Service connection policies, keyed by name. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [shared_vpc_host](variables.tf#L371) | Enable shared VPC for this project. | <code>bool</code> | | <code>false</code> |
| [shared_vpc_service_projects](variables.tf#L377) | Shared VPC service projects to register with this host. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets](variables.tf#L383) | Subnet configuration. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_private_nat](variables.tf#L463) | List of private NAT subnets. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_proxy_only](variables.tf#L475) | List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_psc](variables.tf#L509) | List of subnets for Private Service Connect service producers. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc_reuse](variables.tf#L549) | Reuse existing VPC if not null. If the network_id number is not passed in, a data source is used. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [internal_ranges](variables.tf#L103) | Internal range configuration for IPAM operations within the VPC network. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [ipv6_config](variables.tf#L167) | Optional IPv6 configuration for this network. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [mtu](variables.tf#L177) | Maximum Transmission Unit in bytes. The minimum value for this field is 1460 (the default) and the maximum value is 1500 bytes. | <code>number</code> | | <code>null</code> |
| [network_attachments](variables.tf#L188) | PSC network attachments, names as keys. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [peering_config](variables.tf#L201) | VPC peering configuration. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [policy_based_routes](variables.tf#L212) | Policy based routes, keyed by name. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [psa_configs](variables.tf#L265) | The Private Service Access configuration. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [routes](variables.tf#L297) | Network routes, keyed by name. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [routing_mode](variables.tf#L318) | The network routing mode (default 'GLOBAL'). | <code>string</code> | | <code>&#34;GLOBAL&#34;</code> |
| [service_connection_policies](variables.tf#L328) | Service connection policies, keyed by name. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [shared_vpc_host](variables.tf#L370) | Enable shared VPC for this project. | <code>bool</code> | | <code>false</code> |
| [shared_vpc_service_projects](variables.tf#L376) | Shared VPC service projects to register with this host. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets](variables.tf#L382) | Subnet configuration. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_private_nat](variables.tf#L462) | List of private NAT subnets. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_proxy_only](variables.tf#L474) | List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_psc](variables.tf#L508) | List of subnets for Private Service Connect service producers. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc_reuse](variables.tf#L548) | Reuse existing VPC if not null. If the network_id number is not passed in, a data source is used. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@@ -94,7 +94,6 @@ variable "firewall_policy_enforcement_order" {
type = string
nullable = false
default = "AFTER_CLASSIC_FIREWALL"
validation {
condition = var.firewall_policy_enforcement_order == "BEFORE_CLASSIC_FIREWALL" || var.firewall_policy_enforcement_order == "AFTER_CLASSIC_FIREWALL"
error_message = "Enforcement order must be BEFORE_CLASSIC_FIREWALL or AFTER_CLASSIC_FIREWALL."

View File

@@ -65,10 +65,10 @@ resource "google_logging_organization_settings" "default" {
? null
: lookup(local.ctx.kms_keys, var.logging_settings.kms_key_name, var.logging_settings.kms_key_name)
)
storage_location = lookup(
local.ctx.locations,
coalesce(var.logging_settings.storage_location, ""),
var.logging_settings.storage_location
storage_location = (
var.logging_settings.storage_location == null
? null
: lookup(local.ctx.locations, var.logging_settings.storage_location, var.logging_settings.storage_location)
)
}

View File

@@ -0,0 +1,45 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# yaml-language-server: $schema=../../../../../fast/stages/0-org-setup/schemas/defaults.schema.json
global:
billing_account: 012345-012345-012345
organization:
domain: example.org
id: 1234567890
customer_id: abcd123456
projects:
defaults:
prefix: ft0
locations:
bigquery: $locations:primary
logging: $locations:primary
storage: $locations:primary
overrides: {}
output_files:
local_path: /tmp/fast-config
storage_bucket: $storage_buckets:iac-0/iac-outputs
providers:
0-org-setup:
bucket: $storage_buckets:iac-0/iac-org-state
service_account: $iam_principals:service_accounts/iac-0/iac-org-rw
0-org-setup-ro:
bucket: $storage_buckets:iac-0/iac-org-state
service_account: $iam_principals:service_accounts/iac-0/iac-org-rw
context:
iam_principals:
gcp-organization-admins: group:fabric-fast-owners@google.com
locations:
primary: u-germany-northeast1

View File

@@ -8464,5 +8464,8 @@ outputs:
gcp-security-admins: group:gcp-security-admins@example.org
gcp-support: group:gcp-support@example.org
projects: __missing__
subnet_ips: {}
subnet_self_links: {}
tfvars: __missing__
vpc_self_links: {}

View File

@@ -2917,5 +2917,8 @@ outputs:
gcp-security-admins: group:gcp-security-admins@example.org
gcp-support: group:gcp-support@example.org
projects: __missing__
subnet_ips: {}
subnet_self_links: {}
tfvars: __missing__
vpc_self_links: {}

View File

@@ -0,0 +1,6 @@
factories_config = {
dataset = "datasets/starter-gcd"
paths = {
defaults = "./data-starter-gcd/defaults.yaml"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -15,13 +15,18 @@
module: fast/stages/0-org-setup
tests:
simple:
inventory:
- simple.yaml
extra_dirs:
- ../../../tests/fast/stages/s0_org_setup/data-simple
hardened:
inventory:
- hardened.yaml
extra_dirs:
- ../../../tests/fast/stages/s0_org_setup/data-hardened
simple:
inventory:
- simple.yaml
extra_dirs:
- ../../../tests/fast/stages/s0_org_setup/data-simple
starter-gcd:
inventory:
- starter-gcd.yaml
extra_dirs:
- ../../../tests/fast/stages/s0_org_setup/data-starter-gcd

View File

@@ -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,19 +29,20 @@ 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
auto_create_subnetworks: false
delete_bgp_always_compare_med: false
delete_default_routes_on_create: true
description: Terraform managed
enable_ula_internal_ipv6: null
mtu: 1500
name: data-vpc-0
network_firewall_policy_enforcement_order: AFTER_CLASSIC_FIREWALL
network_profile: null

View File

@@ -52,7 +52,9 @@ duplicates = [
"modules/vpc-sc/schemas/egress-policy.schema.json",
],
[
"fast/stages/0-org-setup/schemas/firewall-rules.schema.json",
"fast/stages/2-networking/schemas/firewall-rules.schema.json",
"modules/net-vpc-factory/schemas/firewall-rules.schema.json",
"modules/net-vpc-firewall/schemas/firewall-rules.schema.json",
],
[
@@ -98,9 +100,15 @@ duplicates = [
"modules/organization/schemas/scc-sha-custom-modules.schema.json",
],
[
"fast/stages/0-org-setup/schemas/subnet.schema.json",
"fast/stages/2-networking/schemas/subnet.schema.json",
"modules/net-vpc-factory/schemas/subnet.schema.json",
"modules/net-vpc/schemas/subnet.schema.json",
],
[
"fast/stages/0-org-setup/schemas/vpc-factory.schema.json",
"modules/net-vpc-factory/schemas/vpc-factory.schema.json",
],
[
"fast/stages/0-org-setup/schemas/tags.schema.json",
"modules/project/schemas/tags.schema.json",