* 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
213 lines
7.3 KiB
Python
Executable File
213 lines
7.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# 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.
|
|
#
|
|
|
|
import filecmp
|
|
import sys
|
|
import os
|
|
|
|
# List of folders and files that are expected to have same content
|
|
duplicates = [
|
|
# factory policies
|
|
[
|
|
"tests/modules/folder/factory/policies",
|
|
"tests/modules/organization/factory/policies",
|
|
"tests/modules/project/factory/policies",
|
|
],
|
|
# schemas
|
|
[
|
|
"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",
|
|
"modules/billing-account/schemas/budget.schema.json",
|
|
"modules/project-factory/schemas/budget.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/0-org-setup/schemas/custom-constraint.schema.json",
|
|
"modules/organization/schemas/org-policy-custom-constraint.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/0-org-setup/schemas/custom-role.schema.json",
|
|
"modules/project/schemas/custom-role.schema.json",
|
|
"modules/organization/schemas/custom-role.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/1-vpcsc/schemas/egress-policy.schema.json",
|
|
"modules/vpc-sc/schemas/egress-policy.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/0-org-setup/schemas/firewall-rules.schema.json",
|
|
"fast/stages/2-networking/schemas/firewall-rules.schema.json",
|
|
"modules/net-vpc-factory/schemas/firewall-rules.schema.json",
|
|
"modules/net-vpc-firewall/schemas/firewall-rules.schema.json",
|
|
],
|
|
[
|
|
"modules/project-factory/schemas/folder.schema.json",
|
|
"fast/stages/0-org-setup/schemas/folder.schema.json",
|
|
"fast/stages/2-networking/schemas/folder.schema.json",
|
|
"fast/stages/2-project-factory/schemas/folder.schema.json",
|
|
"fast/stages/2-security/schemas/folder.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/0-org-setup/schemas/observability.schema.json",
|
|
"modules/project/schemas/observability.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/1-vpcsc/schemas/ingress-policy.schema.json",
|
|
"modules/vpc-sc/schemas/ingress-policy.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/0-org-setup/schemas/org-policies.schema.json",
|
|
"modules/folder/schemas/org-policies.schema.json",
|
|
"modules/project/schemas/org-policies.schema.json",
|
|
"modules/organization/schemas/org-policies.schema.json",
|
|
],
|
|
[
|
|
"modules/folder/schemas/pam-entitlements.schema.json",
|
|
"modules/project/schemas/pam-entitlements.schema.json",
|
|
"modules/organization/schemas/pam-entitlements.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/1-vpcsc/schemas/perimeter.schema.json",
|
|
"modules/vpc-sc/schemas/perimeter.schema.json",
|
|
],
|
|
[
|
|
"modules/project-factory/schemas/project.schema.json",
|
|
"fast/stages/0-org-setup/schemas/project.schema.json",
|
|
"fast/stages/2-networking/schemas/project.schema.json",
|
|
"fast/stages/2-project-factory/schemas/project.schema.json",
|
|
"fast/stages/2-security/schemas/project.schema.json",
|
|
],
|
|
[
|
|
"modules/folder/schemas/scc-sha-custom-modules.schema.json",
|
|
"modules/project/schemas/scc-sha-custom-modules.schema.json",
|
|
"modules/organization/schemas/scc-sha-custom-modules.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/0-org-setup/schemas/subnet.schema.json",
|
|
"fast/stages/2-networking/schemas/subnet.schema.json",
|
|
"modules/net-vpc-factory/schemas/subnet.schema.json",
|
|
"modules/net-vpc/schemas/subnet.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/0-org-setup/schemas/vpc-factory.schema.json",
|
|
"modules/net-vpc-factory/schemas/vpc-factory.schema.json",
|
|
],
|
|
[
|
|
"fast/stages/0-org-setup/schemas/tags.schema.json",
|
|
"modules/project/schemas/tags.schema.json",
|
|
"modules/organization/schemas/tags.schema.json",
|
|
"fast/stages/2-project-factory/schemas/tags.schema.json",
|
|
],
|
|
[
|
|
"modules/cloud-function-v1/bundle.tf",
|
|
"modules/cloud-function-v2/bundle.tf",
|
|
],
|
|
[
|
|
"modules/cloud-function-v1/serviceaccount.tf",
|
|
"modules/cloud-function-v2/serviceaccount.tf",
|
|
"modules/cloud-run-v2/serviceaccount.tf",
|
|
],
|
|
[
|
|
"modules/cloud-function-v1/variables-serviceaccount.tf",
|
|
"modules/cloud-function-v2/variables-serviceaccount.tf",
|
|
"modules/cloud-run-v2/variables-serviceaccount.tf",
|
|
],
|
|
[
|
|
"modules/cloud-function-v1/variables-vpcconnector.tf",
|
|
"modules/cloud-function-v2/variables-vpcconnector.tf",
|
|
"modules/cloud-run-v2/variables-vpcconnector.tf",
|
|
],
|
|
[
|
|
"modules/cloud-function-v1/vpcconnector.tf",
|
|
"modules/cloud-function-v2/vpcconnector.tf",
|
|
"modules/cloud-run-v2/vpcconnector.tf",
|
|
],
|
|
]
|
|
|
|
|
|
def check_dir_diff(dcmp):
|
|
"""
|
|
Recursively checks a filecmp.dircmp object for any differences.
|
|
Returns True if a difference is found, False otherwise.
|
|
"""
|
|
diff_found = False
|
|
|
|
if dcmp.left_only:
|
|
print(f"[DIFF] Only in {dcmp.left}: {dcmp.left_only}")
|
|
diff_found = True
|
|
if dcmp.right_only:
|
|
print(f"[DIFF] Only in {dcmp.right}: {dcmp.right_only}")
|
|
diff_found = True
|
|
if dcmp.diff_files:
|
|
print(f"[DIFF] Mismatched files: {dcmp.diff_files}")
|
|
diff_found = True
|
|
|
|
for sub_dcmp in dcmp.subdirs.values():
|
|
if check_dir_diff(sub_dcmp):
|
|
diff_found = True
|
|
|
|
return diff_found
|
|
|
|
|
|
has_diff = False
|
|
|
|
for group in duplicates:
|
|
first = group[0]
|
|
if not os.path.exists(first):
|
|
print(f"[ERROR] Path not found: {first}. Skipping group.")
|
|
has_diff = True
|
|
continue
|
|
|
|
is_dir = os.path.isdir(first)
|
|
for second in group[1:]:
|
|
if not os.path.exists(second):
|
|
print(f"[DIFF] Path not found: {second}")
|
|
has_diff = True
|
|
continue
|
|
|
|
if is_dir != os.path.isdir(second):
|
|
print(f"[DIFF] Type mismatch: {first} is {'DIR' if is_dir else 'FILE'}, "
|
|
f"but {second} is {'DIR' if os.path.isdir(second) else 'FILE'}.")
|
|
has_diff = True
|
|
continue
|
|
|
|
if is_dir:
|
|
dcmp = filecmp.dircmp(first, second)
|
|
if check_dir_diff(dcmp):
|
|
print(f"[DIFF] Found differences between directories {first} {second}")
|
|
has_diff = True
|
|
else:
|
|
if not filecmp.cmp(first, second, shallow=False):
|
|
print(f"[DIFF] Files are different: {first} {second}")
|
|
has_diff = True
|
|
|
|
if has_diff:
|
|
print("\nCheck finished: Found differences.")
|
|
sys.exit(1)
|