Skip to content

fix(gcp): upgrade google provider to 8.x and remove service networking peering on destroy - #2380

Merged
Brad-Edwards merged 6 commits into
devfrom
chore/gcp-google-provider-8
Sep 25, 2026
Merged

Brad-Edwards merged 6 commits into
devfrom
chore/gcp-google-provider-8

Conversation

@Brad-Edwards

Copy link
Copy Markdown
Owner

Summary

  • What changed:
    • Bumped every hashicorp/google and hashicorp/google-beta constraint under platform/terraform/gcp from ~> 6.0 to ~> 8.1. That covers the 5 environment roots, global/cicd-oidc, global/github-runner and modules/portal/gke. The rendered preparation root in shared/cloud/preparation_cloud_installation.py got the same bump.
    • Relocked all 25 GCP .terraform.lock.hcl files at google/google-beta 8.4.0. Only the google provider entries changed. Other providers keep their locked versions. Hashes use the existing single-platform (linux_amd64) convention.
    • modules/portal/vpc: google_service_networking_connection.services now sets deletion_policy = "REMOVE_PEERING". This adds a credential-free contract test (tests/main.tftest.hcl) and registers it in validation-inventory.yaml.
    • gcp-dev-destroy.yml: the retry-loop comments no longer claim the loop covers Service Networking detachment.
  • Why: terraform destroy of the balrog platform-core root kept failing on the Service Networking connection ("Producer services ... are still using this connection") even after Cloud SQL and Memorystore were deleted. The retry loop did not clear it. The provider's fix is deletion_policy = "REMOVE_PEERING", which needs google provider >= 8.1. ABANDON would leave the peering in place, and the peering still blocks deleting the network. REMOVE_PEERING is safe here because portal_cloud_sql and portal_redis both depends_on module.portal_vpc, so destroy removes every producer before the connection.

Provider 7.0 / 8.0 breaking changes reviewed

I checked all 47 google_* resource and data-source types in use (plus the two extra types in the rendered preparation root) against both upgrade guides. I also diffed the 6.50.0 and 8.4.0 provider schemas for those types.

Change Impact here Handling
google_storage_bucket.retention_policy.retention_period number -> string (7.0) modules/cicd-oidc-identity evidence bucket Value quoted as "7776000". ADR guard test assertion updated to match.
google_container_node_pool sandbox_config.sandbox_type deprecated in favor of type (8.x schema) modules/portal/gke/runtime-plugins.tf Switched to type = "GVISOR". The provider's SandboxTypeDiffSuppress suppresses the diff between the two fields, so this does not replace the ForceNew block. gke contract test updated.
google_container_cluster logging_config/monitoring_config.enable_components list -> set (8.0) modules/portal/gke/main.tf No change. The config uses list literals and nothing indexes them.
google_project_service.disable_on_destroy default removed (7.0) modules/project-services Already explicitly false, so behavior is unchanged.
google_compute_subnetwork.enable_flow_logs removed, google_compute_router advertised_ip_ranges set, google_secret_manager_secret_version.secret_data_wo_version string, google_sql_user password_wo pairing, node_config.host_maintenance_policy removed, artifact registry public_repository defaults Not used None

ADR Impact

  • No ADR impact
  • Existing ADRs updated
  • New ADR added
  • Temporary exception added to docs/adr/exceptions.yaml

ADRs touched: none

Exceptions added or renewed: none

Guardrail Changes

  • No guardrail files changed
  • Guardrail files changed and matching docs were updated

Guardrail files changed: platform/terraform/validation-inventory.yaml (gcp/modules/portal/vpc moves from deferred to terraform_test), and scripts/adr_guard/tests/test_deploy_workflow.py (retention literal is now a string).

Verification

  • python3 scripts/adr_guard/adr_guard.py --all --level ci passes. scripts/adr_guard/tests pass.
  • Relevant stack-native checks passed: terraform fmt -check -recursive, terraform validate in all 25 GCP dirs, tflint --recursive (clean), Checkov on platform/terraform/gcp (336 passed, 0 failed), check_tf_roots --check and its unittests, and the CI check_tf_* scanners with their unittests.
  • Relevant tests: every GCP terraform test suite (cicd-oidc 7, github-runner 2, portal/gke 3, portal/vpc 1, range/vpc 3). shifter/packer/tests 412 passed. shifter/installation/tests/test_gcp_bundle.py 24 passed. shifter/engine/provisioner/tests/test_terraform_base.py passed. shifter_platform preparation-cloud and runtime-plugin policy tests: 34 passed.
  • Docs updated where behavior or enforcement changed (not applicable)

Live read-only plan: terraform plan -lock=false of the sauron environment root against its real GCS state succeeded under 8.4.0 with no errors or new warnings. That state currently holds 0 managed resources, so the plan is all creates and cannot show replacement behavior on existing resources. No gcp-dev state bucket exists, and no nazgul tfvars are available locally. So no-replacement on live resources (the retention_period state migration, the sandbox field switch, the enable_components set conversion) is backed by the provider source and schema checks, not by a populated-state plan.

Bump every hashicorp/google and hashicorp/google-beta constraint under
platform/terraform/gcp from ~> 6.0 to ~> 8.1 and relock all GCP lock
files at 8.4.0. Only the google provider entries were relocked; other
providers keep their existing locked versions.

Breaking changes from the 7.0 and 8.0 upgrade guides that apply here:

- google_storage_bucket retention_policy.retention_period is now a
  string; quote the cicd-oidc evidence bucket value and update the ADR
  guard assertion that pins it.
- google_container_node_pool sandbox_config.sandbox_type is deprecated
  in 8.x; use sandbox_config.type = "GVISOR". The provider suppresses the
  diff between the two fields, so this does not replace the node pool.
- google_container_cluster logging/monitoring enable_components became
  sets; configuration passes list literals and nothing indexes them, so
  no change is needed.
- google_project_service disable_on_destroy default removal is already
  covered by the explicit disable_on_destroy = false.

The rendered preparation root also pins google ~> 8.1 so it matches the
platform provider major.
…ction

Destroying the platform-core root failed on
google_service_networking_connection.services with "Producer services
(e.g. CloudSQL, Cloud Memstore, etc.) are still using this connection"
after Cloud SQL and Memorystore were already deleted, and the destroy
retry loop never converged. Set deletion_policy = "REMOVE_PEERING"
(google provider >= 8.1) so the delete removes the producer-held VPC
peering and the platform network can be deleted. Cloud SQL and Redis
depend on the portal_vpc module, so destroy removes them first.

Add a credential-free contract test for the portal VPC module asserting
the policy, register it in the validation inventory, and stop the
gcp-dev destroy workflow comment from claiming its retry loop covers the
Service Networking detachment.
@Brad-Edwards
Brad-Edwards merged commit 36ac9e1 into dev Sep 25, 2026
5 checks passed
@Brad-Edwards
Brad-Edwards deleted the chore/gcp-google-provider-8 branch September 25, 2026 01:56
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant