github crossplane-contrib/provider-upjet-gcp v3.0.0

2 hours ago

Release Notes — v3.0.0

Overview

v3.0.0 is a major release with significant breaking changes. The most critical change is the removal of all previously-deprecated v1beta1 API versions, driven by a major upstream Terraform Google Provider version bump (v6.47.0 → v7.39.0). This release also ships a new Storage Version Migrator that must be run before upgrading if you are coming from v2.x or v1.x. Skipping the migration will leave CRDs in an inconsistent state and controllers will fail to start cleanly.


⚠️ Mandatory: Storage Version Migration

This step is required for all users upgrading from v1.x or v2.x.

This release removes v1beta1 API versions that were deprecated in prior releases. If you have existing managed resources stored in etcd under the old API version, the old version must be migrated to the current storage version before it can be removed from the CRD. Skipping this step will block API server from decoding objects correctly, causing reconciliation failures.

A built-in Storage Version Migrator is shipped in this release. It runs as an init container before the provider starts and automatically migrates all CRD objects to the current storage version.

How to apply

Apply the DeploymentRuntimeConfig included in the repository at examples/deploymentruntimeconfig-sv-migration.yaml before or alongside upgrading the provider package. You must update the image fields in the file to match the v3.0.0 package image you are deploying.

# Apply before or alongside the provider upgrade

# DeploymentRuntimeConfig that adds a storage version migration init container.
# Apply this before or alongside the Provider resource when upgrading from a
# release that carries v1beta1 CRDs to one where v1beta2 is the storage version.
#
# Reference it from your Provider via:
#   spec:
#     runtimeConfigRef:
#       name: sv-migration
#
# NOTE: Do NOT apply this DRC to the family/config provider package. That
# package has no managed resources with version history and does not generate
# the init subcommand, so the init container would fail to start.
#
# The init container image must match the provider package image being deployed.
# Update the image tag whenever you upgrade the provider.
#
# RBAC NOTE:
#   The init container runs under the provider's ServiceAccount. To fully
#   complete the migration it needs permission to patch customresourcedefinitions/status
#   (so it can remove the old version from status.storedVersions). This permission
#   is not granted by Crossplane's RBAC manager by default.
#
#   Without it, the object-level migration still succeeds (all v1beta1 objects
#   are patched and re-stored as v1beta2), but status.storedVersions is not
#   cleared. The init container logs a warning and continues rather than failing.
#
#   To grant the missing permission, apply the ClusterRole and ClusterRoleBinding
#   defined at the bottom of this file. They bind to the ServiceAccount whose
#   name is fixed via spec.serviceAccountTemplate.metadata.name below ("sv-migration-sa").
#   By pinning the SA name in the DRC we can pre-create the binding without
#   knowing the ephemeral revision name that Crossplane would otherwise assign.
#   Without this DRC, the SA would be named after the provider revision
#   (e.g. provider-gcp-storage-abc1234) and would change on every upgrade.
apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
metadata:
  name: sv-migration
spec:
  serviceAccountTemplate:
    metadata:
      # Pinning the SA name makes the ClusterRoleBinding below stable across
      # provider upgrades. Change this per sub-provider if needed.
      name: sv-migration-sa
  deploymentTemplate:
    spec:
      selector: {}
      template:
        spec:
          containers:
            - name: package-runtime
              # Must match the provider package image being deployed.
              image: xpkg.upbound.io/upbound/provider-gcp-storage:v3.0.0
              args:
                - --debug
          initContainers:
            - name: sv-migrator
              # Must match the provider package image being deployed.
              image: xpkg.upbound.io/upbound/provider-gcp-storage:v3.0.0
              args:
                - init
                - --debug
              securityContext:
                runAsUser: 2000
                runAsGroup: 2000
                allowPrivilegeEscalation: false
                privileged: false
                runAsNonRoot: true
              resources:
                limits:
                  cpu: 500m
                  memory: 512Mi
                requests:
                  cpu: 100m
                  memory: 256Mi
