diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5447235c7..9346fc030 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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. diff --git a/GEMINI.md b/GEMINI.md index 9746ded63..142c2632c 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -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_/tftest.yaml::`. For example: `pytest tests/fast/stages/s0_org_setup/tftest.yaml::starter-gcd`. diff --git a/fast/stages/0-org-setup/README.md b/fast/stages/0-org-setup/README.md index 95d60330d..a456ad0e1 100644 --- a/fast/stages/0-org-setup/README.md +++ b/fast/stages/0-org-setup/README.md @@ -899,7 +899,7 @@ Define values for the `var.environments` variable in a tfvars file. | [billing.tf](./billing.tf) | None | billing-account | | | [cicd-workflows-preconditions.tf](./cicd-workflows-preconditions.tf) | None | | terraform_data | | [cicd-workflows.tf](./cicd-workflows.tf) | None | iam-service-account | google_storage_bucket_object · local_file | -| [factory.tf](./factory.tf) | None | project-factory | | +| [factory.tf](./factory.tf) | None | net-vpc-factory · project-factory | | | [identity-providers-defs.tf](./identity-providers-defs.tf) | None | | | | [imports.tf](./imports.tf) | None | | | | [main.tf](./main.tf) | Module-level locals and resources. | | terraform_data | @@ -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. | object({…}) | | {} | -| [factories_config](variables.tf#L40) | Configuration for the resource factories or external data. | object({…}) | | {} | -| [org_policies_imports](variables.tf#L59) | List of org policies to import. These need to also be defined in data files. | list(string) | | [] | +| [factories_config](variables.tf#L41) | Configuration for the resource factories or external data. | object({…}) | | {} | +| [org_policies_imports](variables.tf#L61) | List of org policies to import. These need to also be defined in data files. | list(string) | | [] | ## 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. | | diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/defaults.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/defaults.yaml new file mode 100644 index 000000000..b7acfc6ac --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/defaults.yaml @@ -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: + 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: +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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/folders/dev/.config.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/folders/dev/.config.yaml new file mode 100644 index 000000000..700f5219a --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/folders/dev/.config.yaml @@ -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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/folders/prod/.config.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/folders/prod/.config.yaml new file mode 100644 index 000000000..f09758b6c --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/folders/prod/.config.yaml @@ -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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/organization/.config.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/organization/.config.yaml new file mode 100644 index 000000000..d99f496ac --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/organization/.config.yaml @@ -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: [] diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/organization/tags/environment.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/organization/tags/environment.yaml new file mode 100644 index 000000000..4580772b4 --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/organization/tags/environment.yaml @@ -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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/projects/apps/dev-app-0.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/projects/apps/dev-app-0.yaml new file mode 100644 index 000000000..de3a36d9d --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/projects/apps/dev-app-0.yaml @@ -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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/projects/apps/prod-app-0.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/projects/apps/prod-app-0.yaml new file mode 100644 index 000000000..272953578 --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/projects/apps/prod-app-0.yaml @@ -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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/projects/iac-0.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/projects/iac-0.yaml new file mode 100644 index 000000000..1ad613537 --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/projects/iac-0.yaml @@ -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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/projects/net/dev-net-0.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/projects/net/dev-net-0.yaml new file mode 100644 index 000000000..b25044eec --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/projects/net/dev-net-0.yaml @@ -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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/projects/net/prod-net-0.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/projects/net/prod-net-0.yaml new file mode 100644 index 000000000..4607c7669 --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/projects/net/prod-net-0.yaml @@ -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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/dev/.config.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/dev/.config.yaml new file mode 100644 index 000000000..a03764602 --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/dev/.config.yaml @@ -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 diff --git a/modules/net-vpc-factory/data/defaults.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/dev/firewall-rules/default-ingress.yaml similarity index 54% rename from modules/net-vpc-factory/data/defaults.yaml rename to fast/stages/0-org-setup/datasets/starter-gcd/vpcs/dev/firewall-rules/default-ingress.yaml index a7a1fd14e..f224df256 100644 --- a/modules/net-vpc-factory/data/defaults.yaml +++ b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/dev/firewall-rules/default-ingress.yaml @@ -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: [] diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/dev/subnets/default.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/dev/subnets/default.yaml new file mode 100644 index 000000000..ba2683ce3 --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/dev/subnets/default.yaml @@ -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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/prod/.config.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/prod/.config.yaml new file mode 100644 index 000000000..98071fab3 --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/prod/.config.yaml @@ -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 diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/prod/firewall-rules/default-ingress.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/prod/firewall-rules/default-ingress.yaml new file mode 100644 index 000000000..f224df256 --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/prod/firewall-rules/default-ingress.yaml @@ -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: [] diff --git a/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/prod/subnets/default.yaml b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/prod/subnets/default.yaml new file mode 100644 index 000000000..15f1b856b --- /dev/null +++ b/fast/stages/0-org-setup/datasets/starter-gcd/vpcs/prod/subnets/default.yaml @@ -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 diff --git a/fast/stages/0-org-setup/factory.tf b/fast/stages/0-org-setup/factory.tf index 4a6acf9cd..185a26a3b 100644 --- a/fast/stages/0-org-setup/factory.tf +++ b/fast/stages/0-org-setup/factory.tf @@ -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 + } + } +} diff --git a/fast/stages/0-org-setup/main.tf b/fast/stages/0-org-setup/main.tf index 129c2f6e1..8c9b6cdf9 100644 --- a/fast/stages/0-org-setup/main.tf +++ b/fast/stages/0-org-setup/main.tf @@ -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 : diff --git a/fast/stages/0-org-setup/output-files.tf b/fast/stages/0-org-setup/output-files.tf index ce79a16e6..fba1a3204 100644 --- a/fast/stages/0-org-setup/output-files.tf +++ b/fast/stages/0-org-setup/output-files.tf @@ -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 } diff --git a/fast/stages/0-org-setup/outputs.tf b/fast/stages/0-org-setup/outputs.tf index d4a36a32a..aa64ecf77 100644 --- a/fast/stages/0-org-setup/outputs.tf +++ b/fast/stages/0-org-setup/outputs.tf @@ -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 + } +} + diff --git a/fast/stages/0-org-setup/schemas/defaults.schema.json b/fast/stages/0-org-setup/schemas/defaults.schema.json index 3f61f05f5..ba9012e2f 100644 --- a/fast/stages/0-org-setup/schemas/defaults.schema.json +++ b/fast/stages/0-org-setup/schemas/defaults.schema.json @@ -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": { diff --git a/fast/stages/0-org-setup/schemas/defaults.schema.md b/fast/stages/0-org-setup/schemas/defaults.schema.md index 336eb607e..1a720275e 100644 --- a/fast/stages/0-org-setup/schemas/defaults.schema.md +++ b/fast/stages/0-org-setup/schemas/defaults.schema.md @@ -127,8 +127,78 @@ - **vpc_sc**: *object* - ⁺**perimeter_name**: *string* - **is_dry_run**: *boolean* +- **vpcs**: *object* +
*additional properties: false* + - **defaults**: *object* +
*additional properties: false* + - **project_id**: *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**: *object* +
*additional properties: false* + - **directpath**: *boolean* + - **directpath-6**: *boolean* + - **private**: *boolean* + - **private-6**: *boolean* + - **restricted**: *boolean* + - **restricted-6**: *boolean* + - **dns_policy**: *object* +
*additional properties: false* + - **inbound**: *boolean* + - **logging**: *boolean* + - **outbound**: *object* +
*additional properties: false* + - **private_ns**: *array* + - items: *string* + - **public_ns**: *array* + - items: *string* + - **ipv6_config**: *object* +
*additional properties: false* + - **enable_ula_internal**: *boolean* + - **internal_range**: *string* + - **overrides**: *object* +
*additional properties: false* + - **project_id**: *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**: *object* +
*additional properties: false* + - **directpath**: *boolean* + - **directpath-6**: *boolean* + - **private**: *boolean* + - **private-6**: *boolean* + - **restricted**: *boolean* + - **restricted-6**: *boolean* + - **dns_policy**: *object* +
*additional properties: false* + - **inbound**: *boolean* + - **logging**: *boolean* + - **outbound**: *object* +
*additional properties: false* + - **private_ns**: *array* + - items: *string* + - **public_ns**: *array* + - items: *string* + - **ipv6_config**: *object* +
*additional properties: false* + - **enable_ula_internal**: *boolean* + - **internal_range**: *string* - **context**: *object*
*additional properties: false* + - **cidr_ranges_sets**: *object* +
*additional properties: array* - **custom_roles**: *object*
*additional properties: string* - **email_addresses**: *object* diff --git a/fast/stages/0-org-setup/schemas/firewall-rules.schema.json b/fast/stages/0-org-setup/schemas/firewall-rules.schema.json new file mode 100644 index 000000000..029bf85a6 --- /dev/null +++ b/fast/stages/0-org-setup/schemas/firewall-rules.schema.json @@ -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]+)?$" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/fast/stages/0-org-setup/schemas/firewall-rules.schema.md b/fast/stages/0-org-setup/schemas/firewall-rules.schema.md new file mode 100644 index 000000000..40dd6d8e8 --- /dev/null +++ b/fast/stages/0-org-setup/schemas/firewall-rules.schema.md @@ -0,0 +1,42 @@ +# Firewall Rules + + + +## Properties + +*additional properties: false* + +- **egress**: *object* +
*additional properties: false* + - **`^[a-z0-9_-]+$`**: *reference([rule](#refs-rule))* +- **ingress**: *object* +
*additional properties: false* + - **`^[a-z0-9_-]+$`**: *reference([rule](#refs-rule))* + +## Definitions + +- **rule**: *object* +
*additional properties: false* + - **deny**: *boolean* + - **description**: *string* + - **destination_ranges**: *array* + - items: *string* + - **disabled**: *boolean* + - **enable_logging**: *object* +
*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* +
*additional properties: false* + - **protocol**: *string* + - **ports**: *array* + - items: *(integer|string)* +
*pattern: `^[0-9]+(?:-[0-9]+)?$`* diff --git a/fast/stages/0-org-setup/schemas/subnet.schema.json b/fast/stages/0-org-setup/schemas/subnet.schema.json new file mode 100644 index 000000000..6e1095692 --- /dev/null +++ b/fast/stages/0-org-setup/schemas/subnet.schema.json @@ -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" + } + } + } + } + } + } + } + } +} diff --git a/fast/stages/0-org-setup/schemas/subnet.schema.md b/fast/stages/0-org-setup/schemas/subnet.schema.md new file mode 100644 index 000000000..26e23fcd8 --- /dev/null +++ b/fast/stages/0-org-setup/schemas/subnet.schema.md @@ -0,0 +1,77 @@ +# Subnet + + + +## Properties + +*additional properties: false* + +- **active**: *boolean* +- **description**: *string* +- **enable_private_access**: *boolean* +- **allow_subnet_cidr_routes_overlap**: *boolean* +- **flow_logs_config**: *object* +
*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* +
*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* +
*additional properties: oneof* + - *string* + - *object* +
*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**: *object* +
*additional properties: false* + - **`^roles/`**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|ro|rw)* +- **iam_bindings**: *object* +
*additional properties: false* + - **`^[a-z0-9_-]+$`**: *object* +
*additional properties: false* + - **members**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|ro|rw)* + - **role**: *string* +
*pattern: ^roles/* + - **condition**: *object* +
*additional properties: false* + - ⁺**expression**: *string* + - ⁺**title**: *string* + - **description**: *string* +- **iam_bindings_additive**: *object* +
*additional properties: false* + - **`^[a-z0-9_-]+$`**: *object* +
*additional properties: false* + - **member**: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|ro|rw)* + - **role**: *string* +
*pattern: ^roles/* + - **condition**: *object* +
*additional properties: false* + - ⁺**expression**: *string* + - ⁺**title**: *string* + - **description**: *string* diff --git a/fast/stages/0-org-setup/schemas/vpc-factory.schema.json b/fast/stages/0-org-setup/schemas/vpc-factory.schema.json new file mode 100644 index 000000000..6ba88bff1 --- /dev/null +++ b/fast/stages/0-org-setup/schemas/vpc-factory.schema.json @@ -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" + } + } + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/fast/stages/0-org-setup/schemas/vpc-factory.schema.md b/fast/stages/0-org-setup/schemas/vpc-factory.schema.md new file mode 100644 index 000000000..1e60c09d2 --- /dev/null +++ b/fast/stages/0-org-setup/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/fast/stages/0-org-setup/variables.tf b/fast/stages/0-org-setup/variables.tf index facd77314..d866b1397 100644 --- a/fast/stages/0-org-setup/variables.tf +++ b/fast/stages/0-org-setup/variables.tf @@ -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 diff --git a/fast/stages/2-networking/datasets/hub-and-spokes-ncc/defaults.yaml b/fast/stages/2-networking/datasets/hub-and-spokes-ncc/defaults.yaml index f741812c5..a38bdec87 100644 --- a/fast/stages/2-networking/datasets/hub-and-spokes-ncc/defaults.yaml +++ b/fast/stages/2-networking/datasets/hub-and-spokes-ncc/defaults.yaml @@ -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 diff --git a/fast/stages/2-networking/datasets/hub-and-spokes-nva/defaults.yaml b/fast/stages/2-networking/datasets/hub-and-spokes-nva/defaults.yaml index f741812c5..a38bdec87 100644 --- a/fast/stages/2-networking/datasets/hub-and-spokes-nva/defaults.yaml +++ b/fast/stages/2-networking/datasets/hub-and-spokes-nva/defaults.yaml @@ -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 diff --git a/fast/stages/2-networking/datasets/hub-and-spokes-peerings/defaults.yaml b/fast/stages/2-networking/datasets/hub-and-spokes-peerings/defaults.yaml index f741812c5..a38bdec87 100644 --- a/fast/stages/2-networking/datasets/hub-and-spokes-peerings/defaults.yaml +++ b/fast/stages/2-networking/datasets/hub-and-spokes-peerings/defaults.yaml @@ -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 diff --git a/fast/stages/2-networking/datasets/hub-and-spokes-vpns/defaults.yaml b/fast/stages/2-networking/datasets/hub-and-spokes-vpns/defaults.yaml index f741812c5..a38bdec87 100644 --- a/fast/stages/2-networking/datasets/hub-and-spokes-vpns/defaults.yaml +++ b/fast/stages/2-networking/datasets/hub-and-spokes-vpns/defaults.yaml @@ -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 diff --git a/fast/stages/2-networking/factory-vpcs.tf b/fast/stages/2-networking/factory-vpcs.tf index 2274ee97b..a580a1ced 100644 --- a/fast/stages/2-networking/factory-vpcs.tf +++ b/fast/stages/2-networking/factory-vpcs.tf @@ -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 diff --git a/fast/stages/2-networking/main.tf b/fast/stages/2-networking/main.tf index 929f6891f..3bcff6b90 100644 --- a/fast/stages/2-networking/main.tf +++ b/fast/stages/2-networking/main.tf @@ -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, {}) + } } diff --git a/fast/stages/2-networking/schemas/defaults.schema.json b/fast/stages/2-networking/schemas/defaults.schema.json index cb125a16c..7d91715df 100644 --- a/fast/stages/2-networking/schemas/defaults.schema.json +++ b/fast/stages/2-networking/schemas/defaults.schema.json @@ -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" + } + } + } + } } } }, diff --git a/fast/stages/2-networking/schemas/defaults.schema.md b/fast/stages/2-networking/schemas/defaults.schema.md index 4914408c7..e7478f846 100644 --- a/fast/stages/2-networking/schemas/defaults.schema.md +++ b/fast/stages/2-networking/schemas/defaults.schema.md @@ -123,10 +123,72 @@ - **is_dry_run**: *boolean* - **vpcs**: *object*
*additional properties: false* - - **auto_create_subnetworks**: *boolean* - - **delete_default_route_on_create**: *boolean* - - **mtu**: *number* -
*default: 1500* + - **defaults**: *object* +
*additional properties: false* + - **project_id**: *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**: *object* +
*additional properties: false* + - **directpath**: *boolean* + - **directpath-6**: *boolean* + - **private**: *boolean* + - **private-6**: *boolean* + - **restricted**: *boolean* + - **restricted-6**: *boolean* + - **dns_policy**: *object* +
*additional properties: false* + - **inbound**: *boolean* + - **logging**: *boolean* + - **outbound**: *object* +
*additional properties: false* + - **private_ns**: *array* + - items: *string* + - **public_ns**: *array* + - items: *string* + - **ipv6_config**: *object* +
*additional properties: false* + - **enable_ula_internal**: *boolean* + - **internal_range**: *string* + - **overrides**: *object* +
*additional properties: false* + - **project_id**: *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**: *object* +
*additional properties: false* + - **directpath**: *boolean* + - **directpath-6**: *boolean* + - **private**: *boolean* + - **private-6**: *boolean* + - **restricted**: *boolean* + - **restricted-6**: *boolean* + - **dns_policy**: *object* +
*additional properties: false* + - **inbound**: *boolean* + - **logging**: *boolean* + - **outbound**: *object* +
*additional properties: false* + - **private_ns**: *array* + - items: *string* + - **public_ns**: *array* + - items: *string* + - **ipv6_config**: *object* +
*additional properties: false* + - **enable_ula_internal**: *boolean* + - **internal_range**: *string* - **context**: *object*
*additional properties: false* - **cidr_ranges_sets**: *object* diff --git a/fast/stages/2-project-factory/schemas/budget.schema.json b/fast/stages/2-project-factory/schemas/budget.schema.json deleted file mode 120000 index cc5d28d4d..000000000 --- a/fast/stages/2-project-factory/schemas/budget.schema.json +++ /dev/null @@ -1 +0,0 @@ -../../../../modules/billing-account/schemas/budget.schema.json \ No newline at end of file diff --git a/fast/stages/2-project-factory/schemas/budget.schema.json b/fast/stages/2-project-factory/schemas/budget.schema.json new file mode 100644 index 000000000..af145dcc1 --- /dev/null +++ b/fast/stages/2-project-factory/schemas/budget.schema.json @@ -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" + } + } + } + } +} \ No newline at end of file diff --git a/modules/net-vpc-factory/README.md b/modules/net-vpc-factory/README.md index 03d39c2cf..63c060652 100644 --- a/modules/net-vpc-factory/README.md +++ b/modules/net-vpc-factory/README.md @@ -181,10 +181,10 @@ ingress: | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [factories_config](variables.tf#L97) | Path to folder with YAML resource description data files. | object({…}) | ✓ | | +| [factories_config](variables.tf#L99) | Path to folder with YAML resource description data files. | object({…}) | ✓ | | | [context](variables.tf#L17) | Context-specific interpolations. | object({…}) | | {} | -| [data_defaults](variables.tf#L27) | Optional default values used when corresponding vpc data from files are missing. | object({…}) | | {} | -| [data_overrides](variables.tf#L62) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | +| [data_defaults](variables.tf#L29) | Optional default values used when corresponding vpc data from files are missing. | object({…}) | | {} | +| [data_overrides](variables.tf#L64) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | ## Outputs diff --git a/modules/net-vpc-factory/main.tf b/modules/net-vpc-factory/main.tf index f6c29226a..5df1af3c8 100644 --- a/modules/net-vpc-factory/main.tf +++ b/modules/net-vpc-factory/main.tf @@ -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] } diff --git a/modules/net-vpc-factory/variables.tf b/modules/net-vpc-factory/variables.tf index 9bd65b20c..53162517d 100644 --- a/modules/net-vpc-factory/variables.tf +++ b/modules/net-vpc-factory/variables.tf @@ -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 diff --git a/modules/net-vpc/README.md b/modules/net-vpc/README.md index fb2964c2b..3281d077e 100644 --- a/modules/net-vpc/README.md +++ b/modules/net-vpc/README.md @@ -960,8 +960,8 @@ secondary_ip_ranges: | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [name](variables.tf#L184) | The name of the network being created. | string | ✓ | | -| [project_id](variables.tf#L261) | The ID of the project where this VPC will be created. | string | ✓ | | +| [name](variables.tf#L183) | The name of the network being created. | string | ✓ | | +| [project_id](variables.tf#L260) | The ID of the project where this VPC will be created. | string | ✓ | | | [auto_create_subnetworks](variables.tf#L17) | Set to true to create an auto mode subnet, defaults to custom mode. | bool | | false | | [context](variables.tf#L23) | Context-specific interpolations. | object({…}) | | {} | | [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. | object({…}) | | {} | @@ -970,23 +970,23 @@ secondary_ip_ranges: | [dns_policy](variables.tf#L70) | DNS policy setup for the VPC. | object({…}) | | null | | [factories_config](variables.tf#L83) | Paths to data files and folders that enable factory functionality. | object({…}) | | {} | | [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'. | string | | "AFTER_CLASSIC_FIREWALL" | -| [internal_ranges](variables.tf#L104) | Internal range configuration for IPAM operations within the VPC network. | list(object({…})) | | [] | -| [ipv6_config](variables.tf#L168) | Optional IPv6 configuration for this network. | object({…}) | | {} | -| [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. | number | | null | -| [network_attachments](variables.tf#L189) | PSC network attachments, names as keys. | map(object({…})) | | {} | -| [peering_config](variables.tf#L202) | VPC peering configuration. | object({…}) | | null | -| [policy_based_routes](variables.tf#L213) | Policy based routes, keyed by name. | map(object({…})) | | {} | -| [psa_configs](variables.tf#L266) | The Private Service Access configuration. | list(object({…})) | | [] | -| [routes](variables.tf#L298) | Network routes, keyed by name. | map(object({…})) | | {} | -| [routing_mode](variables.tf#L319) | The network routing mode (default 'GLOBAL'). | string | | "GLOBAL" | -| [service_connection_policies](variables.tf#L329) | Service connection policies, keyed by name. | map(object({…})) | | {} | -| [shared_vpc_host](variables.tf#L371) | Enable shared VPC for this project. | bool | | false | -| [shared_vpc_service_projects](variables.tf#L377) | Shared VPC service projects to register with this host. | list(string) | | [] | -| [subnets](variables.tf#L383) | Subnet configuration. | list(object({…})) | | [] | -| [subnets_private_nat](variables.tf#L463) | List of private NAT subnets. | list(object({…})) | | [] | -| [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. | list(object({…})) | | [] | -| [subnets_psc](variables.tf#L509) | List of subnets for Private Service Connect service producers. | list(object({…})) | | [] | -| [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. | object({…}) | | null | +| [internal_ranges](variables.tf#L103) | Internal range configuration for IPAM operations within the VPC network. | list(object({…})) | | [] | +| [ipv6_config](variables.tf#L167) | Optional IPv6 configuration for this network. | object({…}) | | {} | +| [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. | number | | null | +| [network_attachments](variables.tf#L188) | PSC network attachments, names as keys. | map(object({…})) | | {} | +| [peering_config](variables.tf#L201) | VPC peering configuration. | object({…}) | | null | +| [policy_based_routes](variables.tf#L212) | Policy based routes, keyed by name. | map(object({…})) | | {} | +| [psa_configs](variables.tf#L265) | The Private Service Access configuration. | list(object({…})) | | [] | +| [routes](variables.tf#L297) | Network routes, keyed by name. | map(object({…})) | | {} | +| [routing_mode](variables.tf#L318) | The network routing mode (default 'GLOBAL'). | string | | "GLOBAL" | +| [service_connection_policies](variables.tf#L328) | Service connection policies, keyed by name. | map(object({…})) | | {} | +| [shared_vpc_host](variables.tf#L370) | Enable shared VPC for this project. | bool | | false | +| [shared_vpc_service_projects](variables.tf#L376) | Shared VPC service projects to register with this host. | list(string) | | [] | +| [subnets](variables.tf#L382) | Subnet configuration. | list(object({…})) | | [] | +| [subnets_private_nat](variables.tf#L462) | List of private NAT subnets. | list(object({…})) | | [] | +| [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. | list(object({…})) | | [] | +| [subnets_psc](variables.tf#L508) | List of subnets for Private Service Connect service producers. | list(object({…})) | | [] | +| [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. | object({…}) | | null | ## Outputs diff --git a/modules/net-vpc/variables.tf b/modules/net-vpc/variables.tf index 224f4d7ed..6db0441a9 100644 --- a/modules/net-vpc/variables.tf +++ b/modules/net-vpc/variables.tf @@ -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." diff --git a/modules/organization/logging.tf b/modules/organization/logging.tf index f88b61f02..4aa0113c0 100644 --- a/modules/organization/logging.tf +++ b/modules/organization/logging.tf @@ -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) ) } diff --git a/tests/fast/stages/s0_org_setup/data-starter-gcd/defaults.yaml b/tests/fast/stages/s0_org_setup/data-starter-gcd/defaults.yaml new file mode 100644 index 000000000..1a3cb73c7 --- /dev/null +++ b/tests/fast/stages/s0_org_setup/data-starter-gcd/defaults.yaml @@ -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 diff --git a/tests/fast/stages/s0_org_setup/hardened.yaml b/tests/fast/stages/s0_org_setup/hardened.yaml index 36c497d27..178d48305 100644 --- a/tests/fast/stages/s0_org_setup/hardened.yaml +++ b/tests/fast/stages/s0_org_setup/hardened.yaml @@ -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: {} diff --git a/tests/fast/stages/s0_org_setup/simple.yaml b/tests/fast/stages/s0_org_setup/simple.yaml index f210a0f22..f6ebaba3c 100644 --- a/tests/fast/stages/s0_org_setup/simple.yaml +++ b/tests/fast/stages/s0_org_setup/simple.yaml @@ -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: {} diff --git a/tests/fast/stages/s0_org_setup/starter-gcd.tfvars b/tests/fast/stages/s0_org_setup/starter-gcd.tfvars new file mode 100644 index 000000000..ce5179932 --- /dev/null +++ b/tests/fast/stages/s0_org_setup/starter-gcd.tfvars @@ -0,0 +1,6 @@ +factories_config = { + dataset = "datasets/starter-gcd" + paths = { + defaults = "./data-starter-gcd/defaults.yaml" + } +} diff --git a/tests/fast/stages/s0_org_setup/starter-gcd.yaml b/tests/fast/stages/s0_org_setup/starter-gcd.yaml new file mode 100644 index 000000000..eb272b24f --- /dev/null +++ b/tests/fast/stages/s0_org_setup/starter-gcd.yaml @@ -0,0 +1,1383 @@ +# 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. + +values: + google_storage_bucket_object.providers["0-org-setup"]: + bucket: ft0-prod-iac-core-0-iac-outputs + cache_control: null + content: "/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache\ + \ License, Version 2.0 (the \"License\");\n * you may not use this file except\ + \ in compliance with the License.\n * You may obtain a copy of the License at\n\ + \ *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required\ + \ by applicable law or agreed to in writing, software\n * distributed under\ + \ the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR\ + \ CONDITIONS OF ANY KIND, either express or implied.\n * See the License for\ + \ the specific language governing permissions and\n * limitations under the\ + \ License.\n */\n\nterraform {\n backend \"gcs\" {\n bucket \ + \ = \"ft0-prod-iac-core-0-iac-org-state\"\n impersonate_service_account\ + \ = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\n }\n}\nprovider\ + \ \"google\" {\n impersonate_service_account = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\ + \n}\nprovider \"google-beta\" {\n impersonate_service_account = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\ + \n}\n" + content_disposition: null + content_encoding: null + content_language: null + contexts: [] + customer_encryption: [] + deletion_policy: null + detect_md5hash: null + event_based_hold: null + force_empty_content_type: null + metadata: null + name: providers/0-org-setup-providers.tf + retention: [] + source: null + source_md5hash: 2a0bbb00e4b7f1454a50ac7f26c23c05 + temporary_hold: null + timeouts: null + google_storage_bucket_object.providers["0-org-setup-ro"]: + bucket: ft0-prod-iac-core-0-iac-outputs + cache_control: null + content: "/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache\ + \ License, Version 2.0 (the \"License\");\n * you may not use this file except\ + \ in compliance with the License.\n * You may obtain a copy of the License at\n\ + \ *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required\ + \ by applicable law or agreed to in writing, software\n * distributed under\ + \ the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR\ + \ CONDITIONS OF ANY KIND, either express or implied.\n * See the License for\ + \ the specific language governing permissions and\n * limitations under the\ + \ License.\n */\n\nterraform {\n backend \"gcs\" {\n bucket \ + \ = \"ft0-prod-iac-core-0-iac-org-state\"\n impersonate_service_account\ + \ = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\n }\n}\nprovider\ + \ \"google\" {\n impersonate_service_account = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\ + \n}\nprovider \"google-beta\" {\n impersonate_service_account = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\ + \n}\n" + content_disposition: null + content_encoding: null + content_language: null + contexts: [] + customer_encryption: [] + deletion_policy: null + detect_md5hash: null + event_based_hold: null + force_empty_content_type: null + metadata: null + name: providers/0-org-setup-ro-providers.tf + retention: [] + source: null + source_md5hash: 2a0bbb00e4b7f1454a50ac7f26c23c05 + temporary_hold: null + timeouts: null + google_storage_bucket_object.tfvars["globals"]: + bucket: ft0-prod-iac-core-0-iac-outputs + cache_control: null + content: '{"billing_account":{"id":"012345-012345-012345"},"groups":{"domain":"domain:example.org","gcp-billing-admins":"group:gcp-billing-admins@example.org","gcp-devops":"group:gcp-devops@example.org","gcp-network-admins":"group:gcp-network-admins@example.org","gcp-organization-admins":"group:fabric-fast-owners@google.com","gcp-secops-admins":"group:gcp-secops-admins@example.org","gcp-security-admins":"group:gcp-security-admins@example.org","gcp-support":"group:gcp-support@example.org"},"organization":{"customer_id":"abcd123456","domain":"example.org","id":"1234567890"},"prefix":"ft0","universe":null}' + content_disposition: null + content_encoding: null + content_language: null + contexts: [] + customer_encryption: [] + deletion_policy: null + detect_md5hash: null + event_based_hold: null + force_empty_content_type: null + metadata: null + name: tfvars/0-globals.auto.tfvars.json + retention: [] + source: null + source_md5hash: cdbf79d3eff8bced040e5deccf39d765 + temporary_hold: null + timeouts: null + google_storage_bucket_object.tfvars["org-setup"]: + bucket: ft0-prod-iac-core-0-iac-outputs + cache_control: null + content_disposition: null + content_encoding: null + content_language: null + contexts: [] + customer_encryption: [] + deletion_policy: null + detect_md5hash: null + event_based_hold: null + force_empty_content_type: null + metadata: null + name: tfvars/0-org-setup.auto.tfvars.json + retention: [] + source: null + temporary_hold: null + timeouts: null + google_storage_bucket_object.version[0]: + bucket: ft0-prod-iac-core-0-iac-outputs + cache_control: null + content_disposition: null + content_encoding: null + content_language: null + contexts: [] + customer_encryption: [] + deletion_policy: null + detect_md5hash: null + event_based_hold: null + force_empty_content_type: null + metadata: null + name: versions/0-org-setup-version.txt + retention: [] + source: fast_version.txt + source_md5hash: f20ea48e4666fcbce129cff9fa658d16 + temporary_hold: null + timeouts: null + local_file.providers["0-org-setup"]: + content: "/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache\ + \ License, Version 2.0 (the \"License\");\n * you may not use this file except\ + \ in compliance with the License.\n * You may obtain a copy of the License at\n\ + \ *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required\ + \ by applicable law or agreed to in writing, software\n * distributed under\ + \ the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR\ + \ CONDITIONS OF ANY KIND, either express or implied.\n * See the License for\ + \ the specific language governing permissions and\n * limitations under the\ + \ License.\n */\n\nterraform {\n backend \"gcs\" {\n bucket \ + \ = \"ft0-prod-iac-core-0-iac-org-state\"\n impersonate_service_account\ + \ = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\n }\n}\nprovider\ + \ \"google\" {\n impersonate_service_account = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\ + \n}\nprovider \"google-beta\" {\n impersonate_service_account = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\ + \n}\n" + content_base64: null + directory_permission: '0777' + file_permission: '0644' + filename: /tmp/fast-config/providers/0-org-setup-providers.tf + sensitive_content: null + source: null + local_file.providers["0-org-setup-ro"]: + content: "/**\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache\ + \ License, Version 2.0 (the \"License\");\n * you may not use this file except\ + \ in compliance with the License.\n * You may obtain a copy of the License at\n\ + \ *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required\ + \ by applicable law or agreed to in writing, software\n * distributed under\ + \ the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR\ + \ CONDITIONS OF ANY KIND, either express or implied.\n * See the License for\ + \ the specific language governing permissions and\n * limitations under the\ + \ License.\n */\n\nterraform {\n backend \"gcs\" {\n bucket \ + \ = \"ft0-prod-iac-core-0-iac-org-state\"\n impersonate_service_account\ + \ = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\n }\n}\nprovider\ + \ \"google\" {\n impersonate_service_account = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\ + \n}\nprovider \"google-beta\" {\n impersonate_service_account = \"iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com\"\ + \n}\n" + content_base64: null + directory_permission: '0777' + file_permission: '0644' + filename: /tmp/fast-config/providers/0-org-setup-ro-providers.tf + sensitive_content: null + source: null + local_file.tfvars["globals"]: + content: '{"billing_account":{"id":"012345-012345-012345"},"groups":{"domain":"domain:example.org","gcp-billing-admins":"group:gcp-billing-admins@example.org","gcp-devops":"group:gcp-devops@example.org","gcp-network-admins":"group:gcp-network-admins@example.org","gcp-organization-admins":"group:fabric-fast-owners@google.com","gcp-secops-admins":"group:gcp-secops-admins@example.org","gcp-security-admins":"group:gcp-security-admins@example.org","gcp-support":"group:gcp-support@example.org"},"organization":{"customer_id":"abcd123456","domain":"example.org","id":"1234567890"},"prefix":"ft0","universe":null}' + content_base64: null + directory_permission: '0777' + file_permission: '0644' + filename: /tmp/fast-config/tfvars/0-globals.auto.tfvars.json + sensitive_content: null + source: null + local_file.tfvars["org-setup"]: + content_base64: null + directory_permission: '0777' + file_permission: '0644' + filename: /tmp/fast-config/tfvars/0-org-setup.auto.tfvars.json + sensitive_content: null + source: null + module.factory.module.bigquery-datasets["iac-0/billing_export"].google_bigquery_dataset.default: + dataset_id: billing_export + default_encryption_configuration: [] + default_partition_expiration_ms: null + default_table_expiration_ms: null + delete_contents_on_destroy: false + description: Terraform managed. + effective_labels: + goog-terraform-provisioned: 'true' + external_catalog_dataset_options: [] + external_dataset_reference: [] + friendly_name: Billing export + labels: null + location: u-germany-northeast1 + max_time_travel_hours: '168' + project: ft0-prod-iac-core-0 + resource_tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.buckets["iac-0/iac-org-state"].google_storage_bucket.bucket[0]: + autoclass: [] + cors: [] + custom_placement_config: [] + default_event_based_hold: null + effective_labels: + goog-terraform-provisioned: 'true' + enable_object_retention: null + encryption: [] + force_destroy: false + hierarchical_namespace: [] + ip_filter: [] + labels: null + lifecycle_rule: [] + location: U-GERMANY-NORTHEAST1 + logging: [] + name: ft0-prod-iac-core-0-iac-org-state + project: ft0-prod-iac-core-0 + requester_pays: null + retention_policy: [] + storage_class: STANDARD + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + uniform_bucket_level_access: true + versioning: + - enabled: true + ? module.factory.module.buckets["iac-0/iac-org-state"].google_storage_bucket_iam_binding.authoritative["$custom_roles:storage_viewer"] + : bucket: ft0-prod-iac-core-0-iac-org-state + condition: [] + role: $custom_roles:storage_viewer + timeouts: null + ? module.factory.module.buckets["iac-0/iac-org-state"].google_storage_bucket_iam_binding.authoritative["roles/storage.admin"] + : bucket: ft0-prod-iac-core-0-iac-org-state + condition: [] + role: roles/storage.admin + timeouts: null + module.factory.module.buckets["iac-0/iac-outputs"].google_storage_bucket.bucket[0]: + autoclass: [] + cors: [] + custom_placement_config: [] + default_event_based_hold: null + effective_labels: + goog-terraform-provisioned: 'true' + enable_object_retention: null + encryption: [] + force_destroy: false + hierarchical_namespace: [] + ip_filter: [] + labels: null + lifecycle_rule: [] + location: U-GERMANY-NORTHEAST1 + logging: [] + name: ft0-prod-iac-core-0-iac-outputs + project: ft0-prod-iac-core-0 + requester_pays: null + retention_policy: [] + storage_class: STANDARD + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + uniform_bucket_level_access: true + versioning: + - enabled: true + module.factory.module.buckets["iac-0/iac-outputs"].google_storage_bucket_iam_binding.authoritative["roles/storage.admin"]: + bucket: ft0-prod-iac-core-0-iac-outputs + condition: [] + role: roles/storage.admin + timeouts: null + module.factory.module.folder-1["dev"].google_folder.folder[0]: + deletion_protection: false + display_name: Development + parent: organizations/1234567890 + tags: null + timeouts: null + module.factory.module.folder-1["dev"].google_tags_tag_binding.binding["environment"]: + timeouts: null + module.factory.module.folder-1["prod"].google_folder.folder[0]: + deletion_protection: false + display_name: Production + parent: organizations/1234567890 + tags: null + timeouts: null + module.factory.module.folder-1["prod"].google_tags_tag_binding.binding["environment"]: + timeouts: null + module.factory.module.log-buckets["iac-0/audit-logs"].google_logging_project_bucket_config.bucket[0]: + bucket_id: audit-logs + cmek_settings: [] + enable_analytics: true + index_configs: [] + location: u-germany-northeast1 + locked: null + project: ft0-prod-iac-core-0 + retention_days: 31 + module.factory.module.projects-iam["dev-app-0"].google_compute_shared_vpc_service_project.shared_vpc_service[0]: + deletion_policy: null + host_project: ft0-dev-net-shared-0 + service_project: ft0-dev-app-example-0 + timeouts: null + module.factory.module.projects-iam["dev-net-0"].google_compute_shared_vpc_host_project.shared_vpc_host[0]: + project: ft0-dev-net-shared-0 + timeouts: null + module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["roles/cloudbuild.builds.editor"]: + condition: [] + project: ft0-prod-iac-core-0 + role: roles/cloudbuild.builds.editor + module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["roles/iam.serviceAccountAdmin"]: + condition: [] + project: ft0-prod-iac-core-0 + role: roles/iam.serviceAccountAdmin + ? module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["roles/iam.serviceAccountTokenCreator"] + : condition: [] + project: ft0-prod-iac-core-0 + role: roles/iam.serviceAccountTokenCreator + ? module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["roles/iam.workloadIdentityPoolAdmin"] + : condition: [] + project: ft0-prod-iac-core-0 + role: roles/iam.workloadIdentityPoolAdmin + module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["roles/owner"]: + condition: [] + project: ft0-prod-iac-core-0 + role: roles/owner + module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["roles/storage.admin"]: + condition: [] + project: ft0-prod-iac-core-0 + role: roles/storage.admin + module.factory.module.projects-iam["prod-app-0"].google_compute_shared_vpc_service_project.shared_vpc_service[0]: + deletion_policy: null + host_project: ft0-prod-net-shared-0 + service_project: ft0-prod-app-example-0 + timeouts: null + module.factory.module.projects-iam["prod-net-0"].google_compute_shared_vpc_host_project.shared_vpc_host[0]: + project: ft0-prod-net-shared-0 + timeouts: null + module.factory.module.projects["dev-app-0"].data.google_bigquery_default_service_account.bq_sa[0]: + project: ft0-dev-app-example-0 + module.factory.module.projects["dev-app-0"].data.google_logging_project_settings.logging_sa[0]: + project: ft0-dev-app-example-0 + module.factory.module.projects["dev-app-0"].data.google_storage_project_service_account.gcs_sa[0]: + project: ft0-dev-app-example-0 + user_project: null + module.factory.module.projects["dev-app-0"].google_project.project[0]: + auto_create_network: false + billing_account: 012345-012345-012345 + deletion_policy: DELETE + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: ft0-dev-app-example-0 + org_id: null + project_id: ft0-dev-app-example-0 + tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.projects["dev-app-0"].google_project_iam_member.service_agents["compute-system"]: + condition: [] + project: ft0-dev-app-example-0 + role: roles/compute.serviceAgent + module.factory.module.projects["dev-app-0"].google_project_iam_member.service_agents["monitoring-notification"]: + condition: [] + project: ft0-dev-app-example-0 + role: roles/monitoring.notificationServiceAgent + module.factory.module.projects["dev-app-0"].google_project_service.project_services["bigquery.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-app-example-0 + service: bigquery.googleapis.com + timeouts: null + module.factory.module.projects["dev-app-0"].google_project_service.project_services["compute.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-app-example-0 + service: compute.googleapis.com + timeouts: null + module.factory.module.projects["dev-app-0"].google_project_service.project_services["logging.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-app-example-0 + service: logging.googleapis.com + timeouts: null + module.factory.module.projects["dev-app-0"].google_project_service.project_services["monitoring.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-app-example-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["dev-app-0"].google_project_service.project_services["storage.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-app-example-0 + service: storage.googleapis.com + timeouts: null + module.factory.module.projects["dev-app-0"].google_project_service_identity.default["monitoring.googleapis.com"]: + project: ft0-dev-app-example-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["dev-net-0"].data.google_logging_project_settings.logging_sa[0]: + project: ft0-dev-net-shared-0 + module.factory.module.projects["dev-net-0"].google_project.project[0]: + auto_create_network: false + billing_account: 012345-012345-012345 + deletion_policy: DELETE + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: ft0-dev-net-shared-0 + org_id: null + project_id: ft0-dev-net-shared-0 + tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.projects["dev-net-0"].google_project_iam_member.service_agents["compute-system"]: + condition: [] + project: ft0-dev-net-shared-0 + role: roles/compute.serviceAgent + module.factory.module.projects["dev-net-0"].google_project_iam_member.service_agents["container-engine-robot"]: + condition: [] + project: ft0-dev-net-shared-0 + role: roles/container.serviceAgent + module.factory.module.projects["dev-net-0"].google_project_iam_member.service_agents["dns"]: + condition: [] + project: ft0-dev-net-shared-0 + role: roles/dns.serviceAgent + module.factory.module.projects["dev-net-0"].google_project_iam_member.service_agents["gkenode"]: + condition: [] + project: ft0-dev-net-shared-0 + role: roles/container.defaultNodeServiceAgent + module.factory.module.projects["dev-net-0"].google_project_iam_member.service_agents["monitoring-notification"]: + condition: [] + project: ft0-dev-net-shared-0 + role: roles/monitoring.notificationServiceAgent + module.factory.module.projects["dev-net-0"].google_project_service.project_services["compute.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-net-shared-0 + service: compute.googleapis.com + timeouts: null + module.factory.module.projects["dev-net-0"].google_project_service.project_services["container.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-net-shared-0 + service: container.googleapis.com + timeouts: null + module.factory.module.projects["dev-net-0"].google_project_service.project_services["dns.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-net-shared-0 + service: dns.googleapis.com + timeouts: null + module.factory.module.projects["dev-net-0"].google_project_service.project_services["iap.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-net-shared-0 + service: iap.googleapis.com + timeouts: null + module.factory.module.projects["dev-net-0"].google_project_service.project_services["logging.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-net-shared-0 + service: logging.googleapis.com + timeouts: null + module.factory.module.projects["dev-net-0"].google_project_service.project_services["monitoring.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-dev-net-shared-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["dev-net-0"].google_project_service_identity.default["container.googleapis.com"]: + project: ft0-dev-net-shared-0 + service: container.googleapis.com + timeouts: null + module.factory.module.projects["dev-net-0"].google_project_service_identity.default["dns.googleapis.com"]: + project: ft0-dev-net-shared-0 + service: dns.googleapis.com + timeouts: null + module.factory.module.projects["dev-net-0"].google_project_service_identity.default["iap.googleapis.com"]: + project: ft0-dev-net-shared-0 + service: iap.googleapis.com + timeouts: null + module.factory.module.projects["dev-net-0"].google_project_service_identity.default["monitoring.googleapis.com"]: + project: ft0-dev-net-shared-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].data.google_bigquery_default_service_account.bq_sa[0]: + project: ft0-prod-iac-core-0 + module.factory.module.projects["iac-0"].data.google_logging_project_settings.logging_sa[0]: + project: ft0-prod-iac-core-0 + module.factory.module.projects["iac-0"].data.google_storage_project_service_account.gcs_sa[0]: + project: ft0-prod-iac-core-0 + user_project: null + module.factory.module.projects["iac-0"].google_project.project[0]: + auto_create_network: false + billing_account: 012345-012345-012345 + deletion_policy: DELETE + effective_labels: + goog-terraform-provisioned: 'true' + folder_id: null + labels: null + name: ft0-prod-iac-core-0 + org_id: '1234567890' + project_id: ft0-prod-iac-core-0 + tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.projects["iac-0"].google_project_iam_member.service_agents["cloudkms"]: + condition: [] + project: ft0-prod-iac-core-0 + role: roles/cloudkms.serviceAgent + module.factory.module.projects["iac-0"].google_project_iam_member.service_agents["compute-system"]: + condition: [] + project: ft0-prod-iac-core-0 + role: roles/compute.serviceAgent + module.factory.module.projects["iac-0"].google_project_iam_member.service_agents["container-engine-robot"]: + condition: [] + project: ft0-prod-iac-core-0 + role: roles/container.serviceAgent + module.factory.module.projects["iac-0"].google_project_iam_member.service_agents["gkenode"]: + condition: [] + project: ft0-prod-iac-core-0 + role: roles/container.defaultNodeServiceAgent + module.factory.module.projects["iac-0"].google_project_iam_member.service_agents["monitoring-notification"]: + condition: [] + project: ft0-prod-iac-core-0 + role: roles/monitoring.notificationServiceAgent + module.factory.module.projects["iac-0"].google_project_iam_member.service_agents["pubsub"]: + condition: [] + project: ft0-prod-iac-core-0 + role: roles/pubsub.serviceAgent + module.factory.module.projects["iac-0"].google_project_service.org_policy_service[0]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: orgpolicy.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["accesscontextmanager.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: accesscontextmanager.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["bigquery.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: bigquery.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["bigquerystorage.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: bigquerystorage.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["cloudbilling.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: cloudbilling.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["cloudkms.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: cloudkms.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["cloudresourcemanager.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: cloudresourcemanager.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["compute.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: compute.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["container.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: container.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["essentialcontacts.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: essentialcontacts.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["iam.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: iam.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["iamcredentials.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: iamcredentials.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["logging.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: logging.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["monitoring.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["pubsub.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: pubsub.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["serviceusage.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: serviceusage.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["storage-component.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: storage-component.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["storage.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: storage.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service.project_services["sts.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: sts.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service_identity.default["cloudkms.googleapis.com"]: + project: ft0-prod-iac-core-0 + service: cloudkms.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service_identity.default["container.googleapis.com"]: + project: ft0-prod-iac-core-0 + service: container.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service_identity.default["monitoring.googleapis.com"]: + project: ft0-prod-iac-core-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["iac-0"].google_project_service_identity.default["pubsub.googleapis.com"]: + project: ft0-prod-iac-core-0 + service: pubsub.googleapis.com + timeouts: null + module.factory.module.projects["prod-app-0"].data.google_bigquery_default_service_account.bq_sa[0]: + project: ft0-prod-app-example-0 + module.factory.module.projects["prod-app-0"].data.google_logging_project_settings.logging_sa[0]: + project: ft0-prod-app-example-0 + module.factory.module.projects["prod-app-0"].data.google_storage_project_service_account.gcs_sa[0]: + project: ft0-prod-app-example-0 + user_project: null + module.factory.module.projects["prod-app-0"].google_project.project[0]: + auto_create_network: false + billing_account: 012345-012345-012345 + deletion_policy: DELETE + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: ft0-prod-app-example-0 + org_id: null + project_id: ft0-prod-app-example-0 + tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.projects["prod-app-0"].google_project_iam_member.service_agents["compute-system"]: + condition: [] + project: ft0-prod-app-example-0 + role: roles/compute.serviceAgent + module.factory.module.projects["prod-app-0"].google_project_iam_member.service_agents["monitoring-notification"]: + condition: [] + project: ft0-prod-app-example-0 + role: roles/monitoring.notificationServiceAgent + module.factory.module.projects["prod-app-0"].google_project_service.project_services["bigquery.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-app-example-0 + service: bigquery.googleapis.com + timeouts: null + module.factory.module.projects["prod-app-0"].google_project_service.project_services["compute.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-app-example-0 + service: compute.googleapis.com + timeouts: null + module.factory.module.projects["prod-app-0"].google_project_service.project_services["logging.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-app-example-0 + service: logging.googleapis.com + timeouts: null + module.factory.module.projects["prod-app-0"].google_project_service.project_services["monitoring.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-app-example-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["prod-app-0"].google_project_service.project_services["storage.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-app-example-0 + service: storage.googleapis.com + timeouts: null + module.factory.module.projects["prod-app-0"].google_project_service_identity.default["monitoring.googleapis.com"]: + project: ft0-prod-app-example-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["prod-net-0"].data.google_logging_project_settings.logging_sa[0]: + project: ft0-prod-net-shared-0 + module.factory.module.projects["prod-net-0"].google_project.project[0]: + auto_create_network: false + billing_account: 012345-012345-012345 + deletion_policy: DELETE + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: ft0-prod-net-shared-0 + org_id: null + project_id: ft0-prod-net-shared-0 + tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.projects["prod-net-0"].google_project_iam_member.service_agents["compute-system"]: + condition: [] + project: ft0-prod-net-shared-0 + role: roles/compute.serviceAgent + module.factory.module.projects["prod-net-0"].google_project_iam_member.service_agents["container-engine-robot"]: + condition: [] + project: ft0-prod-net-shared-0 + role: roles/container.serviceAgent + module.factory.module.projects["prod-net-0"].google_project_iam_member.service_agents["dns"]: + condition: [] + project: ft0-prod-net-shared-0 + role: roles/dns.serviceAgent + module.factory.module.projects["prod-net-0"].google_project_iam_member.service_agents["gkenode"]: + condition: [] + project: ft0-prod-net-shared-0 + role: roles/container.defaultNodeServiceAgent + module.factory.module.projects["prod-net-0"].google_project_iam_member.service_agents["monitoring-notification"]: + condition: [] + project: ft0-prod-net-shared-0 + role: roles/monitoring.notificationServiceAgent + module.factory.module.projects["prod-net-0"].google_project_service.project_services["compute.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-net-shared-0 + service: compute.googleapis.com + timeouts: null + module.factory.module.projects["prod-net-0"].google_project_service.project_services["container.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-net-shared-0 + service: container.googleapis.com + timeouts: null + module.factory.module.projects["prod-net-0"].google_project_service.project_services["dns.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-net-shared-0 + service: dns.googleapis.com + timeouts: null + module.factory.module.projects["prod-net-0"].google_project_service.project_services["iap.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-net-shared-0 + service: iap.googleapis.com + timeouts: null + module.factory.module.projects["prod-net-0"].google_project_service.project_services["logging.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-net-shared-0 + service: logging.googleapis.com + timeouts: null + module.factory.module.projects["prod-net-0"].google_project_service.project_services["monitoring.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-net-shared-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["prod-net-0"].google_project_service_identity.default["container.googleapis.com"]: + project: ft0-prod-net-shared-0 + service: container.googleapis.com + timeouts: null + module.factory.module.projects["prod-net-0"].google_project_service_identity.default["dns.googleapis.com"]: + project: ft0-prod-net-shared-0 + service: dns.googleapis.com + timeouts: null + module.factory.module.projects["prod-net-0"].google_project_service_identity.default["iap.googleapis.com"]: + project: ft0-prod-net-shared-0 + service: iap.googleapis.com + timeouts: null + module.factory.module.projects["prod-net-0"].google_project_service_identity.default["monitoring.googleapis.com"]: + project: ft0-prod-net-shared-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.service-accounts["iac-0/iac-org-rw"].google_service_account.service_account[0]: + account_id: iac-org-rw + create_ignore_already_exists: null + description: null + disabled: false + display_name: IaC service account for org setup (read-write). + email: iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + member: serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + project: ft0-prod-iac-core-0 + timeouts: null + module.factory.terraform_data.defaults_preconditions: + input: null + output: null + triggers_replace: null + module.factory.terraform_data.project-preconditions: + input: null + output: null + triggers_replace: null + module.organization-iam[0].google_logging_organization_sink.sink["audit-logs"]: + description: audit-logs (Terraform-managed). + disabled: false + exclusions: [] + 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") + + ' + include_children: true + intercept_children: false + name: audit-logs + org_id: '1234567890' + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/accesscontextmanager.policyAdmin"]: + condition: [] + members: + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/accesscontextmanager.policyAdmin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/billing.creator"]: + condition: [] + members: null + org_id: '1234567890' + role: roles/billing.creator + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/cloudasset.owner"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + org_id: '1234567890' + role: roles/cloudasset.owner + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/cloudasset.viewer"]: + condition: [] + members: + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/cloudasset.viewer + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/cloudsupport.admin"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + org_id: '1234567890' + role: roles/cloudsupport.admin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/cloudsupport.techSupportEditor"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + org_id: '1234567890' + role: roles/cloudsupport.techSupportEditor + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/compute.osAdminLogin"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + org_id: '1234567890' + role: roles/compute.osAdminLogin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/compute.osLoginExternalUser"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + org_id: '1234567890' + role: roles/compute.osLoginExternalUser + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/compute.xpnAdmin"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + org_id: '1234567890' + role: roles/compute.xpnAdmin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/essentialcontacts.admin"]: + condition: [] + members: + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/essentialcontacts.admin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/iam.organizationRoleAdmin"]: + condition: [] + members: + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/iam.organizationRoleAdmin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/iam.workforcePoolAdmin"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/iam.workforcePoolAdmin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/logging.admin"]: + condition: [] + members: + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/logging.admin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/orgpolicy.policyAdmin"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/orgpolicy.policyAdmin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/owner"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + org_id: '1234567890' + role: roles/owner + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/resourcemanager.folderAdmin"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/resourcemanager.folderAdmin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/resourcemanager.organizationAdmin"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/resourcemanager.organizationAdmin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/resourcemanager.projectCreator"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/resourcemanager.projectCreator + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/resourcemanager.projectMover"]: + condition: [] + members: + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/resourcemanager.projectMover + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/resourcemanager.tagAdmin"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/resourcemanager.tagAdmin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/resourcemanager.tagUser"]: + condition: [] + members: + - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + org_id: '1234567890' + role: roles/resourcemanager.tagUser + module.organization-iam[0].google_project_iam_member.bucket-sinks-binding["audit-logs"]: + condition: + - title: audit-logs bucket writer + role: roles/logging.bucketWriter + ? module.organization-iam[0].google_tags_tag_value_iam_binding.default["environment/development:roles/resourcemanager.tagUser"] + : condition: [] + members: + - $iam_principals:service_accounts/iac-0/iac-networking-rw + - $iam_principals:service_accounts/iac-0/iac-pf-rw + - $iam_principals:service_accounts/iac-0/iac-security-rw + role: roles/resourcemanager.tagUser + ? module.organization-iam[0].google_tags_tag_value_iam_binding.default["environment/development:roles/resourcemanager.tagViewer"] + : condition: [] + members: + - $iam_principals:service_accounts/iac-0/iac-networking-ro + - $iam_principals:service_accounts/iac-0/iac-pf-ro + - $iam_principals:service_accounts/iac-0/iac-security-ro + role: roles/resourcemanager.tagViewer + ? module.organization-iam[0].google_tags_tag_value_iam_binding.default["environment/production:roles/resourcemanager.tagUser"] + : condition: [] + members: + - $iam_principals:service_accounts/iac-0/iac-networking-rw + - $iam_principals:service_accounts/iac-0/iac-pf-rw + - $iam_principals:service_accounts/iac-0/iac-security-rw + role: roles/resourcemanager.tagUser + ? module.organization-iam[0].google_tags_tag_value_iam_binding.default["environment/production:roles/resourcemanager.tagViewer"] + : condition: [] + members: + - $iam_principals:service_accounts/iac-0/iac-networking-ro + - $iam_principals:service_accounts/iac-0/iac-pf-ro + - $iam_principals:service_accounts/iac-0/iac-security-ro + role: roles/resourcemanager.tagViewer + module.organization[0].google_logging_organization_settings.default[0]: + organization: '1234567890' + timeouts: null + module.organization[0].google_tags_tag_key.default["environment"]: + allowed_values_regex: null + description: Organization-level environments. + parent: organizations/1234567890 + purpose: null + purpose_data: null + short_name: environment + timeouts: null + module.organization[0].google_tags_tag_value.default["environment/development"]: + description: Development. + short_name: development + timeouts: null + module.organization[0].google_tags_tag_value.default["environment/production"]: + description: Production. + short_name: production + timeouts: null + module.vpcs.module.firewall["dev"].google_compute_firewall.custom-rules["ingress-default-allow-healthchecks"]: + allow: + - ports: [] + protocol: all + deny: [] + description: Allow GCP Healthcheck Ranges. + direction: INGRESS + disabled: false + log_config: [] + name: ingress-default-allow-healthchecks + network: dev-shared-0 + params: [] + priority: 1000 + project: ft0-dev-net-shared-0 + source_ranges: + - 130.211.0.0/22 + - 209.85.152.0/22 + - 209.85.204.0/22 + - 35.191.0.0/16 + source_service_accounts: null + source_tags: null + target_service_accounts: null + target_tags: null + timeouts: null + module.vpcs.module.firewall["dev"].google_compute_firewall.custom-rules["ingress-default-allow-iap"]: + allow: + - ports: [] + protocol: all + deny: [] + description: Allow IAP. + direction: INGRESS + disabled: false + log_config: [] + name: ingress-default-allow-iap + network: dev-shared-0 + params: [] + priority: 1000 + project: ft0-dev-net-shared-0 + source_ranges: + - 35.235.240.0/20 + source_service_accounts: null + source_tags: null + target_service_accounts: null + target_tags: null + timeouts: null + module.vpcs.module.firewall["dev"].google_compute_firewall.custom-rules["ingress-default-allow-icmp"]: + allow: + - ports: [] + protocol: icmp + deny: [] + description: Allow ICMP. + direction: INGRESS + disabled: false + log_config: [] + name: ingress-default-allow-icmp + network: dev-shared-0 + params: [] + priority: 1000 + project: ft0-dev-net-shared-0 + source_ranges: + - 0.0.0.0/0 + source_service_accounts: null + source_tags: null + target_service_accounts: null + target_tags: null + timeouts: null + module.vpcs.module.firewall["prod"].google_compute_firewall.custom-rules["ingress-default-allow-healthchecks"]: + allow: + - ports: [] + protocol: all + deny: [] + description: Allow GCP Healthcheck Ranges. + direction: INGRESS + disabled: false + log_config: [] + name: ingress-default-allow-healthchecks + network: prod-shared-0 + params: [] + priority: 1000 + project: ft0-prod-net-shared-0 + source_ranges: + - 130.211.0.0/22 + - 209.85.152.0/22 + - 209.85.204.0/22 + - 35.191.0.0/16 + source_service_accounts: null + source_tags: null + target_service_accounts: null + target_tags: null + timeouts: null + module.vpcs.module.firewall["prod"].google_compute_firewall.custom-rules["ingress-default-allow-iap"]: + allow: + - ports: [] + protocol: all + deny: [] + description: Allow IAP. + direction: INGRESS + disabled: false + log_config: [] + name: ingress-default-allow-iap + network: prod-shared-0 + params: [] + priority: 1000 + project: ft0-prod-net-shared-0 + source_ranges: + - 35.235.240.0/20 + source_service_accounts: null + source_tags: null + target_service_accounts: null + target_tags: null + timeouts: null + module.vpcs.module.firewall["prod"].google_compute_firewall.custom-rules["ingress-default-allow-icmp"]: + allow: + - ports: [] + protocol: icmp + deny: [] + description: Allow ICMP. + direction: INGRESS + disabled: false + log_config: [] + name: ingress-default-allow-icmp + network: prod-shared-0 + params: [] + priority: 1000 + project: ft0-prod-net-shared-0 + source_ranges: + - 0.0.0.0/0 + source_service_accounts: null + source_tags: null + target_service_accounts: null + target_tags: null + timeouts: null + module.vpcs.module.vpcs["dev"].google_compute_network.network[0]: + auto_create_subnetworks: false + delete_bgp_always_compare_med: false + delete_default_routes_on_create: true + description: Terraform managed + enable_ula_internal_ipv6: null + name: dev-shared-0 + network_firewall_policy_enforcement_order: AFTER_CLASSIC_FIREWALL + network_profile: null + params: [] + project: ft0-dev-net-shared-0 + routing_mode: GLOBAL + timeouts: null + module.vpcs.module.vpcs["dev"].google_compute_route.gateway["directpath-googleapis"]: + description: Terraform-managed. + dest_range: 34.126.0.0/18 + name: dev-shared-0-directpath-googleapis + network: dev-shared-0 + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + params: [] + priority: 1000 + project: ft0-dev-net-shared-0 + tags: null + timeouts: null + module.vpcs.module.vpcs["dev"].google_compute_route.gateway["private-googleapis"]: + description: Terraform-managed. + dest_range: 199.36.153.8/30 + name: dev-shared-0-private-googleapis + network: dev-shared-0 + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + params: [] + priority: 1000 + project: ft0-dev-net-shared-0 + tags: null + timeouts: null + module.vpcs.module.vpcs["dev"].google_compute_route.gateway["restricted-googleapis"]: + description: Terraform-managed. + dest_range: 199.36.153.4/30 + name: dev-shared-0-restricted-googleapis + network: dev-shared-0 + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + params: [] + priority: 1000 + project: ft0-dev-net-shared-0 + tags: null + timeouts: null + module.vpcs.module.vpcs["dev"].google_compute_subnetwork.subnetwork["u-germany-northeast1/default"]: + description: Default primary-region subnet for dev + ip_cidr_range: 10.0.0.0/24 + ip_collection: null + ipv6_access_type: null + log_config: [] + name: default + network: dev-shared-0 + params: [] + private_ip_google_access: true + project: ft0-dev-net-shared-0 + region: u-germany-northeast1 + reserved_internal_range: null + resolve_subnet_mask: null + role: null + send_secondary_ip_range_if_empty: true + timeouts: null + module.vpcs.module.vpcs["prod"].google_compute_network.network[0]: + auto_create_subnetworks: false + delete_bgp_always_compare_med: false + delete_default_routes_on_create: true + description: Terraform managed + enable_ula_internal_ipv6: null + name: prod-shared-0 + network_firewall_policy_enforcement_order: AFTER_CLASSIC_FIREWALL + network_profile: null + params: [] + project: ft0-prod-net-shared-0 + routing_mode: GLOBAL + timeouts: null + module.vpcs.module.vpcs["prod"].google_compute_route.gateway["directpath-googleapis"]: + description: Terraform-managed. + dest_range: 34.126.0.0/18 + name: prod-shared-0-directpath-googleapis + network: prod-shared-0 + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + params: [] + priority: 1000 + project: ft0-prod-net-shared-0 + tags: null + timeouts: null + module.vpcs.module.vpcs["prod"].google_compute_route.gateway["private-googleapis"]: + description: Terraform-managed. + dest_range: 199.36.153.8/30 + name: prod-shared-0-private-googleapis + network: prod-shared-0 + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + params: [] + priority: 1000 + project: ft0-prod-net-shared-0 + tags: null + timeouts: null + module.vpcs.module.vpcs["prod"].google_compute_route.gateway["restricted-googleapis"]: + description: Terraform-managed. + dest_range: 199.36.153.4/30 + name: prod-shared-0-restricted-googleapis + network: prod-shared-0 + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + params: [] + priority: 1000 + project: ft0-prod-net-shared-0 + tags: null + timeouts: null + module.vpcs.module.vpcs["prod"].google_compute_subnetwork.subnetwork["u-germany-northeast1/default"]: + description: Default primary-region subnet for prod + ip_cidr_range: 10.0.0.0/24 + ip_collection: null + ipv6_access_type: null + log_config: [] + name: default + network: prod-shared-0 + params: [] + private_ip_google_access: true + project: ft0-prod-net-shared-0 + region: u-germany-northeast1 + reserved_internal_range: null + resolve_subnet_mask: null + role: null + send_secondary_ip_range_if_empty: true + timeouts: null + terraform_data.precondition: + input: null + output: null + triggers_replace: null + terraform_data.precondition-cicd: + input: null + output: null + triggers_replace: null + +counts: + google_bigquery_dataset: 1 + google_bigquery_default_service_account: 3 + google_compute_firewall: 6 + google_compute_network: 2 + google_compute_route: 6 + google_compute_shared_vpc_host_project: 2 + google_compute_shared_vpc_service_project: 2 + google_compute_subnetwork: 2 + google_folder: 2 + google_logging_organization_settings: 1 + google_logging_organization_sink: 1 + google_logging_project_bucket_config: 1 + google_logging_project_settings: 5 + google_organization_iam_binding: 21 + google_project: 5 + google_project_iam_binding: 6 + google_project_iam_member: 21 + google_project_service: 41 + google_project_service_identity: 14 + google_service_account: 1 + google_storage_bucket: 2 + google_storage_bucket_iam_binding: 3 + google_storage_bucket_object: 5 + google_storage_project_service_account: 3 + google_tags_tag_binding: 2 + google_tags_tag_key: 1 + google_tags_tag_value: 2 + google_tags_tag_value_iam_binding: 4 + local_file: 4 + modules: 25 + resources: 173 + terraform_data: 4 + +outputs: + iam_principals: + domain: domain:example.org + gcp-billing-admins: group:gcp-billing-admins@example.org + gcp-devops: group:gcp-devops@example.org + gcp-network-admins: group:gcp-network-admins@example.org + gcp-organization-admins: group:fabric-fast-owners@google.com + gcp-secops-admins: group:gcp-secops-admins@example.org + gcp-security-admins: group:gcp-security-admins@example.org + gcp-support: group:gcp-support@example.org + projects: __missing__ + subnet_ips: + dev: + u-germany-northeast1/default: 10.0.0.0/24 + prod: + u-germany-northeast1/default: 10.0.0.0/24 + subnet_self_links: __missing__ + tfvars: __missing__ + vpc_self_links: __missing__ + diff --git a/tests/fast/stages/s0_org_setup/tftest.yaml b/tests/fast/stages/s0_org_setup/tftest.yaml index 6e9f91220..26f3a3a61 100644 --- a/tests/fast/stages/s0_org_setup/tftest.yaml +++ b/tests/fast/stages/s0_org_setup/tftest.yaml @@ -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 diff --git a/tests/modules/net_vpc_factory/examples/example.yaml b/tests/modules/net_vpc_factory/examples/example.yaml index 6335ed804..8e42cb1e8 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,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 diff --git a/tools/duplicate-diff.py b/tools/duplicate-diff.py index 294f777e4..4c7ab5939 100755 --- a/tools/duplicate-diff.py +++ b/tools/duplicate-diff.py @@ -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",