From 981e4581ee3e1a8affea8f41a77622554dd2f81c Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 12 May 2026 16:44:32 +0200 Subject: [PATCH] Add project-factory based data platform dataset to FAST project factory stage (#3957) * dp rewrite stage 0, projects * remove plan files * generalize handling of basepath for projects in project-factory module * central-0 ---> core-0 * add schemas, validate YAMLs, tags * aspect types * data catalog policy tag factory * add support for data catalog taxonomy to project factory * complete retrofit of old stage configuration, except networking * shared vpc networking * networking * data platform as pf dataset * docs * test * remove legacy dp stage, fix tests and links * boilerplate * tfdoc * fix unrelated tfdoc * schemas * fix errors * schema * duplicate schemas * yamllint * Fix module naming convention for aspect-types * Fix factories_config in vpcs.tf for net-vpc-factory compatibility * Update schema documentation based on schema changes * Fix false rename conflict in .config.yaml files * Sync schemas and update documentation * Fix path expansion for aspect-types and revert projects_input to master * Restore path expansion for org_policies in projects-iam call * Fix trailing newlines in schema duplicates to satisfy duplicate-diff * Fix path expansion for data_catalog_taxonomy in taxonomies.tf * Update inventory for data-platform test and clean up debug prints * Add full values to data-platform inventory * Align Stage 2 VPC Factory integration with Stage 0 and fix tests TAG=agy * Fix project factory context resolution and data platform datasets - Update tag context keys in project factory to use file key without 'projects/' prefix. - Fix tag reference in product-0.yaml. - Fix shared_vpc_service_config in shared-0.yaml by moving service account to network_users. - Set parent for domain-0 folder to data-platform. - Mock net-dev-0 project ID in tests. - Update inventories. TAG=agy CONV=4b37fa5b-bf59-4604-9e8f-b55353d967a0 * Fix project-level tag keys context resolution in project factory * Fix commented out tag reference in domain-0 .config.yaml * Fix merge() calls with empty arguments in project-factory and data-catalog-policy-tag * Update Data Platform dataset README with prerequisites and customization guide * Add Table of Contents to Data Platform dataset README * docs: update Data Platform README with project templates tip * Document data platform output files and linking sequence in README * Update data platform README with VPC-SC and delegated IAM details * Refactor data platform dataset and align stage defaults * Update test inventory and variables for data platform with new prefix --- .gitignore | 2 + fast/addons/2-networking-test/README.md | 4 +- fast/addons/2-networking-test/outputs.tf | 1 + .../0-org-setup/schemas/project.schema.json | 9 + .../0-org-setup/schemas/project.schema.md | 3 + .../2-networking/schemas/project.schema.json | 9 + .../2-networking/schemas/project.schema.md | 3 + fast/stages/2-project-factory/README.md | 11 +- .../datasets/data-platform/README.md | 403 +++++++++ .../aspect-types/core-0/basic.yaml | 46 + .../datasets/data-platform/defaults.yaml | 34 + .../data-platform/diagram-data-platform.png | Bin 0 -> 152881 bytes .../data-platform/diagram-folders.png | Bin 0 -> 43577 bytes .../folders/domain-0/.config.yaml | 42 + .../project-templates/data-product.yaml | 25 + .../data-platform/projects/core-0.yaml | 36 + .../projects/domain-0/product-0.yaml | 104 +++ .../projects/domain-0/shared-0.yaml | 73 ++ .../data-platform/tags/core-0/exposure.yaml | 23 + .../data-platform/taxonomies/tags.yaml | 22 + .../datasets/data-platform/vpcs/README.md | 29 + .../data-platform/vpcs/domain-0/.config.yaml | 20 + fast/stages/2-project-factory/main.tf | 4 + fast/stages/2-project-factory/outputs.tf | 5 + .../schemas/aspect-type.schema.json | 125 +++ .../schemas/aspect-type.schema.md | 50 ++ .../schemas/defaults.schema.json | 221 +++++ .../schemas/defaults.schema.md | 70 ++ .../schemas/project.schema.json | 9 + .../schemas/project.schema.md | 3 + .../schemas/tags.schema.json | 174 ++++ .../2-project-factory/schemas/tags.schema.md | 61 ++ fast/stages/2-project-factory/variables.tf | 11 +- fast/stages/2-project-factory/vpcs.tf | 35 + .../2-security/schemas/project.schema.json | 9 + .../2-security/schemas/project.schema.md | 3 + modules/data-catalog-policy-tag/README.md | 53 +- modules/data-catalog-policy-tag/iam.tf | 86 +- modules/data-catalog-policy-tag/main.tf | 25 +- .../schemas/policy-tag.schema.json | 153 ++++ .../schemas/policy-tag.schema.md | 57 ++ modules/data-catalog-policy-tag/variables.tf | 27 + modules/project-factory/README.md | 32 +- modules/project-factory/aspect-types.tf | 44 + .../data/taxonomies/sample.yaml | 26 + modules/project-factory/outputs.tf | 5 + modules/project-factory/projects-defaults.tf | 2 + modules/project-factory/projects.tf | 13 +- .../schemas/aspect-type.schema.json | 125 +++ .../schemas/aspect-type.schema.md | 50 ++ .../schemas/project.schema.json | 9 + .../project-factory/schemas/project.schema.md | 3 + .../schemas/taxonomy.schema.json | 153 ++++ .../schemas/taxonomy.schema.md | 57 ++ modules/project-factory/taxonomies.tf | 46 + modules/project-factory/variables-projects.tf | 2 + .../s2_project_factory/data-platform.tfvars | 25 + .../s2_project_factory/data-platform.yaml | 815 ++++++++++++++++++ .../stages/s2_project_factory/tftest.yaml | 1 + .../project_factory/examples/example.yaml | 13 +- tools/duplicate-diff.py | 10 + 61 files changed, 3471 insertions(+), 40 deletions(-) create mode 100644 fast/stages/2-project-factory/datasets/data-platform/README.md create mode 100644 fast/stages/2-project-factory/datasets/data-platform/aspect-types/core-0/basic.yaml create mode 100644 fast/stages/2-project-factory/datasets/data-platform/defaults.yaml create mode 100644 fast/stages/2-project-factory/datasets/data-platform/diagram-data-platform.png create mode 100644 fast/stages/2-project-factory/datasets/data-platform/diagram-folders.png create mode 100644 fast/stages/2-project-factory/datasets/data-platform/folders/domain-0/.config.yaml create mode 100644 fast/stages/2-project-factory/datasets/data-platform/project-templates/data-product.yaml create mode 100644 fast/stages/2-project-factory/datasets/data-platform/projects/core-0.yaml create mode 100644 fast/stages/2-project-factory/datasets/data-platform/projects/domain-0/product-0.yaml create mode 100644 fast/stages/2-project-factory/datasets/data-platform/projects/domain-0/shared-0.yaml create mode 100644 fast/stages/2-project-factory/datasets/data-platform/tags/core-0/exposure.yaml create mode 100644 fast/stages/2-project-factory/datasets/data-platform/taxonomies/tags.yaml create mode 100644 fast/stages/2-project-factory/datasets/data-platform/vpcs/README.md create mode 100644 fast/stages/2-project-factory/datasets/data-platform/vpcs/domain-0/.config.yaml create mode 100644 fast/stages/2-project-factory/schemas/aspect-type.schema.json create mode 100644 fast/stages/2-project-factory/schemas/aspect-type.schema.md create mode 100644 fast/stages/2-project-factory/schemas/tags.schema.json create mode 100644 fast/stages/2-project-factory/schemas/tags.schema.md create mode 100644 fast/stages/2-project-factory/vpcs.tf create mode 100644 modules/data-catalog-policy-tag/schemas/policy-tag.schema.json create mode 100644 modules/data-catalog-policy-tag/schemas/policy-tag.schema.md create mode 100644 modules/project-factory/aspect-types.tf create mode 100644 modules/project-factory/data/taxonomies/sample.yaml create mode 100644 modules/project-factory/schemas/aspect-type.schema.json create mode 100644 modules/project-factory/schemas/aspect-type.schema.md create mode 100644 modules/project-factory/schemas/taxonomy.schema.json create mode 100644 modules/project-factory/schemas/taxonomy.schema.md create mode 100644 modules/project-factory/taxonomies.tf create mode 100644 tests/fast/stages/s2_project_factory/data-platform.tfvars create mode 100644 tests/fast/stages/s2_project_factory/data-platform.yaml diff --git a/.gitignore b/.gitignore index 21f3a2f50..8f632a30e 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ node_modules fast/**/globals.auto.tfvars.json cloud_sql_proxy env/ +.jetskicli +.agents diff --git a/fast/addons/2-networking-test/README.md b/fast/addons/2-networking-test/README.md index f0313e5da..5edf969d5 100644 --- a/fast/addons/2-networking-test/README.md +++ b/fast/addons/2-networking-test/README.md @@ -111,6 +111,6 @@ terraform apply | name | description | sensitive | consumers | |---|---|:---:|---| | [instance_addresses](outputs.tf#L17) | Instance names and addresses. | | | -| [instance_ssh](outputs.tf#L24) | Instance SSH commands. | | | -| [service_account_emails](outputs.tf#L33) | Service account emails. | | | +| [instance_ssh](outputs.tf#L24) | Instance SSH commands. | ✓ | | +| [service_account_emails](outputs.tf#L34) | Service account emails. | | | diff --git a/fast/addons/2-networking-test/outputs.tf b/fast/addons/2-networking-test/outputs.tf index 69b880c93..a778f6331 100644 --- a/fast/addons/2-networking-test/outputs.tf +++ b/fast/addons/2-networking-test/outputs.tf @@ -23,6 +23,7 @@ output "instance_addresses" { output "instance_ssh" { description = "Instance SSH commands." + sensitive = true value = { for k, v in module.instances : k => ( "gcloud compute ssh ${k} --project ${nonsensitive(v.instance.project)} --zone ${nonsensitive(v.instance.zone)}" diff --git a/fast/stages/0-org-setup/schemas/project.schema.json b/fast/stages/0-org-setup/schemas/project.schema.json index d65fa4a58..94c224062 100644 --- a/fast/stages/0-org-setup/schemas/project.schema.json +++ b/fast/stages/0-org-setup/schemas/project.schema.json @@ -111,6 +111,9 @@ "type": "object", "additionalProperties": false, "properties": { + "display_name": { + "type": "string" + }, "description": { "type": "string" }, @@ -297,9 +300,15 @@ "type": "object", "additionalProperties": false, "properties": { + "aspect_types": { + "type": "string" + }, "custom_roles": { "type": "string" }, + "data_catalog_taxonomy": { + "type": "string" + }, "observability": { "type": "string" }, diff --git a/fast/stages/0-org-setup/schemas/project.schema.md b/fast/stages/0-org-setup/schemas/project.schema.md index a14fb866d..31998ca8a 100644 --- a/fast/stages/0-org-setup/schemas/project.schema.md +++ b/fast/stages/0-org-setup/schemas/project.schema.md @@ -37,6 +37,7 @@
*additional properties: false* - **`^[a-z0-9-]+$`**: *object*
*additional properties: false* + - **display_name**: *string* - **description**: *string* - **prefix**: *string* - **iam**: *reference([iam](#refs-iam))* @@ -95,7 +96,9 @@
*enum: ['PREVENT', 'DELETE', 'ABANDON']* - **factories_config**: *object*
*additional properties: false* + - **aspect_types**: *string* - **custom_roles**: *string* + - **data_catalog_taxonomy**: *string* - **observability**: *string* - **org_policies**: *string* - **quotas**: *string* diff --git a/fast/stages/2-networking/schemas/project.schema.json b/fast/stages/2-networking/schemas/project.schema.json index d65fa4a58..94c224062 100644 --- a/fast/stages/2-networking/schemas/project.schema.json +++ b/fast/stages/2-networking/schemas/project.schema.json @@ -111,6 +111,9 @@ "type": "object", "additionalProperties": false, "properties": { + "display_name": { + "type": "string" + }, "description": { "type": "string" }, @@ -297,9 +300,15 @@ "type": "object", "additionalProperties": false, "properties": { + "aspect_types": { + "type": "string" + }, "custom_roles": { "type": "string" }, + "data_catalog_taxonomy": { + "type": "string" + }, "observability": { "type": "string" }, diff --git a/fast/stages/2-networking/schemas/project.schema.md b/fast/stages/2-networking/schemas/project.schema.md index a14fb866d..31998ca8a 100644 --- a/fast/stages/2-networking/schemas/project.schema.md +++ b/fast/stages/2-networking/schemas/project.schema.md @@ -37,6 +37,7 @@
*additional properties: false* - **`^[a-z0-9-]+$`**: *object*
*additional properties: false* + - **display_name**: *string* - **description**: *string* - **prefix**: *string* - **iam**: *reference([iam](#refs-iam))* @@ -95,7 +96,9 @@
*enum: ['PREVENT', 'DELETE', 'ABANDON']* - **factories_config**: *object*
*additional properties: false* + - **aspect_types**: *string* - **custom_roles**: *string* + - **data_catalog_taxonomy**: *string* - **observability**: *string* - **org_policies**: *string* - **quotas**: *string* diff --git a/fast/stages/2-project-factory/README.md b/fast/stages/2-project-factory/README.md index a4ce8909a..47f5a724d 100644 --- a/fast/stages/2-project-factory/README.md +++ b/fast/stages/2-project-factory/README.md @@ -9,6 +9,7 @@ - [Organization IAM](#organization-iam) - [Parent folder](#parent-folder) - [Factory configuration](#factory-configuration) + - [Data Platform Dataset](#data-platform-dataset) - [Stage provider and Terraform variables](#stage-provider-and-terraform-variables) - [Managing folders and projects](#managing-folders-and-projects) - [Project defaults and overrides](#project-defaults-and-overrides) @@ -149,6 +150,10 @@ tag_bindings: The `data` folder in this stage contains factory files that can be used as examples to implement the team-based design shown above. Before running `terraform apply` check the YAML files, as project names and other attributes will need basic editing to match your desired setup. +### Data Platform Dataset + +A specialized dataset for Data Platform workloads is available in [`datasets/data-platform`](./datasets/data-platform/). It includes configuration for projects, VPCs, tags, and taxonomies tailored for data analytics. To use it, set the `factories_config.dataset` variable to `datasets/data-platform`. + ### Stage provider and Terraform variables As all other FAST stages, the [mechanism](../0-org-setup/README.md#output-files-and-cross-stage-variables) used to pass variable values and pre-built provider files from one stage to the next is also leveraged here. @@ -473,6 +478,7 @@ Pattern-based files make specific assumptions: | [variables-fast.tf](./variables-fast.tf) | None | | | | [variables-projects.tf](./variables-projects.tf) | None | | | | [variables.tf](./variables.tf) | Module variables. | | | +| [vpcs.tf](./vpcs.tf) | VPC factory. | net-vpc-factory | | ## Variables @@ -487,7 +493,7 @@ Pattern-based files make specific assumptions: | [data_defaults](variables-projects.tf#L17) | Optional default values used when corresponding project or folder data from files are missing. | object({…}) | | {} | | | [data_merges](variables-projects.tf#L93) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} | | | [data_overrides](variables-projects.tf#L112) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | | -| [factories_config](variables.tf#L41) | Path to folder with YAML resource description data files. | object({…}) | | {} | | +| [factories_config](variables.tf#L42) | Path to folder with YAML resource description data files. | object({…}) | | {} | | | [folder_ids](variables-fast.tf#L42) | Folders created in the bootstrap stage. | map(string) | | {} | 0-org-setup | | [host_project_ids](variables-fast.tf#L58) | Host project for the shared VPC. | map(string) | | {} | 2-networking | | [iam_principals](variables-fast.tf#L50) | IAM-format principals. | map(string) | | {} | 0-org-setup | @@ -495,7 +501,7 @@ Pattern-based files make specific assumptions: | [perimeters](variables-fast.tf#L84) | Optional VPC-SC perimeter ids. | map(string) | | {} | 1-vpcsc | | [project_ids](variables-fast.tf#L102) | Projects created in the bootstrap stage. | map(string) | | {} | 0-org-setup | | [service_accounts](variables-fast.tf#L110) | Service accounts created in the bootstrap stage. | map(string) | | {} | 0-org-setup | -| [stage_name](variables.tf#L62) | FAST stage name. Used to separate output files across different factories. | string | | "2-project-factory" | | +| [stage_name](variables.tf#L65) | FAST stage name. Used to separate output files across different factories. | string | | "2-project-factory" | | | [subnet_self_links](variables-fast.tf#L118) | Shared VPC subnet IDs. | map(map(string)) | | {} | 2-networking | | [tag_values](variables-fast.tf#L126) | FAST-managed resource manager tag values. | map(string) | | {} | 0-org-setup | | [tag_vars](variables-fast.tf#L134) | FAST-managed resource manager tag key namespaced names. | object({…}) | | {} | 0-org-setup | @@ -506,4 +512,5 @@ Pattern-based files make specific assumptions: | name | description | sensitive | consumers | |---|---|:---:|---| | [projects](outputs.tf#L17) | Attributes for managed projects. | | | +| [vpcs](outputs.tf#L22) | VPCs. | | | diff --git a/fast/stages/2-project-factory/datasets/data-platform/README.md b/fast/stages/2-project-factory/datasets/data-platform/README.md new file mode 100644 index 000000000..80d8898e2 --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/README.md @@ -0,0 +1,403 @@ +# Data Platform Dataset + +This dataset configures an opinionated Data Platform architecture based on Google Cloud best practices, managed via the Project Factory. + +Its architecture is designed to be reliable, robust, and scalable, facilitating the continuous onboarding of new Data Products (or data workloads). + + +- [Design Overview and Choices](#design-overview-and-choices) + - [Data Platform Architecture](#data-platform-architecture) + - [Folder and Project Structure](#folder-and-project-structure) + - [Central Shared Services (Federated Governance)](#central-shared-services-federated-governance) + - [Data Domains (Domain-Driven Ownership)](#data-domains-domain-driven-ownership) + - [Data Products (DaaP)](#data-products-daap) + - [Delegated Automation Model](#delegated-automation-model) + - [Teams and Personas](#teams-and-personas) + - [Central Data Platform Team](#central-data-platform-team) + - [Data Domain Team](#data-domain-team) + - [Data Product Team](#data-product-team) +- [Stage Prerequisites](#stage-prerequisites) + - [Service Accounts](#service-accounts) + - [Storage](#storage) + - [IAM Bindings](#iam-bindings) + - [Data Platform Folder](#data-platform-folder) + - [Networking](#networking) + - [Security](#security) + - [Organization Level (VPC-SC)](#organization-level-vpc-sc) + - [Output Files and Provider Generation](#output-files-and-provider-generation) + - [Environment File and Linking](#environment-file-and-linking) +- [Customization Guide](#customization-guide) + - [1. IAM Principals and Context](#1-iam-principals-and-context) + - [2. Data Governance Assets](#2-data-governance-assets) + - [3. Adding Domains and Products](#3-adding-domains-and-products) + - [4. VPC-SC Perimeter](#4-vpc-sc-perimeter) +- [Deployment Choices](#deployment-choices) + - [Networking Models](#networking-models) + - [Project-Local VPCs](#project-local-vpcs) +- [Usage](#usage) + + +## Design Overview and Choices + +### Data Platform Architecture + +The following diagram represents the high-level architecture of the Data Platform related projects and their associated resources managed by this dataset: + +

+ High level diagram. +

+ +### Folder and Project Structure + +The dataset manages the following three high-level logical components implemented via GCP folders and projects: + +- "Central Shared Services", a single central project, in which Dataplex Catalog Aspect Types, Policy Tags, and Resource Manager tags a.k.a. "Secure Tags" are defined +- one or more "Data Domains", each composed of a folder with a top-level shared project hosting shared resources such as Composer at the domain level, and an additional sub-folder for hosting data products e.g. "Data Products" +- one or more "Data Products" per domain, each composed of a project, and related resources that are optional + +

+Folder structure. +

+ +#### Central Shared Services (Federated Governance) + +Central Shared Services Project provides the standardized central capabilities to foster federated governance processes. These are implemented via established foundations that enable cross-domain data discovery, data sharing, self-service functionalities, and consistent governance. + +Core, platform-wide capabilities are delivered as shared services managed within a dedicated "Central Shared Services" project. These capabilities include: + +- [Dataplex Catalog Aspect Types](https://cloud.google.com/dataplex/docs/enrich-entries-metadata): Defined in `aspect-types/`. +- [Policy Tags](https://cloud.google.com/bigquery/docs/best-practices-policy-tags): Configured via the `central_project_config.policy_tags` variable (if applicable) or YAML. + +#### Data Domains (Domain-Driven Ownership) + +A Data Domain typically aligns with a business unit (BU) or a distinct function within an enterprise. To support this ownership model, each logical Data Domain is provisioned with its own isolated GCP folder. + +Within each Data Domain, a corresponding Google Cloud "Data Domain" project serves as the primary container for all its specific services and resources. A dedicated Cloud Composer environment is provisioned within this project for orchestrating the domain's data workflows. + +#### Data Products (DaaP) + +Each Data Product within a Data Domain is encapsulated in its own dedicated Google Cloud Project. This separation is key to achieving modularity, scalability, flexibility, and distinct ownership for each product. + +### Delegated Automation Model + +To enable domain-driven ownership and self-service, the dataset implements a multi-tiered automation model using the Project Factory's `automation` feature: + +1. **Central Platform**: Managed by the main Stage 0 service accounts (or the principal running the stage). +2. **Data Domains**: The Domain project (`projects/domain-0/shared-0.yaml`) creates its own automation service accounts (read-only and read-write) in the Central project (`prod-dp-core-0`). +3. **Data Products**: The Product project (`projects/domain-0/product-0.yaml`) uses the Domain's read-write service account for its automation, and stores its state in a bucket within the Domain project. + +This structure allows central teams to bootstrap domains, and then delegate the management of products within a domain to the respective domain team, using their specific service accounts. + +### Teams and Personas + +Effective data mesh operation relies on well-defined roles and responsibilities. + +| Group | Central Shared Services Project | Data Domain Folder | Data Product Project | +| - | :-: | :-: | :-: | +| Central Data Platform Team | `ADMIN` | `Log and Metrics Viewer` | `Log and Metrics Viewer` | +| Data Domain Team | `READ/USAGE` | `ADMIN` | `Log and Metrics Viewer` | +| Data Product Team | `READ/USAGE` | `READ/USAGE` | `ADMIN` | + +#### Central Data Platform Team + +This team defines the overall data platform architecture, establishes shared infrastructure, and enforces central data governance policies and standards across the data mesh. + +#### Data Domain Team + +Aligned with specific business areas (e.g., customer, finance, distribution), this team holds clearly defined ownership of data within that domain. They are responsible for the domain-wide data product roadmap and security. + +#### Data Product Team + +This team is responsible for the end-to-end lifecycle of a specific Data Product. They develop, operate, and maintain their assigned Data Product, including ingestion, transformation, and exposure. + +## Stage Prerequisites + +When using this dataset as an additional project factory (separate from the main `2-project-factory` stage), you need to configure Stage 0 to provision the necessary automation resources and IAM permissions. + +This typically involves adding a new set of service accounts and a dedicated state bucket folder for the data platform automation. + +### Service Accounts + +Add the following service accounts to your Stage 0 configuration (e.g., in `projects/core/iac-0.yaml`): + +```yaml +service_accounts: + iac-dp-ro: + display_name: IaC service account for data platform (read-only). + iac-dp-rw: + display_name: IaC service account for data platform (read-write). +``` + +### Storage + +Configure a dedicated managed folder for the data platform state in the Stage 0 state bucket, and grant access to the service accounts: + +```yaml +buckets: + iac-stage-state: + managed_folders: + 2-data-platform: + iam: + roles/storage.admin: + - $iam_principals:service_accounts/iac-0/iac-dp-rw + $custom_roles:storage_viewer: + - $iam_principals:service_accounts/iac-0/iac-dp-ro +``` + +Also, ensure the data platform service accounts have access to the `iac-outputs` bucket: + +```yaml + iac-outputs: + iam: + roles/storage.admin: + - $iam_principals:service_accounts/iac-0/iac-dp-rw + $custom_roles:storage_viewer: + - $iam_principals:service_accounts/iac-0/iac-dp-ro +``` + +### IAM Bindings + +Grant the necessary permissions to the data platform service accounts on the folders they will manage. + +#### Data Platform Folder + +Since the Data Platform folder is not part of the default dataset, you need to create a new folder configuration file. + +Create a file named `.config.yaml` for the folder. You can place it: +- Directly under the organization by creating `folders/data-platform/.config.yaml` in your Stage 0 dataset directory. +- Within an existing folder, for example under `teams`, by creating `folders/teams/data-platform/.config.yaml`. + +Here is the complete `.config.yaml` content: + +```yaml +name: Data Platform +iam_by_principals: + $iam_principals:service_accounts/iac-0/iac-dp-rw: + - roles/logging.admin + - roles/owner + - roles/resourcemanager.folderAdmin + - roles/resourcemanager.projectCreator + - roles/compute.xpnAdmin + $iam_principals:service_accounts/iac-0/iac-dp-ro: + - roles/viewer + - roles/resourcemanager.folderViewer +``` + +#### Networking + +This configuration is used if you rely on the centralized network stage, and access to share networking resources is required from the data platform. Grant the following roles on the `networking` folder. + +> [!NOTE] +> These prerequisites are only required if you are using the default Shared VPCs model described in the [Deployment Choices](#deployment-choices) section. + +```yaml +iam_bindings: + dp_rw: + members: + - $iam_principals:service_accounts/iac-0/iac-dp-rw + role: $custom_roles:service_project_network_admin + dp_ro: + role: roles/compute.networkViewer + members: + - $iam_principals:service_accounts/iac-0/iac-dp-ro +``` + +And to delegate IAM project administration for networking resources: + +```yaml +iam_bindings: + dp_delegated_iam: + role: roles/resourcemanager.projectIamAdmin + members: + - $iam_principals:service_accounts/iac-0/iac-dp-rw + condition: + title: Data platform delegated IAM grant. + expression: | + api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([ + 'roles/compute.networkUser', 'roles/composer.sharedVpcAgent', + 'roles/container.hostServiceAgentUser', 'roles/vpcaccess.user', + '${custom_roles["dns_zone_binder"]}' + ]) +``` + +> [!TIP] +> If your Stage 0 configuration already includes a `project_factory` delegated IAM grant with these roles (e.g., for the main Project Factory stage), you can simply add the data platform service account (`iac-dp-rw`) to the members list of that existing binding instead of creating a new `dp_delegated_iam` binding. This applies to both networking and security configurations if similar delegations are needed. + +#### Security + +This configuration is used if you rely on the centralized security stage, and access to manage security resources (like KMS keys) is required from the data platform. Grant the following roles on the `security` folder (or the specific project hosting the keys): + +```yaml +iam_bindings: + dp_rw_viewer: + role: roles/cloudkms.viewer + members: + - $iam_principals:service_accounts/iac-0/iac-dp-rw + dp_ro_viewer: + role: roles/cloudkms.viewer + members: + - $iam_principals:service_accounts/iac-0/iac-dp-ro +``` + +And to delegate IAM project administration for KMS resources (allow granting encrypt/decrypt roles on keys): + +```yaml +iam_bindings: + dp_delegated_kms: + role: roles/cloudkms.admin + members: + - $iam_principals:service_accounts/iac-0/iac-dp-rw + condition: + title: Data platform delegated KMS grant. + expression: | + api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly( +[ + 'roles/cloudkms.cryptoKeyEncrypterDecrypter', + 'roles/cloudkms.cryptoKeyEncrypterDecrypterViaDelegation' + ]) && resource.type == 'cloudkms.googleapis.com/CryptoKey' +``` + +#### Organization Level (VPC-SC) + +If you are using VPC-SC and need this stage to manage perimeters or add projects to them, you must grant the following roles at the organization level to the data platform service accounts: + +```yaml +iam_by_principals: + $iam_principals:service_accounts/iac-0/iac-dp-rw: + - roles/accesscontextmanager.policyEditor + $iam_principals:service_accounts/iac-0/iac-dp-ro: + - roles/accesscontextmanager.policyReader +``` + +### Output Files and Provider Generation + +To automatically generate the provider files for this stage, you need to configure the `output_files` section in your Stage 0 `defaults.yaml` file (e.g., `fast/stages/0-org-setup/datasets/classic/defaults.yaml`). + +Add the following entries under `output_files.providers`: + +```yaml + 2-data-platform: + bucket: $storage_buckets:iac-0/iac-stage-state + prefix: 2-data-platform + service_account: $iam_principals:service_accounts/iac-0/iac-dp-rw + 2-data-platform-ro: + bucket: $storage_buckets:iac-0/iac-stage-state + prefix: 2-data-platform + service_account: $iam_principals:service_accounts/iac-0/iac-dp-ro +``` + +This configuration instructs Stage 0 to generate `2-data-platform-providers.tf` and `2-data-platform-ro-providers.tf` files in the outputs folder and/or bucket. + +### Environment File and Linking + +To use these generated files in your custom stage directory (e.g., `custom-stages/2-project-factory-dp`), you need to configure the `.fast-stage.env` file in that directory. + +Set `FAST_STAGE_NAME` to `data-platform`: + +```text +FAST_STAGE_DESCRIPTION="data platform" +FAST_STAGE_LEVEL=2 +FAST_STAGE_NAME=data-platform +FAST_STAGE_DEPS="0-globals 0-org-setup" +FAST_STAGE_OPTIONAL="1-vpcsc 2-networking 2-security" +``` + +This allows the `fast-links.sh` script to correctly identify and link the data platform specific provider and tfvars files. + +To create the links, run the script from inside your stage folder: + +```bash +../../fast/stages/fast-links.sh path/to/your/fast-config or gs://automation_bucket_name +``` + +## Customization Guide + +You can customize the deployment by modifying the YAML files in this directory: + +#### 1. IAM Principals and Context +In `defaults.yaml`, update the `context.iam_principals` map with the actual groups or users for your organization: +- `dp-platform`: Central data platform team. +- `dp-domain-a`: Data domain team members. +- `dp-product-a-0`: Data product team members. +- `data-consumer-bi`: Consumers of public data. + +#### 2. Data Governance Assets +The Central project (`projects/core-0.yaml`) is configured to load data governance assets from the following directories: +- `aspect-types/`: Define Dataplex Catalog Aspect Types. +- `tags/`: Define Resource Manager tags. +- `taxonomies/`: Define Data Catalog taxonomies and policy tags (e.g., `taxonomies/tags.yaml`). + +#### 3. Adding Domains and Products +The provided `domain-0` directory is a template. To add new domains or products: +1. Replicate or modify the folder structure under `projects/`. +2. Update the `parent` and `name` attributes in the new YAML files. +3. Ensure the `automation` block references the correct parent project and service accounts. + +> [!TIP] +> **Project Templates**: For data products that follow a similar configuration, you can use the project templates feature by placing template files in the `project-templates/` directory. This dataset provides a simple example in `project-templates/data-product.yaml`. +> +> Note that the project template feature implements a **shallow merge**, meaning that top-level keys defined in your specific project YAML file will completely overwrite the corresponding top-level keys from the template. + +#### 4. VPC-SC Perimeter +If you are using VPC-SC, you can add projects to a perimeter by specifying it in `defaults.yaml` under `projects.defaults`: + +```yaml +projects: + defaults: + vpc_sc: + perimeter_name: $vpc_sc_perimeters:default + is_dry_run: false +``` + +## Deployment Choices + +The Data Platform dataset allows for flexibility in networking models, supporting both Shared VPCs (standard enterprise pattern) and Project-Local VPCs (isolated workloads). + +### Networking Models + +The Data Platform dataset supports two networking models, which can also be used together: + +1. **Project-Local VPCs (Default)**: By default, this dataset creates project-local VPCs using the VPC factory (reading from the `vpcs` directory). +2. **Shared VPCs**: To attach projects to a Shared VPC managed in the `2-networking` stage, you must: + * Delete the files in the `vpcs` directory (or set `factories_config.paths.vpcs` to a non-existent path). + * Uncomment the `shared_vpc_service_config` block in the project YAML files (e.g., `projects/domain-0/shared-0.yaml`). + +### Project-Local VPCs + +This folder can contain YAML files defining VPCs that are local to specific projects. +The structure should follow the `net-vpc-factory` pattern: + +1. Create a folder for the VPC (e.g., `my-vpc-0`). +2. Inside that folder, create a `.config.yaml` file. +3. Define the VPC configuration in `.config.yaml` (see `net-vpc-factory` module documentation for schema details). + +Example `.config.yaml` (e.g. `domain-0/.config.yaml`): + +```yaml +name: domain-0 +project_id: $project_ids:shared-0 # Use context interpolation for project IDs +subnets: + - name: default + ip_cidr_range: 10.0.0.0/24 + region: $locations:primary +``` + +Note: You must also enable the `vpcs` factory path in your `terraform.tfvars` or `*.auto.tfvars` file if it's not enabled by default: + +```hcl +factories_config = { + paths = { + vpcs = "vpcs" + } +} +``` + +## Usage + +To deploy this dataset, configure your `2-project-factory` stage to use this directory by setting the `dataset` attribute in `factories_config`: + +```hcl +factories_config = { + dataset = "datasets/data-platform" +} +``` diff --git a/fast/stages/2-project-factory/datasets/data-platform/aspect-types/core-0/basic.yaml b/fast/stages/2-project-factory/datasets/data-platform/aspect-types/core-0/basic.yaml new file mode 100644 index 000000000..cbd0c0a79 --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/aspect-types/core-0/basic.yaml @@ -0,0 +1,46 @@ +# 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=../../../../schemas/aspect-type.schema.json + +display_name: "Basic template" +metadata_template: | + { + "name": "tf-basic-template", + "type": "record", + "recordFields": [ + { + "name": "source", + "type": "string", + "annotations": { + "displayName": "Source", + "description": "Specifies the source of data." + }, + "index": 1, + "constraints": { + "required": true + } + }, + { + "name": "owner", + "type": "string", + "annotations": { + "displayName": "Owner", + "description": "Specifies the data owner." + }, + "index": 2, + "constraints": {} + } + ] + } diff --git a/fast/stages/2-project-factory/datasets/data-platform/defaults.yaml b/fast/stages/2-project-factory/datasets/data-platform/defaults.yaml new file mode 100644 index 000000000..2c76aab99 --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/defaults.yaml @@ -0,0 +1,34 @@ +# 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=../../schemas/defaults.schema.json + +projects: + defaults: + locations: + bigquery: $locations:primary + storage: $locations:primary + merges: + services: + - logging.googleapis.com + - monitoring.googleapis.com + +context: + locations: + primary: europe-west1 + iam_principals: + dp-platform: "group:dp-platform@example.com" + dp-domain-a: "group:dp-domain-a@example.com" + dp-product-a-0: "group:dp-product-a-0@example.com" + data-consumer-bi: "group:data-consumer-bi@example.com" diff --git a/fast/stages/2-project-factory/datasets/data-platform/diagram-data-platform.png b/fast/stages/2-project-factory/datasets/data-platform/diagram-data-platform.png new file mode 100644 index 0000000000000000000000000000000000000000..c01a73853f3c8a4edc72a03149167e66cba5d5b9 GIT binary patch literal 152881 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 XG27eY5yi1z{eKl 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 z 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 literal 0 HcmV?d00001 diff --git a/fast/stages/2-project-factory/datasets/data-platform/folders/domain-0/.config.yaml b/fast/stages/2-project-factory/datasets/data-platform/folders/domain-0/.config.yaml new file mode 100644 index 000000000..efce94474 --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/folders/domain-0/.config.yaml @@ -0,0 +1,42 @@ +# 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=../../../../schemas/folder.schema.json + +parent: $folder_ids:data-platform +name: Data Domain 0 + +# iam_bindings: +# bigquery_metadata_viewer: +# members: +# - $iam_principals:dp-platform +# - $iam_principals:dp-domain-a +# - $iam_principals:dp-product-a-0 +# - data-consumer-bi +# role: roles/bigquery.metadataViewer +# condition: +# title: exposure +# description: Expose via secure tag. +# expression: resource.matchTagId('$tag_values:core-0/exposure/public') +# dataplex_catalog_viewer: +# members: +# - $iam_principals:dp-platform +# - $iam_principals:dp-domain-a +# - $iam_principals:dp-product-a-0 +# - data-consumer-bi +# role: roles/dataplex.catalogViewer +# condition: +# title: exposure +# description: Expose via secure tag. +# expression: resource.matchTagId('$tag_values:core-0/exposure/public') diff --git a/fast/stages/2-project-factory/datasets/data-platform/project-templates/data-product.yaml b/fast/stages/2-project-factory/datasets/data-platform/project-templates/data-product.yaml new file mode 100644 index 000000000..4b497002c --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/project-templates/data-product.yaml @@ -0,0 +1,25 @@ +# 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. + +services: + - bigquery.googleapis.com + - cloudresourcemanager.googleapis.com + - datacatalog.googleapis.com + - dataplex.googleapis.com + - datastream.googleapis.com + - logging.googleapis.com + - monitoring.googleapis.com + - notebooks.googleapis.com + - storage.googleapis.com + - storage-component.googleapis.com diff --git a/fast/stages/2-project-factory/datasets/data-platform/projects/core-0.yaml b/fast/stages/2-project-factory/datasets/data-platform/projects/core-0.yaml new file mode 100644 index 000000000..729f5618f --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/projects/core-0.yaml @@ -0,0 +1,36 @@ +# 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=../../../schemas/project.schema.json + +parent: $folder_ids:data-platform +name: prod-dp-core-0 +services: + - bigquery.googleapis.com + - datacatalog.googleapis.com + - logging.googleapis.com + - monitoring.googleapis.com + - storage.googleapis.com + # Uncomment the following lines to enable a centralized Composer environment + # - composer.googleapis.com +# service_accounts: + # Uncomment the following lines to enable a centralized Composer environment + # composer: + # iam_project_roles: + # roles/composer.worker: + # - $iam_principals:service_accounts/_self_/composer +factories_config: + aspect_types: aspect-types/core-0 + tags: tags/core-0 + data_catalog_taxonomy: taxonomies/tags.yaml diff --git a/fast/stages/2-project-factory/datasets/data-platform/projects/domain-0/product-0.yaml b/fast/stages/2-project-factory/datasets/data-platform/projects/domain-0/product-0.yaml new file mode 100644 index 000000000..73172257a --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/projects/domain-0/product-0.yaml @@ -0,0 +1,104 @@ +# 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=../../../../schemas/project.schema.json + +parent: $folder_ids:domain-0 +name: prod-dp-dd0-p0 +services: + - bigquery.googleapis.com + - cloudaicompanion.googleapis.com + - cloudresourcemanager.googleapis.com + - composer.googleapis.com + - datacatalog.googleapis.com + - dataplex.googleapis.com + - datalineage.googleapis.com + - logging.googleapis.com + - monitoring.googleapis.com + - storage.googleapis.com +automation: + project: $project_ids:shared-0 + service_accounts: + iac-ro: + display_name: Product 0/0 (ro) + iam: + roles/iam.serviceAccountTokenCreator: + - $iam_principals:dp-product-a-0 + iac-rw: + display_name: Product 0/0 (rw) + iam: + roles/iam.serviceAccountTokenCreator: + - $iam_principals:dp-product-a-0 + bucket: + name: tf-state + iam: + roles/storage.admin: + - $iam_principals:service_accounts/product-0/automation/iac-rw + roles/storage.objectViewer: + - $iam_principals:service_accounts/product-0/automation/iac-ro + - $iam_principals:dp-product-a-0 + versioning: true + +service_accounts: + processing: + display_name: Processing service account. + iam: + roles/iam.serviceAccountUser: + - $iam_principals:service_accounts/product-0/automation/iac-rw + +datasets: + # TODO: this dataset is exposed to consumers via the 'exposure/public' tag + public: + iam: + roles/bigquery.dataViewer: + - $iam_principals:data-consumer-bi + tag_bindings: + exposure: $tag_values:core-0/exposure/public + + # TODO: this dataset is internal/private + private: {} + +buckets: + # TODO: this bucket is exposed to consumers via the 'exposure/public' tag + public: + iam: + roles/storage.objectViewer: + - $iam_principals:data-consumer-bi + tag_bindings: + exposure: $tag_values:core-0/exposure/public + + # TODO: this bucket is internal/private + private: {} + +iam_by_principals: + $iam_principals:service_accounts/product-0/automation/iac-rw: + - roles/owner + $iam_principals:service_accounts/product-0/automation/iac-ro: + - roles/viewer + $iam_principals:service_accounts/_self_/processing: + - roles/bigquery.dataEditor + - roles/bigquery.jobUser + - roles/dataflow.admin + - roles/dataproc.editor + - roles/dataproc.worker + - roles/iam.serviceAccountUser + - roles/storage.bucketViewer + - roles/storage.objectAdmin + + +# shared_vpc_service_config: +# host_project: $project_ids:net-dev-0 +# service_agent_iam: +# roles/compute.networkUser: +# - $service_agents:dataproc diff --git a/fast/stages/2-project-factory/datasets/data-platform/projects/domain-0/shared-0.yaml b/fast/stages/2-project-factory/datasets/data-platform/projects/domain-0/shared-0.yaml new file mode 100644 index 000000000..53f1bb4d9 --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/projects/domain-0/shared-0.yaml @@ -0,0 +1,73 @@ +# 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=../../../../schemas/project.schema.json + +parent: $folder_ids:domain-0 +name: prod-dp-dd-0 +services: + - bigquery.googleapis.com + - datacatalog.googleapis.com + - dataplex.googleapis.com + - datalineage.googleapis.com + - logging.googleapis.com + - monitoring.googleapis.com + - storage.googleapis.com + - composer.googleapis.com +automation: + project: $project_ids:core-0 + service_accounts: + iac-ro: + display_name: Domain 0 (ro) + iam: + roles/iam.serviceAccountTokenCreator: + - $iam_principals:dp-product-a-0 + iac-rw: + display_name: Domain 0 (rw) + iam: + roles/iam.serviceAccountTokenCreator: + - $iam_principals:dp-product-a-0 + bucket: + name: tf-state + iam: + roles/storage.admin: + - $iam_principals:service_accounts/shared-0/automation/iac-rw + roles/storage.objectViewer: + - $iam_principals:service_accounts/shared-0/automation/iac-ro + - $iam_principals:dp-product-a-0 + versioning: true +iam_by_principals: + $iam_principals:service_accounts/shared-0/automation/iac-rw: + - roles/owner + $iam_principals:service_accounts/shared-0/automation/iac-ro: + - roles/viewer + $iam_principals:service_accounts/_self_/composer: + - roles/composer.worker +service_accounts: + composer: {} + +# TODO: Uncomment the following block if you want to use Shared VPC instead of local VPCs. +# shared_vpc_service_config: +# host_project: $project_ids:net-dev-0 +# service_agent_iam: +# roles/composer.sharedVpcAgent: +# - $service_agents:composer +# roles/compute.networkUser: +# - $service_agents:composer +# network_users: +# - $iam_principals:service_accounts/_self_/composer + +# If this project contains a local VPC, it should be configured as a Shared VPC host. +# shared_vpc_host_config: +# enabled: true diff --git a/fast/stages/2-project-factory/datasets/data-platform/tags/core-0/exposure.yaml b/fast/stages/2-project-factory/datasets/data-platform/tags/core-0/exposure.yaml new file mode 100644 index 000000000..1c9f06fe2 --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/tags/core-0/exposure.yaml @@ -0,0 +1,23 @@ +# 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: "Data exposure controls." +# iam: +# "roles/resourcemanager.tagViewer": +# - "group:finance-team@example.com" +values: + public: + description: "Data exposure allowed." diff --git a/fast/stages/2-project-factory/datasets/data-platform/taxonomies/tags.yaml b/fast/stages/2-project-factory/datasets/data-platform/taxonomies/tags.yaml new file mode 100644 index 000000000..71cdad1c2 --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/taxonomies/tags.yaml @@ -0,0 +1,22 @@ +# 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. + +description: Taxonomy for data platform. +tags: + high: + description: High sensitivity data. + medium: + description: Medium sensitivity data. + low: + description: Low sensitivity data. diff --git a/fast/stages/2-project-factory/datasets/data-platform/vpcs/README.md b/fast/stages/2-project-factory/datasets/data-platform/vpcs/README.md new file mode 100644 index 000000000..98126df2e --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/vpcs/README.md @@ -0,0 +1,29 @@ +# Project-Local VPCs + +This folder can contain YAML files defining VPCs that are local to specific projects. +The structure should follow the `net-vpc-factory` pattern: + +1. Create a folder for the VPC (e.g., `my-vpc-0`). +2. Inside that folder, create a `.config.yaml` file. +3. Define the VPC configuration in `.config.yaml`. + +Example `.config.yaml` (see `domain-0/.config.yaml`): + +```yaml +name: domain-0 +project_id: $project_ids:shared-0 # Use context interpolation for project IDs +subnets: + - name: default + ip_cidr_range: 10.0.0.0/24 + region: $locations:primary +``` + +Note: You must also enable the `vpcs` factory path in your `terraform.tfvars` or `*.auto.tfvars` file if it's not enabled by default: + +```hcl +factories_config = { + paths = { + vpcs = "vpcs" + } +} +``` diff --git a/fast/stages/2-project-factory/datasets/data-platform/vpcs/domain-0/.config.yaml b/fast/stages/2-project-factory/datasets/data-platform/vpcs/domain-0/.config.yaml new file mode 100644 index 000000000..15371b0b7 --- /dev/null +++ b/fast/stages/2-project-factory/datasets/data-platform/vpcs/domain-0/.config.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. + +name: domain-0 +project_id: $project_ids:shared-0 +subnets: + - name: example-subnet-0 + ip_cidr_range: 10.0.0.0/24 + region: $locations:primary diff --git a/fast/stages/2-project-factory/main.tf b/fast/stages/2-project-factory/main.tf index 338e16262..65d58c6c6 100644 --- a/fast/stages/2-project-factory/main.tf +++ b/fast/stages/2-project-factory/main.tf @@ -64,6 +64,10 @@ locals { } ) } + vpc_defaults = { + defaults = try(local.defaults.vpcs.defaults, {}) + overrides = try(local.defaults.vpcs.overrides, {}) + } subnet_self_links = flatten([ for net, subnets in var.subnet_self_links : [ for subnet_name, subnet_link in subnets : { diff --git a/fast/stages/2-project-factory/outputs.tf b/fast/stages/2-project-factory/outputs.tf index 1dc0e6c3c..cf6d2dfdc 100644 --- a/fast/stages/2-project-factory/outputs.tf +++ b/fast/stages/2-project-factory/outputs.tf @@ -19,6 +19,11 @@ output "projects" { value = module.factory.projects } +output "vpcs" { + description = "VPCs." + value = module.vpc-factory.vpcs +} + resource "google_storage_bucket_object" "version" { count = fileexists("fast_version.txt") ? 1 : 0 bucket = var.automation.outputs_bucket diff --git a/fast/stages/2-project-factory/schemas/aspect-type.schema.json b/fast/stages/2-project-factory/schemas/aspect-type.schema.json new file mode 100644 index 000000000..49a8f8e31 --- /dev/null +++ b/fast/stages/2-project-factory/schemas/aspect-type.schema.json @@ -0,0 +1,125 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Dataplex Aspect Type", + "type": "object", + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "labels": { + "type": "object" + }, + "metadata_template": { + "type": "string" + }, + "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/|\\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/roles/)": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:||\\$iam_principals:[a-z0-9_-]+)" + } + } + } + }, + "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:|\\$iam_principals:[a-z0-9_-]+)" + } + }, + "role": { + "type": "string", + "pattern": "^(?:roles/|\\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/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:|\\$iam_principals:[a-z0-9_-]+)" + }, + "role": { + "type": "string", + "pattern": "^(?:roles/|\\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/roles/)" + }, + "condition": { + "type": "object", + "additionalProperties": false, + "required": [ + "expression", + "title" + ], + "properties": { + "expression": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + } + } + } + } + } + } + } +} diff --git a/fast/stages/2-project-factory/schemas/aspect-type.schema.md b/fast/stages/2-project-factory/schemas/aspect-type.schema.md new file mode 100644 index 000000000..81576d96e --- /dev/null +++ b/fast/stages/2-project-factory/schemas/aspect-type.schema.md @@ -0,0 +1,50 @@ +# Dataplex Aspect Type + + + +## Properties + +*additional properties: false* + +- **description**: *string* +- **display_name**: *string* +- **labels**: *object* +- **metadata_template**: *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/|\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/roles/)`**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:||\$iam_principals:[a-z0-9_-]+)* +- **iam_bindings**: *object* +
*additional properties: false* + - **`^[a-z0-9_-]+$`**: *object* +
*additional properties: false* + - **members**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)* + - **role**: *string* +
*pattern: ^(?:roles/|\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/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:|\$iam_principals:[a-z0-9_-]+)* + - **role**: *string* +
*pattern: ^(?:roles/|\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/roles/)* + - **condition**: *object* +
*additional properties: false* + - ⁺**expression**: *string* + - ⁺**title**: *string* + - **description**: *string* diff --git a/fast/stages/2-project-factory/schemas/defaults.schema.json b/fast/stages/2-project-factory/schemas/defaults.schema.json index 117783a93..c8bf0d0fa 100644 --- a/fast/stages/2-project-factory/schemas/defaults.schema.json +++ b/fast/stages/2-project-factory/schemas/defaults.schema.json @@ -472,10 +472,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/2-project-factory/schemas/defaults.schema.md b/fast/stages/2-project-factory/schemas/defaults.schema.md index eee6f3b76..689359e72 100644 --- a/fast/stages/2-project-factory/schemas/defaults.schema.md +++ b/fast/stages/2-project-factory/schemas/defaults.schema.md @@ -129,8 +129,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/2-project-factory/schemas/project.schema.json b/fast/stages/2-project-factory/schemas/project.schema.json index d65fa4a58..94c224062 100644 --- a/fast/stages/2-project-factory/schemas/project.schema.json +++ b/fast/stages/2-project-factory/schemas/project.schema.json @@ -111,6 +111,9 @@ "type": "object", "additionalProperties": false, "properties": { + "display_name": { + "type": "string" + }, "description": { "type": "string" }, @@ -297,9 +300,15 @@ "type": "object", "additionalProperties": false, "properties": { + "aspect_types": { + "type": "string" + }, "custom_roles": { "type": "string" }, + "data_catalog_taxonomy": { + "type": "string" + }, "observability": { "type": "string" }, diff --git a/fast/stages/2-project-factory/schemas/project.schema.md b/fast/stages/2-project-factory/schemas/project.schema.md index a14fb866d..31998ca8a 100644 --- a/fast/stages/2-project-factory/schemas/project.schema.md +++ b/fast/stages/2-project-factory/schemas/project.schema.md @@ -37,6 +37,7 @@
*additional properties: false* - **`^[a-z0-9-]+$`**: *object*
*additional properties: false* + - **display_name**: *string* - **description**: *string* - **prefix**: *string* - **iam**: *reference([iam](#refs-iam))* @@ -95,7 +96,9 @@
*enum: ['PREVENT', 'DELETE', 'ABANDON']* - **factories_config**: *object*
*additional properties: false* + - **aspect_types**: *string* - **custom_roles**: *string* + - **data_catalog_taxonomy**: *string* - **observability**: *string* - **org_policies**: *string* - **quotas**: *string* diff --git a/fast/stages/2-project-factory/schemas/tags.schema.json b/fast/stages/2-project-factory/schemas/tags.schema.json new file mode 100644 index 000000000..22b5357b4 --- /dev/null +++ b/fast/stages/2-project-factory/schemas/tags.schema.json @@ -0,0 +1,174 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Resource Manager Tags", + "type": "object", + "additionalProperties": false, + "properties": { + "allowed_values_regex": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "network": { + "type": "string" + }, + "iam": { + "$ref": "#/$defs/iam" + }, + "iam_bindings": { + "$ref": "#/$defs/iam_bindings" + }, + "iam_bindings_additive": { + "$ref": "#/$defs/iam_bindings_additive" + }, + "values": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^[a-z-][^\\\\'\"/]+$": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "iam": { + "$ref": "#/$defs/iam" + }, + "iam_bindings": { + "$ref": "#/$defs/iam_bindings" + }, + "iam_bindings_additive": { + "$ref": "#/$defs/iam_bindings_additive" + } + } + } + } + } + }, + "allOf": [ + { + "if": { + "required": [ + "allowed_values_regex" + ] + }, + "then": { + "not": { + "required": [ + "values" + ] + } + } + } + ], + "$defs": { + "iam": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^roles/": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)" + } + } + } + }, + "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:|\\$iam_principals:[a-z0-9_-]+)" + } + }, + "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:|\\$iam_principals:[a-z0-9_-]+)" + }, + "role": { + "type": "string", + "pattern": "^[a-zA-Z0-9_/]+$" + }, + "condition": { + "type": "object", + "additionalProperties": false, + "required": [ + "expression", + "title" + ], + "properties": { + "expression": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + } + } + } + } + } + } + } +} diff --git a/fast/stages/2-project-factory/schemas/tags.schema.md b/fast/stages/2-project-factory/schemas/tags.schema.md new file mode 100644 index 000000000..592e01ada --- /dev/null +++ b/fast/stages/2-project-factory/schemas/tags.schema.md @@ -0,0 +1,61 @@ +# Resource Manager Tags + + + +## Properties + +*additional properties: false* + +- **allowed_values_regex**: *string* +- **name**: *string* +- **description**: *string* +- **id**: *string* +- **network**: *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))* +- **values**: *object* +
*additional properties: false* + - **`^[a-z-][^\\'"/]+$`**: *object* +
*additional properties: false* + - **name**: *string* + - **description**: *string* + - **id**: *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:|\$iam_principals:[a-z0-9_-]+)* +- **iam_bindings**: *object* +
*additional properties: false* + - **`^[a-z0-9_-]+$`**: *object* +
*additional properties: false* + - **members**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)* + - **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:|\$iam_principals:[a-z0-9_-]+)* + - **role**: *string* +
*pattern: ^[a-zA-Z0-9_/]+$* + - **condition**: *object* +
*additional properties: false* + - ⁺**expression**: *string* + - ⁺**title**: *string* + - **description**: *string* diff --git a/fast/stages/2-project-factory/variables.tf b/fast/stages/2-project-factory/variables.tf index e637055d3..a23760be1 100644 --- a/fast/stages/2-project-factory/variables.tf +++ b/fast/stages/2-project-factory/variables.tf @@ -17,6 +17,7 @@ variable "context" { description = "Context-specific interpolations." type = object({ + cidr_ranges_sets = optional(map(list(string)), {}) condition_vars = optional(map(map(string)), {}) custom_roles = optional(map(string), {}) email_addresses = optional(map(string), {}) @@ -43,10 +44,12 @@ variable "factories_config" { type = object({ dataset = optional(string, "datasets/classic") paths = optional(object({ - defaults = optional(string, "defaults.yaml") - folders = optional(string, "folders") - projects = optional(string, "projects") - budgets = optional(string) + defaults = optional(string, "defaults.yaml") + folders = optional(string, "folders") + projects = optional(string, "projects") + project_templates = optional(string, "project-templates") + budgets = optional(string) + vpcs = optional(string, "vpcs") }), {}) }) nullable = false diff --git a/fast/stages/2-project-factory/vpcs.tf b/fast/stages/2-project-factory/vpcs.tf new file mode 100644 index 000000000..a6f77425f --- /dev/null +++ b/fast/stages/2-project-factory/vpcs.tf @@ -0,0 +1,35 @@ +/** + * 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. + */ + +# tfdoc:file:description VPC factory. + +module "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 = { + vpcs = var.factories_config.paths.vpcs + } + } + context = merge(local.context, { + project_ids = merge( + local.context.project_ids, + module.factory.project_ids + ) + }) +} diff --git a/fast/stages/2-security/schemas/project.schema.json b/fast/stages/2-security/schemas/project.schema.json index d65fa4a58..94c224062 100644 --- a/fast/stages/2-security/schemas/project.schema.json +++ b/fast/stages/2-security/schemas/project.schema.json @@ -111,6 +111,9 @@ "type": "object", "additionalProperties": false, "properties": { + "display_name": { + "type": "string" + }, "description": { "type": "string" }, @@ -297,9 +300,15 @@ "type": "object", "additionalProperties": false, "properties": { + "aspect_types": { + "type": "string" + }, "custom_roles": { "type": "string" }, + "data_catalog_taxonomy": { + "type": "string" + }, "observability": { "type": "string" }, diff --git a/fast/stages/2-security/schemas/project.schema.md b/fast/stages/2-security/schemas/project.schema.md index a14fb866d..31998ca8a 100644 --- a/fast/stages/2-security/schemas/project.schema.md +++ b/fast/stages/2-security/schemas/project.schema.md @@ -37,6 +37,7 @@
*additional properties: false* - **`^[a-z0-9-]+$`**: *object*
*additional properties: false* + - **display_name**: *string* - **description**: *string* - **prefix**: *string* - **iam**: *reference([iam](#refs-iam))* @@ -95,7 +96,9 @@
*enum: ['PREVENT', 'DELETE', 'ABANDON']* - **factories_config**: *object*
*additional properties: false* + - **aspect_types**: *string* - **custom_roles**: *string* + - **data_catalog_taxonomy**: *string* - **observability**: *string* - **org_policies**: *string* - **quotas**: *string* diff --git a/modules/data-catalog-policy-tag/README.md b/modules/data-catalog-policy-tag/README.md index 717e95ab2..42fe07153 100644 --- a/modules/data-catalog-policy-tag/README.md +++ b/modules/data-catalog-policy-tag/README.md @@ -9,6 +9,7 @@ Note: Data Catalog is still in beta, hence this module currently uses the beta p - [Examples](#examples) - [Simple Taxonomy with policy tags](#simple-taxonomy-with-policy-tags) - [Taxonomy with IAM binding](#taxonomy-with-iam-binding) + - [Factory](#factory) - [Variables](#variables) - [Outputs](#outputs) - [TODO](#todo) @@ -76,22 +77,66 @@ module "cmn-dc" { } # tftest modules=1 resources=7 ``` +### Factory + +```hcl +module "taxonomy" { + source = "./fabric/modules/data-catalog-policy-tag" + project_id = "my-project" + name = "taxonomy" + location = "europe-west1" + context = { + iam_principals = { + user-a = "user:a@example.org" + user-b = "user:b@example.org" + } + } + factories_config = { + taxonomy = "data-catalog/taxonomy.yaml" + } +} +# tftest modules=1 resources=6 files=factory +``` + +```yaml +description: taxonomy description +activated_policy_types: + - FINE_GRAINED_ACCESS_CONTROL +iam: + roles/viewer: + - $iam_principals:user-a +tags: + tag-a: + description: tag a description + iam: + roles/viewer: + - $iam_principals:user-b + tag-b: + description: tag b description + iam_bindings: + viewer: + role: roles/viewer + members: + - user:c@example.org +# tftest-file id=factory path=data-catalog/taxonomy.yaml +``` ## Variables | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [location](variables.tf#L52) | Data Catalog Taxonomy location. | string | ✓ | | -| [name](variables.tf#L58) | Name of this taxonomy. | string | ✓ | | -| [project_id](variables.tf#L64) | GCP project id. | string | ✓ | | +| [location](variables.tf#L61) | Data Catalog Taxonomy location. | string | ✓ | | +| [name](variables.tf#L67) | Name of this taxonomy. | string | ✓ | | +| [project_id](variables.tf#L73) | GCP project id. | string | ✓ | | | [activated_policy_types](variables.tf#L17) | A list of policy types that are activated for this taxonomy. | list(string) | | ["FINE_GRAINED_ACCESS_CONTROL"] | | [context](variables.tf#L32) | Context-specific interpolations. | object({…}) | | {} | | [description](variables.tf#L45) | Description of this taxonomy. | string | | "Taxonomy - Terraform managed" | +| [factories_config](variables.tf#L52) | Paths to folders and files for the optional factories. | object({…}) | | {} | | [iam](variables-iam.tf#L23) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | | [iam_bindings](variables-iam.tf#L29) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…})) | | {} | | [iam_bindings_additive](variables-iam.tf#L44) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…})) | | {} | | [iam_by_principals](variables-iam.tf#L17) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | map(list(string)) | | {} | -| [tags](variables.tf#L70) | List of Data Catalog Policy tags to be created with optional IAM binging configuration in {tag => {ROLE => [MEMBERS]}} format. | map(object({…})) | | {} | +| [tags](variables.tf#L79) | List of Data Catalog Policy tags to be created with optional IAM binging configuration in {tag => {ROLE => [MEMBERS]}} format. | map(object({…})) | | {} | ## Outputs diff --git a/modules/data-catalog-policy-tag/iam.tf b/modules/data-catalog-policy-tag/iam.tf index ef3fb914a..521de79e3 100644 --- a/modules/data-catalog-policy-tag/iam.tf +++ b/modules/data-catalog-policy-tag/iam.tf @@ -25,14 +25,35 @@ locals { ] } iam = { - for role in distinct(concat(keys(var.iam), keys(local._iam_principals))) : + for role in distinct(concat( + keys(var.iam), + keys(local._iam_principals), + keys(try(local._factory_data.iam, {})) + )) : role => concat( try(var.iam[role], []), - try(local._iam_principals[role], []) + try(local._iam_principals[role], []), + try(local._factory_data.iam[role], []) ) } + iam_bindings = merge( + var.iam_bindings, + { + for k, v in try(local._factory_data.iam_bindings, {}) : k => merge(v, { + condition = try(v.condition, null) + }) + } + ) + iam_bindings_additive = merge( + var.iam_bindings_additive, + { + for k, v in try(local._factory_data.iam_bindings_additive, {}) : k => merge(v, { + condition = try(v.condition, null) + }) + } + ) tags_iam = flatten([ - for k, v in var.tags : [ + for k, v in local.tags : [ for role, members in v.iam : { tag = k role = role @@ -40,6 +61,22 @@ locals { } ] ]) + tags_iam_bindings = merge({}, [ + for k, v in local.tags : { + for bk, bv in v.iam_bindings : "${k}.${bk}" => merge(bv, { + tag = k + key = bk + }) + } + ]...) + tags_iam_bindings_additive = merge({}, [ + for k, v in local.tags : { + for bk, bv in v.iam_bindings_additive : "${k}.${bk}" => merge(bv, { + tag = k + key = bk + }) + } + ]...) } resource "google_data_catalog_taxonomy_iam_binding" "authoritative" { @@ -55,7 +92,7 @@ resource "google_data_catalog_taxonomy_iam_binding" "authoritative" { resource "google_data_catalog_taxonomy_iam_binding" "bindings" { provider = google-beta - for_each = var.iam_bindings + for_each = local.iam_bindings taxonomy = google_data_catalog_taxonomy.default.id role = lookup(local.ctx.custom_roles, each.value.role, each.value.role) members = [ @@ -76,7 +113,7 @@ resource "google_data_catalog_taxonomy_iam_binding" "bindings" { resource "google_data_catalog_taxonomy_iam_member" "bindings" { provider = google-beta - for_each = var.iam_bindings_additive + for_each = local.iam_bindings_additive taxonomy = google_data_catalog_taxonomy.default.id role = lookup(local.ctx.custom_roles, each.value.role, each.value.role) member = lookup(local.ctx.iam_principals, each.value.member, each.value.member) @@ -104,3 +141,42 @@ resource "google_data_catalog_policy_tag_iam_binding" "authoritative" { lookup(local.ctx.iam_principals, v, v) ] } + +resource "google_data_catalog_policy_tag_iam_binding" "bindings" { + provider = google-beta + for_each = local.tags_iam_bindings + policy_tag = google_data_catalog_policy_tag.default[each.value.tag].name + role = lookup(local.ctx.custom_roles, each.value.role, each.value.role) + members = [ + for v in each.value.members : + lookup(local.ctx.iam_principals, v, v) + ] + dynamic "condition" { + for_each = each.value.condition == null ? [] : [""] + content { + expression = templatestring( + each.value.condition.expression, var.context.condition_vars + ) + title = each.value.condition.title + description = each.value.condition.description + } + } +} + +resource "google_data_catalog_policy_tag_iam_member" "bindings" { + provider = google-beta + for_each = local.tags_iam_bindings_additive + policy_tag = google_data_catalog_policy_tag.default[each.value.tag].name + role = lookup(local.ctx.custom_roles, each.value.role, each.value.role) + member = lookup(local.ctx.iam_principals, each.value.member, each.value.member) + dynamic "condition" { + for_each = each.value.condition == null ? [] : [""] + content { + expression = templatestring( + each.value.condition.expression, var.context.condition_vars + ) + title = each.value.condition.title + description = each.value.condition.description + } + } +} diff --git a/modules/data-catalog-policy-tag/main.tf b/modules/data-catalog-policy-tag/main.tf index 189dc9bb0..0cd5b23d1 100644 --- a/modules/data-catalog-policy-tag/main.tf +++ b/modules/data-catalog-policy-tag/main.tf @@ -27,6 +27,27 @@ locals { project_id = var.project_id == null ? null : lookup( local.ctx.project_ids, var.project_id, var.project_id ) + _factory_data = try( + yamldecode(file(pathexpand(var.factories_config.taxonomy))), + {} + ) + description = try(local._factory_data.description, var.description) + tags = merge(var.tags, { + for k, v in try(local._factory_data.tags, {}) : k => { + description = try(v.description, null) + iam = try(v.iam, {}) + iam_bindings = { + for ik, iv in try(v.iam_bindings, {}) : ik => merge(iv, { + condition = try(iv.condition, null) + }) + } + iam_bindings_additive = { + for ik, iv in try(v.iam_bindings_additive, {}) : ik => merge(iv, { + condition = try(iv.condition, null) + }) + } + } + }) } resource "google_data_catalog_taxonomy" "default" { @@ -34,13 +55,13 @@ resource "google_data_catalog_taxonomy" "default" { project = local.project_id region = local.location display_name = var.name - description = var.description + description = local.description activated_policy_types = var.activated_policy_types } resource "google_data_catalog_policy_tag" "default" { provider = google-beta - for_each = var.tags + for_each = local.tags taxonomy = google_data_catalog_taxonomy.default.id display_name = each.key description = coalesce( diff --git a/modules/data-catalog-policy-tag/schemas/policy-tag.schema.json b/modules/data-catalog-policy-tag/schemas/policy-tag.schema.json new file mode 100644 index 000000000..23da50da8 --- /dev/null +++ b/modules/data-catalog-policy-tag/schemas/policy-tag.schema.json @@ -0,0 +1,153 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "additionalProperties": false, + "properties": { + "activated_policy_types": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "type": "string" + }, + "iam": { + "$ref": "#/$defs/iam" + }, + "iam_bindings": { + "$ref": "#/$defs/iam_bindings" + }, + "iam_bindings_additive": { + "$ref": "#/$defs/iam_bindings_additive" + }, + "tags": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^.+$": { + "type": "object", + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "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/|\\$custom_roles:)": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)" + } + } + } + }, + "iam_bindings": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^[a-z0-9_-]+$": { + "type": "object", + "additionalProperties": false, + "required": [ + "members", + "role" + ], + "properties": { + "members": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)" + } + }, + "role": { + "type": "string", + "pattern": "^(?:roles/|\\$custom_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, + "required": [ + "member", + "role" + ], + "properties": { + "member": { + "type": "string", + "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)" + }, + "role": { + "type": "string", + "pattern": "^(?:roles/|\\$custom_roles:)" + }, + "condition": { + "type": "object", + "additionalProperties": false, + "required": [ + "expression", + "title" + ], + "properties": { + "expression": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/modules/data-catalog-policy-tag/schemas/policy-tag.schema.md b/modules/data-catalog-policy-tag/schemas/policy-tag.schema.md new file mode 100644 index 000000000..da41b4360 --- /dev/null +++ b/modules/data-catalog-policy-tag/schemas/policy-tag.schema.md @@ -0,0 +1,57 @@ +# None + + + +## Properties + +*additional properties: false* + +- **activated_policy_types**: *array* + - items: *string* +- **description**: *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))* +- **tags**: *object* +
*additional properties: false* + - **`^.+$`**: *object* +
*additional properties: false* + - **description**: *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/|\$custom_roles:)`**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)* +- **iam_bindings**: *object* +
*additional properties: false* + - **`^[a-z0-9_-]+$`**: *object* +
*additional properties: false* + - ⁺**members**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)* + - ⁺**role**: *string* +
*pattern: ^(?:roles/|\$custom_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:|\$iam_principals:[a-z0-9_-]+)* + - ⁺**role**: *string* +
*pattern: ^(?:roles/|\$custom_roles:)* + - **condition**: *object* +
*additional properties: false* + - ⁺**expression**: *string* + - ⁺**title**: *string* + - **description**: *string* diff --git a/modules/data-catalog-policy-tag/variables.tf b/modules/data-catalog-policy-tag/variables.tf index 51a16de8d..94e616494 100644 --- a/modules/data-catalog-policy-tag/variables.tf +++ b/modules/data-catalog-policy-tag/variables.tf @@ -49,6 +49,15 @@ variable "description" { default = "Taxonomy - Terraform managed" } +variable "factories_config" { + description = "Paths to folders and files for the optional factories." + type = object({ + taxonomy = optional(string) + }) + nullable = false + default = {} +} + variable "location" { description = "Data Catalog Taxonomy location." type = string @@ -72,6 +81,24 @@ variable "tags" { type = map(object({ description = optional(string) iam = optional(map(list(string)), {}) + iam_bindings = optional(map(object({ + members = list(string) + role = string + condition = optional(object({ + expression = string + title = string + description = optional(string) + })) + })), {}) + iam_bindings_additive = optional(map(object({ + member = string + role = string + condition = optional(object({ + expression = string + title = string + description = optional(string) + })) + })), {}) })) nullable = false default = {} diff --git a/modules/project-factory/README.md b/modules/project-factory/README.md index 6d89af6c7..f95815588 100644 --- a/modules/project-factory/README.md +++ b/modules/project-factory/README.md @@ -766,6 +766,8 @@ iam: - $iam_principals:service_accounts/dev-tb-app0-0/automation/rw "roles/viewer": - $iam_principals:service_accounts/dev-tb-app0-0/automation/ro +factories_config: + data_catalog_taxonomy: data/taxonomies/sample.yaml shared_vpc_host_config: enabled: true service_accounts: @@ -871,6 +873,7 @@ compute.disableSerialPortAccess: | name | description | modules | resources | |---|---|---|---| +| [aspect-types.tf](./aspect-types.tf) | Aspect types resources. | dataplex-aspect-types | | | [automation.tf](./automation.tf) | None | gcs · iam-service-account | | | [budgets.tf](./budgets.tf) | Billing budget factory locals. | billing-account | | | [folders.tf](./folders.tf) | Folder hierarchy factory resources. | folder | | @@ -885,6 +888,7 @@ compute.disableSerialPortAccess: | [projects-pubsub.tf](./projects-pubsub.tf) | None | pubsub | | | [projects-service-accounts.tf](./projects-service-accounts.tf) | None | iam-service-account | | | [projects.tf](./projects.tf) | None | project | terraform_data | +| [taxonomies.tf](./taxonomies.tf) | Taxonomy resources. | data-catalog-policy-tag | | | [variables-billing.tf](./variables-billing.tf) | None | | | | [variables-folders.tf](./variables-folders.tf) | None | | | | [variables-projects.tf](./variables-projects.tf) | None | | | @@ -907,20 +911,20 @@ compute.disableSerialPortAccess: | name | description | sensitive | |---|---|:---:| -| [folder_ids](outputs.tf#L102) | Folder ids. | | -| [iam_principals](outputs.tf#L107) | IAM principals mappings. | | -| [kms_keys](outputs.tf#L112) | KMS key ids. | | -| [log_buckets](outputs.tf#L117) | Log bucket ids. | | -| [project_ids](outputs.tf#L124) | Project ids. | | -| [project_numbers](outputs.tf#L129) | Project numbers. | | -| [projects](outputs.tf#L136) | Project attributes. | | -| [pubsub_topics](outputs.tf#L141) | PubSub topic ids. | | -| [service_account_emails](outputs.tf#L148) | Service account emails. | | -| [service_account_iam_emails](outputs.tf#L155) | Service account IAM-format emails. | | -| [service_account_ids](outputs.tf#L162) | Service account IDs. | | -| [service_accounts](outputs.tf#L169) | Service account emails. | | -| [service_agents](outputs.tf#L174) | Service agent emails. | | -| [storage_buckets](outputs.tf#L185) | Bucket names. | | +| [folder_ids](outputs.tf#L107) | Folder ids. | | +| [iam_principals](outputs.tf#L112) | IAM principals mappings. | | +| [kms_keys](outputs.tf#L117) | KMS key ids. | | +| [log_buckets](outputs.tf#L122) | Log bucket ids. | | +| [project_ids](outputs.tf#L129) | Project ids. | | +| [project_numbers](outputs.tf#L134) | Project numbers. | | +| [projects](outputs.tf#L141) | Project attributes. | | +| [pubsub_topics](outputs.tf#L146) | PubSub topic ids. | | +| [service_account_emails](outputs.tf#L153) | Service account emails. | | +| [service_account_iam_emails](outputs.tf#L160) | Service account IAM-format emails. | | +| [service_account_ids](outputs.tf#L167) | Service account IDs. | | +| [service_accounts](outputs.tf#L174) | Service account emails. | | +| [service_agents](outputs.tf#L179) | Service agent emails. | | +| [storage_buckets](outputs.tf#L190) | Bucket names. | | ## Tests diff --git a/modules/project-factory/aspect-types.tf b/modules/project-factory/aspect-types.tf new file mode 100644 index 000000000..93b9b8eb8 --- /dev/null +++ b/modules/project-factory/aspect-types.tf @@ -0,0 +1,44 @@ +/** + * 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. + */ + +# tfdoc:file:description Aspect types resources. + +module "aspect-types" { + source = "../dataplex-aspect-types" + for_each = { + for k, v in local.projects_input : k => v + if try(v.factories_config.aspect_types, null) != null + } + project_id = module.projects[each.key].project_id + factories_config = { + aspect_types = lookup(each.value.factories_config, "aspect_types", null) == null ? null : try(pathexpand( + var.factories_config.basepath == null || startswith(each.value.factories_config.aspect_types, "/") || startswith(each.value.factories_config.aspect_types, ".") + ? each.value.factories_config.aspect_types : + "${var.factories_config.basepath}/${each.value.factories_config.aspect_types}" + ), null) + } + context = merge(local.ctx, { + iam_principals = merge( + local.ctx_iam_principals, + lookup(local.self_sas_iam_emails, each.key, {}), + local.projects_service_agents + ) + project_ids = merge( + local.ctx.project_ids, + { for k, v in module.projects : k => v.project_id } + ) + }) +} diff --git a/modules/project-factory/data/taxonomies/sample.yaml b/modules/project-factory/data/taxonomies/sample.yaml new file mode 100644 index 000000000..cfaf7b57c --- /dev/null +++ b/modules/project-factory/data/taxonomies/sample.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. + +description: taxonomy description +activated_policy_types: + - FINE_GRAINED_ACCESS_CONTROL +iam: + roles/viewer: + - $iam_principals:gcp-devops +tags: + tag-a: + description: tag a description + iam: + roles/viewer: + - $iam_principals:gcp-devops diff --git a/modules/project-factory/outputs.tf b/modules/project-factory/outputs.tf index 3ea8d3027..546b410b7 100644 --- a/modules/project-factory/outputs.tf +++ b/modules/project-factory/outputs.tf @@ -23,6 +23,11 @@ locals { } outputs_projects = { for k, v in local.projects_input : k => { + aspect_types = ( + v.factories_config.aspect_types == null + ? {} + : module.aspect-types[k].ids + ) automation = { bucket = try( module.automation-bucket[local._outputs_automation_buckets[k]].name, diff --git a/modules/project-factory/projects-defaults.tf b/modules/project-factory/projects-defaults.tf index 6b3842a84..4a7f5e6a1 100644 --- a/modules/project-factory/projects-defaults.tf +++ b/modules/project-factory/projects-defaults.tf @@ -51,7 +51,9 @@ locals { local.data_defaults.defaults.contacts ) factories_config = { + aspect_types = try(v.factories_config.aspect_types, null) custom_roles = try(v.factories_config.custom_roles, null) + data_catalog_taxonomy = try(v.factories_config.data_catalog_taxonomy, null) observability = try(v.factories_config.observability, null) org_policies = try(v.factories_config.org_policies, null) pam_entitlements = try(v.factories_config.pam_entitlements, null) diff --git a/modules/project-factory/projects.tf b/modules/project-factory/projects.tf index e334597a7..8ad850134 100644 --- a/modules/project-factory/projects.tf +++ b/modules/project-factory/projects.tf @@ -53,18 +53,18 @@ locals { ctx_project_numbers = merge(local.ctx.project_numbers, local.project_numbers) # cross-project tag contexts, keyed on project name ctx_tag_keys = merge(local.ctx.tag_keys, { - for k, v in merge([ + for k, v in merge({}, [ for pk, pv in local.projects_input : { for tk, tv in module.projects[pk].tag_keys : - "${pv.name}/${tk}" => tv.id + "${pk}/${tk}" => tv.id } ]...) : k => v }) ctx_tag_values = merge(local.ctx.tag_values, { - for k, v in merge([ + for k, v in merge({}, [ for pk, pv in local.projects_input : { for tk, tv in module.projects[pk].tag_values : - "${pv.name}/${tk}" => tv.id + "${pk}/${tk}" => tv.id } ]...) : k => v }) @@ -140,13 +140,16 @@ module "projects" { folder_ids = local.ctx_folder_ids }) default_service_account = try(each.value.default_service_account, "keep") + # Exclude factories that are either: + # a) Handled in parallel by calling specific modules (e.g., aspect_types, data_catalog_taxonomy) + # b) Handled in the projects-iam call to leverage expanded context (e.g., org_policies) factories_config = { for k, v in each.value.factories_config : k => try(pathexpand( var.factories_config.basepath == null || startswith(v, "/") || startswith(v, ".") ? v : "${var.factories_config.basepath}/${v}" ), null) - if k != "org_policies" + if !contains(["aspect_types", "data_catalog_taxonomy", "org_policies"], k) } kms_autokeys = try(each.value.kms.autokeys, {}) labels = merge( diff --git a/modules/project-factory/schemas/aspect-type.schema.json b/modules/project-factory/schemas/aspect-type.schema.json new file mode 100644 index 000000000..49a8f8e31 --- /dev/null +++ b/modules/project-factory/schemas/aspect-type.schema.json @@ -0,0 +1,125 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Dataplex Aspect Type", + "type": "object", + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "labels": { + "type": "object" + }, + "metadata_template": { + "type": "string" + }, + "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/|\\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/roles/)": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:||\\$iam_principals:[a-z0-9_-]+)" + } + } + } + }, + "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:|\\$iam_principals:[a-z0-9_-]+)" + } + }, + "role": { + "type": "string", + "pattern": "^(?:roles/|\\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/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:|\\$iam_principals:[a-z0-9_-]+)" + }, + "role": { + "type": "string", + "pattern": "^(?:roles/|\\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/roles/)" + }, + "condition": { + "type": "object", + "additionalProperties": false, + "required": [ + "expression", + "title" + ], + "properties": { + "expression": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + } + } + } + } + } + } + } +} diff --git a/modules/project-factory/schemas/aspect-type.schema.md b/modules/project-factory/schemas/aspect-type.schema.md new file mode 100644 index 000000000..81576d96e --- /dev/null +++ b/modules/project-factory/schemas/aspect-type.schema.md @@ -0,0 +1,50 @@ +# Dataplex Aspect Type + + + +## Properties + +*additional properties: false* + +- **description**: *string* +- **display_name**: *string* +- **labels**: *object* +- **metadata_template**: *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/|\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/roles/)`**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:||\$iam_principals:[a-z0-9_-]+)* +- **iam_bindings**: *object* +
*additional properties: false* + - **`^[a-z0-9_-]+$`**: *object* +
*additional properties: false* + - **members**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)* + - **role**: *string* +
*pattern: ^(?:roles/|\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/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:|\$iam_principals:[a-z0-9_-]+)* + - **role**: *string* +
*pattern: ^(?:roles/|\$custom_roles:|organizations/[0-9]+/roles/|([a-z0-9.]+:)?projects/[a-z0-9-]+/roles/)* + - **condition**: *object* +
*additional properties: false* + - ⁺**expression**: *string* + - ⁺**title**: *string* + - **description**: *string* diff --git a/modules/project-factory/schemas/project.schema.json b/modules/project-factory/schemas/project.schema.json index d65fa4a58..94c224062 100644 --- a/modules/project-factory/schemas/project.schema.json +++ b/modules/project-factory/schemas/project.schema.json @@ -111,6 +111,9 @@ "type": "object", "additionalProperties": false, "properties": { + "display_name": { + "type": "string" + }, "description": { "type": "string" }, @@ -297,9 +300,15 @@ "type": "object", "additionalProperties": false, "properties": { + "aspect_types": { + "type": "string" + }, "custom_roles": { "type": "string" }, + "data_catalog_taxonomy": { + "type": "string" + }, "observability": { "type": "string" }, diff --git a/modules/project-factory/schemas/project.schema.md b/modules/project-factory/schemas/project.schema.md index a14fb866d..31998ca8a 100644 --- a/modules/project-factory/schemas/project.schema.md +++ b/modules/project-factory/schemas/project.schema.md @@ -37,6 +37,7 @@
*additional properties: false* - **`^[a-z0-9-]+$`**: *object*
*additional properties: false* + - **display_name**: *string* - **description**: *string* - **prefix**: *string* - **iam**: *reference([iam](#refs-iam))* @@ -95,7 +96,9 @@
*enum: ['PREVENT', 'DELETE', 'ABANDON']* - **factories_config**: *object*
*additional properties: false* + - **aspect_types**: *string* - **custom_roles**: *string* + - **data_catalog_taxonomy**: *string* - **observability**: *string* - **org_policies**: *string* - **quotas**: *string* diff --git a/modules/project-factory/schemas/taxonomy.schema.json b/modules/project-factory/schemas/taxonomy.schema.json new file mode 100644 index 000000000..23da50da8 --- /dev/null +++ b/modules/project-factory/schemas/taxonomy.schema.json @@ -0,0 +1,153 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "additionalProperties": false, + "properties": { + "activated_policy_types": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "type": "string" + }, + "iam": { + "$ref": "#/$defs/iam" + }, + "iam_bindings": { + "$ref": "#/$defs/iam_bindings" + }, + "iam_bindings_additive": { + "$ref": "#/$defs/iam_bindings_additive" + }, + "tags": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^.+$": { + "type": "object", + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "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/|\\$custom_roles:)": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)" + } + } + } + }, + "iam_bindings": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^[a-z0-9_-]+$": { + "type": "object", + "additionalProperties": false, + "required": [ + "members", + "role" + ], + "properties": { + "members": { + "type": "array", + "items": { + "type": "string", + "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)" + } + }, + "role": { + "type": "string", + "pattern": "^(?:roles/|\\$custom_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, + "required": [ + "member", + "role" + ], + "properties": { + "member": { + "type": "string", + "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)" + }, + "role": { + "type": "string", + "pattern": "^(?:roles/|\\$custom_roles:)" + }, + "condition": { + "type": "object", + "additionalProperties": false, + "required": [ + "expression", + "title" + ], + "properties": { + "expression": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/modules/project-factory/schemas/taxonomy.schema.md b/modules/project-factory/schemas/taxonomy.schema.md new file mode 100644 index 000000000..da41b4360 --- /dev/null +++ b/modules/project-factory/schemas/taxonomy.schema.md @@ -0,0 +1,57 @@ +# None + + + +## Properties + +*additional properties: false* + +- **activated_policy_types**: *array* + - items: *string* +- **description**: *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))* +- **tags**: *object* +
*additional properties: false* + - **`^.+$`**: *object* +
*additional properties: false* + - **description**: *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/|\$custom_roles:)`**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)* +- **iam_bindings**: *object* +
*additional properties: false* + - **`^[a-z0-9_-]+$`**: *object* +
*additional properties: false* + - ⁺**members**: *array* + - items: *string* +
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)* + - ⁺**role**: *string* +
*pattern: ^(?:roles/|\$custom_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:|\$iam_principals:[a-z0-9_-]+)* + - ⁺**role**: *string* +
*pattern: ^(?:roles/|\$custom_roles:)* + - **condition**: *object* +
*additional properties: false* + - ⁺**expression**: *string* + - ⁺**title**: *string* + - **description**: *string* diff --git a/modules/project-factory/taxonomies.tf b/modules/project-factory/taxonomies.tf new file mode 100644 index 000000000..d8bb4997a --- /dev/null +++ b/modules/project-factory/taxonomies.tf @@ -0,0 +1,46 @@ +/** + * 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. + */ + +# tfdoc:file:description Taxonomy resources. + +module "taxonomies" { + source = "../data-catalog-policy-tag" + for_each = { + for k, v in local.projects_input : k => v + if try(v.factories_config.data_catalog_taxonomy, null) != null + } + project_id = module.projects[each.key].project_id + factories_config = { + taxonomy = lookup(each.value.factories_config, "data_catalog_taxonomy", null) == null ? null : try(pathexpand( + var.factories_config.basepath == null || startswith(each.value.factories_config.data_catalog_taxonomy, "/") || startswith(each.value.factories_config.data_catalog_taxonomy, ".") + ? each.value.factories_config.data_catalog_taxonomy : + "${var.factories_config.basepath}/${each.value.factories_config.data_catalog_taxonomy}" + ), null) + } + name = "taxonomy" + location = try(each.value.locations.storage, "europe-west1") + context = merge(local.ctx, { + iam_principals = merge( + local.ctx_iam_principals, + lookup(local.self_sas_iam_emails, each.key, {}), + local.projects_service_agents + ) + project_ids = merge( + local.ctx.project_ids, + { for k, v in module.projects : k => v.project_id } + ) + }) +} diff --git a/modules/project-factory/variables-projects.tf b/modules/project-factory/variables-projects.tf index 5e228fa5c..fc8aad4e2 100644 --- a/modules/project-factory/variables-projects.tf +++ b/modules/project-factory/variables-projects.tf @@ -240,7 +240,9 @@ variable "projects" { threat_detector_provider = optional(string) }), {}) factories_config = optional(object({ + aspect_types = optional(string) custom_roles = optional(string) + data_catalog_taxonomy = optional(string) observability = optional(string) org_policies = optional(string) pam_entitlements = optional(string) diff --git a/tests/fast/stages/s2_project_factory/data-platform.tfvars b/tests/fast/stages/s2_project_factory/data-platform.tfvars new file mode 100644 index 000000000..c22403d2e --- /dev/null +++ b/tests/fast/stages/s2_project_factory/data-platform.tfvars @@ -0,0 +1,25 @@ +automation = { + outputs_bucket = "fast2-prod-iac-core-outputs" +} +prefix = "testorg" +billing_account = { + id = "000000-111111-222222" +} +folder_ids = { + data-platform = "folders/1234567890" +} +project_ids = { + net-dev-0 = "projects/net-dev-0" +} +tag_values = { + "environment/development" = "tagValues/1234567890" + "environment/production" = "tagValues/2345678901" +} +factories_config = { + dataset = "datasets/data-platform" +} +organization = { + domain = "fast.example.com" + id = 123456789012 + customer_id = "C00000000" +} diff --git a/tests/fast/stages/s2_project_factory/data-platform.yaml b/tests/fast/stages/s2_project_factory/data-platform.yaml new file mode 100644 index 000000000..69d9411fe --- /dev/null +++ b/tests/fast/stages/s2_project_factory/data-platform.yaml @@ -0,0 +1,815 @@ +# 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 +# +# https://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.version[0]: + bucket: fast2-prod-iac-core-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/2-project-factory-version.txt + retention: [] + source: fast_version.txt + temporary_hold: null + timeouts: null + module.factory.module.aspect-types["core-0"].google_dataplex_aspect_type.default["basic"]: + aspect_type_id: basic + data_classification: null + description: null + display_name: Basic template + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + location: global + metadata_template: '{"name":"tf-basic-template","recordFields":[{"annotations":{"description":"Specifies + the source of data.","displayName":"Source"},"constraints":{"required":true},"index":1,"name":"source","type":"string"},{"annotations":{"description":"Specifies + the data owner.","displayName":"Owner"},"constraints":{},"index":2,"name":"owner","type":"string"}],"type":"record"}' + project: testorg-prod-dp-core-0 + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.automation-bucket["product-0/automation/tf-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: EUROPE-WEST1 + logging: [] + name: testorg-product-0-tf-state + project: testorg-prod-dp-dd-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.automation-bucket["product-0/automation/tf-state"].google_storage_bucket_iam_binding.authoritative["roles/storage.admin"] + : bucket: testorg-product-0-tf-state + condition: [] + members: + - serviceAccount:product-0-iac-rw@testorg-prod-dp-dd-0.iam.gserviceaccount.com + role: roles/storage.admin + timeouts: null + ? module.factory.module.automation-bucket["product-0/automation/tf-state"].google_storage_bucket_iam_binding.authoritative["roles/storage.objectViewer"] + : bucket: testorg-product-0-tf-state + condition: [] + members: + - group:dp-product-a-0@example.com + - serviceAccount:product-0-iac-ro@testorg-prod-dp-dd-0.iam.gserviceaccount.com + role: roles/storage.objectViewer + timeouts: null + module.factory.module.automation-bucket["shared-0/automation/tf-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: EUROPE-WEST1 + logging: [] + name: testorg-shared-0-tf-state + project: testorg-prod-dp-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.automation-bucket["shared-0/automation/tf-state"].google_storage_bucket_iam_binding.authoritative["roles/storage.admin"] + : bucket: testorg-shared-0-tf-state + condition: [] + members: + - serviceAccount:shared-0-iac-rw@testorg-prod-dp-core-0.iam.gserviceaccount.com + role: roles/storage.admin + timeouts: null + ? module.factory.module.automation-bucket["shared-0/automation/tf-state"].google_storage_bucket_iam_binding.authoritative["roles/storage.objectViewer"] + : bucket: testorg-shared-0-tf-state + condition: [] + members: + - group:dp-product-a-0@example.com + - serviceAccount:shared-0-iac-ro@testorg-prod-dp-core-0.iam.gserviceaccount.com + role: roles/storage.objectViewer + timeouts: null + module.factory.module.automation-service-accounts["product-0/automation/iac-ro"].google_service_account.service_account[0]: + account_id: product-0-iac-ro + create_ignore_already_exists: null + description: null + disabled: false + display_name: Product 0/0 (ro) + email: product-0-iac-ro@testorg-prod-dp-dd-0.iam.gserviceaccount.com + member: serviceAccount:product-0-iac-ro@testorg-prod-dp-dd-0.iam.gserviceaccount.com + project: testorg-prod-dp-dd-0 + timeouts: null + ? module.factory.module.automation-service-accounts["product-0/automation/iac-ro"].google_service_account_iam_binding.authoritative["roles/iam.serviceAccountTokenCreator"] + : condition: [] + members: + - group:dp-product-a-0@example.com + role: roles/iam.serviceAccountTokenCreator + module.factory.module.automation-service-accounts["product-0/automation/iac-rw"].google_service_account.service_account[0]: + account_id: product-0-iac-rw + create_ignore_already_exists: null + description: null + disabled: false + display_name: Product 0/0 (rw) + email: product-0-iac-rw@testorg-prod-dp-dd-0.iam.gserviceaccount.com + member: serviceAccount:product-0-iac-rw@testorg-prod-dp-dd-0.iam.gserviceaccount.com + project: testorg-prod-dp-dd-0 + timeouts: null + ? module.factory.module.automation-service-accounts["product-0/automation/iac-rw"].google_service_account_iam_binding.authoritative["roles/iam.serviceAccountTokenCreator"] + : condition: [] + members: + - group:dp-product-a-0@example.com + role: roles/iam.serviceAccountTokenCreator + module.factory.module.automation-service-accounts["shared-0/automation/iac-ro"].google_service_account.service_account[0]: + account_id: shared-0-iac-ro + create_ignore_already_exists: null + description: null + disabled: false + display_name: Domain 0 (ro) + email: shared-0-iac-ro@testorg-prod-dp-core-0.iam.gserviceaccount.com + member: serviceAccount:shared-0-iac-ro@testorg-prod-dp-core-0.iam.gserviceaccount.com + project: testorg-prod-dp-core-0 + timeouts: null + ? module.factory.module.automation-service-accounts["shared-0/automation/iac-ro"].google_service_account_iam_binding.authoritative["roles/iam.serviceAccountTokenCreator"] + : condition: [] + members: + - group:dp-product-a-0@example.com + role: roles/iam.serviceAccountTokenCreator + module.factory.module.automation-service-accounts["shared-0/automation/iac-rw"].google_service_account.service_account[0]: + account_id: shared-0-iac-rw + create_ignore_already_exists: null + description: null + disabled: false + display_name: Domain 0 (rw) + email: shared-0-iac-rw@testorg-prod-dp-core-0.iam.gserviceaccount.com + member: serviceAccount:shared-0-iac-rw@testorg-prod-dp-core-0.iam.gserviceaccount.com + project: testorg-prod-dp-core-0 + timeouts: null + ? module.factory.module.automation-service-accounts["shared-0/automation/iac-rw"].google_service_account_iam_binding.authoritative["roles/iam.serviceAccountTokenCreator"] + : condition: [] + members: + - group:dp-product-a-0@example.com + role: roles/iam.serviceAccountTokenCreator + module.factory.module.bigquery-datasets["product-0/private"].google_bigquery_dataset.default: + dataset_id: private + 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: null + labels: null + location: europe-west1 + max_time_travel_hours: '168' + project: testorg-prod-dp-dd0-p0 + resource_tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.bigquery-datasets["product-0/public"].google_bigquery_dataset.default: + dataset_id: public + 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: null + labels: null + location: europe-west1 + max_time_travel_hours: '168' + project: testorg-prod-dp-dd0-p0 + resource_tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + ? module.factory.module.bigquery-datasets["product-0/public"].google_bigquery_dataset_iam_binding.authoritative["roles/bigquery.dataViewer"] + : condition: [] + dataset_id: public + members: + - group:data-consumer-bi@example.com + project: testorg-prod-dp-dd0-p0 + role: roles/bigquery.dataViewer + module.factory.module.bigquery-datasets["product-0/public"].google_tags_location_tag_binding.binding["exposure"]: + location: europe-west1 + timeouts: null + module.factory.module.buckets["product-0/private"].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: EUROPE-WEST1 + logging: [] + name: testorg-prod-dp-dd0-p0-private + project: testorg-prod-dp-dd0-p0 + requester_pays: null + retention_policy: [] + storage_class: STANDARD + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + uniform_bucket_level_access: true + versioning: + - enabled: false + module.factory.module.buckets["product-0/public"].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: EUROPE-WEST1 + logging: [] + name: testorg-prod-dp-dd0-p0-public + project: testorg-prod-dp-dd0-p0 + requester_pays: null + retention_policy: [] + storage_class: STANDARD + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + uniform_bucket_level_access: true + versioning: + - enabled: false + ? module.factory.module.buckets["product-0/public"].google_storage_bucket_iam_binding.authoritative["roles/storage.objectViewer"] + : bucket: testorg-prod-dp-dd0-p0-public + condition: [] + members: + - group:data-consumer-bi@example.com + role: roles/storage.objectViewer + timeouts: null + module.factory.module.buckets["product-0/public"].google_tags_location_tag_binding.binding["exposure"]: + location: europe-west1 + parent: //storage.googleapis.com/projects/_/buckets/testorg-prod-dp-dd0-p0-public + timeouts: null + module.factory.module.folder-1["domain-0"].google_folder.folder[0]: + deletion_protection: false + display_name: Data Domain 0 + parent: folders/1234567890 + tags: null + timeouts: null + module.factory.module.projects-iam["product-0"].google_project_iam_binding.authoritative["roles/bigquery.dataEditor"]: + condition: [] + members: + - serviceAccount:processing@testorg-prod-dp-dd0-p0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + role: roles/bigquery.dataEditor + module.factory.module.projects-iam["product-0"].google_project_iam_binding.authoritative["roles/bigquery.jobUser"]: + condition: [] + members: + - serviceAccount:processing@testorg-prod-dp-dd0-p0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + role: roles/bigquery.jobUser + module.factory.module.projects-iam["product-0"].google_project_iam_binding.authoritative["roles/dataflow.admin"]: + condition: [] + members: + - serviceAccount:processing@testorg-prod-dp-dd0-p0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + role: roles/dataflow.admin + module.factory.module.projects-iam["product-0"].google_project_iam_binding.authoritative["roles/dataproc.editor"]: + condition: [] + members: + - serviceAccount:processing@testorg-prod-dp-dd0-p0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + role: roles/dataproc.editor + module.factory.module.projects-iam["product-0"].google_project_iam_binding.authoritative["roles/dataproc.worker"]: + condition: [] + members: + - serviceAccount:processing@testorg-prod-dp-dd0-p0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + role: roles/dataproc.worker + module.factory.module.projects-iam["product-0"].google_project_iam_binding.authoritative["roles/iam.serviceAccountUser"]: + condition: [] + members: + - serviceAccount:processing@testorg-prod-dp-dd0-p0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + role: roles/iam.serviceAccountUser + module.factory.module.projects-iam["product-0"].google_project_iam_binding.authoritative["roles/owner"]: + condition: [] + members: + - serviceAccount:product-0-iac-rw@testorg-prod-dp-dd-0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + role: roles/owner + module.factory.module.projects-iam["product-0"].google_project_iam_binding.authoritative["roles/storage.bucketViewer"]: + condition: [] + members: + - serviceAccount:processing@testorg-prod-dp-dd0-p0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + role: roles/storage.bucketViewer + module.factory.module.projects-iam["product-0"].google_project_iam_binding.authoritative["roles/storage.objectAdmin"]: + condition: [] + members: + - serviceAccount:processing@testorg-prod-dp-dd0-p0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + role: roles/storage.objectAdmin + module.factory.module.projects-iam["product-0"].google_project_iam_binding.authoritative["roles/viewer"]: + condition: [] + members: + - serviceAccount:product-0-iac-ro@testorg-prod-dp-dd-0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + role: roles/viewer + module.factory.module.projects-iam["shared-0"].google_project_iam_binding.authoritative["roles/composer.worker"]: + condition: [] + members: + - serviceAccount:composer@testorg-prod-dp-dd-0.iam.gserviceaccount.com + project: testorg-prod-dp-dd-0 + role: roles/composer.worker + module.factory.module.projects-iam["shared-0"].google_project_iam_binding.authoritative["roles/owner"]: + condition: [] + members: + - serviceAccount:shared-0-iac-rw@testorg-prod-dp-core-0.iam.gserviceaccount.com + project: testorg-prod-dp-dd-0 + role: roles/owner + module.factory.module.projects-iam["shared-0"].google_project_iam_binding.authoritative["roles/viewer"]: + condition: [] + members: + - serviceAccount:shared-0-iac-ro@testorg-prod-dp-core-0.iam.gserviceaccount.com + project: testorg-prod-dp-dd-0 + role: roles/viewer + module.factory.module.projects["core-0"].data.google_bigquery_default_service_account.bq_sa[0]: + project: testorg-prod-dp-core-0 + module.factory.module.projects["core-0"].data.google_logging_project_settings.logging_sa[0]: + project: testorg-prod-dp-core-0 + module.factory.module.projects["core-0"].data.google_storage_project_service_account.gcs_sa[0]: + project: testorg-prod-dp-core-0 + user_project: null + module.factory.module.projects["core-0"].google_project.project[0]: + auto_create_network: false + billing_account: 000000-111111-222222 + deletion_policy: DELETE + effective_labels: + goog-terraform-provisioned: 'true' + folder_id: '1234567890' + labels: null + name: testorg-prod-dp-core-0 + org_id: null + project_id: testorg-prod-dp-core-0 + tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.projects["core-0"].google_project_iam_member.service_agents["monitoring-notification"]: + condition: [] + project: testorg-prod-dp-core-0 + role: roles/monitoring.notificationServiceAgent + module.factory.module.projects["core-0"].google_project_service.project_services["bigquery.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-core-0 + service: bigquery.googleapis.com + timeouts: null + module.factory.module.projects["core-0"].google_project_service.project_services["datacatalog.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-core-0 + service: datacatalog.googleapis.com + timeouts: null + module.factory.module.projects["core-0"].google_project_service.project_services["logging.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-core-0 + service: logging.googleapis.com + timeouts: null + module.factory.module.projects["core-0"].google_project_service.project_services["monitoring.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-core-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["core-0"].google_project_service.project_services["storage.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-core-0 + service: storage.googleapis.com + timeouts: null + module.factory.module.projects["core-0"].google_project_service_identity.default["monitoring.googleapis.com"]: + project: testorg-prod-dp-core-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["core-0"].google_tags_tag_key.default["exposure"]: + allowed_values_regex: null + description: Data exposure controls. + parent: projects/testorg-prod-dp-core-0 + purpose: null + purpose_data: null + short_name: exposure + timeouts: null + module.factory.module.projects["core-0"].google_tags_tag_value.default["exposure/public"]: + description: Data exposure allowed. + short_name: public + timeouts: null + module.factory.module.projects["product-0"].data.google_bigquery_default_service_account.bq_sa[0]: + project: testorg-prod-dp-dd0-p0 + module.factory.module.projects["product-0"].data.google_logging_project_settings.logging_sa[0]: + project: testorg-prod-dp-dd0-p0 + module.factory.module.projects["product-0"].data.google_storage_project_service_account.gcs_sa[0]: + project: testorg-prod-dp-dd0-p0 + user_project: null + module.factory.module.projects["product-0"].google_project.project[0]: + auto_create_network: false + billing_account: 000000-111111-222222 + deletion_policy: DELETE + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: testorg-prod-dp-dd0-p0 + org_id: null + project_id: testorg-prod-dp-dd0-p0 + tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.projects["product-0"].google_project_iam_member.service_agents["cloudaicompanion"]: + condition: [] + project: testorg-prod-dp-dd0-p0 + role: roles/cloudaicompanion.serviceAgent + module.factory.module.projects["product-0"].google_project_iam_member.service_agents["cloudcomposer-accounts"]: + condition: [] + project: testorg-prod-dp-dd0-p0 + role: roles/composer.serviceAgent + module.factory.module.projects["product-0"].google_project_iam_member.service_agents["dataplex"]: + condition: [] + project: testorg-prod-dp-dd0-p0 + role: roles/dataplex.serviceAgent + module.factory.module.projects["product-0"].google_project_iam_member.service_agents["monitoring-notification"]: + condition: [] + project: testorg-prod-dp-dd0-p0 + role: roles/monitoring.notificationServiceAgent + module.factory.module.projects["product-0"].google_project_service.project_services["bigquery.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd0-p0 + service: bigquery.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service.project_services["cloudaicompanion.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd0-p0 + service: cloudaicompanion.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service.project_services["cloudresourcemanager.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd0-p0 + service: cloudresourcemanager.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service.project_services["composer.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd0-p0 + service: composer.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service.project_services["datacatalog.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd0-p0 + service: datacatalog.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service.project_services["datalineage.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd0-p0 + service: datalineage.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service.project_services["dataplex.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd0-p0 + service: dataplex.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service.project_services["logging.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd0-p0 + service: logging.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service.project_services["monitoring.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd0-p0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service.project_services["storage.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd0-p0 + service: storage.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service_identity.default["cloudaicompanion.googleapis.com"]: + project: testorg-prod-dp-dd0-p0 + service: cloudaicompanion.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service_identity.default["composer.googleapis.com"]: + project: testorg-prod-dp-dd0-p0 + service: composer.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service_identity.default["dataplex.googleapis.com"]: + project: testorg-prod-dp-dd0-p0 + service: dataplex.googleapis.com + timeouts: null + module.factory.module.projects["product-0"].google_project_service_identity.default["monitoring.googleapis.com"]: + project: testorg-prod-dp-dd0-p0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].data.google_bigquery_default_service_account.bq_sa[0]: + project: testorg-prod-dp-dd-0 + module.factory.module.projects["shared-0"].data.google_logging_project_settings.logging_sa[0]: + project: testorg-prod-dp-dd-0 + module.factory.module.projects["shared-0"].data.google_storage_project_service_account.gcs_sa[0]: + project: testorg-prod-dp-dd-0 + user_project: null + module.factory.module.projects["shared-0"].google_project.project[0]: + auto_create_network: false + billing_account: 000000-111111-222222 + deletion_policy: DELETE + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: testorg-prod-dp-dd-0 + org_id: null + project_id: testorg-prod-dp-dd-0 + tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.projects["shared-0"].google_project_iam_member.service_agents["cloudcomposer-accounts"]: + condition: [] + project: testorg-prod-dp-dd-0 + role: roles/composer.serviceAgent + module.factory.module.projects["shared-0"].google_project_iam_member.service_agents["dataplex"]: + condition: [] + project: testorg-prod-dp-dd-0 + role: roles/dataplex.serviceAgent + module.factory.module.projects["shared-0"].google_project_iam_member.service_agents["monitoring-notification"]: + condition: [] + project: testorg-prod-dp-dd-0 + role: roles/monitoring.notificationServiceAgent + module.factory.module.projects["shared-0"].google_project_service.project_services["bigquery.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd-0 + service: bigquery.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].google_project_service.project_services["composer.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd-0 + service: composer.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].google_project_service.project_services["datacatalog.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd-0 + service: datacatalog.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].google_project_service.project_services["datalineage.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd-0 + service: datalineage.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].google_project_service.project_services["dataplex.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd-0 + service: dataplex.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].google_project_service.project_services["logging.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd-0 + service: logging.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].google_project_service.project_services["monitoring.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd-0 + service: monitoring.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].google_project_service.project_services["storage.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: testorg-prod-dp-dd-0 + service: storage.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].google_project_service_identity.default["composer.googleapis.com"]: + project: testorg-prod-dp-dd-0 + service: composer.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].google_project_service_identity.default["dataplex.googleapis.com"]: + project: testorg-prod-dp-dd-0 + service: dataplex.googleapis.com + timeouts: null + module.factory.module.projects["shared-0"].google_project_service_identity.default["monitoring.googleapis.com"]: + project: testorg-prod-dp-dd-0 + service: monitoring.googleapis.com + timeouts: null + ? module.factory.module.service-accounts-iam["product-0/processing"].google_service_account_iam_binding.authoritative["roles/iam.serviceAccountUser"] + : condition: [] + members: + - serviceAccount:product-0-iac-rw@testorg-prod-dp-dd-0.iam.gserviceaccount.com + role: roles/iam.serviceAccountUser + module.factory.module.service-accounts["product-0/processing"].google_service_account.service_account[0]: + account_id: processing + create_ignore_already_exists: null + description: null + disabled: false + display_name: Processing service account. + email: processing@testorg-prod-dp-dd0-p0.iam.gserviceaccount.com + member: serviceAccount:processing@testorg-prod-dp-dd0-p0.iam.gserviceaccount.com + project: testorg-prod-dp-dd0-p0 + timeouts: null + module.factory.module.service-accounts["shared-0/composer"].google_service_account.service_account[0]: + account_id: composer + create_ignore_already_exists: null + description: null + disabled: false + display_name: Terraform-managed. + email: composer@testorg-prod-dp-dd-0.iam.gserviceaccount.com + member: serviceAccount:composer@testorg-prod-dp-dd-0.iam.gserviceaccount.com + project: testorg-prod-dp-dd-0 + timeouts: null + module.factory.module.taxonomies["core-0"].google_data_catalog_policy_tag.default["high"]: + description: High sensitivity data. + display_name: high + parent_policy_tag: null + timeouts: null + module.factory.module.taxonomies["core-0"].google_data_catalog_policy_tag.default["low"]: + description: Low sensitivity data. + display_name: low + parent_policy_tag: null + timeouts: null + module.factory.module.taxonomies["core-0"].google_data_catalog_policy_tag.default["medium"]: + description: Medium sensitivity data. + display_name: medium + parent_policy_tag: null + timeouts: null + module.factory.module.taxonomies["core-0"].google_data_catalog_taxonomy.default: + activated_policy_types: + - FINE_GRAINED_ACCESS_CONTROL + description: Taxonomy for data platform. + display_name: taxonomy + project: testorg-prod-dp-core-0 + region: europe-west1 + 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.vpc-factory.module.vpcs["domain-0"].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 + mtu: 1500 + name: domain-0 + network_firewall_policy_enforcement_order: AFTER_CLASSIC_FIREWALL + network_profile: null + params: [] + project: testorg-prod-dp-dd-0 + routing_mode: GLOBAL + timeouts: null + module.vpc-factory.module.vpcs["domain-0"].google_compute_route.gateway["directpath-googleapis"]: + description: Terraform-managed. + dest_range: 34.126.0.0/18 + name: domain-0-directpath-googleapis + network: domain-0 + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + params: [] + priority: 1000 + project: testorg-prod-dp-dd-0 + tags: null + timeouts: null + module.vpc-factory.module.vpcs["domain-0"].google_compute_route.gateway["private-googleapis"]: + description: Terraform-managed. + dest_range: 199.36.153.8/30 + name: domain-0-private-googleapis + network: domain-0 + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + params: [] + priority: 1000 + project: testorg-prod-dp-dd-0 + tags: null + timeouts: null + module.vpc-factory.module.vpcs["domain-0"].google_compute_route.gateway["restricted-googleapis"]: + description: Terraform-managed. + dest_range: 199.36.153.4/30 + name: domain-0-restricted-googleapis + network: domain-0 + next_hop_gateway: default-internet-gateway + next_hop_ilb: null + next_hop_instance: null + next_hop_vpn_tunnel: null + params: [] + priority: 1000 + project: testorg-prod-dp-dd-0 + tags: null + timeouts: null + +counts: + google_bigquery_dataset: 2 + google_bigquery_dataset_iam_binding: 1 + google_bigquery_default_service_account: 3 + google_compute_network: 1 + google_compute_route: 3 + google_data_catalog_policy_tag: 3 + google_data_catalog_taxonomy: 1 + google_dataplex_aspect_type: 1 + google_folder: 1 + google_logging_project_settings: 3 + google_project: 3 + google_project_iam_binding: 13 + google_project_iam_member: 8 + google_project_service: 23 + google_project_service_identity: 8 + google_service_account: 6 + google_service_account_iam_binding: 5 + google_storage_bucket: 4 + google_storage_bucket_iam_binding: 5 + google_storage_bucket_object: 1 + google_storage_project_service_account: 3 + google_tags_location_tag_binding: 2 + google_tags_tag_key: 1 + google_tags_tag_value: 1 + modules: 24 + resources: 104 + terraform_data: 2 + +outputs: + projects: __missing__ + vpcs: __missing__ diff --git a/tests/fast/stages/s2_project_factory/tftest.yaml b/tests/fast/stages/s2_project_factory/tftest.yaml index 2e7b27a19..4645a7006 100644 --- a/tests/fast/stages/s2_project_factory/tftest.yaml +++ b/tests/fast/stages/s2_project_factory/tftest.yaml @@ -16,3 +16,4 @@ module: fast/stages/2-project-factory tests: simple: + data-platform: diff --git a/tests/modules/project_factory/examples/example.yaml b/tests/modules/project_factory/examples/example.yaml index 6ce1ed424..22595f6d4 100644 --- a/tests/modules/project_factory/examples/example.yaml +++ b/tests/modules/project_factory/examples/example.yaml @@ -963,6 +963,14 @@ values: member: serviceAccount:app-0-be@test-pf-dev-tb-app0-1.iam.gserviceaccount.com project: test-pf-dev-tb-app0-1 timeouts: null + module.project-factory.module.taxonomies["dev-tb-app0-0"].google_data_catalog_taxonomy.default: + activated_policy_types: + - FINE_GRAINED_ACCESS_CONTROL + description: Taxonomy - Terraform managed + display_name: taxonomy + project: test-pf-dev-tb-app0-0 + region: europe-west1 + timeouts: null module.project-factory.terraform_data.defaults_preconditions: input: null output: null @@ -979,6 +987,7 @@ counts: google_cloud_asset_folder_feed: 1 google_compute_shared_vpc_host_project: 1 google_compute_shared_vpc_service_project: 1 + google_data_catalog_taxonomy: 1 google_essential_contacts_contact: 4 google_folder: 8 google_folder_iam_audit_config: 1 @@ -1012,8 +1021,8 @@ counts: google_tags_tag_key: 1 google_tags_tag_value: 2 google_tags_tag_value_iam_binding: 1 - modules: 37 - resources: 119 + modules: 38 + resources: 120 terraform_data: 2 outputs: {} diff --git a/tools/duplicate-diff.py b/tools/duplicate-diff.py index 01f4811e0..b9213aa6b 100755 --- a/tools/duplicate-diff.py +++ b/tools/duplicate-diff.py @@ -32,6 +32,15 @@ duplicates = [ "fast/stages/1-vpcsc/schemas/access-level.schema.json", "modules/vpc-sc/schemas/access-level.schema.json", ], + [ + "modules/dataplex-aspect-types/schemas/aspect-type.schema.json", + "modules/project-factory/schemas/aspect-type.schema.json", + "fast/stages/2-project-factory/schemas/aspect-type.schema.json", + ], + [ + "modules/data-catalog-policy-tag/schemas/policy-tag.schema.json", + "modules/project-factory/schemas/taxonomy.schema.json", + ], [ "fast/stages/2-project-factory/schemas/budget.schema.json", "fast/stages/0-org-setup/schemas/budget.schema.json", @@ -113,6 +122,7 @@ duplicates = [ "fast/stages/0-org-setup/schemas/tags.schema.json", "modules/project/schemas/tags.schema.json", "modules/organization/schemas/tags.schema.json", + "fast/stages/2-project-factory/schemas/tags.schema.json", ], [ "modules/cloud-function-v1/bundle.tf",