---
# ClusterRole granting permission to patch CRD status.
# Required for the init container to clear status.storedVersions after migration.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: provider-gcp-crd-status-patcher
rules:
  - apiGroups: ["apiextensions.k8s.io"]
    resources: ["customresourcedefinitions/status"]
    verbs: ["patch"]
---
# Binds the ClusterRole to the ServiceAccount named above.
# Adjust the namespace to match where Crossplane is installed
# (typically upbound-system or crossplane-system).
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: provider-gcp-crd-status-patcher
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: provider-gcp-crd-status-patcher
subjects:
  - kind: ServiceAccount
    name: sv-migration-sa
    namespace: upbound-system

Then reference it from your Provider resource:

spec:
  runtimeConfigRef:
    name: sv-migration

Important: Do NOT apply this DRC to the provider-gcp-family / provider-gcp-config package. That package carries no managed resources and does not include the init subcommand — the init container would fail to start.

The RBAC resources bundled in the example file grant the init container permission to patch customresourcedefinitions/status, which is required to clear status.storedVersions. Adjust the namespace field in the ClusterRoleBinding to match your Crossplane installation namespace (typically upbound-system or crossplane-system).

Once migration is verified (check init container logs for per-CRD progress), you may remove the runtimeConfigRef and revert to your normal DeploymentRuntimeConfig.

See the upstream documentation for the full step-by-step guide:

Also see the MR API Versioning Policy.


Required Upgrade Path

Do not skip versions when upgrading to v3.0.0. The storage version migration is a multi-step process tied to the API versions present at each release.

Coming from v2.x

v2.x.y → v2.6.0 → v3.0.0

You must pass through v2.6.0 first. v2.6.0 introduced the v1beta2 storage version for resources that previously used v1beta1 as storage. Reaching v2.6.0 before v3.0.0 ensures all objects are written into v1beta2 while both API versions are still served; the storage version migrator in v3.0.0 then clears the v1beta1 entry from status.storedVersions before the version is removed.

Coming from v1.x

v1.x → v2.0.0 → v2.6.0 → v3.0.0

Rule of thumb: you must visit v2.6.x (minimum v2.6.0) and then to v3.0.0.


Breaking Changes

1. Terraform Google Provider: v6.47.0 → v7.39.0

The underlying Terraform Google provider has been bumped by a full major version. This brings a large set of upstream schema changes that are reflected as API changes in the generated CRDs.

2. v1beta1 API Versions Removed

All v1beta1 API versions that were deprecated in prior releases have been permanently removed. Resources that only had a v1beta1 version have been deleted entirely. Resources that had multiple API versions (e.g. v1beta1 + v1beta2) retain their non-v1beta1 versions.

The following groups had one or more v1beta1 resources removed:

Group Affected resources (v1beta1 removed)
accesscontextmanager AccessLevel, AccessLevelCondition, AccessPolicyIAMMember, ServicePerimeter
alloydb Backup, Cluster, Instance
apigee Environment, EnvironmentIAMMember, Organization
appengine Application, ServiceNetworkSettings, StandardAppVersion
artifact RegistryRepository, RegistryRepositoryIAMMember
beyondcorp AppConnection, AppConnector
bigquery AnalyticsHubDataExchangeIAMMember, AnalyticsHubListing, Connection, Dataset, DatasetAccess, DatasetIAMBinding, DatasetIAMMember, DataTransferConfig, Job, Reservation, Routine, Table, TableIAMBinding
bigtable AppProfile, GarbageCollectionPolicy, Instance, InstanceIAMMember
binaryauthorization Attestor, Policy
certificatemanager Certificate
cloudbuild Trigger, WorkerPool
cloudfunctions Function, FunctionIAMMember
cloudfunctions2 Function
cloudplatform FolderIAMMember, OrganizationIAMMember, ProjectIAMMember, ServiceAccountIAMMember
cloudrun DomainMapping, Service, ServiceIAMMember, V2Job, V2Service
cloudscheduler Job
cloudtasks Queue
composer Environment
compute Autoscaler, BackendBucket, BackendService, Disk, DiskIAMMember, Firewall, FirewallPolicyRule, ForwardingRule, GlobalForwardingRule, HealthCheck, Image, ImageIAMMember, Instance, InstanceFromTemplate, InstanceGroupManager, InstanceIAMMember, InstanceTemplate, ManagedSSLCertificate, NodeGroup, NodeTemplate, PacketMirroring, PerInstanceConfig, RegionAutoscaler, RegionBackendService, RegionDisk, RegionDiskIAMMember
container Cluster, NodePool
containeranalysis Note
containerattached Cluster
containeraws Cluster, NodePool
containerazure Cluster, NodePool
datacatalog Entry, EntryGroup, PolicyTag, Taxonomy
datafusion Instance
datalossprevention DeidentifyTemplate, InspectTemplate, JobTrigger, StoredInfoType
dataplex Lake, Zone
dataproc Cluster, MetastoreService
datastream ConnectionProfile, PrivateConnection, Stream
dialogflowcx Agent, EntityType, Flow, Intent, Page, Version, Webhook
dns ManagedZone, RecordSet, ResponsePolicy
eventarc Channel, GoogleChannelConfig, Trigger
filestore Backup, Instance
firebaserules Release, Ruleset
gke BackupBackupPlan, BackupRestorePlan, HubMembership
gkehub Feature, MembershipIAMMember
healthcare DatasetIAMMember, DicomStore, FhirStore, Hl7V2Store
iam WorkforcePool, WorkforcePoolProvider, WorkloadIdentityPool, WorkloadIdentityPoolProvider
iap TunnelIAMMember, WebIAMMember
identityplatform DefaultSupportedIdPConfig, TenantOAuthIdPConfig
kms CryptoKey, CryptoKeyIAMMember, KeyRing, KeyRingIAMMember
logging ProjectSink
memcache Instance
mlengine Model
monitoring AlertPolicy, CustomService, MetricDescriptor, NotificationChannel, Service, SLO, UptimeCheckConfig
networkconnectivity Spoke
networkmanagement ConnectivityTest
notebooks Environment, Instance, InstanceIAMMember, Runtime, RuntimeIAMMember
osconfig OSPolicyAssignment, PatchDeployment
privateca CAPool, CAPoolIAMMember, Certificate, CertificateAuthority, CertificateTemplate, CertificateTemplateIAMMember
pubsub LiteSubscription, LiteTopic, Subscription, SubscriptionIAMMember, Topic, TopicIAMMember
redis Instance
secretmanager Secret, SecretIAMMember
sourcerepo RepositoryIAMMember
spanner Database, DatabaseIAMMember, Instance, InstanceIAMMember
sql DatabaseInstance, User
storage BucketIAMMember, BucketObject
storagetransfer AgentPool
tpu Node (entire CRD deleted — see below)
vertexai Dataset, Featurestore, FeaturestoreEntityType, Tensorboard
vpcaccess Connector

3. tpu.Node — CRD Completely Deleted

The google_tpu_node resource was dropped from the upstream Terraform Google provider in v7.x. The tpu.Node CRD no longer exists. Any deployed tpu.Node resources will have no managing controller and must be manually cleaned up.

4. apigee.KeystoresAliasesKeyCertFile — Plugin Framework Migration

This resource was migrated to the Terraform Plugin Framework runtime. As a result:

  • certsInfo is now computed-only and has been removed from spec.forProvider and spec.initProvider.
  • certsInfo is now an array in status.atProvider.

5. bigtable.TableIAMBinding, TableIAMMember, TableIAMPolicy — New API Versions

These resources have new API versions (v1beta3 for cluster-scoped, v1beta2 for namespaced). The field instance has been renamed to instanceName. Conversion webhooks handle the translation automatically, but ensure you are using the latest API version in your manifests.

6. compute.Disk, compute.RegionDisk — Sensitive Field Changes

The following fields became sensitive and were replaced with Secret references:

  • sourceImageEncryptionKey.rawKeysourceImageEncryptionKey.rawKeySecretRef
  • sourceSnapshotEncryptionKey.rawKeysourceSnapshotEncryptionKey.rawKeySecretRef

If you have these fields set directly in spec.forProvider, you must migrate them to reference a Kubernetes Secret.

7. compute.SubnetworkenableFlowLogs Removed

The enableFlowLogs field has been removed upstream. Use the dedicated logConfig block instead.

8. memorystore.Instance and redis.ClusterallowFewerZonesDeployment Removed

The allowFewerZonesDeployment field has been removed from both resources upstream.

9. storage.Bucket — Storage Version Bumped to v1beta3, retentionPolicy Type Change

storage.Bucket is now at v1beta3 (cluster-scoped) / v1beta2 (namespaced). The retentionPolicy.retentionPeriod field type changed from a number to a string. Conversion functions handle this automatically across API versions.

10. storage.Notification — Plugin Framework Migration

This resource was migrated to the Terraform Plugin Framework runtime. There are no schema-level changes.

11. cloudfunctions2.FunctionserviceConfig.service Becomes Computed-Only

serviceConfig.service is now computed-only and has been removed from spec.forProvider and spec.initProvider.

12. networkservices.Gatewayports Optional, allPorts Introduced

ports is now optional. A new mutually-exclusive field allPorts has been introduced.

13. compute.VPNTunnelsharedSecretSecretRef Becomes Optional

Previously required; now optional.

14. Write-Only Fields Removed (*_wo, *_wo_version)

All write-only variant fields (those suffixed with _wo or _wo_version) have been removed from resource schemas across all resources. These fields were never implemented for upjet-based providers and were a security concern as they stored values in plain text. This is a breaking API change for any resource that exposed these fields.

15. deletion_policy Field Suppressed on Most Resources

The upstream Terraform Google provider v7.33.0 introduced a deletion_policy field to many resources. To avoid inadvertent breaking CRD API changes, this field is centrally suppressed for all resources except the 24 resources that already exposed it prior to this bump. If a resource you rely on now has deletion_policy surfaced for the first time, and you are on a resource that was previously suppressing it, contact the maintainers.


New Features

Storage Version Migrator Init Container

Provider binaries now ship with an init subcommand that runs the storage version migration and exits, allowing normal provider startup to proceed without interference. This is orchestrated via a Kubernetes init container using a DeploymentRuntimeConfig. See the mandatory upgrade section above for details.

New Resources

  • networksecurity.DNSThreatDetectorgoogle_network_security_dns_threat_detector support added.
  • firestore.Database, firestore.Index, firestore.Field — Full Firestore resource support added via google_firestore_database, google_firestore_index, google_firestore_field.

ProviderConfig: userProjectOverride and billingProject

The ProviderConfig now supports two new fields for GCP quota management:

  • userProjectOverride — enables billing to a different project than where the identity was created.
  • billingProject — specifies the billing project for quota purposes.

See the GCP provider quota management docs for details.

upjet_resource_external_api_calls_total Metric

A new Prometheus metric upjet_resource_external_api_calls_total is now exposed, counting outbound GCP API calls by HTTP operation and GCP service name. Useful for quota monitoring and observability of provider activity.

Conversion Webhook Decoupled from Leader Election

Conversion webhooks are now registered unconditionally before the canSafeStart gate, fixing a race condition where leader election could block conversion webhooks from starting. This resolves issues with multi-replica provider deployments.

GKE DNS Endpoint Kubeconfig Fix

When a GKE cluster is configured with DNS-based control plane endpoints (ipEndpointsConfig disabled), the cluster CA certificate is no longer pinned in the generated kubeconfig. DNS endpoints are served with publicly-trusted certificates; pinning the cluster CA caused TLS validation to fail. Clusters using IP endpoints are unaffected.

New Reference Field for compute.RegionBackendService

A resolver reference for security_policy has been added to compute.RegionBackendService.

compute.Cluster (container) — Additional Fields

The TF provider bump introduces several new fields on container.Cluster:

  • nodeConfig.sandboxConfig
  • networkConfig.subnetwork on container.NodePool
  • maintenanceExclusion.exclusionOptions.endTimeBehavior
  • enableK8SCertsViaDns and enableK8STokensViaDns

sql.UserdatabaseRoles Field

databaseRoles field is now available on sql.User.

sql.DatabaseInstance — New Status Fields

ipAddress, status, and consumerNetworkStatus are now surfaced in status.atProvider on sql.DatabaseInstance.

compute.SSLCertificate — Write-Only Fields

privateKeySecretRef is now optional and write-only fields have been introduced for this resource.


Dependency Updates

Dependency New
Terraform Google Provider v7.39.0
Upjet v2.4.1-0.20260728...
crossplane-runtime v2.3.3
crossplane/crossplane APIs v2.3.4

Bug Fixes

  • compute.NetworkFirewallPolicyRule: Fixed a HTTP 400 error that prevented creating a global network firewall policy rule when the rule did not already exist. (#909)
  • container.Cluster (GKE DNS kubeconfig): Cluster CA is no longer pinned in the kubeconfig when the DNS endpoint is active, fixing TLS validation failures for clusters with IP endpoints disabled. (#991)

What's Changed

  • Bump underlying TF provider version to v7.39.0 by @sergenyalcin in #960
  • Decouple conversion webhook registration from leader election by @ulucinar in #961
  • Add google_network_security_dns_threat_detector resource and add referencer for RegionBackendService.security_policy by @sergenyalcin in #962
  • renovate: fix and refactor configuration by @erhancagirici in #964
  • Remove write only fields from resource schemas by @sergenyalcin in #963
  • Update actions/cache action to v6 by @renovate[bot] in #968
  • Update actions/checkout action to v7 by @renovate[bot] in #969
  • Update actions/setup-go action to v7 by @renovate[bot] in #970
  • Update docker/setup-qemu-action digest to 96fe6ef by @renovate[bot] in #967
  • Update actions/stale digest to 1e223db by @renovate[bot] in #966
  • Update fkirc/skip-duplicate-actions action to v5.3.2 by @renovate[bot] in #972
  • Update go module directive to v1.26.5 by @renovate[bot] in #973
  • Update dependency crossplane/crossplane to v2.3.3 by @renovate[bot] in #971
  • Pin crossplane-contrib/provider-workflows action to 451c4dc by @renovate[bot] in #941
  • Integrate dynamic storage version migration by @sergenyalcin in #980
  • Implement upjet_resource_external_api_calls_total metric by @jonasz-lasut in #958
  • Update crossplane-runtime to v2.3.3 by @jonasz-lasut in #984
  • Replace --init flag with init subcommand by @sergenyalcin in #983
  • Add some firestore resources by @ulrichgiraud in #939
  • bump upjet to 4f6e6e10dff2 by @erhancagirici in #986
  • Update actions/stale action to v11 by @renovate[bot] in #981
  • Update module github.com/crossplane/crossplane/apis/v2 to v2.3.4 by @renovate[bot] in #989
  • Update dependency crossplane/crossplane to v2.3.4 by @renovate[bot] in #978
  • Support userProjectOverride / billingProject on the GCP ProviderConfig by @jonasz-lasut in #987
  • fix(container): omit cluster CA from kubeconfig for DNS endpoint by @jonasz-lasut in #991
  • fix: NetworkFirewallPolicyRule add r.TerraformResource.Read function to handle HTTP 400 by @PhilipEkholm in #909
  • Update alpine Docker tag to v3.24.1 by @renovate[bot] in #947
  • Update dependency golangci/golangci-lint to v2.12.2 by @renovate[bot] in #975
  • fix: external-name configuration for Contact.essentialcontacts by @jonasz-lasut in #993
  • fix(security): remediate CVE vulnerabilities by @ulucinar in #994

New Contributors

Full Changelog: v2.6.0...v3.0.0

Don't miss a new provider-upjet-gcp release

NewReleases is sending notifications on new releases.