From 91aac5186eb0aa2c5c3def94d7a7c79f948ac9a9 Mon Sep 17 00:00:00 2001 From: Jason Vigil Date: Wed, 31 Jul 2024 20:43:18 +0000 Subject: [PATCH] feat: Implement sqlinstance direct controller --- apis/refs/v1beta1/computerefs.go | 5 +- apis/refs/v1beta1/sqlinstanceref.go | 24 + apis/refs/v1beta1/storagebucketref.go | 24 + apis/sql/v1beta1/sqlinstance_types.go | 15 +- apis/sql/v1beta1/zz_generated.deepcopy.go | 9 +- ...ools.cloudbuild.cnrm.cloud.google.com.yaml | 4 +- ...orkconnectivity.cnrm.cloud.google.com.yaml | 2 +- ...sclusters.redis.cnrm.cloud.google.com.yaml | 4 +- ...qlinstances.sql.cnrm.cloud.google.com.yaml | 66 +- hack/compare-mock | 1 + hack/record-gcp | 1 + .../apis/sql/v1beta1/sqlinstance_types.go | 16 +- .../directbase/directbase_controller.go | 4 + pkg/controller/direct/register/register.go | 1 + pkg/controller/direct/sql/client.go | 100 ++ pkg/controller/direct/sql/mapping.go | 531 ++++++++++ pkg/controller/direct/sql/merge.go | 907 ++++++++++++++++++ pkg/controller/direct/sql/normalize.go | 321 +++++++ .../direct/sql/sqlinstance_controller.go | 347 +++++++ pkg/controller/direct/sql/utils.go | 23 + ...generated_object_mysqlinstance.golden.yaml | 26 +- .../sqlinstance/mysqlinstance/_http.log | 239 ++++- ...ated_object_mysqlinstancebasic.golden.yaml | 7 +- .../sqlinstance/mysqlinstancebasic/_http.log | 243 ++++- ...erated_object_postgresinstance.golden.yaml | 15 +- .../sqlinstance/postgresinstance/_http.log | 245 +++-- ...d_object_postgresinstancebasic.golden.yaml | 7 +- .../postgresinstancebasic/_http.log | 178 +++- ...bject_sqlinstanceencryptionkey.golden.yaml | 14 +- .../sqlinstanceencryptionkey/_http.log | 267 ++++-- ...rated_object_sqlserverinstance.golden.yaml | 28 +- .../sqlinstance/sqlserverinstance/_http.log | 177 +++- .../sqlinstance/sqlserverinstance/update.yaml | 1 + ..._object_sqlserverinstancebasic.golden.yaml | 12 +- .../sqlserverinstancebasic/_http.log | 268 +++--- .../sqlserverinstancebasic/create.yaml | 5 +- .../sqlserverinstancebasic/dependencies.yaml | 21 + .../sqlserverinstancebasic/update.yaml | 5 +- .../basic/sql/v1beta1/sqluser/_http.log | 220 ++--- .../sqlinstanceref/_http.log | 220 ++--- .../cloudbuild/cloudbuildworkerpool.md | 2 +- .../resource-docs/sql/sqlinstance.md | 42 +- scripts/github-actions/tests-e2e-fixtures | 1 + scripts/github-actions/tests-e2e-samples | 1 + 44 files changed, 3727 insertions(+), 922 deletions(-) create mode 100644 apis/refs/v1beta1/sqlinstanceref.go create mode 100644 apis/refs/v1beta1/storagebucketref.go create mode 100644 pkg/controller/direct/sql/client.go create mode 100644 pkg/controller/direct/sql/mapping.go create mode 100644 pkg/controller/direct/sql/merge.go create mode 100644 pkg/controller/direct/sql/normalize.go create mode 100644 pkg/controller/direct/sql/sqlinstance_controller.go create mode 100644 pkg/controller/direct/sql/utils.go create mode 100644 pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/dependencies.yaml diff --git a/apis/refs/v1beta1/computerefs.go b/apis/refs/v1beta1/computerefs.go index 8e5c1959f2..f2c1aa00b6 100644 --- a/apis/refs/v1beta1/computerefs.go +++ b/apis/refs/v1beta1/computerefs.go @@ -19,6 +19,7 @@ import ( "fmt" "strings" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" @@ -27,7 +28,7 @@ import ( ) type ComputeNetworkRef struct { - /* The compute network selflink of form "projects//global/networks/", when not managed by KCC. */ + /* The compute network selflink of form "projects//global/networks/", when not managed by Config Connector. */ External string `json:"external,omitempty"` /* The `name` field of a `ComputeNetwork` resource. */ Name string `json:"name,omitempty"` @@ -83,7 +84,7 @@ func ResolveComputeNetwork(ctx context.Context, reader client.Reader, src client }) if err := reader.Get(ctx, key, computenetwork); err != nil { if apierrors.IsNotFound(err) { - return nil, fmt.Errorf("referenced ComputeNetwork %v not found", key) + return nil, k8s.NewReferenceNotFoundError(computenetwork.GroupVersionKind(), key) } return nil, fmt.Errorf("error reading referenced ComputeNetwork %v: %w", key, err) } diff --git a/apis/refs/v1beta1/sqlinstanceref.go b/apis/refs/v1beta1/sqlinstanceref.go new file mode 100644 index 0000000000..ea5daa8ee3 --- /dev/null +++ b/apis/refs/v1beta1/sqlinstanceref.go @@ -0,0 +1,24 @@ +// Copyright 2024 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. + +package v1beta1 + +type SQLInstanceRef struct { + /* The SQLInstance selfLink, when not managed by Config Connector. */ + External string `json:"external,omitempty"` + /* The `name` field of a `SQLInstance` resource. */ + Name string `json:"name,omitempty"` + /* The `namespace` field of a `SQLInstance` resource. */ + Namespace string `json:"namespace,omitempty"` +} diff --git a/apis/refs/v1beta1/storagebucketref.go b/apis/refs/v1beta1/storagebucketref.go new file mode 100644 index 0000000000..4d7a197c82 --- /dev/null +++ b/apis/refs/v1beta1/storagebucketref.go @@ -0,0 +1,24 @@ +// Copyright 2024 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. + +package v1beta1 + +type StorageBucketRef struct { + /* The StorageBucket selfLink, when not managed by Config Connector. */ + External string `json:"external,omitempty"` + /* The `name` field of a `StorageBucket` resource. */ + Name string `json:"name,omitempty"` + /* The `namespace` field of a `StorageBucket` resource. */ + Namespace string `json:"namespace,omitempty"` +} diff --git a/apis/sql/v1beta1/sqlinstance_types.go b/apis/sql/v1beta1/sqlinstance_types.go index 85c4e29d0a..d7f8ca6ecf 100644 --- a/apis/sql/v1beta1/sqlinstance_types.go +++ b/apis/sql/v1beta1/sqlinstance_types.go @@ -21,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/scheme" + refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/k8s/v1alpha1" ) @@ -161,7 +162,7 @@ type InstanceIpConfiguration struct { Ipv4Enabled *bool `json:"ipv4Enabled,omitempty"` // +optional - PrivateNetworkRef *v1alpha1.ResourceRef `json:"privateNetworkRef,omitempty"` + PrivateNetworkRef *refsv1beta1.ComputeNetworkRef `json:"privateNetworkRef,omitempty"` /* PSC settings for a Cloud SQL instance. */ // +optional @@ -203,6 +204,8 @@ type InstanceMaintenanceWindow struct { UpdateTrack *string `json:"updateTrack,omitempty"` } +// +kubebuilder:validation:XValidation:rule="has(self.value) ? !has(self.valueFrom) : true",message="valueFrom is forbidden when value is specified" +// +kubebuilder:validation:XValidation:rule="has(self.valueFrom) ? !has(self.value): true",message="value is forbidden when valueFrom is specified" type InstancePassword struct { /* Value of the field. Cannot be used if 'valueFrom' is specified. */ // +optional @@ -294,6 +297,8 @@ type InstanceReplicaConfiguration struct { VerifyServerCertificate *bool `json:"verifyServerCertificate,omitempty"` } +// +kubebuilder:validation:XValidation:rule="has(self.value) ? !has(self.valueFrom) : true",message="valueFrom is forbidden when value is specified" +// +kubebuilder:validation:XValidation:rule="has(self.valueFrom) ? !has(self.value): true",message="value is forbidden when valueFrom is specified" type InstanceRootPassword struct { /* Value of the field. Cannot be used if 'valueFrom' is specified. */ // +optional @@ -419,7 +424,7 @@ type InstanceSettings struct { type InstanceSqlServerAuditConfig struct { /* The name of the destination bucket (e.g., gs://mybucket). */ // +optional - BucketRef *v1alpha1.ResourceRef `json:"bucketRef,omitempty"` + BucketRef *refsv1beta1.StorageBucketRef `json:"bucketRef,omitempty"` /* How long to keep generated audit files. A duration in seconds with up to nine fractional digits, terminated by 's'. Example: "3.5s".. */ // +optional @@ -442,7 +447,7 @@ type SQLInstanceSpec struct { DatabaseVersion *string `json:"databaseVersion,omitempty"` // +optional - EncryptionKMSCryptoKeyRef *v1alpha1.ResourceRef `json:"encryptionKMSCryptoKeyRef,omitempty"` + EncryptionKMSCryptoKeyRef *refsv1beta1.KMSCryptoKeyRef `json:"encryptionKMSCryptoKeyRef,omitempty"` /* The type of the instance. The valid values are:- 'SQL_INSTANCE_TYPE_UNSPECIFIED', 'CLOUD_SQL_INSTANCE', 'ON_PREMISES_INSTANCE' and 'READ_REPLICA_INSTANCE'. */ // +optional @@ -453,7 +458,7 @@ type SQLInstanceSpec struct { MaintenanceVersion *string `json:"maintenanceVersion,omitempty"` // +optional - MasterInstanceRef *v1alpha1.ResourceRef `json:"masterInstanceRef,omitempty"` + MasterInstanceRef *refsv1beta1.SQLInstanceRef `json:"masterInstanceRef,omitempty"` /* Immutable. The region the instance will sit in. Note, Cloud SQL is not available in all regions. A valid region must be provided to use this resource. If a region is not provided in the resource definition, the provider region will be used instead, but this will be an apply-time error for instances if the provider region is not supported with Cloud SQL. If you choose not to provide the region argument for this resource, make sure you understand this. */ // +optional @@ -576,7 +581,7 @@ type SQLInstance struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec SQLInstanceSpec `json:"spec,omitempty"` + Spec SQLInstanceSpec `json:"spec"` Status SQLInstanceStatus `json:"status,omitempty"` } diff --git a/apis/sql/v1beta1/zz_generated.deepcopy.go b/apis/sql/v1beta1/zz_generated.deepcopy.go index 32d5fa371a..a4efc1c72c 100644 --- a/apis/sql/v1beta1/zz_generated.deepcopy.go +++ b/apis/sql/v1beta1/zz_generated.deepcopy.go @@ -19,6 +19,7 @@ package v1beta1 import ( + refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1" v1alpha1 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/k8s/v1alpha1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -310,7 +311,7 @@ func (in *InstanceIpConfiguration) DeepCopyInto(out *InstanceIpConfiguration) { } if in.PrivateNetworkRef != nil { in, out := &in.PrivateNetworkRef, &out.PrivateNetworkRef - *out = new(v1alpha1.ResourceRef) + *out = new(refsv1beta1.ComputeNetworkRef) **out = **in } if in.PscConfig != nil { @@ -792,7 +793,7 @@ func (in *InstanceSqlServerAuditConfig) DeepCopyInto(out *InstanceSqlServerAudit *out = *in if in.BucketRef != nil { in, out := &in.BucketRef, &out.BucketRef - *out = new(v1alpha1.ResourceRef) + *out = new(refsv1beta1.StorageBucketRef) **out = **in } if in.RetentionInterval != nil { @@ -910,7 +911,7 @@ func (in *SQLInstanceSpec) DeepCopyInto(out *SQLInstanceSpec) { } if in.EncryptionKMSCryptoKeyRef != nil { in, out := &in.EncryptionKMSCryptoKeyRef, &out.EncryptionKMSCryptoKeyRef - *out = new(v1alpha1.ResourceRef) + *out = new(refsv1beta1.KMSCryptoKeyRef) **out = **in } if in.InstanceType != nil { @@ -925,7 +926,7 @@ func (in *SQLInstanceSpec) DeepCopyInto(out *SQLInstanceSpec) { } if in.MasterInstanceRef != nil { in, out := &in.MasterInstanceRef, &out.MasterInstanceRef - *out = new(v1alpha1.ResourceRef) + *out = new(refsv1beta1.SQLInstanceRef) **out = **in } if in.Region != nil { diff --git a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_cloudbuildworkerpools.cloudbuild.cnrm.cloud.google.com.yaml b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_cloudbuildworkerpools.cloudbuild.cnrm.cloud.google.com.yaml index 07c58ce43f..aa7df4abd2 100644 --- a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_cloudbuildworkerpools.cloudbuild.cnrm.cloud.google.com.yaml +++ b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_cloudbuildworkerpools.cloudbuild.cnrm.cloud.google.com.yaml @@ -71,7 +71,7 @@ spec: properties: external: description: The compute network selflink of form "projects//global/networks/", - when not managed by KCC. + when not managed by Config Connector. type: string name: description: The `name` field of a `ComputeNetwork` resource. @@ -276,7 +276,7 @@ spec: properties: external: description: The compute network selflink of form "projects//global/networks/", - when not managed by KCC. + when not managed by Config Connector. type: string name: description: The `name` field of a `ComputeNetwork` resource. diff --git a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_networkconnectivityserviceconnectionpolicies.networkconnectivity.cnrm.cloud.google.com.yaml b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_networkconnectivityserviceconnectionpolicies.networkconnectivity.cnrm.cloud.google.com.yaml index 27d6d3e66d..d5ea58db53 100644 --- a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_networkconnectivityserviceconnectionpolicies.networkconnectivity.cnrm.cloud.google.com.yaml +++ b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_networkconnectivityserviceconnectionpolicies.networkconnectivity.cnrm.cloud.google.com.yaml @@ -79,7 +79,7 @@ spec: properties: external: description: The compute network selflink of form "projects//global/networks/", - when not managed by KCC. + when not managed by Config Connector. type: string name: description: The `name` field of a `ComputeNetwork` resource. diff --git a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_redisclusters.redis.cnrm.cloud.google.com.yaml b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_redisclusters.redis.cnrm.cloud.google.com.yaml index f389d442e1..cf65539464 100644 --- a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_redisclusters.redis.cnrm.cloud.google.com.yaml +++ b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_redisclusters.redis.cnrm.cloud.google.com.yaml @@ -123,7 +123,7 @@ spec: properties: external: description: The compute network selflink of form "projects//global/networks/", - when not managed by KCC. + when not managed by Config Connector. type: string name: description: The `name` field of a `ComputeNetwork` resource. @@ -264,7 +264,7 @@ spec: external: description: The compute network selflink of form "projects//global/networks/", - when not managed by KCC. + when not managed by Config Connector. type: string name: description: The `name` field of a `ComputeNetwork` diff --git a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_sqlinstances.sql.cnrm.cloud.google.com.yaml b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_sqlinstances.sql.cnrm.cloud.google.com.yaml index a5ed819ead..e3085be2af 100644 --- a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_sqlinstances.sql.cnrm.cloud.google.com.yaml +++ b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_sqlinstances.sql.cnrm.cloud.google.com.yaml @@ -75,29 +75,24 @@ spec: - external required: - name - - kind - not: anyOf: - required: - name - required: - namespace - - required: - - kind required: - external properties: external: - description: The external name of the referenced resource - type: string - kind: - description: Kind of the referent. + description: ' If provided must be in the format `projects/[kms_project_id]/locations/[region]/keyRings/[key_ring_id]/cryptoKeys/[key]`.' type: string name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: The `name` field of a `KMSCryptoKey` resource. type: string namespace: - description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + description: The `metadata.namespace` field of a `KMSCryptoKey` + resource. type: string type: object instanceType: @@ -114,29 +109,24 @@ spec: - external required: - name - - kind - not: anyOf: - required: - name - required: - namespace - - required: - - kind required: - external properties: external: - description: The external name of the referenced resource - type: string - kind: - description: Kind of the referent. + description: The SQLInstance selfLink, when not managed by Config + Connector. type: string name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: The `name` field of a `SQLInstance` resource. type: string namespace: - description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + description: The `namespace` field of a `SQLInstance` resource. type: string type: object region: @@ -211,6 +201,11 @@ spec: type: object type: object type: object + x-kubernetes-validations: + - message: valueFrom is forbidden when value is specified + rule: 'has(self.value) ? !has(self.valueFrom) : true' + - message: value is forbidden when valueFrom is specified + rule: 'has(self.valueFrom) ? !has(self.value): true' sslCipher: description: Immutable. Permissible ciphers for use in SSL encryption. type: string @@ -254,6 +249,11 @@ spec: type: object type: object type: object + x-kubernetes-validations: + - message: valueFrom is forbidden when value is specified + rule: 'has(self.value) ? !has(self.valueFrom) : true' + - message: value is forbidden when valueFrom is specified + rule: 'has(self.valueFrom) ? !has(self.value): true' settings: description: The settings to use for the database. The configuration is detailed below. @@ -488,29 +488,25 @@ spec: - external required: - name - - kind - not: anyOf: - required: - name - required: - namespace - - required: - - kind required: - external properties: external: - description: The external name of the referenced resource - type: string - kind: - description: Kind of the referent. + description: The compute network selflink of form "projects//global/networks/", + when not managed by Config Connector. type: string name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: The `name` field of a `ComputeNetwork` resource. type: string namespace: - description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + description: The `namespace` field of a `ComputeNetwork` + resource. type: string type: object pscConfig: @@ -620,29 +616,25 @@ spec: - external required: - name - - kind - not: anyOf: - required: - name - required: - namespace - - required: - - kind required: - external properties: external: - description: The external name of the referenced resource - type: string - kind: - description: Kind of the referent. + description: The StorageBucket selfLink, when not managed + by Config Connector. type: string name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: The `name` field of a `StorageBucket` resource. type: string namespace: - description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + description: The `namespace` field of a `StorageBucket` + resource. type: string type: object retentionInterval: @@ -772,6 +764,8 @@ spec: description: The service account email address assigned to the instance. type: string type: object + required: + - spec type: object served: true storage: true diff --git a/hack/compare-mock b/hack/compare-mock index 771dc46573..268920d4ab 100755 --- a/hack/compare-mock +++ b/hack/compare-mock @@ -16,5 +16,6 @@ E2E_GCP_TARGET=mock \ GOLDEN_REQUEST_CHECKS=1 \ GOLDEN_OBJECT_CHECKS=1 \ WRITE_GOLDEN_OUTPUT=1 \ +KCC_USE_DIRECT_RECONCILERS="SQLInstance" \ RUN_E2E=1 \ go test ./tests/e2e -timeout 3600s -v -run $RUN_TESTS \ No newline at end of file diff --git a/hack/record-gcp b/hack/record-gcp index a07b122fb5..f154e789fb 100755 --- a/hack/record-gcp +++ b/hack/record-gcp @@ -24,5 +24,6 @@ E2E_GCP_TARGET=real \ GOLDEN_REQUEST_CHECKS=1 \ GOLDEN_OBJECT_CHECKS=1 \ WRITE_GOLDEN_OUTPUT=1 \ +KCC_USE_DIRECT_RECONCILERS="SQLInstance" \ RUN_E2E=1 \ go test ./tests/e2e -timeout 3600s -v -run $RUN_TESTS \ No newline at end of file diff --git a/pkg/clients/generated/apis/sql/v1beta1/sqlinstance_types.go b/pkg/clients/generated/apis/sql/v1beta1/sqlinstance_types.go index db27c8ca35..010380c053 100644 --- a/pkg/clients/generated/apis/sql/v1beta1/sqlinstance_types.go +++ b/pkg/clients/generated/apis/sql/v1beta1/sqlinstance_types.go @@ -312,17 +312,11 @@ type InstanceSettings struct { // +optional AdvancedMachineFeatures *InstanceAdvancedMachineFeatures `json:"advancedMachineFeatures,omitempty"` - /* DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. - Specifying this field has no-ops; it's recommended to remove this field from your configuration. */ + /* DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. Specifying this field has no-ops; it's recommended to remove this field from your configuration. */ // +optional AuthorizedGaeApplications []string `json:"authorizedGaeApplications,omitempty"` - /* The availability type of the Cloud SQL instance, high availability - (REGIONAL) or single zone (ZONAL). For all instances, ensure that - settings.backup_configuration.enabled is set to true. - For MySQL instances, ensure that settings.backup_configuration.binary_log_enabled is set to true. - For Postgres instances, ensure that settings.backup_configuration.point_in_time_recovery_enabled - is set to true. Defaults to ZONAL. */ + /* The availability type of the Cloud SQL instance, high availability (REGIONAL) or single zone (ZONAL). For all instances, ensure that settings.backup_configuration.enabled is set to true. For MySQL instances, ensure that settings.backup_configuration.binary_log_enabled is set to true. For Postgres instances, ensure that settings.backup_configuration.point_in_time_recovery_enabled is set to true. Defaults to ZONAL. */ // +optional AvailabilityType *string `json:"availabilityType,omitempty"` @@ -337,8 +331,7 @@ type InstanceSettings struct { // +optional ConnectorEnforcement *string `json:"connectorEnforcement,omitempty"` - /* DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. - Specifying this field has no-ops; it's recommended to remove this field from your configuration. */ + /* DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. Specifying this field has no-ops; it's recommended to remove this field from your configuration. */ // +optional CrashSafeReplication *bool `json:"crashSafeReplication,omitempty"` @@ -397,8 +390,7 @@ type InstanceSettings struct { // +optional PricingPlan *string `json:"pricingPlan,omitempty"` - /* DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. - Specifying this field has no-ops; it's recommended to remove this field from your configuration. */ + /* DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. Specifying this field has no-ops; it's recommended to remove this field from your configuration. */ // +optional ReplicationType *string `json:"replicationType,omitempty"` diff --git a/pkg/controller/direct/directbase/directbase_controller.go b/pkg/controller/direct/directbase/directbase_controller.go index cc85739fea..447a1d50cf 100644 --- a/pkg/controller/direct/directbase/directbase_controller.go +++ b/pkg/controller/direct/directbase/directbase_controller.go @@ -225,6 +225,10 @@ func (r *reconcileContext) doReconcile(ctx context.Context, u *unstructured.Unst adapter, err := r.Reconciler.model.AdapterForObject(ctx, r.Reconciler.Client, u) if err != nil { + if unwrappedErr, ok := lifecyclehandler.CausedByUnresolvableDeps(err); ok { + logger.Info(unwrappedErr.Error(), "resource", k8s.GetNamespacedName(u)) + return r.handleUnresolvableDeps(ctx, u, unwrappedErr) + } return false, r.handleUpdateFailed(ctx, u, err) } diff --git a/pkg/controller/direct/register/register.go b/pkg/controller/direct/register/register.go index f51dd47ea5..076a22e905 100644 --- a/pkg/controller/direct/register/register.go +++ b/pkg/controller/direct/register/register.go @@ -25,4 +25,5 @@ import ( _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/networkconnectivity" _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/privateca" _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/resourcemanager" + _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/sql" ) diff --git a/pkg/controller/direct/sql/client.go b/pkg/controller/direct/sql/client.go new file mode 100644 index 0000000000..baeb59ecee --- /dev/null +++ b/pkg/controller/direct/sql/client.go @@ -0,0 +1,100 @@ +// Copyright 2024 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. + +package sql + +import ( + "context" + "fmt" + "net/http" + + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/config" + "google.golang.org/api/option" + api "google.golang.org/api/sqladmin/v1beta4" +) + +type gcpClient struct { + config config.ControllerConfig + service *api.Service +} + +func newGCPClient(ctx context.Context, config *config.ControllerConfig) (*gcpClient, error) { + gcpClient := &gcpClient{ + config: *config, + } + + opts, err := gcpClient.options() + if err != nil { + return nil, err + } + + gcpClient.service, err = api.NewService(ctx, opts...) + if err != nil { + return nil, fmt.Errorf("building gcp service client: %w", err) + } + + return gcpClient, nil +} + +func (m *gcpClient) options() ([]option.ClientOption, error) { + var opts []option.ClientOption + if m.config.UserAgent != "" { + opts = append(opts, option.WithUserAgent(m.config.UserAgent)) + } + if m.config.HTTPClient != nil { + // TODO: Set UserAgent in this scenario (error is: WithHTTPClient is incompatible with gRPC dial options) + + httpClient := &http.Client{} + *httpClient = *m.config.HTTPClient + httpClient.Transport = &optionsRoundTripper{ + config: m.config, + inner: m.config.HTTPClient.Transport, + } + opts = append(opts, option.WithHTTPClient(httpClient)) + } + if m.config.UserProjectOverride && m.config.BillingProject != "" { + opts = append(opts, option.WithQuotaProject(m.config.BillingProject)) + } + + // TODO: support endpoints? + // if m.config.Endpoint != "" { + // opts = append(opts, option.WithEndpoint(m.config.Endpoint)) + // } + + return opts, nil +} + +type optionsRoundTripper struct { + config config.ControllerConfig + inner http.RoundTripper +} + +func (m *optionsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + if m.config.UserAgent != "" { + req.Header.Set("User-Agent", m.config.UserAgent) + } + return m.inner.RoundTrip(req) +} + +func (m *gcpClient) sqlOperationsClient() *api.OperationsService { + return api.NewOperationsService(m.service) +} + +func (m *gcpClient) sqlInstancesClient() *api.InstancesService { + return api.NewInstancesService(m.service) +} + +func (m *gcpClient) sqlUsersClient() *api.UsersService { + return api.NewUsersService(m.service) +} diff --git a/pkg/controller/direct/sql/mapping.go b/pkg/controller/direct/sql/mapping.go new file mode 100644 index 0000000000..99fff3768c --- /dev/null +++ b/pkg/controller/direct/sql/mapping.go @@ -0,0 +1,531 @@ +// Copyright 2024 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. + +package sql + +import ( + "fmt" + + api "google.golang.org/api/sqladmin/v1beta4" + + krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/sql/v1beta1" +) + +func SQLInstanceKRMToGCP(in *krm.SQLInstance, refs *SQLInstanceInternalRefs) (*api.DatabaseInstance, error) { + out := &api.DatabaseInstance{} + + if in == nil { + return nil, fmt.Errorf("cannot convert nil SQLInstance") + } + + if in.Spec.DatabaseVersion != nil { + out.DatabaseVersion = *in.Spec.DatabaseVersion + } + + if in.Spec.EncryptionKMSCryptoKeyRef != nil { + out.DiskEncryptionConfiguration = &api.DiskEncryptionConfiguration{ + Kind: "sql#diskEncryptionConfiguration", + KmsKeyName: refs.cryptoKey, + } + } + + if in.Spec.InstanceType != nil { + out.InstanceType = *in.Spec.InstanceType + } + + if in.Spec.MaintenanceVersion != nil { + out.MaintenanceVersion = *in.Spec.MaintenanceVersion + } + + if in.Spec.MasterInstanceRef != nil { + out.MasterInstanceName = refs.masterInstance + } + + if in.Spec.Region != nil { + out.Region = *in.Spec.Region + } + + if in.Spec.ReplicaConfiguration != nil { + replicaConfiguration := &api.ReplicaConfiguration{ + Kind: "sql#replicaConfiguration", + } + + if in.Spec.ReplicaConfiguration.FailoverTarget != nil { + replicaConfiguration.FailoverTarget = *in.Spec.ReplicaConfiguration.FailoverTarget + } + + // todo: requires mysql + if in.Spec.ReplicaConfiguration.CaCertificate != nil || + in.Spec.ReplicaConfiguration.ClientCertificate != nil || + in.Spec.ReplicaConfiguration.ClientKey != nil || + in.Spec.ReplicaConfiguration.ConnectRetryInterval != nil || + in.Spec.ReplicaConfiguration.DumpFilePath != nil || + in.Spec.ReplicaConfiguration.MasterHeartbeatPeriod != nil || + in.Spec.ReplicaConfiguration.Password != nil || + in.Spec.ReplicaConfiguration.SslCipher != nil || + in.Spec.ReplicaConfiguration.Username != nil || + in.Spec.ReplicaConfiguration.VerifyServerCertificate != nil { + replicaConfiguration.MysqlReplicaConfiguration = &api.MySqlReplicaConfiguration{} + } + + if in.Spec.ReplicaConfiguration.CaCertificate != nil { + replicaConfiguration.MysqlReplicaConfiguration.CaCertificate = *in.Spec.ReplicaConfiguration.CaCertificate + } + + if in.Spec.ReplicaConfiguration.ClientCertificate != nil { + replicaConfiguration.MysqlReplicaConfiguration.ClientCertificate = *in.Spec.ReplicaConfiguration.ClientCertificate + } + + if in.Spec.ReplicaConfiguration.ClientKey != nil { + replicaConfiguration.MysqlReplicaConfiguration.ClientKey = *in.Spec.ReplicaConfiguration.ClientKey + } + + if in.Spec.ReplicaConfiguration.ConnectRetryInterval != nil { + replicaConfiguration.MysqlReplicaConfiguration.ConnectRetryInterval = *in.Spec.ReplicaConfiguration.ConnectRetryInterval + } + + if in.Spec.ReplicaConfiguration.DumpFilePath != nil { + replicaConfiguration.MysqlReplicaConfiguration.DumpFilePath = *in.Spec.ReplicaConfiguration.DumpFilePath + } + + if in.Spec.ReplicaConfiguration.MasterHeartbeatPeriod != nil { + replicaConfiguration.MysqlReplicaConfiguration.MasterHeartbeatPeriod = *in.Spec.ReplicaConfiguration.MasterHeartbeatPeriod + } + + if in.Spec.ReplicaConfiguration.Password != nil { + replicaConfiguration.MysqlReplicaConfiguration.Password = refs.replicaPassword + } + + if in.Spec.ReplicaConfiguration.SslCipher != nil { + replicaConfiguration.MysqlReplicaConfiguration.SslCipher = *in.Spec.ReplicaConfiguration.SslCipher + } + + if in.Spec.ReplicaConfiguration.Username != nil { + replicaConfiguration.MysqlReplicaConfiguration.Username = *in.Spec.ReplicaConfiguration.Username + } + + if in.Spec.ReplicaConfiguration.VerifyServerCertificate != nil { + replicaConfiguration.MysqlReplicaConfiguration.VerifyServerCertificate = *in.Spec.ReplicaConfiguration.VerifyServerCertificate + } + + out.ReplicaConfiguration = replicaConfiguration + } + + if in.Spec.ResourceID != nil { + out.Name = *in.Spec.ResourceID + } else { + return nil, fmt.Errorf("resourceID is empty") + } + + if in.Spec.RootPassword != nil && refs.rootPassword != "" { + out.RootPassword = refs.rootPassword + } + + out.Settings = &api.Settings{} + + if in.Spec.Settings.ActivationPolicy != nil { + out.Settings.ActivationPolicy = *in.Spec.Settings.ActivationPolicy + } + + if in.Spec.Settings.ActiveDirectoryConfig != nil { + // todo: requires sqlserver + // todo: requires private network + out.Settings.ActiveDirectoryConfig = &api.SqlActiveDirectoryConfig{ + Domain: in.Spec.Settings.ActiveDirectoryConfig.Domain, + } + } + + if in.Spec.Settings.AdvancedMachineFeatures != nil { + // todo: requires sqlserver + // todo: requires >= 6 cpu cores + out.Settings.AdvancedMachineFeatures = &api.AdvancedMachineFeatures{} + if in.Spec.Settings.AdvancedMachineFeatures.ThreadsPerCore != nil { + out.Settings.AdvancedMachineFeatures.ThreadsPerCore = *in.Spec.Settings.AdvancedMachineFeatures.ThreadsPerCore + } + } + + if in.Spec.Settings.AuthorizedGaeApplications != nil { + // todo: deprecated + out.Settings.AuthorizedGaeApplications = in.Spec.Settings.AuthorizedGaeApplications + } + + if in.Spec.Settings.AvailabilityType != nil { + out.Settings.AvailabilityType = *in.Spec.Settings.AvailabilityType + } + + if in.Spec.Settings.BackupConfiguration != nil { + backupConfig := &api.BackupConfiguration{} + + if in.Spec.Settings.BackupConfiguration.BackupRetentionSettings != nil { + retentionSettings := &api.BackupRetentionSettings{ + RetainedBackups: in.Spec.Settings.BackupConfiguration.BackupRetentionSettings.RetainedBackups, + } + if in.Spec.Settings.BackupConfiguration.BackupRetentionSettings.RetentionUnit != nil { + retentionSettings.RetentionUnit = *in.Spec.Settings.BackupConfiguration.BackupRetentionSettings.RetentionUnit + } + backupConfig.BackupRetentionSettings = retentionSettings + } + + if in.Spec.Settings.BackupConfiguration.BinaryLogEnabled != nil { + // todo: requires mysql + backupConfig.BinaryLogEnabled = *in.Spec.Settings.BackupConfiguration.BinaryLogEnabled + } + + if in.Spec.Settings.BackupConfiguration.Enabled != nil { + backupConfig.Enabled = *in.Spec.Settings.BackupConfiguration.Enabled + } + + if in.Spec.Settings.BackupConfiguration.Location != nil { + backupConfig.Location = *in.Spec.Settings.BackupConfiguration.Location + } + + if in.Spec.Settings.BackupConfiguration.PointInTimeRecoveryEnabled != nil { + backupConfig.PointInTimeRecoveryEnabled = *in.Spec.Settings.BackupConfiguration.PointInTimeRecoveryEnabled + } + + if in.Spec.Settings.BackupConfiguration.StartTime != nil { + backupConfig.StartTime = *in.Spec.Settings.BackupConfiguration.StartTime + } + + if in.Spec.Settings.BackupConfiguration.TransactionLogRetentionDays != nil { + backupConfig.TransactionLogRetentionDays = *in.Spec.Settings.BackupConfiguration.TransactionLogRetentionDays + } + + out.Settings.BackupConfiguration = backupConfig + } + + if in.Spec.Settings.Collation != nil { + // todo: requires sqlserver + out.Settings.Collation = *in.Spec.Settings.Collation + } + + if in.Spec.Settings.ConnectorEnforcement != nil { + out.Settings.ConnectorEnforcement = *in.Spec.Settings.ConnectorEnforcement + } + + if in.Spec.Settings.CrashSafeReplication != nil { + // todo: deprecated + out.Settings.CrashSafeReplicationEnabled = *in.Spec.Settings.CrashSafeReplication + } + + if in.Spec.Settings.DataCacheConfig != nil { + // todo: requires ENTERPRISE_PLUS edition + // todo: requires mysql or postgres + out.Settings.DataCacheConfig = &api.DataCacheConfig{ + DataCacheEnabled: *in.Spec.Settings.DataCacheConfig.DataCacheEnabled, + } + } + + if in.Spec.Settings.DatabaseFlags != nil { + dbFlags := []*api.DatabaseFlags{} + for _, dbFlag := range in.Spec.Settings.DatabaseFlags { + dbFlags = append(dbFlags, &api.DatabaseFlags{ + Name: dbFlag.Name, + Value: dbFlag.Value, + }) + } + out.Settings.DatabaseFlags = dbFlags + } + + if in.Spec.Settings.DeletionProtectionEnabled != nil { + out.Settings.DeletionProtectionEnabled = *in.Spec.Settings.DeletionProtectionEnabled + } + + if in.Spec.Settings.DenyMaintenancePeriod != nil { + // todo: handle multiple periods (?) + out.Settings.DenyMaintenancePeriods = []*api.DenyMaintenancePeriod{ + { + EndDate: in.Spec.Settings.DenyMaintenancePeriod.EndDate, + StartDate: in.Spec.Settings.DenyMaintenancePeriod.StartDate, + Time: in.Spec.Settings.DenyMaintenancePeriod.Time, + }, + } + } + + if in.Spec.Settings.DiskAutoresize != nil { + out.Settings.StorageAutoResize = in.Spec.Settings.DiskAutoresize + } + + if in.Spec.Settings.DiskAutoresizeLimit != nil { + // todo: requires DiskAutoresize == true + out.Settings.StorageAutoResizeLimit = *in.Spec.Settings.DiskAutoresizeLimit + } + + if in.Spec.Settings.DiskSize != nil { + out.Settings.DataDiskSizeGb = *in.Spec.Settings.DiskSize + } + + if in.Spec.Settings.DiskType != nil { + out.Settings.DataDiskType = *in.Spec.Settings.DiskType + } + + if in.Spec.Settings.Edition != nil { + out.Settings.Edition = *in.Spec.Settings.Edition + } + + if in.Spec.Settings.InsightsConfig != nil { + insightsConfig := &api.InsightsConfig{} + + if in.Spec.Settings.InsightsConfig.QueryInsightsEnabled != nil { + insightsConfig.QueryInsightsEnabled = *in.Spec.Settings.InsightsConfig.QueryInsightsEnabled + } + + if in.Spec.Settings.InsightsConfig.QueryPlansPerMinute != nil { + insightsConfig.QueryPlansPerMinute = *in.Spec.Settings.InsightsConfig.QueryPlansPerMinute + } + + if in.Spec.Settings.InsightsConfig.QueryStringLength != nil { + insightsConfig.QueryStringLength = *in.Spec.Settings.InsightsConfig.QueryStringLength + } + + if in.Spec.Settings.InsightsConfig.RecordApplicationTags != nil { + insightsConfig.RecordApplicationTags = *in.Spec.Settings.InsightsConfig.RecordApplicationTags + } + + if in.Spec.Settings.InsightsConfig.RecordClientAddress != nil { + insightsConfig.RecordClientAddress = *in.Spec.Settings.InsightsConfig.RecordClientAddress + } + + out.Settings.InsightsConfig = insightsConfig + } + + if in.Spec.Settings.IpConfiguration != nil { + out.Settings.IpConfiguration = &api.IpConfiguration{} + + if in.Spec.Settings.IpConfiguration.AllocatedIpRange != nil { + out.Settings.IpConfiguration.AllocatedIpRange = *in.Spec.Settings.IpConfiguration.AllocatedIpRange + } + + if in.Spec.Settings.IpConfiguration.AuthorizedNetworks != nil { + authorizedNetworks := []*api.AclEntry{} + for _, net := range in.Spec.Settings.IpConfiguration.AuthorizedNetworks { + netEntry := &api.AclEntry{ + Kind: "sql#aclEntry", + Value: net.Value, + } + if net.ExpirationTime != nil { + netEntry.ExpirationTime = *net.ExpirationTime + } + if net.Name != nil { + netEntry.Name = *net.Name + } + authorizedNetworks = append(authorizedNetworks, netEntry) + } + out.Settings.IpConfiguration.AuthorizedNetworks = authorizedNetworks + } + + if in.Spec.Settings.IpConfiguration.EnablePrivatePathForGoogleCloudServices != nil { + out.Settings.IpConfiguration.EnablePrivatePathForGoogleCloudServices = *in.Spec.Settings.IpConfiguration.EnablePrivatePathForGoogleCloudServices + } + + if in.Spec.Settings.IpConfiguration.Ipv4Enabled != nil { + out.Settings.IpConfiguration.Ipv4Enabled = *in.Spec.Settings.IpConfiguration.Ipv4Enabled + } else { + out.Settings.IpConfiguration.Ipv4Enabled = false + } + // todo: must do this for all fields (?) + out.Settings.IpConfiguration.ForceSendFields = []string{"Ipv4Enabled"} + + if in.Spec.Settings.IpConfiguration.PrivateNetworkRef != nil { + out.Settings.IpConfiguration.PrivateNetwork = refs.privateNetwork + } + + if in.Spec.Settings.IpConfiguration.PscConfig != nil { + if len(in.Spec.Settings.IpConfiguration.PscConfig) != 1 { + return nil, fmt.Errorf("only one psc config allowed per instance") + } + out.Settings.IpConfiguration.PscConfig = &api.PscConfig{ + AllowedConsumerProjects: in.Spec.Settings.IpConfiguration.PscConfig[0].AllowedConsumerProjects, + } + if in.Spec.Settings.IpConfiguration.PscConfig[0].PscEnabled != nil { + out.Settings.IpConfiguration.PscConfig.PscEnabled = *in.Spec.Settings.IpConfiguration.PscConfig[0].PscEnabled + } + } + + if in.Spec.Settings.IpConfiguration.RequireSsl != nil { + // todo: deprecated + out.Settings.IpConfiguration.RequireSsl = *in.Spec.Settings.IpConfiguration.RequireSsl + } + + if in.Spec.Settings.IpConfiguration.SslMode != nil { + out.Settings.IpConfiguration.SslMode = *in.Spec.Settings.IpConfiguration.SslMode + } + } + + if in.Spec.Settings.LocationPreference != nil { + out.Settings.LocationPreference = &api.LocationPreference{} + if in.Spec.Settings.LocationPreference.FollowGaeApplication != nil { + // todo: deprecated + out.Settings.LocationPreference.FollowGaeApplication = *in.Spec.Settings.LocationPreference.FollowGaeApplication + } + if in.Spec.Settings.LocationPreference.SecondaryZone != nil { + out.Settings.LocationPreference.SecondaryZone = *in.Spec.Settings.LocationPreference.SecondaryZone + } + if in.Spec.Settings.LocationPreference.Zone != nil { + out.Settings.LocationPreference.Zone = *in.Spec.Settings.LocationPreference.Zone + } + } + + if in.Spec.Settings.MaintenanceWindow != nil { + out.Settings.MaintenanceWindow = &api.MaintenanceWindow{} + if in.Spec.Settings.MaintenanceWindow.Day != nil { + out.Settings.MaintenanceWindow.Day = *in.Spec.Settings.MaintenanceWindow.Day + } + if in.Spec.Settings.MaintenanceWindow.Hour != nil { + out.Settings.MaintenanceWindow.Hour = *in.Spec.Settings.MaintenanceWindow.Hour + } + if in.Spec.Settings.MaintenanceWindow.UpdateTrack != nil { + out.Settings.MaintenanceWindow.UpdateTrack = *in.Spec.Settings.MaintenanceWindow.UpdateTrack + } + } + + if in.Spec.Settings.PasswordValidationPolicy != nil { + policy := &api.PasswordValidationPolicy{ + EnablePasswordPolicy: in.Spec.Settings.PasswordValidationPolicy.EnablePasswordPolicy, + } + + if in.Spec.Settings.PasswordValidationPolicy.Complexity != nil { + policy.Complexity = *in.Spec.Settings.PasswordValidationPolicy.Complexity + } + + if in.Spec.Settings.PasswordValidationPolicy.DisallowUsernameSubstring != nil { + policy.DisallowUsernameSubstring = *in.Spec.Settings.PasswordValidationPolicy.DisallowUsernameSubstring + } + + if in.Spec.Settings.PasswordValidationPolicy.MinLength != nil { + policy.MinLength = *in.Spec.Settings.PasswordValidationPolicy.MinLength + } + + if in.Spec.Settings.PasswordValidationPolicy.PasswordChangeInterval != nil { + policy.PasswordChangeInterval = *in.Spec.Settings.PasswordValidationPolicy.PasswordChangeInterval + } + + if in.Spec.Settings.PasswordValidationPolicy.ReuseInterval != nil { + policy.ReuseInterval = *in.Spec.Settings.PasswordValidationPolicy.ReuseInterval + } + + out.Settings.PasswordValidationPolicy = policy + } + + if in.Spec.Settings.PricingPlan != nil { + // todo: can only be PER_USE + out.Settings.PricingPlan = *in.Spec.Settings.PricingPlan + } + + if in.Spec.Settings.ReplicationType != nil { + // todo: deprecated + out.Settings.ReplicationType = *in.Spec.Settings.ReplicationType + } + + if in.Spec.Settings.SqlServerAuditConfig != nil { + // todo: requires sqlserver + out.Settings.SqlServerAuditConfig = &api.SqlServerAuditConfig{ + Kind: "sql#sqlServerAuditConfig", + } + + if in.Spec.Settings.SqlServerAuditConfig.BucketRef != nil { + // todo: required + out.Settings.SqlServerAuditConfig.Bucket = refs.auditLogBucket + } + + if in.Spec.Settings.SqlServerAuditConfig.RetentionInterval != nil { + out.Settings.SqlServerAuditConfig.RetentionInterval = *in.Spec.Settings.SqlServerAuditConfig.RetentionInterval + } + + if in.Spec.Settings.SqlServerAuditConfig.UploadInterval != nil { + out.Settings.SqlServerAuditConfig.UploadInterval = *in.Spec.Settings.SqlServerAuditConfig.UploadInterval + } + } + + out.Settings.Tier = in.Spec.Settings.Tier + + if in.Spec.Settings.TimeZone != nil { + // todo: requires sqlserver + out.Settings.TimeZone = *in.Spec.Settings.TimeZone + } + + if in.Labels != nil { + out.Settings.UserLabels = make(map[string]string) + for k, v := range in.Labels { + out.Settings.UserLabels[k] = v + } + } + + return out, nil +} + +func Convert_SQLInstance_API_v1_To_KRM_status(in *api.DatabaseInstance, out *krm.SQLInstanceStatus) error { + if in == nil { + return fmt.Errorf("cannot convert nil DatabaseInstance") + } + + if in.AvailableMaintenanceVersions != nil { + out.AvailableMaintenanceVersions = append(out.AvailableMaintenanceVersions, in.AvailableMaintenanceVersions...) + } + + out.ConnectionName = LazyPtr(in.ConnectionName) + + out.DnsName = LazyPtr(in.DnsName) + + if len(in.IpAddresses) >= 1 { + out.FirstIpAddress = LazyPtr(in.IpAddresses[0].IpAddress) + } + + out.InstanceType = LazyPtr(in.InstanceType) + + if in.IpAddresses != nil { + for _, ia := range in.IpAddresses { + ipAddr := krm.InstanceIpAddressStatus{ + IpAddress: LazyPtr(ia.IpAddress), + TimeToRetire: LazyPtr(ia.TimeToRetire), + Type: LazyPtr(ia.Type), + } + out.IpAddress = append(out.IpAddress, ipAddr) + + if ia.Type == "PRIMARY" { + out.PublicIpAddress = LazyPtr(ia.IpAddress) + } + + if ia.Type == "PRIVATE" { + out.PrivateIpAddress = LazyPtr(ia.IpAddress) + } + } + } + + out.PscServiceAttachmentLink = LazyPtr(in.PscServiceAttachmentLink) + + out.SelfLink = LazyPtr(in.SelfLink) + + if in.ServerCaCert != nil { + out.ServerCaCert = &krm.InstanceServerCaCertStatus{ + Cert: LazyPtr(in.ServerCaCert.Cert), + CommonName: LazyPtr(in.ServerCaCert.CommonName), + CreateTime: LazyPtr(in.ServerCaCert.CreateTime), + ExpirationTime: LazyPtr(in.ServerCaCert.ExpirationTime), + Sha1Fingerprint: LazyPtr(in.ServerCaCert.Sha1Fingerprint), + } + } + + out.ServiceAccountEmailAddress = LazyPtr(in.ServiceAccountEmailAddress) + + return nil +} + +func LazyPtr[T comparable](v T) *T { + var defaultValue T + if v == defaultValue { + return nil + } + return &v +} diff --git a/pkg/controller/direct/sql/merge.go b/pkg/controller/direct/sql/merge.go new file mode 100644 index 0000000000..10966dd654 --- /dev/null +++ b/pkg/controller/direct/sql/merge.go @@ -0,0 +1,907 @@ +// Copyright 2024 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. + +package sql + +import ( + "fmt" + "reflect" + + krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/sql/v1beta1" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct" + api "google.golang.org/api/sqladmin/v1beta4" +) + +// The goal of this function is to merge the desired state with the actual API state. Some fields in the API are defaulted by GCP. +// Additionally, some fields may be desirable to "unmanage". To handle these quirks, this function implements some merging logic +// for every API field. +func MergeDesiredSQLInstanceWithActual(desired *krm.SQLInstance, refs *SQLInstanceInternalRefs, actual *api.DatabaseInstance) (*api.DatabaseInstance, bool, error) { + merged := &api.DatabaseInstance{} + updateRequired := false + + if desired == nil || actual == nil { + return nil, false, fmt.Errorf("cannot merge nil SQLInstance") + } + + if desired.Spec.ResourceID != nil { + merged.Name = direct.ValueOf(desired.Spec.ResourceID) + } else { + merged.Name = desired.Name + } + if merged.Name != actual.Name { + return nil, false, fmt.Errorf("cannot rename SQLInstance") + } + + if desired.Spec.DatabaseVersion != nil { + if direct.ValueOf(desired.Spec.DatabaseVersion) != actual.DatabaseVersion { + // Change version + updateRequired = true + } + merged.DatabaseVersion = direct.ValueOf(desired.Spec.DatabaseVersion) + } else { + // Keep same version + merged.DatabaseVersion = actual.DatabaseVersion + } + + if desired.Spec.EncryptionKMSCryptoKeyRef != nil { + if actual.DiskEncryptionConfiguration == nil { + // Add key + updateRequired = true + } else if refs.cryptoKey != actual.DiskEncryptionConfiguration.KmsKeyName { + // Change keys + updateRequired = true + } + merged.DiskEncryptionConfiguration = &api.DiskEncryptionConfiguration{ + Kind: "sql#diskEncryptionConfiguration", + KmsKeyName: refs.cryptoKey, + } + } else if actual.DiskEncryptionConfiguration != nil { + // Remove key + updateRequired = true + } + + if desired.Spec.InstanceType != nil { + if direct.ValueOf(desired.Spec.InstanceType) != actual.InstanceType { + // Change instance type + updateRequired = true + } + merged.InstanceType = direct.ValueOf(desired.Spec.InstanceType) + } else { + // Keep instance type + merged.InstanceType = actual.InstanceType + } + + if desired.Spec.MaintenanceVersion != nil { + if direct.ValueOf(desired.Spec.MaintenanceVersion) != actual.MaintenanceVersion { + // Change maintenance version + updateRequired = true + } + merged.MaintenanceVersion = direct.ValueOf(desired.Spec.MaintenanceVersion) + } else { + // Keep maintenance version + merged.MaintenanceVersion = actual.MaintenanceVersion + } + + if desired.Spec.MasterInstanceRef != nil { + if refs.masterInstance != actual.MasterInstanceName { + // Change master + updateRequired = true + } + merged.MasterInstanceName = refs.masterInstance + } else if actual.MasterInstanceName != "" { + // Remove master + updateRequired = true + } + + if desired.Spec.Region != nil { + if direct.ValueOf(desired.Spec.Region) != actual.Region { + // Change region + updateRequired = true + } + merged.Region = direct.ValueOf(desired.Spec.Region) + } else { + // Keep region + merged.Region = actual.Region + } + + existingReplicaConfig := actual.ReplicaConfiguration != nil + if desired.Spec.ReplicaConfiguration != nil { + existingMysqlReplicaConfig := existingReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration != nil + + if !existingReplicaConfig { + // Add replica configuration + updateRequired = true + } + + merged.ReplicaConfiguration = &api.ReplicaConfiguration{ + Kind: "sql#replicaConfiguration", + } + + if desired.Spec.ReplicaConfiguration.FailoverTarget != nil { + if existingReplicaConfig { + if direct.ValueOf(desired.Spec.ReplicaConfiguration.FailoverTarget) != actual.ReplicaConfiguration.FailoverTarget { + // Change failover target + updateRequired = true + } + } else { + // Add failover target + updateRequired = true + } + merged.ReplicaConfiguration.FailoverTarget = direct.ValueOf(desired.Spec.ReplicaConfiguration.FailoverTarget) + } else if existingReplicaConfig { + // Remove failover target + updateRequired = true + } + + if desired.Spec.ReplicaConfiguration.CaCertificate != nil || + desired.Spec.ReplicaConfiguration.ClientCertificate != nil || + desired.Spec.ReplicaConfiguration.ClientKey != nil || + desired.Spec.ReplicaConfiguration.ConnectRetryInterval != nil || + desired.Spec.ReplicaConfiguration.DumpFilePath != nil || + desired.Spec.ReplicaConfiguration.MasterHeartbeatPeriod != nil || + desired.Spec.ReplicaConfiguration.Password != nil || + desired.Spec.ReplicaConfiguration.SslCipher != nil || + desired.Spec.ReplicaConfiguration.Username != nil || + desired.Spec.ReplicaConfiguration.VerifyServerCertificate != nil { + merged.ReplicaConfiguration.MysqlReplicaConfiguration = &api.MySqlReplicaConfiguration{} + } + + if desired.Spec.ReplicaConfiguration.CaCertificate != nil { + if existingMysqlReplicaConfig { + if direct.ValueOf(desired.Spec.ReplicaConfiguration.CaCertificate) != actual.ReplicaConfiguration.MysqlReplicaConfiguration.CaCertificate { + // Change CA certificate + updateRequired = true + } + } else { + // Add CA certificate + updateRequired = true + } + merged.ReplicaConfiguration.MysqlReplicaConfiguration.CaCertificate = direct.ValueOf(desired.Spec.ReplicaConfiguration.CaCertificate) + } else if existingMysqlReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration.CaCertificate != "" { + // Remove CA certificate + updateRequired = true + } + + if desired.Spec.ReplicaConfiguration.ClientCertificate != nil { + if existingMysqlReplicaConfig { + if direct.ValueOf(desired.Spec.ReplicaConfiguration.ClientCertificate) != actual.ReplicaConfiguration.MysqlReplicaConfiguration.ClientCertificate { + // Change client certificate + updateRequired = true + } + } else { + // Add client certificate + updateRequired = true + } + merged.ReplicaConfiguration.MysqlReplicaConfiguration.ClientCertificate = direct.ValueOf(desired.Spec.ReplicaConfiguration.ClientCertificate) + } else if existingMysqlReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration.ClientCertificate != "" { + // Remove client certificate + updateRequired = true + } + + if desired.Spec.ReplicaConfiguration.ClientKey != nil { + if existingMysqlReplicaConfig { + if direct.ValueOf(desired.Spec.ReplicaConfiguration.ClientKey) != actual.ReplicaConfiguration.MysqlReplicaConfiguration.ClientKey { + // Change client key + updateRequired = true + } + } else { + // Add client key + updateRequired = true + } + merged.ReplicaConfiguration.MysqlReplicaConfiguration.ClientKey = direct.ValueOf(desired.Spec.ReplicaConfiguration.ClientKey) + } else if existingMysqlReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration.ClientKey != "" { + // Remove client key + updateRequired = true + } + + if desired.Spec.ReplicaConfiguration.ConnectRetryInterval != nil { + if existingMysqlReplicaConfig { + if direct.ValueOf(desired.Spec.ReplicaConfiguration.ConnectRetryInterval) != actual.ReplicaConfiguration.MysqlReplicaConfiguration.ConnectRetryInterval { + // Change connect retry interval + updateRequired = true + } + } else { + // Add connect retry interval + updateRequired = true + } + merged.ReplicaConfiguration.MysqlReplicaConfiguration.ConnectRetryInterval = direct.ValueOf(desired.Spec.ReplicaConfiguration.ConnectRetryInterval) + } else if existingMysqlReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration.ConnectRetryInterval != 0 { + // Remove connect retry interval + updateRequired = true + } + + if desired.Spec.ReplicaConfiguration.DumpFilePath != nil { + if existingMysqlReplicaConfig { + if direct.ValueOf(desired.Spec.ReplicaConfiguration.DumpFilePath) != actual.ReplicaConfiguration.MysqlReplicaConfiguration.DumpFilePath { + // Change dump file path + updateRequired = true + } + } else { + // Add dump file path + updateRequired = true + } + merged.ReplicaConfiguration.MysqlReplicaConfiguration.DumpFilePath = direct.ValueOf(desired.Spec.ReplicaConfiguration.DumpFilePath) + } else if existingMysqlReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration.DumpFilePath != "" { + // Remove dump file path + updateRequired = true + } + + if desired.Spec.ReplicaConfiguration.MasterHeartbeatPeriod != nil { + if existingMysqlReplicaConfig { + if direct.ValueOf(desired.Spec.ReplicaConfiguration.MasterHeartbeatPeriod) != actual.ReplicaConfiguration.MysqlReplicaConfiguration.MasterHeartbeatPeriod { + // Change master heartbeat period + updateRequired = true + } + } else { + // Add master heartbeat period + updateRequired = true + } + merged.ReplicaConfiguration.MysqlReplicaConfiguration.MasterHeartbeatPeriod = direct.ValueOf(desired.Spec.ReplicaConfiguration.MasterHeartbeatPeriod) + } else if existingMysqlReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration.MasterHeartbeatPeriod != 0 { + // Remove master heartbeat period + updateRequired = true + } + + if desired.Spec.ReplicaConfiguration.Password != nil { + if existingMysqlReplicaConfig { + if refs.replicaPassword != actual.ReplicaConfiguration.MysqlReplicaConfiguration.Password { + // Change password + updateRequired = true + } + } else { + // Add password + updateRequired = true + } + merged.ReplicaConfiguration.MysqlReplicaConfiguration.Password = refs.replicaPassword + } else if existingMysqlReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration.Password != "" { + // Remove password + updateRequired = true + } + + if desired.Spec.ReplicaConfiguration.SslCipher != nil { + if existingMysqlReplicaConfig { + if direct.ValueOf(desired.Spec.ReplicaConfiguration.SslCipher) != actual.ReplicaConfiguration.MysqlReplicaConfiguration.SslCipher { + // Change SSL cipher + updateRequired = true + } + } else { + // Add SSL cipher + updateRequired = true + } + merged.ReplicaConfiguration.MysqlReplicaConfiguration.SslCipher = direct.ValueOf(desired.Spec.ReplicaConfiguration.SslCipher) + } else if existingMysqlReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration.SslCipher != "" { + // Remove SSL cipher + updateRequired = true + } + + if desired.Spec.ReplicaConfiguration.Username != nil { + if existingMysqlReplicaConfig { + if direct.ValueOf(desired.Spec.ReplicaConfiguration.Username) != actual.ReplicaConfiguration.MysqlReplicaConfiguration.Username { + // Change username + updateRequired = true + } + } else { + // Add username + updateRequired = true + } + merged.ReplicaConfiguration.MysqlReplicaConfiguration.Username = direct.ValueOf(desired.Spec.ReplicaConfiguration.Username) + } else if existingMysqlReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration.Username != "" { + // Remove username + updateRequired = true + } + + if desired.Spec.ReplicaConfiguration.VerifyServerCertificate != nil { + if existingMysqlReplicaConfig { + if direct.ValueOf(desired.Spec.ReplicaConfiguration.VerifyServerCertificate) != actual.ReplicaConfiguration.MysqlReplicaConfiguration.VerifyServerCertificate { + // Change verify server certificate + updateRequired = true + } + } else { + // Add verify server certificate + updateRequired = true + } + merged.ReplicaConfiguration.MysqlReplicaConfiguration.VerifyServerCertificate = direct.ValueOf(desired.Spec.ReplicaConfiguration.VerifyServerCertificate) + } else if existingMysqlReplicaConfig && actual.ReplicaConfiguration.MysqlReplicaConfiguration.VerifyServerCertificate { + // Remove verify server certificate + updateRequired = true + } + } else if existingReplicaConfig { + // Remove replica configuration + updateRequired = true + } + + if desired.Spec.RootPassword != nil && refs.rootPassword != "" { + if refs.rootPassword != actual.RootPassword { + // Change root password + updateRequired = true + } + merged.RootPassword = refs.rootPassword + } else { + // Keep root password + merged.RootPassword = actual.RootPassword + } + + merged.Settings = &api.Settings{ + SettingsVersion: actual.Settings.SettingsVersion, + } + + if desired.Spec.Settings.ActivationPolicy != nil { + if direct.ValueOf(desired.Spec.Settings.ActivationPolicy) != actual.Settings.ActivationPolicy { + // Change activation policy + updateRequired = true + } + merged.Settings.ActivationPolicy = direct.ValueOf(desired.Spec.Settings.ActivationPolicy) + } else { + // Keep activation policy + merged.Settings.ActivationPolicy = actual.Settings.ActivationPolicy + } + + if desired.Spec.Settings.ActiveDirectoryConfig != nil { + if actual.Settings.ActiveDirectoryConfig == nil { + // Add active directory config + updateRequired = true + } else if desired.Spec.Settings.ActiveDirectoryConfig.Domain != actual.Settings.ActiveDirectoryConfig.Domain { + // Change active directory config + updateRequired = true + } + merged.Settings.ActiveDirectoryConfig.Domain = desired.Spec.Settings.ActiveDirectoryConfig.Domain + } else if actual.Settings.ActiveDirectoryConfig != nil { + // Remove active directory config + updateRequired = true + } + + if desired.Spec.Settings.AdvancedMachineFeatures != nil { + if actual.Settings.AdvancedMachineFeatures == nil { + // Add advanced machine features + updateRequired = true + } else if desired.Spec.Settings.AdvancedMachineFeatures.ThreadsPerCore != &actual.Settings.AdvancedMachineFeatures.ThreadsPerCore { + // Change advanced machine features + updateRequired = true + } + merged.Settings.AdvancedMachineFeatures.ThreadsPerCore = direct.ValueOf(desired.Spec.Settings.AdvancedMachineFeatures.ThreadsPerCore) + } else if actual.Settings.AdvancedMachineFeatures != nil { + // Remove advanced machine features + updateRequired = true + } + + if desired.Spec.Settings.AuthorizedGaeApplications != nil { + if actual.Settings.AuthorizedGaeApplications == nil { + // Add authorized gae applications + updateRequired = true + } else if len(desired.Spec.Settings.AuthorizedGaeApplications) != len(actual.Settings.AuthorizedGaeApplications) { + // todo: fix this + // Change authorized gae applications + updateRequired = true + } + merged.Settings.AuthorizedGaeApplications = desired.Spec.Settings.AuthorizedGaeApplications + } else if len(actual.Settings.AuthorizedGaeApplications) > 0 { + // Remove authorized gae applications + updateRequired = true + } + + if desired.Spec.Settings.AvailabilityType != nil { + if direct.ValueOf(desired.Spec.Settings.AvailabilityType) != actual.Settings.AvailabilityType { + // Change availability type + updateRequired = true + } + merged.Settings.AvailabilityType = direct.ValueOf(desired.Spec.Settings.AvailabilityType) + } else { + // Keep availability type + merged.Settings.AvailabilityType = actual.Settings.AvailabilityType + } + + existingBackupConfig := actual.Settings.BackupConfiguration != nil + + if desired.Spec.Settings.BackupConfiguration != nil { + existingRetentionSettings := existingBackupConfig && actual.Settings.BackupConfiguration.BackupRetentionSettings != nil + + if !existingBackupConfig { + // Add backup configuration + updateRequired = true + } + + merged.Settings.BackupConfiguration = &api.BackupConfiguration{ + Kind: "sql#backupConfiguration", + } + + if desired.Spec.Settings.BackupConfiguration.BackupRetentionSettings != nil { + if !existingRetentionSettings { + // Add retention settings + updateRequired = true + } else if (desired.Spec.Settings.BackupConfiguration.BackupRetentionSettings.RetainedBackups != actual.Settings.BackupConfiguration.BackupRetentionSettings.RetainedBackups) || + (direct.ValueOf(desired.Spec.Settings.BackupConfiguration.BackupRetentionSettings.RetentionUnit) != actual.Settings.BackupConfiguration.BackupRetentionSettings.RetentionUnit) { + // Change retention settings + updateRequired = true + } + merged.Settings.BackupConfiguration.BackupRetentionSettings = &api.BackupRetentionSettings{ + RetainedBackups: desired.Spec.Settings.BackupConfiguration.BackupRetentionSettings.RetainedBackups, + RetentionUnit: direct.ValueOf(desired.Spec.Settings.BackupConfiguration.BackupRetentionSettings.RetentionUnit), + } + } else if existingRetentionSettings { + // Keep same retention settings + merged.Settings.BackupConfiguration.BackupRetentionSettings = actual.Settings.BackupConfiguration.BackupRetentionSettings + } + + if desired.Spec.Settings.BackupConfiguration.BinaryLogEnabled != nil { + if existingBackupConfig { + if direct.ValueOf(desired.Spec.Settings.BackupConfiguration.BinaryLogEnabled) != actual.Settings.BackupConfiguration.BinaryLogEnabled { + // Change binary log enabled + updateRequired = true + } + } + merged.Settings.BackupConfiguration.BinaryLogEnabled = direct.ValueOf(desired.Spec.Settings.BackupConfiguration.BinaryLogEnabled) + } else if existingBackupConfig { + // Keep same binary log enabled + merged.Settings.BackupConfiguration.BinaryLogEnabled = actual.Settings.BackupConfiguration.BinaryLogEnabled + } + + if desired.Spec.Settings.BackupConfiguration.Enabled != nil { + if existingBackupConfig { + if direct.ValueOf(desired.Spec.Settings.BackupConfiguration.Enabled) != actual.Settings.BackupConfiguration.Enabled { + // Change enabled + updateRequired = true + } + } + merged.Settings.BackupConfiguration.Enabled = direct.ValueOf(desired.Spec.Settings.BackupConfiguration.Enabled) + } else if existingBackupConfig { + // Keep same enabled + merged.Settings.BackupConfiguration.Enabled = actual.Settings.BackupConfiguration.Enabled + } + + if desired.Spec.Settings.BackupConfiguration.Location != nil { + if existingBackupConfig { + if direct.ValueOf(desired.Spec.Settings.BackupConfiguration.Location) != actual.Settings.BackupConfiguration.Location { + // Change location + updateRequired = true + } + } + merged.Settings.BackupConfiguration.Location = direct.ValueOf(desired.Spec.Settings.BackupConfiguration.Location) + } else if existingBackupConfig { + // Keep same location + merged.Settings.BackupConfiguration.Location = actual.Settings.BackupConfiguration.Location + } + + if desired.Spec.Settings.BackupConfiguration.PointInTimeRecoveryEnabled != nil { + if existingBackupConfig { + if direct.ValueOf(desired.Spec.Settings.BackupConfiguration.PointInTimeRecoveryEnabled) != actual.Settings.BackupConfiguration.PointInTimeRecoveryEnabled { + // Change point in time recovery enabled + updateRequired = true + } + } + merged.Settings.BackupConfiguration.PointInTimeRecoveryEnabled = direct.ValueOf(desired.Spec.Settings.BackupConfiguration.PointInTimeRecoveryEnabled) + } else if existingBackupConfig { + // Keep same point in time recovery enabled + merged.Settings.BackupConfiguration.PointInTimeRecoveryEnabled = actual.Settings.BackupConfiguration.PointInTimeRecoveryEnabled + } + + if desired.Spec.Settings.BackupConfiguration.StartTime != nil { + if existingBackupConfig { + if direct.ValueOf(desired.Spec.Settings.BackupConfiguration.StartTime) != actual.Settings.BackupConfiguration.StartTime { + // Change start time + updateRequired = true + } + } + merged.Settings.BackupConfiguration.StartTime = direct.ValueOf(desired.Spec.Settings.BackupConfiguration.StartTime) + } else if existingBackupConfig { + // Keep same start time + merged.Settings.BackupConfiguration.StartTime = actual.Settings.BackupConfiguration.StartTime + } + + if desired.Spec.Settings.BackupConfiguration.TransactionLogRetentionDays != nil { + if existingBackupConfig { + if direct.ValueOf(desired.Spec.Settings.BackupConfiguration.TransactionLogRetentionDays) != actual.Settings.BackupConfiguration.TransactionLogRetentionDays { + // Change transaction log retention days + updateRequired = true + } + } + merged.Settings.BackupConfiguration.TransactionLogRetentionDays = direct.ValueOf(desired.Spec.Settings.BackupConfiguration.TransactionLogRetentionDays) + } else if existingBackupConfig { + // Keep same transaction log retention days + merged.Settings.BackupConfiguration.TransactionLogRetentionDays = actual.Settings.BackupConfiguration.TransactionLogRetentionDays + } + } else if existingBackupConfig { + // Keep same backup configuration + merged.Settings.BackupConfiguration = actual.Settings.BackupConfiguration + } + if merged.Settings.BackupConfiguration != nil { + merged.Settings.BackupConfiguration.ForceSendFields = []string{ + "BinaryLogEnabled", + "Enabled", + "PointInTimeRecoveryEnabled", + } + } + + if desired.Spec.Settings.Collation != nil { + if direct.ValueOf(desired.Spec.Settings.Collation) != actual.Settings.Collation { + // Change collation + updateRequired = true + } + merged.Settings.Collation = direct.ValueOf(desired.Spec.Settings.Collation) + } else { + // Keep collation + merged.Settings.Collation = actual.Settings.Collation + } + + if desired.Spec.Settings.ConnectorEnforcement != nil { + if direct.ValueOf(desired.Spec.Settings.ConnectorEnforcement) != actual.Settings.ConnectorEnforcement { + // Change connector enforcement + updateRequired = true + } + merged.Settings.ConnectorEnforcement = direct.ValueOf(desired.Spec.Settings.ConnectorEnforcement) + } else { + // Keep connector enforcement + merged.Settings.ConnectorEnforcement = actual.Settings.ConnectorEnforcement + } + + if desired.Spec.Settings.CrashSafeReplication != nil { + if direct.ValueOf(desired.Spec.Settings.CrashSafeReplication) != actual.Settings.CrashSafeReplicationEnabled { + // Change crash safe replication + updateRequired = true + } + merged.Settings.CrashSafeReplicationEnabled = direct.ValueOf(desired.Spec.Settings.CrashSafeReplication) + } else { + // Keep crash safe replication + merged.Settings.CrashSafeReplicationEnabled = actual.Settings.CrashSafeReplicationEnabled + } + + if desired.Spec.Settings.DataCacheConfig != nil { + if actual.Settings.DataCacheConfig == nil { + // Add data cache config + updateRequired = true + } else if direct.ValueOf(desired.Spec.Settings.DataCacheConfig.DataCacheEnabled) != actual.Settings.DataCacheConfig.DataCacheEnabled { + // Change data cache config + updateRequired = true + } + merged.Settings.DataCacheConfig = &api.DataCacheConfig{ + DataCacheEnabled: direct.ValueOf(desired.Spec.Settings.DataCacheConfig.DataCacheEnabled), + } + } else if actual.Settings.DataCacheConfig != nil { + // Remove data cache config + updateRequired = true + } + + if desired.Spec.Settings.DatabaseFlags != nil { + if actual.Settings.DatabaseFlags == nil { + // Add database flags + updateRequired = true + } else if len(desired.Spec.Settings.DatabaseFlags) != len(actual.Settings.DatabaseFlags) { + // todo: fix this + // Change database flags + updateRequired = true + } + merged.Settings.DatabaseFlags = []*api.DatabaseFlags{} + for _, flag := range desired.Spec.Settings.DatabaseFlags { + merged.Settings.DatabaseFlags = append(merged.Settings.DatabaseFlags, &api.DatabaseFlags{ + Name: flag.Name, + Value: flag.Value, + }) + } + } else if actual.Settings.DatabaseFlags != nil { + // Remove database flags + updateRequired = true + } + + if desired.Spec.Settings.DeletionProtectionEnabled != nil { + if direct.ValueOf(desired.Spec.Settings.DeletionProtectionEnabled) != actual.Settings.DeletionProtectionEnabled { + // Change deletion protection enabled + updateRequired = true + } + merged.Settings.DeletionProtectionEnabled = direct.ValueOf(desired.Spec.Settings.DeletionProtectionEnabled) + } else { + // Keep deletion protection enabled + merged.Settings.DeletionProtectionEnabled = actual.Settings.DeletionProtectionEnabled + } + + if desired.Spec.Settings.DenyMaintenancePeriod != nil { + if actual.Settings.DenyMaintenancePeriods == nil { + // Add deny maintenance period + updateRequired = true + } else if (len(actual.Settings.DenyMaintenancePeriods) == 1) && ((desired.Spec.Settings.DenyMaintenancePeriod.EndDate != actual.Settings.DenyMaintenancePeriods[0].EndDate) || + (desired.Spec.Settings.DenyMaintenancePeriod.StartDate != actual.Settings.DenyMaintenancePeriods[0].StartDate) || + (desired.Spec.Settings.DenyMaintenancePeriod.Time != actual.Settings.DenyMaintenancePeriods[0].Time)) { + // Change deny maintenance period + updateRequired = true + } + merged.Settings.DenyMaintenancePeriods = []*api.DenyMaintenancePeriod{ + { + EndDate: desired.Spec.Settings.DenyMaintenancePeriod.EndDate, + StartDate: desired.Spec.Settings.DenyMaintenancePeriod.StartDate, + Time: desired.Spec.Settings.DenyMaintenancePeriod.Time, + }, + } + } else if actual.Settings.DenyMaintenancePeriods != nil { + // Remove deny maintenance period + updateRequired = true + } + + if desired.Spec.Settings.DiskAutoresize != nil { + if desired.Spec.Settings.DiskAutoresize != actual.Settings.StorageAutoResize { + // Change disk autoresize + updateRequired = true + } + merged.Settings.StorageAutoResize = desired.Spec.Settings.DiskAutoresize + } else { + // Keep disk autoresize + merged.Settings.StorageAutoResize = actual.Settings.StorageAutoResize + } + + if desired.Spec.Settings.DiskAutoresizeLimit != nil { + if direct.ValueOf(desired.Spec.Settings.DiskAutoresizeLimit) != actual.Settings.StorageAutoResizeLimit { + // Change disk autoresize limit + updateRequired = true + } + merged.Settings.StorageAutoResizeLimit = direct.ValueOf(desired.Spec.Settings.DiskAutoresizeLimit) + } else { + // Keep disk autoresize limit + merged.Settings.StorageAutoResizeLimit = actual.Settings.StorageAutoResizeLimit + } + + if desired.Spec.Settings.DiskSize != nil { + if direct.ValueOf(desired.Spec.Settings.DiskSize) != actual.Settings.DataDiskSizeGb { + // Change disk size + updateRequired = true + } + merged.Settings.DataDiskSizeGb = direct.ValueOf(desired.Spec.Settings.DiskSize) + } else { + // Keep disk size + merged.Settings.DataDiskSizeGb = actual.Settings.DataDiskSizeGb + } + + if desired.Spec.Settings.DiskType != nil { + if direct.ValueOf(desired.Spec.Settings.DiskType) != actual.Settings.DataDiskType { + // Change disk type + updateRequired = true + } + merged.Settings.DataDiskType = direct.ValueOf(desired.Spec.Settings.DiskType) + } else { + // Keep disk type + merged.Settings.DataDiskType = actual.Settings.DataDiskType + } + + if desired.Spec.Settings.Edition != nil { + if direct.ValueOf(desired.Spec.Settings.Edition) != actual.Settings.Edition { + // Change edition + updateRequired = true + } + merged.Settings.Edition = direct.ValueOf(desired.Spec.Settings.Edition) + } else { + // Keep edition + merged.Settings.Edition = actual.Settings.Edition + } + + if desired.Spec.Settings.InsightsConfig != nil { + if actual.Settings.InsightsConfig == nil { + // Add insights config + updateRequired = true + } else if (direct.ValueOf(desired.Spec.Settings.InsightsConfig.QueryInsightsEnabled) != actual.Settings.InsightsConfig.QueryInsightsEnabled) || + (direct.ValueOf(desired.Spec.Settings.InsightsConfig.QueryPlansPerMinute) != actual.Settings.InsightsConfig.QueryPlansPerMinute) || + (direct.ValueOf(desired.Spec.Settings.InsightsConfig.QueryStringLength) != actual.Settings.InsightsConfig.QueryStringLength) || + (direct.ValueOf(desired.Spec.Settings.InsightsConfig.RecordApplicationTags) != actual.Settings.InsightsConfig.RecordApplicationTags) || + (direct.ValueOf(desired.Spec.Settings.InsightsConfig.RecordClientAddress) != actual.Settings.InsightsConfig.RecordClientAddress) { + // Change insights config + updateRequired = true + } + merged.Settings.InsightsConfig = &api.InsightsConfig{ + QueryInsightsEnabled: direct.ValueOf(desired.Spec.Settings.InsightsConfig.QueryInsightsEnabled), + QueryPlansPerMinute: direct.ValueOf(desired.Spec.Settings.InsightsConfig.QueryPlansPerMinute), + QueryStringLength: direct.ValueOf(desired.Spec.Settings.InsightsConfig.QueryStringLength), + RecordApplicationTags: direct.ValueOf(desired.Spec.Settings.InsightsConfig.RecordApplicationTags), + RecordClientAddress: direct.ValueOf(desired.Spec.Settings.InsightsConfig.RecordClientAddress), + } + } else if actual.Settings.InsightsConfig != nil { + // Keep insights config + merged.Settings.InsightsConfig = actual.Settings.InsightsConfig + } + + if desired.Spec.Settings.IpConfiguration != nil { + if actual.Settings.IpConfiguration == nil { + // Add ip configuration + updateRequired = true + } else if (direct.ValueOf(desired.Spec.Settings.IpConfiguration.AllocatedIpRange) != actual.Settings.IpConfiguration.AllocatedIpRange) || + (len(desired.Spec.Settings.IpConfiguration.AuthorizedNetworks) != len(actual.Settings.IpConfiguration.AuthorizedNetworks)) || + (desired.Spec.Settings.IpConfiguration.EnablePrivatePathForGoogleCloudServices != &actual.Settings.IpConfiguration.EnablePrivatePathForGoogleCloudServices) || + (direct.ValueOf(desired.Spec.Settings.IpConfiguration.Ipv4Enabled) != actual.Settings.IpConfiguration.Ipv4Enabled) || + (refs.privateNetwork != actual.Settings.IpConfiguration.PrivateNetwork) || + (len(desired.Spec.Settings.IpConfiguration.PscConfig) == 1 && + (len(desired.Spec.Settings.IpConfiguration.PscConfig[0].AllowedConsumerProjects) != len(actual.Settings.IpConfiguration.PscConfig.AllowedConsumerProjects)) || + (direct.ValueOf(desired.Spec.Settings.IpConfiguration.PscConfig[0].PscEnabled) != actual.Settings.IpConfiguration.PscConfig.PscEnabled)) || + (direct.ValueOf(desired.Spec.Settings.IpConfiguration.RequireSsl) != actual.Settings.IpConfiguration.RequireSsl) || + (direct.ValueOf(desired.Spec.Settings.IpConfiguration.SslMode) != actual.Settings.IpConfiguration.SslMode) { + // Change ip configuration + updateRequired = true + } + merged.Settings.IpConfiguration = &api.IpConfiguration{ + AllocatedIpRange: direct.ValueOf(desired.Spec.Settings.IpConfiguration.AllocatedIpRange), + EnablePrivatePathForGoogleCloudServices: direct.ValueOf(desired.Spec.Settings.IpConfiguration.EnablePrivatePathForGoogleCloudServices), + Ipv4Enabled: direct.ValueOf(desired.Spec.Settings.IpConfiguration.Ipv4Enabled), + PrivateNetwork: refs.privateNetwork, + RequireSsl: direct.ValueOf(desired.Spec.Settings.IpConfiguration.RequireSsl), + SslMode: direct.ValueOf(desired.Spec.Settings.IpConfiguration.SslMode), + } + if len(desired.Spec.Settings.IpConfiguration.PscConfig) == 1 { + merged.Settings.IpConfiguration.PscConfig = &api.PscConfig{ + PscEnabled: direct.ValueOf(desired.Spec.Settings.IpConfiguration.PscConfig[0].PscEnabled), + } + merged.Settings.IpConfiguration.PscConfig.AllowedConsumerProjects = append(merged.Settings.IpConfiguration.PscConfig.AllowedConsumerProjects, desired.Spec.Settings.IpConfiguration.PscConfig[0].AllowedConsumerProjects...) + } + for _, authorizedNetwork := range desired.Spec.Settings.IpConfiguration.AuthorizedNetworks { + merged.Settings.IpConfiguration.AuthorizedNetworks = append(merged.Settings.IpConfiguration.AuthorizedNetworks, &api.AclEntry{ + Name: direct.ValueOf(authorizedNetwork.Name), + ExpirationTime: direct.ValueOf(authorizedNetwork.ExpirationTime), + Value: authorizedNetwork.Value, + Kind: "sql#aclEntry", + }) + } + } else if actual.Settings.IpConfiguration != nil { + // Keep ip configuration + merged.Settings.IpConfiguration = actual.Settings.IpConfiguration + } + if merged.Settings.IpConfiguration != nil { + merged.Settings.IpConfiguration.ForceSendFields = []string{ + "EnablePrivatePathForGoogleCloudServices", + "Ipv4Enabled", + "RequireSsl", + } + } + + if desired.Spec.Settings.LocationPreference != nil { + if actual.Settings.LocationPreference == nil { + // Add location preference + updateRequired = true + } else if (direct.ValueOf(desired.Spec.Settings.LocationPreference.FollowGaeApplication) != actual.Settings.LocationPreference.FollowGaeApplication) || + (direct.ValueOf(desired.Spec.Settings.LocationPreference.SecondaryZone) != actual.Settings.LocationPreference.SecondaryZone) || + (direct.ValueOf(desired.Spec.Settings.LocationPreference.Zone) != actual.Settings.LocationPreference.Zone) { + // Change location preference + updateRequired = true + } + merged.Settings.LocationPreference = &api.LocationPreference{ + FollowGaeApplication: direct.ValueOf(desired.Spec.Settings.LocationPreference.FollowGaeApplication), + SecondaryZone: direct.ValueOf(desired.Spec.Settings.LocationPreference.SecondaryZone), + Zone: direct.ValueOf(desired.Spec.Settings.LocationPreference.Zone), + } + } else if actual.Settings.LocationPreference != nil { + // Keep location preference + merged.Settings.LocationPreference = actual.Settings.LocationPreference + } + + if desired.Spec.Settings.MaintenanceWindow != nil { + if actual.Settings.MaintenanceWindow == nil { + // Add maintenance window + updateRequired = true + } else if (direct.ValueOf(desired.Spec.Settings.MaintenanceWindow.Day) != actual.Settings.MaintenanceWindow.Day) || + (direct.ValueOf(desired.Spec.Settings.MaintenanceWindow.Hour) != actual.Settings.MaintenanceWindow.Hour) || + (direct.ValueOf(desired.Spec.Settings.MaintenanceWindow.UpdateTrack) != actual.Settings.MaintenanceWindow.UpdateTrack) { + // Change maintenance window + updateRequired = true + } + merged.Settings.MaintenanceWindow = &api.MaintenanceWindow{ + Day: direct.ValueOf(desired.Spec.Settings.MaintenanceWindow.Day), + Hour: direct.ValueOf(desired.Spec.Settings.MaintenanceWindow.Hour), + UpdateTrack: direct.ValueOf(desired.Spec.Settings.MaintenanceWindow.UpdateTrack), + } + } else if actual.Settings.MaintenanceWindow != nil { + // Remove maintenance window + updateRequired = true + } + + if desired.Spec.Settings.PasswordValidationPolicy != nil { + if actual.Settings.PasswordValidationPolicy == nil { + // Add password validation policy + updateRequired = true + } else if (direct.ValueOf(desired.Spec.Settings.PasswordValidationPolicy.Complexity) != actual.Settings.PasswordValidationPolicy.Complexity) || + (direct.ValueOf(desired.Spec.Settings.PasswordValidationPolicy.DisallowUsernameSubstring) != actual.Settings.PasswordValidationPolicy.DisallowUsernameSubstring) || + (desired.Spec.Settings.PasswordValidationPolicy.EnablePasswordPolicy != actual.Settings.PasswordValidationPolicy.EnablePasswordPolicy) || + (direct.ValueOf(desired.Spec.Settings.PasswordValidationPolicy.MinLength) != actual.Settings.PasswordValidationPolicy.MinLength) || + (direct.ValueOf(desired.Spec.Settings.PasswordValidationPolicy.PasswordChangeInterval) != actual.Settings.PasswordValidationPolicy.PasswordChangeInterval) || + (direct.ValueOf(desired.Spec.Settings.PasswordValidationPolicy.ReuseInterval) != actual.Settings.PasswordValidationPolicy.ReuseInterval) { + // Change password validation policy + updateRequired = true + } + merged.Settings.PasswordValidationPolicy = &api.PasswordValidationPolicy{ + Complexity: direct.ValueOf(desired.Spec.Settings.PasswordValidationPolicy.Complexity), + DisallowUsernameSubstring: direct.ValueOf(desired.Spec.Settings.PasswordValidationPolicy.DisallowUsernameSubstring), + EnablePasswordPolicy: desired.Spec.Settings.PasswordValidationPolicy.EnablePasswordPolicy, + MinLength: direct.ValueOf(desired.Spec.Settings.PasswordValidationPolicy.MinLength), + PasswordChangeInterval: direct.ValueOf(desired.Spec.Settings.PasswordValidationPolicy.PasswordChangeInterval), + ReuseInterval: direct.ValueOf(desired.Spec.Settings.PasswordValidationPolicy.ReuseInterval), + } + } else if actual.Settings.PasswordValidationPolicy != nil { + // Remove password validation policy + updateRequired = true + } + + if desired.Spec.Settings.PricingPlan != nil { + if actual.Settings.PricingPlan == "" { + // Add pricing plan + updateRequired = true + } else if direct.ValueOf(desired.Spec.Settings.PricingPlan) != actual.Settings.PricingPlan { + // Change pricing plan + updateRequired = true + } + merged.Settings.PricingPlan = direct.ValueOf(desired.Spec.Settings.PricingPlan) + } else if actual.Settings.PricingPlan != "" { + // Keep pricing plan + merged.Settings.PricingPlan = actual.Settings.PricingPlan + } + + if desired.Spec.Settings.ReplicationType != nil { + if actual.Settings.ReplicationType == "" { + // Add replication type + updateRequired = true + } else if direct.ValueOf(desired.Spec.Settings.ReplicationType) != actual.Settings.ReplicationType { + // Change replication type + updateRequired = true + } + merged.Settings.ReplicationType = direct.ValueOf(desired.Spec.Settings.ReplicationType) + } else if actual.Settings.ReplicationType != "" { + // Keep replication type + merged.Settings.ReplicationType = actual.Settings.ReplicationType + } + + if desired.Spec.Settings.SqlServerAuditConfig != nil { + if actual.Settings.SqlServerAuditConfig == nil { + // Add sql server audit config + updateRequired = true + } else if (refs.auditLogBucket != actual.Settings.SqlServerAuditConfig.Bucket) || + (direct.ValueOf(desired.Spec.Settings.SqlServerAuditConfig.RetentionInterval) != actual.Settings.SqlServerAuditConfig.RetentionInterval) || + (direct.ValueOf(desired.Spec.Settings.SqlServerAuditConfig.UploadInterval) != actual.Settings.SqlServerAuditConfig.UploadInterval) { + // Change sql server audit config + updateRequired = true + } + merged.Settings.SqlServerAuditConfig = &api.SqlServerAuditConfig{ + Bucket: refs.auditLogBucket, + RetentionInterval: direct.ValueOf(desired.Spec.Settings.SqlServerAuditConfig.RetentionInterval), + UploadInterval: direct.ValueOf(desired.Spec.Settings.SqlServerAuditConfig.UploadInterval), + Kind: "sql#sqlServerAuditConfig", + } + } else if actual.Settings.SqlServerAuditConfig != nil { + // Remove sql server audit config + updateRequired = true + } + + if desired.Spec.Settings.Tier != "" { + if actual.Settings.Tier == "" { + // Add tier + updateRequired = true + } else if desired.Spec.Settings.Tier != actual.Settings.Tier { + // Change tier + updateRequired = true + } + merged.Settings.Tier = desired.Spec.Settings.Tier + } else { + // Keep tier + merged.Settings.Tier = actual.Settings.Tier + } + + if desired.Spec.Settings.TimeZone != nil { + if actual.Settings.TimeZone == "" { + // Add time zone + updateRequired = true + } else if direct.ValueOf(desired.Spec.Settings.TimeZone) != actual.Settings.TimeZone { + // Change time zone + updateRequired = true + } + merged.Settings.TimeZone = direct.ValueOf(desired.Spec.Settings.TimeZone) + } else { + // Keep time zone + merged.Settings.TimeZone = actual.Settings.TimeZone + } + + if !reflect.DeepEqual(desired.Labels, actual.Settings.UserLabels) { + updateRequired = true + } + merged.Settings.UserLabels = desired.Labels + + return merged, updateRequired, nil +} diff --git a/pkg/controller/direct/sql/normalize.go b/pkg/controller/direct/sql/normalize.go new file mode 100644 index 0000000000..ccd313a4c7 --- /dev/null +++ b/pkg/controller/direct/sql/normalize.go @@ -0,0 +1,321 @@ +// Copyright 2024 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. + +package sql + +import ( + "context" + "fmt" + + refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1" + krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/sql/v1beta1" + kmsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/kms/v1beta1" + storagev1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/storage/v1beta1" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type SQLInstanceInternalRefs struct { + cryptoKey string + masterInstance string + replicaPassword string + rootPassword string + privateNetwork string + auditLogBucket string +} + +func NormalizeSQLInstance(ctx context.Context, kube client.Reader, obj *krm.SQLInstance) (*SQLInstanceInternalRefs, error) { + cryptoKeyRef, err := normalizeCryptoKeyRef(ctx, kube, obj) + if err != nil { + return nil, err + } + masterInstanceRef, err := normalizeMasterInstanceRef(ctx, kube, obj) + if err != nil { + return nil, err + } + replicaPassword, err := normalizeReplicaPasswordRef(ctx, kube, obj) + if err != nil { + return nil, err + } + rootPassword, err := normalizeRootPasswordRef(ctx, kube, obj) + if err != nil { + return nil, err + } + privateNetwork, err := normalizePrivateNetworkRef(ctx, kube, obj) + if err != nil { + return nil, err + } + auditLogBucket, err := normalizeAuditLogBucketRef(ctx, kube, obj) + if err != nil { + return nil, err + } + if err := normalizeLabels(obj); err != nil { + return nil, err + } + if err := normalizeTFDefaults(obj); err != nil { + return nil, err + } + return &SQLInstanceInternalRefs{ + cryptoKey: cryptoKeyRef, + masterInstance: masterInstanceRef, + replicaPassword: replicaPassword, + rootPassword: rootPassword, + privateNetwork: privateNetwork, + auditLogBucket: auditLogBucket, + }, nil +} + +func normalizeCryptoKeyRef(ctx context.Context, kube client.Reader, obj *krm.SQLInstance) (string, error) { + if obj.Spec.EncryptionKMSCryptoKeyRef == nil { + return "", nil + } + + keyRef := obj.Spec.EncryptionKMSCryptoKeyRef + + if keyRef.External != "" && keyRef.Name != "" { + return "", fmt.Errorf("cannot specify both spec.encryptionKMSCryptoKeyRef.external and spec.encryptionKMSCryptoKeyRef.name") + } + + if keyRef.External != "" { + return keyRef.External, nil + } else if keyRef.Name != "" { + if keyRef.Namespace == "" { + keyRef.Namespace = obj.Namespace + } + + key := types.NamespacedName{ + Namespace: keyRef.Namespace, + Name: keyRef.Name, + } + + cryptoKey := &unstructured.Unstructured{} + cryptoKey.SetGroupVersionKind(kmsv1beta1.KMSCryptoKeyGVK) + if err := kube.Get(ctx, key, cryptoKey); err != nil { + if apierrors.IsNotFound(err) { + return "", k8s.NewReferenceNotFoundError(kmsv1beta1.KMSCryptoKeyGVK, key) + } + return "", fmt.Errorf("error reading referenced KMSCryptoKey %v: %w", cryptoKey, err) + } + + keyLink, _, err := unstructured.NestedString(cryptoKey.Object, "status", "selfLink") + if err != nil || keyLink == "" { + return "", fmt.Errorf("reading status.selfLink from %v %v/%v: %w", cryptoKey.GroupVersionKind().Kind, cryptoKey.GetNamespace(), cryptoKey.GetName(), err) + } + return keyLink, nil + } else { + return "", fmt.Errorf("must specify either spec.encryptionKMSCryptoKeyRef.external or spec.encryptionKMSCryptoKeyRef.name") + } +} + +func normalizeMasterInstanceRef(ctx context.Context, kube client.Reader, obj *krm.SQLInstance) (string, error) { + if obj.Spec.MasterInstanceRef == nil { + return "", nil + } + + if obj.Spec.MasterInstanceRef.External != "" && obj.Spec.MasterInstanceRef.Name != "" { + return "", fmt.Errorf("cannot specify both spec.masterInstanceRef.external and spec.masterInstanceRef.name") + } + + if obj.Spec.MasterInstanceRef.External != "" { + return obj.Spec.MasterInstanceRef.External, nil + } else if obj.Spec.MasterInstanceRef.Name != "" { + if obj.Spec.MasterInstanceRef.Namespace == "" { + obj.Spec.MasterInstanceRef.Namespace = obj.Namespace + } + + key := types.NamespacedName{ + Namespace: obj.Spec.MasterInstanceRef.Namespace, + Name: obj.Spec.MasterInstanceRef.Name, + } + + masterInstance := &unstructured.Unstructured{} + masterInstance.SetGroupVersionKind(krm.SQLInstanceGVK) + if err := kube.Get(ctx, key, masterInstance); err != nil { + if apierrors.IsNotFound(err) { + return "", k8s.NewReferenceNotFoundError(krm.SQLInstanceGVK, key) + } + return "", fmt.Errorf("error reading referenced master instance %v: %w", key, err) + } + + masterInstanceName, err := refs.GetResourceID(masterInstance) + if err != nil { + return "", err + } + return masterInstanceName, nil + } else { + return "", fmt.Errorf("must specify either spec.masterInstanceRef.external or spec.masterInstanceRef.name") + } +} + +func normalizeReplicaPasswordRef(ctx context.Context, kube client.Reader, obj *krm.SQLInstance) (string, error) { + if obj.Spec.ReplicaConfiguration == nil || obj.Spec.ReplicaConfiguration.Password == nil { + return "", nil + } + + if obj.Spec.ReplicaConfiguration.Password.Value != nil && obj.Spec.ReplicaConfiguration.Password.ValueFrom != nil { + return "", fmt.Errorf("cannot specify both spec.replicaConfiguration.password.value and spec.replicaConfiguration.password.valueFrom") + } + + if obj.Spec.ReplicaConfiguration.Password.Value != nil { + return *obj.Spec.ReplicaConfiguration.Password.Value, nil + } else if obj.Spec.ReplicaConfiguration.Password.ValueFrom != nil { + key := types.NamespacedName{ + Namespace: obj.Namespace, + Name: obj.Spec.ReplicaConfiguration.Password.ValueFrom.SecretKeyRef.Name, + } + + secret := &corev1.Secret{} + if err := kube.Get(ctx, key, secret); err != nil { + if apierrors.IsNotFound(err) { + return "", k8s.NewSecretNotFoundError(key) + } + return "", fmt.Errorf("error reading referenced Secret %v: %w", key, err) + } + + password := string(secret.Data[obj.Spec.ReplicaConfiguration.Password.ValueFrom.SecretKeyRef.Key]) + return password, nil + } + return "", nil +} + +func normalizeRootPasswordRef(ctx context.Context, kube client.Reader, obj *krm.SQLInstance) (string, error) { + if obj.Spec.RootPassword == nil { + return "", nil + } + + if obj.Spec.RootPassword.Value != nil && obj.Spec.RootPassword.ValueFrom != nil { + return "", fmt.Errorf("cannot specify both spec.rootPassword.value and spec.rootPassword.valueFrom") + } + + if obj.Spec.RootPassword.Value != nil { + return *obj.Spec.RootPassword.Value, nil + } else if obj.Spec.RootPassword.ValueFrom != nil { + key := types.NamespacedName{ + Namespace: obj.Namespace, + Name: obj.Spec.RootPassword.ValueFrom.SecretKeyRef.Name, + } + + secret := &corev1.Secret{} + if err := kube.Get(ctx, key, secret); err != nil { + if apierrors.IsNotFound(err) { + return "", k8s.NewSecretNotFoundError(key) + } + return "", fmt.Errorf("error reading referenced Secret %v: %w", key, err) + } + + password := string(secret.Data[obj.Spec.RootPassword.ValueFrom.SecretKeyRef.Key]) + return password, nil + } + return "", nil +} + +func normalizePrivateNetworkRef(ctx context.Context, kube client.Reader, obj *krm.SQLInstance) (string, error) { + if obj.Spec.Settings.IpConfiguration == nil || obj.Spec.Settings.IpConfiguration.PrivateNetworkRef == nil { + return "", nil + } + + resRef := obj.Spec.Settings.IpConfiguration.PrivateNetworkRef + netRef := &refs.ComputeNetworkRef{ + External: resRef.External, + Name: resRef.Name, + Namespace: resRef.Namespace, + } + net, err := refs.ResolveComputeNetwork(ctx, kube, obj, netRef) + if err != nil { + return "", err + } + + return net.String(), nil +} + +func normalizeAuditLogBucketRef(ctx context.Context, kube client.Reader, obj *krm.SQLInstance) (string, error) { + if obj.Spec.Settings.SqlServerAuditConfig == nil { + return "", nil + } + + if obj.Spec.Settings.SqlServerAuditConfig.BucketRef == nil { + return "", fmt.Errorf("must specify bucket for audit config") + } + + bucketRef := obj.Spec.Settings.SqlServerAuditConfig.BucketRef + + if bucketRef.External != "" && bucketRef.Name != "" { + return "", fmt.Errorf("cannot specify both spec.settings.sqlServerAuditConfig.bucketRef.external and spec.settings.sqlServerAuditConfig.bucketRef.name") + } + + if bucketRef.External != "" { + return bucketRef.External, nil + } else if bucketRef.Name != "" { + if bucketRef.Namespace == "" { + bucketRef.Namespace = obj.Namespace + } + + key := types.NamespacedName{ + Namespace: bucketRef.Namespace, + Name: bucketRef.Name, + } + + bucket := &unstructured.Unstructured{} + bucket.SetGroupVersionKind(storagev1beta1.StorageBucketGVK) + if err := kube.Get(ctx, key, bucket); err != nil { + if apierrors.IsNotFound(err) { + return "", k8s.NewReferenceNotFoundError(storagev1beta1.StorageBucketGVK, key) + } + return "", fmt.Errorf("error reading referenced StorageBucket %v: %w", key, err) + } + + storageBucketName, err := refs.GetResourceID(bucket) + if err != nil { + return "", err + } + return "gs://" + storageBucketName, nil + } else { + return "", fmt.Errorf("must specify either spec.settings.sqlServerAuditConfig.bucketRef.external or spec.settings.sqlServerAuditConfig.bucketRef.name") + } +} + +func normalizeLabels(obj *krm.SQLInstance) error { + if obj.Labels == nil { + obj.Labels = make(map[string]string) + } + obj.Labels["managed-by-cnrm"] = "true" + return nil +} + +func normalizeTFDefaults(obj *krm.SQLInstance) error { + if obj.Spec.Settings.ActivationPolicy == nil { + obj.Spec.Settings.ActivationPolicy = direct.PtrTo("ALWAYS") + } + if obj.Spec.Settings.AvailabilityType == nil { + obj.Spec.Settings.AvailabilityType = direct.PtrTo("ZONAL") + } + if obj.Spec.Settings.DiskType == nil { + obj.Spec.Settings.DiskType = direct.PtrTo("PD_SSD") + } + if obj.Spec.Settings.Edition == nil { + obj.Spec.Settings.Edition = direct.PtrTo("ENTERPRISE") + } + if obj.Spec.Settings.PricingPlan == nil { + obj.Spec.Settings.PricingPlan = direct.PtrTo("PER_USE") + } + if obj.Spec.Settings.DiskAutoresize == nil { + obj.Spec.Settings.DiskAutoresize = direct.PtrTo(true) + } + return nil +} diff --git a/pkg/controller/direct/sql/sqlinstance_controller.go b/pkg/controller/direct/sql/sqlinstance_controller.go new file mode 100644 index 0000000000..d6008bd9e1 --- /dev/null +++ b/pkg/controller/direct/sql/sqlinstance_controller.go @@ -0,0 +1,347 @@ +// Copyright 2024 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. + +package sql + +import ( + "context" + "fmt" + "strings" + "time" + + api "google.golang.org/api/sqladmin/v1beta4" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" + + refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1" + krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/sql/v1beta1" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/config" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/directbase" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/registry" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s" + "github.com/googleapis/gax-go/v2" +) + +const ctrlName = "sqlinstance-controller" + +func init() { + registry.RegisterModel(krm.SQLInstanceGVK, newSQLInstanceModel) +} + +func newSQLInstanceModel(ctx context.Context, config *config.ControllerConfig) (directbase.Model, error) { + return &sqlInstanceModel{config: config}, nil +} + +type sqlInstanceModel struct { + config *config.ControllerConfig +} + +var _ directbase.Model = &sqlInstanceModel{} + +type sqlInstanceAdapter struct { + projectID string + resourceID string + + desired *krm.SQLInstance + refs *SQLInstanceInternalRefs + actual *api.DatabaseInstance + + sqlOperationsClient *api.OperationsService + sqlInstancesClient *api.InstancesService + sqlUsersClient *api.UsersService +} + +var _ directbase.Adapter = &sqlInstanceAdapter{} + +func (m *sqlInstanceModel) AdapterForObject(ctx context.Context, kube client.Reader, u *unstructured.Unstructured) (directbase.Adapter, error) { + obj := &krm.SQLInstance{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &obj); err != nil { + return nil, fmt.Errorf("error converting to %T: %w", obj, err) + } + + resourceID, err := refs.GetResourceID(u) + if err != nil { + return nil, err + } + obj.Spec.ResourceID = &resourceID + + projectID, ok := u.GetAnnotations()[k8s.ProjectIDAnnotation] + if !ok { + projectID = u.GetNamespace() + } + + gcpClient, err := newGCPClient(ctx, m.config) + if err != nil { + return nil, fmt.Errorf("building gcp client: %w", err) + } + + refs, err := NormalizeSQLInstance(ctx, kube, obj) + if err != nil { + return nil, err + } + + return &sqlInstanceAdapter{ + projectID: projectID, + resourceID: resourceID, + desired: obj.DeepCopy(), + refs: refs, + sqlOperationsClient: gcpClient.sqlOperationsClient(), + sqlInstancesClient: gcpClient.sqlInstancesClient(), + sqlUsersClient: gcpClient.sqlUsersClient(), + }, nil +} + +func (m *sqlInstanceModel) AdapterForURL(ctx context.Context, url string) (directbase.Adapter, error) { + // TODO: Support URLs + return nil, nil +} + +func (a *sqlInstanceAdapter) Find(ctx context.Context) (bool, error) { + if a.resourceID == "" { + return false, nil + } + + instance, err := a.sqlInstancesClient.Get(a.projectID, a.resourceID).Context(ctx).Do() + if err != nil { + return false, nil + } + + a.actual = instance + + log := klog.FromContext(ctx).WithName(ctrlName) + log.V(2).Info("found cloudsql instance", "actual", a.actual) + + return true, nil +} + +func (a *sqlInstanceAdapter) Create(ctx context.Context, u *unstructured.Unstructured) error { + log := klog.FromContext(ctx).WithName(ctrlName) + log.V(2).Info("creating instance", "desired", a.desired) + + if a.projectID == "" { + return fmt.Errorf("project is empty") + } + if a.resourceID == "" { + return fmt.Errorf("resourceID is empty") + } + + desiredGCP, err := SQLInstanceKRMToGCP(a.desired, a.refs) + if err != nil { + return err + } + + op, err := a.sqlInstancesClient.Insert(a.projectID, desiredGCP).Context(ctx).Do() + if err != nil { + return fmt.Errorf("create SQLInstance %s failed: %w", a.desired.Name, err) + } + + pollingBackoff := gax.Backoff{ + Initial: time.Second, + Max: time.Minute, + Multiplier: 2, + } + for { + log.V(2).Info("polling", "op", op) + + if op.Status == "DONE" { + break + } + if err := gax.Sleep(ctx, pollingBackoff.Pause()); err != nil { + return fmt.Errorf("wait SQLInstance %s creation failed: %w", a.desired.Name, err) + } + op, err = a.sqlOperationsClient.Get(a.projectID, op.Name).Do() + if err != nil { + return fmt.Errorf("get SQLInstance %s create operation %s failed: %w", a.desired.Name, op.Name, err) + } + } + + created, err := a.sqlInstancesClient.Get(a.projectID, a.resourceID).Context(ctx).Do() + if err != nil { + return fmt.Errorf("get SQLInstance %s failed: %w", a.desired.Name, err) + } + + users, err := a.sqlUsersClient.List(a.projectID, a.resourceID).Context(ctx).Do() + if err != nil { + return fmt.Errorf("list SQLInstance %s users failed: %w", a.desired.Name, err) + } + + if users != nil { + for _, user := range users.Items { + if user.Name == "root" && strings.HasPrefix(created.DatabaseVersion, "MYSQL") { + // Delete "root" user to match Terraform behavior, to improve default security. + // Ref: https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance + op, err := a.sqlUsersClient.Delete(a.projectID, a.resourceID).Context(ctx).Name(user.Name).Do() + if err != nil { + return fmt.Errorf("delete SQLInstance %s root user failed: %w", a.desired.Name, err) + } + for { + log.V(2).Info("polling", "op", op) + + if op.Status == "DONE" { + break + } + if err := gax.Sleep(ctx, pollingBackoff.Pause()); err != nil { + return fmt.Errorf("wait SQLInstance %s delete user failed: %w", a.desired.Name, err) + } + op, err = a.sqlOperationsClient.Get(a.projectID, op.Name).Do() + if err != nil { + return fmt.Errorf("get SQLInstance %s delete root user operation %s failed: %w", a.desired.Name, op.Name, err) + } + } + } + } + } + + log.V(2).Info("instance created", "op", op, "instance", created) + + status := &krm.SQLInstanceStatus{} + if err := Convert_SQLInstance_API_v1_To_KRM_status(created, status); err != nil { + return fmt.Errorf("update SQLInstance status failed: %w", err) + } + return setStatus(u, status) +} + +func (a *sqlInstanceAdapter) Update(ctx context.Context, u *unstructured.Unstructured) error { + log := klog.FromContext(ctx) + log.V(2).Info("updating instance", "desired", a.desired) + + // First, handle database version updates + if a.desired.Spec.DatabaseVersion != nil && *a.desired.Spec.DatabaseVersion != a.actual.DatabaseVersion { + newVersionDb := &api.DatabaseInstance{ + DatabaseVersion: *a.desired.Spec.DatabaseVersion, + } + op, err := a.sqlInstancesClient.Patch(a.projectID, *a.desired.Spec.ResourceID, newVersionDb).Context(ctx).Do() + if err != nil { + return fmt.Errorf("patch SQLInstance %s version failed: %w", *a.desired.Spec.ResourceID, err) + } + + pollingBackoff := gax.Backoff{ + Initial: time.Second, + Max: time.Minute, + Multiplier: 2, + } + for { + log.V(2).Info("polling", "op", op) + + if op.Status == "DONE" { + break + } + if err := gax.Sleep(ctx, pollingBackoff.Pause()); err != nil { + return fmt.Errorf("wait SQLInstance %s version patch failed: %w", *a.desired.Spec.ResourceID, err) + } + op, err = a.sqlOperationsClient.Get(a.projectID, op.Name).Do() + if err != nil { + return fmt.Errorf("get SQLInstance %s version patch operation %s failed: %w", *a.desired.Spec.ResourceID, op.Name, err) + } + } + + updated, err := a.sqlInstancesClient.Get(a.projectID, a.resourceID).Context(ctx).Do() + if err != nil { + return fmt.Errorf("get SQLInstance %s failed: %w", *a.desired.Spec.ResourceID, err) + } + + log.V(2).Info("instance version updated", "op", op, "instance", updated) + + a.actual = updated + } + + // Next, update rest of the fields + merged, diffDetected, err := MergeDesiredSQLInstanceWithActual(a.desired, a.refs, a.actual) + if err != nil { + return fmt.Errorf("diff SQL instances failed: %w", err) + } + + if diffDetected { + op, err := a.sqlInstancesClient.Update(a.projectID, merged.Name, merged).Context(ctx).Do() + if err != nil { + return fmt.Errorf("update SQLInstance %s failed: %w", merged.Name, err) + } + + pollingBackoff := gax.Backoff{ + Initial: time.Second, + Max: time.Minute, + Multiplier: 2, + } + for { + log.V(2).Info("polling", "op", op) + + if op.Status == "DONE" { + break + } + if err := gax.Sleep(ctx, pollingBackoff.Pause()); err != nil { + return fmt.Errorf("wait SQLInstance %s update failed: %w", merged.Name, err) + } + op, err = a.sqlOperationsClient.Get(a.projectID, op.Name).Do() + if err != nil { + return fmt.Errorf("get SQLInstance %s update operation %s failed: %w", merged.Name, op.Name, err) + } + } + + updated, err := a.sqlInstancesClient.Get(a.projectID, a.resourceID).Context(ctx).Do() + if err != nil { + return fmt.Errorf("get SQLInstance %s failed: %w", merged.Name, err) + } + + log.V(2).Info("instance updated", "op", op, "instance", updated) + + status := &krm.SQLInstanceStatus{} + if err := Convert_SQLInstance_API_v1_To_KRM_status(updated, status); err != nil { + return fmt.Errorf("update SQLInstance status failed: %w", err) + } + return setStatus(u, status) + } + + return nil +} + +// Delete implements the Adapter interface. +func (a *sqlInstanceAdapter) Delete(ctx context.Context) (bool, error) { + log := klog.FromContext(ctx).WithName(ctrlName) + log.V(2).Info("deleting instance", "actual", a.actual) + + if a.resourceID == "" { + return false, nil + } + op, err := a.sqlInstancesClient.Delete(a.projectID, a.resourceID).Context(ctx).Do() + if err != nil { + return false, fmt.Errorf("deleting SQLInstance %s: %w", a.resourceID, err) + } + + log.V(2).Info("deleted instance", "op", op) + + return true, nil +} + +func (a *sqlInstanceAdapter) Export(ctx context.Context) (*unstructured.Unstructured, error) { + return nil, nil +} + +func setStatus(u *unstructured.Unstructured, typedStatus any) error { + status, err := runtime.DefaultUnstructuredConverter.ToUnstructured(typedStatus) + if err != nil { + return fmt.Errorf("error converting status to unstructured: %w", err) + } + + old, _, _ := unstructured.NestedMap(u.Object, "status") + if old != nil { + status["conditions"] = old["conditions"] + status["observedGeneration"] = old["observedGeneration"] + } + + u.Object["status"] = status + + return nil +} diff --git a/pkg/controller/direct/sql/utils.go b/pkg/controller/direct/sql/utils.go new file mode 100644 index 0000000000..7120b1d516 --- /dev/null +++ b/pkg/controller/direct/sql/utils.go @@ -0,0 +1,23 @@ +// Copyright 2024 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. + +package sql + +func ValueOf[T any](p *T) T { + var v T + if p != nil { + v = *p + } + return v +} diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstance/_generated_object_mysqlinstance.golden.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstance/_generated_object_mysqlinstance.golden.yaml index 7d3d6a3264..7141856536 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstance/_generated_object_mysqlinstance.golden.yaml +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstance/_generated_object_mysqlinstance.golden.yaml @@ -3,14 +3,11 @@ kind: SQLInstance metadata: annotations: cnrm.cloud.google.com/management-conflict-prevention-policy: none - cnrm.cloud.google.com/mutable-but-unreadable-fields: '{}' - cnrm.cloud.google.com/observed-secret-versions: (removed) cnrm.cloud.google.com/project-id: ${projectId} - cnrm.cloud.google.com/state-into-spec: merge finalizers: - cnrm.cloud.google.com/finalizer - cnrm.cloud.google.com/deletion-defender - generation: 3 + generation: 2 labels: cnrm-test: "true" label-one: value-one @@ -19,29 +16,10 @@ metadata: spec: databaseVersion: MYSQL_5_7 instanceType: CLOUD_SQL_INSTANCE - maintenanceVersion: MYSQL_5_7_44.R20231105.01_03 region: us-central1 - resourceID: sqlinstance-sample-${uniqueId} settings: - activationPolicy: ALWAYS - availabilityType: ZONAL - backupConfiguration: - backupRetentionSettings: - retainedBackups: 7 - retentionUnit: COUNT - startTime: "12:00" - transactionLogRetentionDays: 7 - connectorEnforcement: NOT_REQUIRED diskAutoresize: false - diskAutoresizeLimit: 0 diskSize: 20 - diskType: PD_SSD - edition: ENTERPRISE - ipConfiguration: - ipv4Enabled: true - locationPreference: - zone: us-central1-a - pricingPlan: PER_USE tier: db-n1-standard-1 status: conditions: @@ -54,7 +32,7 @@ status: firstIpAddress: 10.1.2.3 instanceType: CLOUD_SQL_INSTANCE ipAddress: 10.1.2.3 - observedGeneration: 3 + observedGeneration: 2 publicIpAddress: 10.1.2.3 selfLink: https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId} serverCaCert: diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstance/_http.log b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstance/_http.log index 0af2360b9e..c2d9b787fb 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstance/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstance/_http.log @@ -1,5 +1,5 @@ GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 404 Not Found Cache-Control: private @@ -30,7 +30,7 @@ X-Xss-Protection: 0 POST https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "MYSQL_5_7", @@ -81,7 +81,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -110,8 +110,180 @@ X-Xss-Protection: 0 --- +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "backendType": "SECOND_GEN", + "connectionName": "${projectId}:us-central1:sqlinstance-sample-${uniqueId}", + "createTime": "2024-04-01T12:34:56.123456Z", + "databaseInstalledVersion": "MYSQL_5_7_44", + "databaseVersion": "MYSQL_5_7", + "etag": "abcdef0123A=", + "gceZone": "us-central1-a", + "geminiConfig": { + "entitled": false, + "flagRecommenderEnabled": false, + "indexAdvisorEnabled": false + }, + "instanceType": "CLOUD_SQL_INSTANCE", + "ipAddresses": [ + { + "ipAddress": "10.1.2.3", + "type": "PRIMARY" + } + ], + "kind": "sql#instance", + "maintenanceVersion": "MYSQL_5_7_44.R20231105.01_03", + "name": "sqlinstance-sample-${uniqueId}", + "project": "${projectId}", + "region": "us-central1", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}", + "serverCaCert": { + "cert": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n", + "certSerialNumber": "0", + "commonName": "common-name", + "createTime": "2024-04-01T12:34:56.123456Z", + "expirationTime": "2024-04-01T12:34:56.123456Z", + "instance": "sqlinstance-sample-${uniqueId}", + "kind": "sql#sslCert", + "sha1Fingerprint": "12345678" + }, + "serviceAccountEmailAddress": "p${projectNumber}-abcdef@gcp-sa-cloud-sql.iam.gserviceaccount.com", + "settings": { + "activationPolicy": "ALWAYS", + "authorizedGaeApplications": [], + "availabilityType": "ZONAL", + "backupConfiguration": { + "backupRetentionSettings": { + "retainedBackups": 7, + "retentionUnit": "COUNT" + }, + "enabled": false, + "kind": "sql#backupConfiguration", + "startTime": "12:00", + "transactionLogRetentionDays": 7, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" + }, + "connectorEnforcement": "NOT_REQUIRED", + "dataDiskSizeGb": "10", + "dataDiskType": "PD_SSD", + "deletionProtectionEnabled": false, + "edition": "ENTERPRISE", + "ipConfiguration": { + "authorizedNetworks": [], + "ipv4Enabled": true, + "requireSsl": false, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" + }, + "kind": "sql#settings", + "locationPreference": { + "kind": "sql#locationPreference", + "zone": "us-central1-a" + }, + "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", + "settingsVersion": "123", + "storageAutoResize": false, + "storageAutoResizeLimit": "0", + "tier": "db-n1-standard-1", + "userLabels": { + "cnrm-test": "true", + "label-one": "value-one", + "managed-by-cnrm": "true" + } + }, + "sqlNetworkArchitecture": "NEW_NETWORK_ARCHITECTURE", + "state": "RUNNABLE", + "upgradableDatabaseVersions": [ + { + "displayName": "MySQL 8.0", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0" + }, + { + "displayName": "MySQL 8.0.18", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_18" + }, + { + "displayName": "MySQL 8.0.26", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_26" + }, + { + "displayName": "MySQL 8.0.27", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_27" + }, + { + "displayName": "MySQL 8.0.28", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_28" + }, + { + "displayName": "MySQL 8.0.29", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_29" + }, + { + "displayName": "MySQL 8.0.30", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_30" + }, + { + "displayName": "MySQL 8.0.31", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_31" + }, + { + "displayName": "MySQL 8.0.32", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_32" + }, + { + "displayName": "MySQL 8.0.33", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_33" + }, + { + "displayName": "MySQL 8.0.34", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_34" + }, + { + "displayName": "MySQL 8.0.35", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_35" + }, + { + "displayName": "MySQL 8.0.36", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_36" + }, + { + "displayName": "MySQL 8.0.37", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_37" + } + ] +} + +--- + GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}/users?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -140,8 +312,8 @@ X-Xss-Protection: 0 --- -DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}/users?alt=json&host=%25&name=root&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}/users?alt=json&name=root&prettyPrint=false +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -170,7 +342,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -200,7 +372,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -373,10 +545,14 @@ X-Xss-Protection: 0 PUT https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { + "databaseVersion": "MYSQL_5_7", "instanceType": "CLOUD_SQL_INSTANCE", + "maintenanceVersion": "MYSQL_5_7_44.R20231105.01_03", + "name": "sqlinstance-sample-${uniqueId}", + "region": "us-central1", "settings": { "activationPolicy": "ALWAYS", "availabilityType": "ZONAL", @@ -387,9 +563,11 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr }, "binaryLogEnabled": false, "enabled": false, + "kind": "sql#backupConfiguration", "pointInTimeRecoveryEnabled": false, "startTime": "12:00", - "transactionLogRetentionDays": 7 + "transactionLogRetentionDays": 7, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" }, "connectorEnforcement": "NOT_REQUIRED", "dataDiskSizeGb": "20", @@ -398,12 +576,15 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr "ipConfiguration": { "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": true, - "requireSsl": false + "requireSsl": false, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" }, "locationPreference": { + "kind": "sql#locationPreference", "zone": "us-central1-a" }, "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", "settingsVersion": "123", "storageAutoResize": false, "tier": "db-n1-standard-1", @@ -442,7 +623,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -472,7 +653,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -646,7 +827,7 @@ X-Xss-Protection: 0 --- DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -670,34 +851,4 @@ X-Xss-Protection: 0 "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}", "targetProject": "${projectId}", "user": "user@example.com" -} - ---- - -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "sqlinstance-sample-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" } \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstancebasic/_generated_object_mysqlinstancebasic.golden.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstancebasic/_generated_object_mysqlinstancebasic.golden.yaml index ce7b5cc438..513a13329e 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstancebasic/_generated_object_mysqlinstancebasic.golden.yaml +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstancebasic/_generated_object_mysqlinstancebasic.golden.yaml @@ -3,14 +3,12 @@ kind: SQLInstance metadata: annotations: cnrm.cloud.google.com/management-conflict-prevention-policy: none - cnrm.cloud.google.com/mutable-but-unreadable-fields: '{}' - cnrm.cloud.google.com/observed-secret-versions: (removed) cnrm.cloud.google.com/project-id: ${projectId} cnrm.cloud.google.com/state-into-spec: absent finalizers: - cnrm.cloud.google.com/finalizer - cnrm.cloud.google.com/deletion-defender - generation: 3 + generation: 2 labels: cnrm-test: "true" name: mysqlbasic-${uniqueId} @@ -18,7 +16,6 @@ metadata: spec: databaseVersion: MYSQL_8_0 region: us-central1 - resourceID: mysqlbasic-${uniqueId} settings: locationPreference: zone: us-central1-a @@ -34,7 +31,7 @@ status: firstIpAddress: 10.1.2.3 instanceType: CLOUD_SQL_INSTANCE ipAddress: 10.1.2.3 - observedGeneration: 3 + observedGeneration: 2 publicIpAddress: 10.1.2.3 selfLink: https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId} serverCaCert: diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstancebasic/_http.log b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstancebasic/_http.log index ca18f3623b..0c65595b37 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstancebasic/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/mysqlinstancebasic/_http.log @@ -1,5 +1,5 @@ GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 404 Not Found Cache-Control: private @@ -30,7 +30,7 @@ X-Xss-Protection: 0 POST https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "MYSQL_5_7", @@ -81,7 +81,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -110,8 +110,179 @@ X-Xss-Protection: 0 --- +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "backendType": "SECOND_GEN", + "connectionName": "${projectId}:us-central1:mysqlbasic-${uniqueId}", + "createTime": "2024-04-01T12:34:56.123456Z", + "databaseInstalledVersion": "MYSQL_5_7_44", + "databaseVersion": "MYSQL_5_7", + "etag": "abcdef0123A=", + "gceZone": "us-central1-a", + "geminiConfig": { + "entitled": false, + "flagRecommenderEnabled": false, + "indexAdvisorEnabled": false + }, + "instanceType": "CLOUD_SQL_INSTANCE", + "ipAddresses": [ + { + "ipAddress": "10.1.2.3", + "type": "PRIMARY" + } + ], + "kind": "sql#instance", + "maintenanceVersion": "MYSQL_5_7_44.R20231105.01_03", + "name": "mysqlbasic-${uniqueId}", + "project": "${projectId}", + "region": "us-central1", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}", + "serverCaCert": { + "cert": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n", + "certSerialNumber": "0", + "commonName": "common-name", + "createTime": "2024-04-01T12:34:56.123456Z", + "expirationTime": "2024-04-01T12:34:56.123456Z", + "instance": "mysqlbasic-${uniqueId}", + "kind": "sql#sslCert", + "sha1Fingerprint": "12345678" + }, + "serviceAccountEmailAddress": "p${projectNumber}-abcdef@gcp-sa-cloud-sql.iam.gserviceaccount.com", + "settings": { + "activationPolicy": "ALWAYS", + "authorizedGaeApplications": [], + "availabilityType": "ZONAL", + "backupConfiguration": { + "backupRetentionSettings": { + "retainedBackups": 7, + "retentionUnit": "COUNT" + }, + "enabled": false, + "kind": "sql#backupConfiguration", + "startTime": "12:00", + "transactionLogRetentionDays": 7, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" + }, + "connectorEnforcement": "NOT_REQUIRED", + "dataDiskSizeGb": "10", + "dataDiskType": "PD_SSD", + "deletionProtectionEnabled": false, + "edition": "ENTERPRISE", + "ipConfiguration": { + "authorizedNetworks": [], + "ipv4Enabled": true, + "requireSsl": false, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" + }, + "kind": "sql#settings", + "locationPreference": { + "kind": "sql#locationPreference", + "zone": "us-central1-a" + }, + "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", + "settingsVersion": "123", + "storageAutoResize": true, + "storageAutoResizeLimit": "0", + "tier": "db-custom-1-3840", + "userLabels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + } + }, + "sqlNetworkArchitecture": "NEW_NETWORK_ARCHITECTURE", + "state": "RUNNABLE", + "upgradableDatabaseVersions": [ + { + "displayName": "MySQL 8.0", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0" + }, + { + "displayName": "MySQL 8.0.18", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_18" + }, + { + "displayName": "MySQL 8.0.26", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_26" + }, + { + "displayName": "MySQL 8.0.27", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_27" + }, + { + "displayName": "MySQL 8.0.28", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_28" + }, + { + "displayName": "MySQL 8.0.29", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_29" + }, + { + "displayName": "MySQL 8.0.30", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_30" + }, + { + "displayName": "MySQL 8.0.31", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_31" + }, + { + "displayName": "MySQL 8.0.32", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_32" + }, + { + "displayName": "MySQL 8.0.33", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_33" + }, + { + "displayName": "MySQL 8.0.34", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_34" + }, + { + "displayName": "MySQL 8.0.35", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_35" + }, + { + "displayName": "MySQL 8.0.36", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_36" + }, + { + "displayName": "MySQL 8.0.37", + "majorVersion": "MYSQL_8_0", + "name": "MYSQL_8_0_37" + } + ] +} + +--- + GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}/users?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -140,8 +311,8 @@ X-Xss-Protection: 0 --- -DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}/users?alt=json&host=%25&name=root&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}/users?alt=json&name=root&prettyPrint=false +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -170,7 +341,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -200,7 +371,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -372,7 +543,7 @@ X-Xss-Protection: 0 PATCH https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "MYSQL_8_0" @@ -405,7 +576,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -435,7 +606,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -597,10 +768,14 @@ X-Xss-Protection: 0 PUT https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { + "databaseVersion": "MYSQL_8_0", "instanceType": "CLOUD_SQL_INSTANCE", + "maintenanceVersion": "MYSQL_8_0_31.R20240527.01_00", + "name": "mysqlbasic-${uniqueId}", + "region": "us-central1", "settings": { "activationPolicy": "ALWAYS", "availabilityType": "ZONAL", @@ -611,9 +786,11 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr }, "binaryLogEnabled": false, "enabled": false, + "kind": "sql#backupConfiguration", "pointInTimeRecoveryEnabled": false, "startTime": "12:00", - "transactionLogRetentionDays": 7 + "transactionLogRetentionDays": 7, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" }, "connectorEnforcement": "NOT_REQUIRED", "dataDiskSizeGb": "10", @@ -622,12 +799,14 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr "ipConfiguration": { "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": true, - "requireSsl": false + "requireSsl": false, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" }, "locationPreference": { "zone": "us-central1-a" }, "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", "settingsVersion": "123", "storageAutoResize": true, "tier": "db-custom-2-7680", @@ -665,7 +844,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -695,7 +874,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -858,7 +1037,7 @@ X-Xss-Protection: 0 --- DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -882,34 +1061,4 @@ X-Xss-Protection: 0 "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}", "targetProject": "${projectId}", "user": "user@example.com" -} - ---- - -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "mysqlbasic-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/mysqlbasic-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" } \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstance/_generated_object_postgresinstance.golden.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstance/_generated_object_postgresinstance.golden.yaml index a8e72557ab..9518f0d2e1 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstance/_generated_object_postgresinstance.golden.yaml +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstance/_generated_object_postgresinstance.golden.yaml @@ -3,25 +3,19 @@ kind: SQLInstance metadata: annotations: cnrm.cloud.google.com/management-conflict-prevention-policy: none - cnrm.cloud.google.com/mutable-but-unreadable-fields: '{"spec":{"settings":{"ipConfiguration":{"sslMode":"ENCRYPTED_ONLY"}}}}' - cnrm.cloud.google.com/observed-secret-versions: (removed) cnrm.cloud.google.com/project-id: ${projectId} - cnrm.cloud.google.com/state-into-spec: merge finalizers: - cnrm.cloud.google.com/finalizer - cnrm.cloud.google.com/deletion-defender - generation: 3 + generation: 2 labels: cnrm-test: "true" name: sqlinstance-${uniqueId} namespace: ${uniqueId} spec: databaseVersion: POSTGRES_9_6 - instanceType: CLOUD_SQL_INSTANCE region: us-central1 - resourceID: sqlinstance-${uniqueId} settings: - activationPolicy: ALWAYS availabilityType: REGIONAL backupConfiguration: backupRetentionSettings: @@ -31,7 +25,6 @@ spec: pointInTimeRecoveryEnabled: true startTime: "05:00" transactionLogRetentionDays: 3 - connectorEnforcement: NOT_REQUIRED databaseFlags: - name: cloudsql.iam_authentication value: "on" @@ -44,7 +37,6 @@ spec: diskAutoresizeLimit: 0 diskSize: 100 diskType: PD_SSD - edition: ENTERPRISE insightsConfig: queryInsightsEnabled: true queryStringLength: 1024 @@ -56,9 +48,6 @@ spec: name: computenetwork-${uniqueId} requireSsl: false sslMode: ENCRYPTED_ONLY - locationPreference: - zone: us-central1-a - pricingPlan: PER_USE tier: db-custom-1-3840 status: conditions: @@ -71,7 +60,7 @@ status: firstIpAddress: 10.1.2.3 instanceType: CLOUD_SQL_INSTANCE ipAddress: 10.1.2.3 - observedGeneration: 3 + observedGeneration: 2 publicIpAddress: 10.1.2.3 selfLink: https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId} serverCaCert: diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstance/_http.log b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstance/_http.log index 9904f2893a..f6cd48a616 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstance/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstance/_http.log @@ -479,7 +479,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 404 Not Found Cache-Control: private @@ -508,61 +508,9 @@ X-Xss-Protection: 0 --- -GET https://cloudresourcemanager.googleapis.com/v1/projects/${projectId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "createTime": "2024-04-01T12:34:56.123456Z", - "lifecycleState": "ACTIVE", - "projectId": "${projectId}", - "projectNumber": "${projectNumber}" -} - ---- - -GET https://servicenetworking.googleapis.com/v1/services/servicenetworking.googleapis.com/connections?alt=json&network=projects%2F${projectNumber}%2Fglobal%2Fnetworks%2Fcomputenetwork-${uniqueId}&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "connections": [ - { - "network": "projects/${projectNumber}/global/networks/computenetwork-${uniqueId}", - "peering": "servicenetworking-googleapis-com", - "reservedPeeringRanges": [ - "computeaddress-${uniqueId}" - ], - "service": "services/servicenetworking.googleapis.com" - } - ] -} - ---- - POST https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "POSTGRES_9_6", @@ -576,7 +524,6 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr "retainedBackups": 7, "retentionUnit": "COUNT" }, - "binaryLogEnabled": false, "enabled": true, "pointInTimeRecoveryEnabled": true, "startTime": "12:00", @@ -606,10 +553,8 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr "recordClientAddress": true }, "ipConfiguration": { - "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": false, - "privateNetwork": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId}", - "requireSsl": false, + "privateNetwork": "projects/${projectId}/global/networks/computenetwork-${uniqueId}", "sslMode": "ENCRYPTED_ONLY" }, "pricingPlan": "PER_USE", @@ -649,7 +594,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -678,8 +623,135 @@ X-Xss-Protection: 0 --- +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "backendType": "SECOND_GEN", + "connectionName": "${projectId}:us-central1:sqlinstance-${uniqueId}", + "createTime": "2024-04-01T12:34:56.123456Z", + "databaseInstalledVersion": "POSTGRES_9_6", + "databaseVersion": "POSTGRES_9_6", + "etag": "abcdef0123A=", + "gceZone": "us-central1-a", + "geminiConfig": { + "activeQueryEnabled": false, + "entitled": false, + "googleVacuumMgmtEnabled": false, + "indexAdvisorEnabled": false, + "oomSessionCancelEnabled": false + }, + "instanceType": "CLOUD_SQL_INSTANCE", + "ipAddresses": [ + { + "ipAddress": "10.1.2.3", + "type": "PRIMARY" + }, + { + "ipAddress": "10.1.2.3", + "type": "OUTGOING" + } + ], + "kind": "sql#instance", + "name": "sqlinstance-${uniqueId}", + "project": "${projectId}", + "region": "us-central1", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}", + "serverCaCert": { + "cert": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n", + "certSerialNumber": "0", + "commonName": "common-name", + "createTime": "2024-04-01T12:34:56.123456Z", + "expirationTime": "2024-04-01T12:34:56.123456Z", + "instance": "sqlinstance-${uniqueId}", + "kind": "sql#sslCert", + "sha1Fingerprint": "12345678" + }, + "serviceAccountEmailAddress": "p${projectNumber}-abcdef@gcp-sa-cloud-sql.iam.gserviceaccount.com", + "settings": { + "activationPolicy": "ALWAYS", + "authorizedGaeApplications": [], + "availabilityType": "REGIONAL", + "backupConfiguration": { + "backupRetentionSettings": { + "retainedBackups": 7, + "retentionUnit": "COUNT" + }, + "enabled": true, + "kind": "sql#backupConfiguration", + "pointInTimeRecoveryEnabled": true, + "replicationLogArchivingEnabled": false, + "startTime": "12:00", + "transactionLogRetentionDays": 3, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" + }, + "connectorEnforcement": "NOT_REQUIRED", + "dataDiskSizeGb": "100", + "dataDiskType": "PD_SSD", + "databaseFlags": [ + { + "name": "cloudsql.iam_authentication", + "value": "on" + }, + { + "name": "max_connections", + "value": "1000" + }, + { + "name": "max_worker_processes", + "value": "8" + } + ], + "deletionProtectionEnabled": false, + "edition": "ENTERPRISE", + "insightsConfig": { + "queryInsightsEnabled": true, + "queryStringLength": 1024, + "recordApplicationTags": true, + "recordClientAddress": true + }, + "ipConfiguration": { + "authorizedNetworks": [], + "ipv4Enabled": false, + "privateNetwork": "projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "requireSsl": false, + "sslMode": "ENCRYPTED_ONLY" + }, + "kind": "sql#settings", + "locationPreference": { + "kind": "sql#locationPreference", + "zone": "us-central1-a" + }, + "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", + "settingsVersion": "123", + "storageAutoResize": false, + "storageAutoResizeLimit": "0", + "tier": "db-custom-1-3840", + "userLabels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + } + }, + "sqlNetworkArchitecture": "NEW_NETWORK_ARCHITECTURE", + "state": "RUNNABLE" +} + +--- + GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}/users?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -709,7 +781,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -808,9 +880,8 @@ X-Xss-Protection: 0 }, "ipConfiguration": { "authorizedNetworks": [], - "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": false, - "privateNetwork": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "privateNetwork": "projects/${projectId}/global/networks/computenetwork-${uniqueId}", "requireSsl": false, "sslMode": "ENCRYPTED_ONLY" }, @@ -838,10 +909,13 @@ X-Xss-Protection: 0 PUT https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { + "databaseVersion": "POSTGRES_9_6", "instanceType": "CLOUD_SQL_INSTANCE", + "name": "sqlinstance-${uniqueId}", + "region": "us-central1", "settings": { "activationPolicy": "ALWAYS", "availabilityType": "REGIONAL", @@ -852,6 +926,7 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr }, "binaryLogEnabled": false, "enabled": true, + "kind": "sql#backupConfiguration", "pointInTimeRecoveryEnabled": true, "startTime": "12:00", "transactionLogRetentionDays": 3 @@ -883,14 +958,16 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr "ipConfiguration": { "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": false, - "privateNetwork": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "privateNetwork": "projects/${projectId}/global/networks/computenetwork-${uniqueId}", "requireSsl": false, "sslMode": "ENCRYPTED_ONLY" }, "locationPreference": { + "kind": "sql#locationPreference", "zone": "us-central1-a" }, "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", "settingsVersion": "123", "storageAutoResize": false, "tier": "db-custom-1-3840", @@ -928,7 +1005,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -958,7 +1035,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -1059,7 +1136,7 @@ X-Xss-Protection: 0 "authorizedNetworks": [], "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": false, - "privateNetwork": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "privateNetwork": "projects/${projectId}/global/networks/computenetwork-${uniqueId}", "requireSsl": false, "sslMode": "ENCRYPTED_ONLY" }, @@ -1086,7 +1163,7 @@ X-Xss-Protection: 0 --- DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -1114,36 +1191,6 @@ X-Xss-Protection: 0 --- -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "sqlinstance-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" -} - ---- - GET https://cloudresourcemanager.googleapis.com/v1/projects/${projectId}?alt=json&prettyPrint=false User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstancebasic/_generated_object_postgresinstancebasic.golden.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstancebasic/_generated_object_postgresinstancebasic.golden.yaml index 31e151bf73..57f45a3b6e 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstancebasic/_generated_object_postgresinstancebasic.golden.yaml +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstancebasic/_generated_object_postgresinstancebasic.golden.yaml @@ -3,14 +3,12 @@ kind: SQLInstance metadata: annotations: cnrm.cloud.google.com/management-conflict-prevention-policy: none - cnrm.cloud.google.com/mutable-but-unreadable-fields: '{}' - cnrm.cloud.google.com/observed-secret-versions: (removed) cnrm.cloud.google.com/project-id: ${projectId} cnrm.cloud.google.com/state-into-spec: absent finalizers: - cnrm.cloud.google.com/finalizer - cnrm.cloud.google.com/deletion-defender - generation: 3 + generation: 2 labels: cnrm-test: "true" name: postgresbasic-${uniqueId} @@ -18,7 +16,6 @@ metadata: spec: databaseVersion: POSTGRES_16 region: us-central1 - resourceID: postgresbasic-${uniqueId} settings: locationPreference: zone: us-central1-a @@ -34,7 +31,7 @@ status: firstIpAddress: 10.1.2.3 instanceType: CLOUD_SQL_INSTANCE ipAddress: 10.1.2.3 - observedGeneration: 3 + observedGeneration: 2 publicIpAddress: 10.1.2.3 selfLink: https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId} serverCaCert: diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstancebasic/_http.log b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstancebasic/_http.log index ea32ef137d..0a896528ca 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstancebasic/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/postgresinstancebasic/_http.log @@ -1,5 +1,5 @@ GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 404 Not Found Cache-Control: private @@ -30,7 +30,7 @@ X-Xss-Protection: 0 POST https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "POSTGRES_15", @@ -81,7 +81,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -110,8 +110,120 @@ X-Xss-Protection: 0 --- +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "backendType": "SECOND_GEN", + "connectionName": "${projectId}:us-central1:postgresbasic-${uniqueId}", + "createTime": "2024-04-01T12:34:56.123456Z", + "databaseInstalledVersion": "POSTGRES_15_7", + "databaseVersion": "POSTGRES_15", + "etag": "abcdef0123A=", + "gceZone": "us-central1-a", + "geminiConfig": { + "activeQueryEnabled": false, + "entitled": false, + "googleVacuumMgmtEnabled": false, + "indexAdvisorEnabled": false, + "oomSessionCancelEnabled": false + }, + "instanceType": "CLOUD_SQL_INSTANCE", + "ipAddresses": [ + { + "ipAddress": "10.1.2.3", + "type": "PRIMARY" + }, + { + "ipAddress": "10.1.2.3", + "type": "OUTGOING" + } + ], + "kind": "sql#instance", + "maintenanceVersion": "POSTGRES_15_7.R20240514.00_08", + "name": "postgresbasic-${uniqueId}", + "project": "${projectId}", + "region": "us-central1", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}", + "serverCaCert": { + "cert": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n", + "certSerialNumber": "0", + "commonName": "common-name", + "createTime": "2024-04-01T12:34:56.123456Z", + "expirationTime": "2024-04-01T12:34:56.123456Z", + "instance": "postgresbasic-${uniqueId}", + "kind": "sql#sslCert", + "sha1Fingerprint": "12345678" + }, + "serviceAccountEmailAddress": "p${projectNumber}-abcdef@gcp-sa-cloud-sql.iam.gserviceaccount.com", + "settings": { + "activationPolicy": "ALWAYS", + "authorizedGaeApplications": [], + "availabilityType": "ZONAL", + "backupConfiguration": { + "backupRetentionSettings": { + "retainedBackups": 7, + "retentionUnit": "COUNT" + }, + "enabled": false, + "kind": "sql#backupConfiguration", + "startTime": "12:00", + "transactionLogRetentionDays": 7, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" + }, + "connectorEnforcement": "NOT_REQUIRED", + "dataDiskSizeGb": "10", + "dataDiskType": "PD_SSD", + "deletionProtectionEnabled": false, + "edition": "ENTERPRISE", + "ipConfiguration": { + "authorizedNetworks": [], + "ipv4Enabled": true, + "requireSsl": false, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" + }, + "kind": "sql#settings", + "locationPreference": { + "kind": "sql#locationPreference", + "zone": "us-central1-a" + }, + "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", + "settingsVersion": "123", + "storageAutoResize": true, + "storageAutoResizeLimit": "0", + "tier": "db-custom-1-3840", + "userLabels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + } + }, + "sqlNetworkArchitecture": "NEW_NETWORK_ARCHITECTURE", + "state": "RUNNABLE", + "upgradableDatabaseVersions": [ + { + "displayName": "PostgreSQL 16", + "majorVersion": "POSTGRES_16", + "name": "POSTGRES_16" + } + ] +} + +--- + GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}/users?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -141,7 +253,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -254,7 +366,7 @@ X-Xss-Protection: 0 PATCH https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "POSTGRES_16" @@ -287,7 +399,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -317,7 +429,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -423,10 +535,14 @@ X-Xss-Protection: 0 PUT https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { + "databaseVersion": "POSTGRES_16", "instanceType": "CLOUD_SQL_INSTANCE", + "maintenanceVersion": "POSTGRES_16_3.R20240527.01_10", + "name": "postgresbasic-${uniqueId}", + "region": "us-central1", "settings": { "activationPolicy": "ALWAYS", "availabilityType": "ZONAL", @@ -437,9 +553,11 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr }, "binaryLogEnabled": false, "enabled": false, + "kind": "sql#backupConfiguration", "pointInTimeRecoveryEnabled": false, "startTime": "12:00", - "transactionLogRetentionDays": 7 + "transactionLogRetentionDays": 7, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" }, "connectorEnforcement": "NOT_REQUIRED", "dataDiskSizeGb": "10", @@ -448,12 +566,14 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr "ipConfiguration": { "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": true, - "requireSsl": false + "requireSsl": false, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" }, "locationPreference": { "zone": "us-central1-a" }, "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", "settingsVersion": "123", "storageAutoResize": true, "tier": "db-custom-2-7680", @@ -491,7 +611,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -521,7 +641,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -629,7 +749,7 @@ X-Xss-Protection: 0 --- DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -653,34 +773,4 @@ X-Xss-Protection: 0 "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}", "targetProject": "${projectId}", "user": "user@example.com" -} - ---- - -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "postgresbasic-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/postgresbasic-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" } \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlinstanceencryptionkey/_generated_object_sqlinstanceencryptionkey.golden.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlinstanceencryptionkey/_generated_object_sqlinstanceencryptionkey.golden.yaml index 71ee26dcbd..581730a028 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlinstanceencryptionkey/_generated_object_sqlinstanceencryptionkey.golden.yaml +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlinstanceencryptionkey/_generated_object_sqlinstanceencryptionkey.golden.yaml @@ -3,14 +3,11 @@ kind: SQLInstance metadata: annotations: cnrm.cloud.google.com/management-conflict-prevention-policy: none - cnrm.cloud.google.com/mutable-but-unreadable-fields: '{}' - cnrm.cloud.google.com/observed-secret-versions: (removed) cnrm.cloud.google.com/project-id: ${projectId} - cnrm.cloud.google.com/state-into-spec: merge finalizers: - cnrm.cloud.google.com/finalizer - cnrm.cloud.google.com/deletion-defender - generation: 2 + generation: 1 labels: cnrm-test: "true" label-one: new-value @@ -20,28 +17,22 @@ spec: databaseVersion: POSTGRES_15 encryptionKMSCryptoKeyRef: external: projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId} - instanceType: CLOUD_SQL_INSTANCE - maintenanceVersion: POSTGRES_15_7.R20240514.00_08 region: us-central1 - resourceID: sqlinstance-sample-${uniqueId} settings: activationPolicy: ALWAYS availabilityType: REGIONAL backupConfiguration: backupRetentionSettings: retainedBackups: 5 - retentionUnit: COUNT enabled: true pointInTimeRecoveryEnabled: true startTime: "01:00" transactionLogRetentionDays: 5 - connectorEnforcement: NOT_REQUIRED databaseFlags: - name: cloudsql.iam_authentication value: "on" deletionProtectionEnabled: false diskAutoresize: true - diskAutoresizeLimit: 0 diskSize: 100 diskType: PD_SSD edition: ENTERPRISE @@ -62,7 +53,6 @@ spec: day: 6 hour: 2 updateTrack: stable - pricingPlan: PER_USE tier: db-custom-8-30720 status: conditions: @@ -75,7 +65,7 @@ status: firstIpAddress: 10.1.2.3 instanceType: CLOUD_SQL_INSTANCE ipAddress: 10.1.2.3 - observedGeneration: 2 + observedGeneration: 1 publicIpAddress: 10.1.2.3 selfLink: https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId} serverCaCert: diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlinstanceencryptionkey/_http.log b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlinstanceencryptionkey/_http.log index 30f229b936..ce982b9b55 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlinstanceencryptionkey/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlinstanceencryptionkey/_http.log @@ -929,7 +929,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 404 Not Found Cache-Control: private @@ -958,65 +958,14 @@ X-Xss-Protection: 0 --- -GET https://cloudresourcemanager.googleapis.com/v1/projects/${projectId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "createTime": "2024-04-01T12:34:56.123456Z", - "lifecycleState": "ACTIVE", - "projectId": "${projectId}", - "projectNumber": "${projectNumber}" -} - ---- - -GET https://servicenetworking.googleapis.com/v1/services/servicenetworking.googleapis.com/connections?alt=json&network=projects%2F${projectNumber}%2Fglobal%2Fnetworks%2Fcomputenetwork-${uniqueId}&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "connections": [ - { - "network": "projects/${projectNumber}/global/networks/computenetwork-${uniqueId}", - "peering": "servicenetworking-googleapis-com", - "reservedPeeringRanges": [ - "computeaddress-${uniqueId}" - ], - "service": "services/servicenetworking.googleapis.com" - } - ] -} - ---- - POST https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "POSTGRES_15", "diskEncryptionConfiguration": { + "kind": "sql#diskEncryptionConfiguration", "kmsKeyName": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}" }, "name": "sqlinstance-sample-${uniqueId}", @@ -1026,10 +975,8 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr "availabilityType": "REGIONAL", "backupConfiguration": { "backupRetentionSettings": { - "retainedBackups": 5, - "retentionUnit": "COUNT" + "retainedBackups": 5 }, - "binaryLogEnabled": false, "enabled": true, "pointInTimeRecoveryEnabled": true, "startTime": "12:00", @@ -1052,7 +999,6 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr "recordClientAddress": true }, "ipConfiguration": { - "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": false, "privateNetwork": "projects/${projectId}/global/networks/computenetwork-${uniqueId}", "requireSsl": true @@ -1103,7 +1049,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -1132,8 +1078,146 @@ X-Xss-Protection: 0 --- +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "backendType": "SECOND_GEN", + "connectionName": "${projectId}:us-central1:sqlinstance-sample-${uniqueId}", + "createTime": "2024-04-01T12:34:56.123456Z", + "databaseInstalledVersion": "POSTGRES_15_7", + "databaseVersion": "POSTGRES_15", + "diskEncryptionConfiguration": { + "kind": "sql#diskEncryptionConfiguration", + "kmsKeyName": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}" + }, + "etag": "abcdef0123A=", + "gceZone": "us-central1-a", + "geminiConfig": { + "activeQueryEnabled": false, + "entitled": false, + "googleVacuumMgmtEnabled": false, + "indexAdvisorEnabled": false, + "oomSessionCancelEnabled": false + }, + "instanceType": "CLOUD_SQL_INSTANCE", + "ipAddresses": [ + { + "ipAddress": "10.1.2.3", + "type": "PRIMARY" + }, + { + "ipAddress": "10.1.2.3", + "type": "OUTGOING" + } + ], + "kind": "sql#instance", + "maintenanceVersion": "POSTGRES_15_7.R20240514.00_08", + "name": "sqlinstance-sample-${uniqueId}", + "project": "${projectId}", + "region": "us-central1", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}", + "serverCaCert": { + "cert": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n", + "certSerialNumber": "0", + "commonName": "common-name", + "createTime": "2024-04-01T12:34:56.123456Z", + "expirationTime": "2024-04-01T12:34:56.123456Z", + "instance": "sqlinstance-sample-${uniqueId}", + "kind": "sql#sslCert", + "sha1Fingerprint": "12345678" + }, + "serviceAccountEmailAddress": "p${projectNumber}-abcdef@gcp-sa-cloud-sql.iam.gserviceaccount.com", + "settings": { + "activationPolicy": "ALWAYS", + "authorizedGaeApplications": [], + "availabilityType": "REGIONAL", + "backupConfiguration": { + "backupRetentionSettings": { + "retainedBackups": 5, + "retentionUnit": "COUNT" + }, + "enabled": true, + "kind": "sql#backupConfiguration", + "pointInTimeRecoveryEnabled": true, + "replicationLogArchivingEnabled": false, + "startTime": "12:00", + "transactionLogRetentionDays": 5, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" + }, + "connectorEnforcement": "NOT_REQUIRED", + "dataDiskSizeGb": "100", + "dataDiskType": "PD_SSD", + "databaseFlags": [ + { + "name": "cloudsql.iam_authentication", + "value": "on" + } + ], + "deletionProtectionEnabled": false, + "edition": "ENTERPRISE", + "insightsConfig": { + "queryInsightsEnabled": true, + "queryPlansPerMinute": 20, + "queryStringLength": 4500, + "recordApplicationTags": true, + "recordClientAddress": true + }, + "ipConfiguration": { + "authorizedNetworks": [], + "ipv4Enabled": false, + "privateNetwork": "projects/${projectId}/global/networks/computenetwork-${uniqueId}", + "requireSsl": true, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" + }, + "kind": "sql#settings", + "locationPreference": { + "kind": "sql#locationPreference", + "zone": "us-central1-a" + }, + "maintenanceWindow": { + "day": 6, + "hour": 2, + "updateTrack": "stable" + }, + "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", + "settingsVersion": "123", + "storageAutoResize": true, + "storageAutoResizeLimit": "0", + "tier": "db-custom-8-30720", + "userLabels": { + "cnrm-test": "true", + "label-one": "value-one", + "managed-by-cnrm": "true" + } + }, + "sqlNetworkArchitecture": "NEW_NETWORK_ARCHITECTURE", + "state": "RUNNABLE", + "upgradableDatabaseVersions": [ + { + "displayName": "PostgreSQL 16", + "majorVersion": "POSTGRES_16", + "name": "POSTGRES_16" + } + ] +} + +--- + GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}/users?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -1163,7 +1247,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -1183,6 +1267,7 @@ X-Xss-Protection: 0 "databaseInstalledVersion": "POSTGRES_15_7", "databaseVersion": "POSTGRES_15", "diskEncryptionConfiguration": { + "kind": "sql#diskEncryptionConfiguration", "kmsKeyName": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}" }, "etag": "abcdef0123A=", @@ -1259,7 +1344,6 @@ X-Xss-Protection: 0 }, "ipConfiguration": { "authorizedNetworks": [], - "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": false, "privateNetwork": "projects/${projectId}/global/networks/computenetwork-${uniqueId}", "requireSsl": true, @@ -1302,20 +1386,28 @@ X-Xss-Protection: 0 PUT https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { + "databaseVersion": "POSTGRES_15", + "diskEncryptionConfiguration": { + "kind": "sql#diskEncryptionConfiguration", + "kmsKeyName": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}" + }, "instanceType": "CLOUD_SQL_INSTANCE", + "maintenanceVersion": "POSTGRES_15_7.R20240514.00_08", + "name": "sqlinstance-sample-${uniqueId}", + "region": "us-central1", "settings": { "activationPolicy": "ALWAYS", "availabilityType": "REGIONAL", "backupConfiguration": { "backupRetentionSettings": { - "retainedBackups": 5, - "retentionUnit": "COUNT" + "retainedBackups": 5 }, "binaryLogEnabled": false, "enabled": true, + "kind": "sql#backupConfiguration", "pointInTimeRecoveryEnabled": true, "startTime": "12:00", "transactionLogRetentionDays": 5 @@ -1352,12 +1444,13 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr "updateTrack": "stable" }, "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", "settingsVersion": "123", "storageAutoResize": true, "tier": "db-custom-8-30720", "userLabels": { "cnrm-test": "true", - "label-one": "value-one", + "label-one": "new-value", "managed-by-cnrm": "true" } } @@ -1390,7 +1483,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -1420,7 +1513,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -1439,6 +1532,10 @@ X-Xss-Protection: 0 "createTime": "2024-04-01T12:34:56.123456Z", "databaseInstalledVersion": "POSTGRES_15_7", "databaseVersion": "POSTGRES_15", + "diskEncryptionConfiguration": { + "kind": "sql#diskEncryptionConfiguration", + "kmsKeyName": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}" + }, "etag": "abcdef0123A=", "gceZone": "us-central1-a", "geminiConfig": { @@ -1537,7 +1634,7 @@ X-Xss-Protection: 0 "tier": "db-custom-8-30720", "userLabels": { "cnrm-test": "true", - "label-one": "value-one", + "label-one": "new-value", "managed-by-cnrm": "true" } }, @@ -1555,7 +1652,7 @@ X-Xss-Protection: 0 --- DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -1583,36 +1680,6 @@ X-Xss-Protection: 0 --- -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "sqlinstance-sample-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" -} - ---- - GET https://cloudresourcemanager.googleapis.com/v1/projects/${projectId}?alt=json&prettyPrint=false User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/_generated_object_sqlserverinstance.golden.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/_generated_object_sqlserverinstance.golden.yaml index 3239777480..bda468bf92 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/_generated_object_sqlserverinstance.golden.yaml +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/_generated_object_sqlserverinstance.golden.yaml @@ -3,47 +3,25 @@ kind: SQLInstance metadata: annotations: cnrm.cloud.google.com/management-conflict-prevention-policy: none - cnrm.cloud.google.com/mutable-but-unreadable-fields: '{"spec":{"rootPassword":{"value":"1234"}}}' - cnrm.cloud.google.com/observed-secret-versions: (removed) cnrm.cloud.google.com/project-id: ${projectId} - cnrm.cloud.google.com/state-into-spec: merge finalizers: - cnrm.cloud.google.com/finalizer - cnrm.cloud.google.com/deletion-defender - generation: 3 + generation: 2 labels: cnrm-test: "true" label-one: value-one + label-two: value-two name: sqlinstance-sample-${uniqueId} namespace: ${uniqueId} spec: databaseVersion: SQLSERVER_2017_EXPRESS - instanceType: CLOUD_SQL_INSTANCE - maintenanceVersion: SQLSERVER_2017_EXPRESS_CU31_GDR.R20231029.00_02 region: us-central1 - resourceID: sqlinstance-sample-${uniqueId} rootPassword: value: "1234" settings: - activationPolicy: ALWAYS - availabilityType: ZONAL - backupConfiguration: - backupRetentionSettings: - retainedBackups: 7 - retentionUnit: COUNT - startTime: "12:00" - transactionLogRetentionDays: 7 - connectorEnforcement: NOT_REQUIRED diskAutoresize: false - diskAutoresizeLimit: 0 diskSize: 20 - diskType: PD_SSD - edition: ENTERPRISE - ipConfiguration: - ipv4Enabled: true - locationPreference: - zone: us-central1-a - pricingPlan: PER_USE sqlServerAuditConfig: bucketRef: name: storagebucket-${uniqueId} @@ -59,7 +37,7 @@ status: firstIpAddress: 10.1.2.3 instanceType: CLOUD_SQL_INSTANCE ipAddress: 10.1.2.3 - observedGeneration: 3 + observedGeneration: 2 publicIpAddress: 10.1.2.3 selfLink: https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId} serverCaCert: diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/_http.log b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/_http.log index 11faf6cf01..bb9ad24154 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/_http.log @@ -140,7 +140,7 @@ Vary: X-Origin --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 404 Not Found Cache-Control: private @@ -171,7 +171,7 @@ X-Xss-Protection: 0 POST https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "SQLSERVER_2017_EXPRESS", @@ -186,7 +186,8 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr "edition": "ENTERPRISE", "pricingPlan": "PER_USE", "sqlServerAuditConfig": { - "bucket": "gs://storagebucket-${uniqueId}" + "bucket": "gs://storagebucket-${uniqueId}", + "kind": "sql#sqlServerAuditConfig" }, "storageAutoResize": false, "tier": "db-custom-1-3840", @@ -225,7 +226,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -254,8 +255,107 @@ X-Xss-Protection: 0 --- +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "backendType": "SECOND_GEN", + "connectionName": "${projectId}:us-central1:sqlinstance-sample-${uniqueId}", + "createTime": "2024-04-01T12:34:56.123456Z", + "databaseInstalledVersion": "SQLSERVER_2017_EXPRESS_CU31_GDR", + "databaseVersion": "SQLSERVER_2017_EXPRESS", + "etag": "abcdef0123A=", + "gceZone": "us-central1-a", + "instanceType": "CLOUD_SQL_INSTANCE", + "ipAddresses": [ + { + "ipAddress": "10.1.2.3", + "type": "PRIMARY" + } + ], + "kind": "sql#instance", + "maintenanceVersion": "SQLSERVER_2017_EXPRESS_CU31_GDR.R20231029.00_02", + "name": "sqlinstance-sample-${uniqueId}", + "project": "${projectId}", + "region": "us-central1", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}", + "serverCaCert": { + "cert": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n", + "certSerialNumber": "0", + "commonName": "common-name", + "createTime": "2024-04-01T12:34:56.123456Z", + "expirationTime": "2024-04-01T12:34:56.123456Z", + "instance": "sqlinstance-sample-${uniqueId}", + "kind": "sql#sslCert", + "sha1Fingerprint": "12345678" + }, + "serviceAccountEmailAddress": "p${projectNumber}-abcdef@gcp-sa-cloud-sql.iam.gserviceaccount.com", + "settings": { + "activationPolicy": "ALWAYS", + "authorizedGaeApplications": [], + "availabilityType": "ZONAL", + "backupConfiguration": { + "backupRetentionSettings": { + "retainedBackups": 7, + "retentionUnit": "COUNT" + }, + "enabled": false, + "kind": "sql#backupConfiguration", + "startTime": "12:00", + "transactionLogRetentionDays": 7, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" + }, + "connectorEnforcement": "NOT_REQUIRED", + "dataDiskSizeGb": "10", + "dataDiskType": "PD_SSD", + "deletionProtectionEnabled": false, + "edition": "ENTERPRISE", + "ipConfiguration": { + "authorizedNetworks": [], + "ipv4Enabled": true, + "requireSsl": false, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" + }, + "kind": "sql#settings", + "locationPreference": { + "kind": "sql#locationPreference", + "zone": "us-central1-a" + }, + "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", + "settingsVersion": "123", + "sqlServerAuditConfig": { + "bucket": "gs://storagebucket-${uniqueId}", + "kind": "sql#sqlServerAuditConfig" + }, + "storageAutoResize": false, + "storageAutoResizeLimit": "0", + "tier": "db-custom-1-3840", + "userLabels": { + "cnrm-test": "true", + "label-one": "value-one", + "managed-by-cnrm": "true" + } + }, + "sqlNetworkArchitecture": "NEW_NETWORK_ARCHITECTURE", + "state": "RUNNABLE" +} + +--- + GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}/users?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -312,7 +412,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -392,7 +492,8 @@ X-Xss-Protection: 0 "replicationType": "SYNCHRONOUS", "settingsVersion": "123", "sqlServerAuditConfig": { - "bucket": "gs://storagebucket-${uniqueId}" + "bucket": "gs://storagebucket-${uniqueId}", + "kind": "sql#sqlServerAuditConfig" }, "storageAutoResize": false, "storageAutoResizeLimit": "0", @@ -411,10 +512,15 @@ X-Xss-Protection: 0 PUT https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { + "databaseVersion": "SQLSERVER_2017_EXPRESS", "instanceType": "CLOUD_SQL_INSTANCE", + "maintenanceVersion": "SQLSERVER_2017_EXPRESS_CU31_GDR.R20231029.00_02", + "name": "sqlinstance-sample-${uniqueId}", + "region": "us-central1", + "rootPassword": "1234", "settings": { "activationPolicy": "ALWAYS", "availabilityType": "ZONAL", @@ -425,31 +531,39 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr }, "binaryLogEnabled": false, "enabled": false, + "kind": "sql#backupConfiguration", "pointInTimeRecoveryEnabled": false, "startTime": "12:00", - "transactionLogRetentionDays": 7 + "transactionLogRetentionDays": 7, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" }, "connectorEnforcement": "NOT_REQUIRED", "dataDiskSizeGb": "20", "dataDiskType": "PD_SSD", "edition": "ENTERPRISE", "ipConfiguration": { + "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": true, - "requireSsl": false + "requireSsl": false, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" }, "locationPreference": { + "kind": "sql#locationPreference", "zone": "us-central1-a" }, "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", "settingsVersion": "123", "sqlServerAuditConfig": { - "bucket": "gs://storagebucket-${uniqueId}" + "bucket": "gs://storagebucket-${uniqueId}", + "kind": "sql#sqlServerAuditConfig" }, "storageAutoResize": false, "tier": "db-custom-1-3840", "userLabels": { "cnrm-test": "true", "label-one": "value-one", + "label-two": "value-two", "managed-by-cnrm": "true" } } @@ -482,7 +596,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -512,7 +626,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -580,6 +694,7 @@ X-Xss-Protection: 0 "edition": "ENTERPRISE", "ipConfiguration": { "authorizedNetworks": [], + "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": true, "requireSsl": false, "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" @@ -593,7 +708,8 @@ X-Xss-Protection: 0 "replicationType": "SYNCHRONOUS", "settingsVersion": "123", "sqlServerAuditConfig": { - "bucket": "gs://storagebucket-${uniqueId}" + "bucket": "gs://storagebucket-${uniqueId}", + "kind": "sql#sqlServerAuditConfig" }, "storageAutoResize": false, "storageAutoResizeLimit": "0", @@ -601,6 +717,7 @@ X-Xss-Protection: 0 "userLabels": { "cnrm-test": "true", "label-one": "value-one", + "label-two": "value-two", "managed-by-cnrm": "true" } }, @@ -611,7 +728,7 @@ X-Xss-Protection: 0 --- DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -639,36 +756,6 @@ X-Xss-Protection: 0 --- -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "sqlinstance-sample-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-sample-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" -} - ---- - GET https://storage.googleapis.com/storage/v1/b/storagebucket-${uniqueId}?alt=json&prettyPrint=false User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/update.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/update.yaml index 26bdc40570..4f0360d9aa 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/update.yaml +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstance/update.yaml @@ -17,6 +17,7 @@ kind: SQLInstance metadata: labels: label-one: "value-one" + label-two: "value-two" name: sqlinstance-sample-${uniqueId} spec: region: us-central1 diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/_generated_object_sqlserverinstancebasic.golden.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/_generated_object_sqlserverinstancebasic.golden.yaml index de6b8d121c..8364391735 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/_generated_object_sqlserverinstancebasic.golden.yaml +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/_generated_object_sqlserverinstancebasic.golden.yaml @@ -3,14 +3,12 @@ kind: SQLInstance metadata: annotations: cnrm.cloud.google.com/management-conflict-prevention-policy: none - cnrm.cloud.google.com/mutable-but-unreadable-fields: '{"spec":{"rootPassword":{"value":"4321"}}}' - cnrm.cloud.google.com/observed-secret-versions: (removed) cnrm.cloud.google.com/project-id: ${projectId} cnrm.cloud.google.com/state-into-spec: absent finalizers: - cnrm.cloud.google.com/finalizer - cnrm.cloud.google.com/deletion-defender - generation: 3 + generation: 2 labels: cnrm-test: "true" name: sqlserverbasic-${uniqueId} @@ -18,9 +16,11 @@ metadata: spec: databaseVersion: SQLSERVER_2022_EXPRESS region: us-central1 - resourceID: sqlserverbasic-${uniqueId} rootPassword: - value: "4321" + valueFrom: + secretKeyRef: + key: password + name: secret-${uniqueId} settings: locationPreference: zone: us-central1-a @@ -36,7 +36,7 @@ status: firstIpAddress: 10.1.2.3 instanceType: CLOUD_SQL_INSTANCE ipAddress: 10.1.2.3 - observedGeneration: 3 + observedGeneration: 2 publicIpAddress: 10.1.2.3 selfLink: https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId} serverCaCert: diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/_http.log b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/_http.log index 114157807c..c477cb10a1 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/_http.log @@ -1,5 +1,5 @@ GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 404 Not Found Cache-Control: private @@ -30,13 +30,13 @@ X-Xss-Protection: 0 POST https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "SQLSERVER_2019_EXPRESS", "name": "sqlserverbasic-${uniqueId}", "region": "us-central1", - "rootPassword": "1234", + "rootPassword": "1234!@#$asdf", "settings": { "activationPolicy": "ALWAYS", "availabilityType": "ZONAL", @@ -82,7 +82,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -111,8 +111,139 @@ X-Xss-Protection: 0 --- +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "backendType": "SECOND_GEN", + "connectionName": "${projectId}:us-central1:sqlserverbasic-${uniqueId}", + "createTime": "2024-04-01T12:34:56.123456Z", + "databaseInstalledVersion": "SQLSERVER_2019_EXPRESS_CU26", + "databaseVersion": "SQLSERVER_2019_EXPRESS", + "etag": "abcdef0123A=", + "gceZone": "us-central1-a", + "instanceType": "CLOUD_SQL_INSTANCE", + "ipAddresses": [ + { + "ipAddress": "10.1.2.3", + "type": "PRIMARY" + } + ], + "kind": "sql#instance", + "maintenanceVersion": "SQLSERVER_2019_EXPRESS_CU26.R20240501.00_05", + "name": "sqlserverbasic-${uniqueId}", + "project": "${projectId}", + "region": "us-central1", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}", + "serverCaCert": { + "cert": "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n", + "certSerialNumber": "0", + "commonName": "common-name", + "createTime": "2024-04-01T12:34:56.123456Z", + "expirationTime": "2024-04-01T12:34:56.123456Z", + "instance": "sqlserverbasic-${uniqueId}", + "kind": "sql#sslCert", + "sha1Fingerprint": "12345678" + }, + "serviceAccountEmailAddress": "p${projectNumber}-abcdef@gcp-sa-cloud-sql.iam.gserviceaccount.com", + "settings": { + "activationPolicy": "ALWAYS", + "authorizedGaeApplications": [], + "availabilityType": "ZONAL", + "backupConfiguration": { + "backupRetentionSettings": { + "retainedBackups": 7, + "retentionUnit": "COUNT" + }, + "enabled": false, + "kind": "sql#backupConfiguration", + "startTime": "12:00", + "transactionLogRetentionDays": 7, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" + }, + "connectorEnforcement": "NOT_REQUIRED", + "dataDiskSizeGb": "10", + "dataDiskType": "PD_SSD", + "deletionProtectionEnabled": false, + "edition": "ENTERPRISE", + "ipConfiguration": { + "authorizedNetworks": [], + "ipv4Enabled": true, + "requireSsl": false, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" + }, + "kind": "sql#settings", + "locationPreference": { + "kind": "sql#locationPreference", + "zone": "us-central1-a" + }, + "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", + "settingsVersion": "123", + "storageAutoResize": true, + "storageAutoResizeLimit": "0", + "tier": "db-custom-1-3840", + "userLabels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + } + }, + "sqlNetworkArchitecture": "NEW_NETWORK_ARCHITECTURE", + "state": "RUNNABLE", + "upgradableDatabaseVersions": [ + { + "displayName": "SQL Server 2019 Standard", + "majorVersion": "SQLSERVER_2019_STANDARD", + "name": "SQLSERVER_2019_STANDARD" + }, + { + "displayName": "SQL Server 2019 Enterprise", + "majorVersion": "SQLSERVER_2019_ENTERPRISE", + "name": "SQLSERVER_2019_ENTERPRISE" + }, + { + "displayName": "SQL Server 2019 Web", + "majorVersion": "SQLSERVER_2019_WEB", + "name": "SQLSERVER_2019_WEB" + }, + { + "displayName": "SQL Server 2022 Standard", + "majorVersion": "SQLSERVER_2022_STANDARD", + "name": "SQLSERVER_2022_STANDARD" + }, + { + "displayName": "SQL Server 2022 Enterprise", + "majorVersion": "SQLSERVER_2022_ENTERPRISE", + "name": "SQLSERVER_2022_ENTERPRISE" + }, + { + "displayName": "SQL Server 2022 Express", + "majorVersion": "SQLSERVER_2022_EXPRESS", + "name": "SQLSERVER_2022_EXPRESS" + }, + { + "displayName": "SQL Server 2022 Web", + "majorVersion": "SQLSERVER_2022_WEB", + "name": "SQLSERVER_2022_WEB" + } + ] +} + +--- + GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}/users?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -169,7 +300,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -301,7 +432,7 @@ X-Xss-Protection: 0 PATCH https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "SQLSERVER_2022_EXPRESS" @@ -334,7 +465,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -364,7 +495,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -474,78 +605,17 @@ X-Xss-Protection: 0 --- -PUT https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}/users?alt=json&host=&name=sqlserver&prettyPrint=false -Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -{ - "instance": "sqlserverbasic-${uniqueId}", - "name": "sqlserver", - "password": "4321" -} - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "UPDATE_USER", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "PENDING", - "targetId": "sqlserverbasic-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" -} - ---- - -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "UPDATE_USER", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "sqlserverbasic-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" -} - ---- - PUT https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { + "databaseVersion": "SQLSERVER_2022_EXPRESS", "instanceType": "CLOUD_SQL_INSTANCE", + "maintenanceVersion": "SQLSERVER_2022_EXPRESS_CU12_GDR.R20240501.00_05", + "name": "sqlserverbasic-${uniqueId}", + "region": "us-central1", + "rootPassword": "1234!@#$asdf", "settings": { "activationPolicy": "ALWAYS", "availabilityType": "ZONAL", @@ -556,22 +626,27 @@ User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terr }, "binaryLogEnabled": false, "enabled": false, + "kind": "sql#backupConfiguration", "pointInTimeRecoveryEnabled": false, "startTime": "12:00", - "transactionLogRetentionDays": 7 + "transactionLogRetentionDays": 7, + "transactionalLogStorageState": "TRANSACTIONAL_LOG_STORAGE_STATE_UNSPECIFIED" }, "connectorEnforcement": "NOT_REQUIRED", "dataDiskSizeGb": "10", "dataDiskType": "PD_SSD", "edition": "ENTERPRISE", "ipConfiguration": { + "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": true, - "requireSsl": false + "requireSsl": false, + "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" }, "locationPreference": { "zone": "us-central1-a" }, "pricingPlan": "PER_USE", + "replicationType": "SYNCHRONOUS", "settingsVersion": "123", "storageAutoResize": true, "tier": "db-custom-2-7680", @@ -609,7 +684,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -639,7 +714,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -707,6 +782,7 @@ X-Xss-Protection: 0 "edition": "ENTERPRISE", "ipConfiguration": { "authorizedNetworks": [], + "enablePrivatePathForGoogleCloudServices": false, "ipv4Enabled": true, "requireSsl": false, "sslMode": "ALLOW_UNENCRYPTED_AND_ENCRYPTED" @@ -751,7 +827,7 @@ X-Xss-Protection: 0 --- DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -775,34 +851,4 @@ X-Xss-Protection: 0 "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}", "targetProject": "${projectId}", "user": "user@example.com" -} - ---- - -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "sqlserverbasic-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlserverbasic-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" } \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/create.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/create.yaml index da70e92a7f..37ba487ced 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/create.yaml +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/create.yaml @@ -23,7 +23,10 @@ spec: region: us-central1 # rootPassword is only a required field for SQL Server instances. rootPassword: - value: "1234" + valueFrom: + secretKeyRef: + key: password + name: secret-${uniqueId} settings: # Location preference is not actually a required field. However, setting it for tests # helps with with normalizing the GCP responses, because otherwise GCP chooses a zone diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/dependencies.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/dependencies.yaml new file mode 100644 index 0000000000..771e87572a --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/dependencies.yaml @@ -0,0 +1,21 @@ +# Copyright 2024 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. + +--- +apiVersion: v1 +kind: Secret +metadata: + name: secret-${uniqueId} +data: + password: MTIzNCFAIyRhc2Rm \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/update.yaml b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/update.yaml index 165025a006..facfddc200 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/update.yaml +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqlinstance/sqlserverinstancebasic/update.yaml @@ -23,7 +23,10 @@ spec: region: us-central1 # rootPassword is only a required field for SQL Server instances. rootPassword: - value: "4321" + valueFrom: + secretKeyRef: + key: password + name: secret-${uniqueId} settings: # Location preference is not actually a required field. However, setting it for tests # helps with with normalizing the GCP responses, because otherwise GCP chooses a zone diff --git a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqluser/_http.log b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqluser/_http.log index 028108cc53..a39d3cfd43 100644 --- a/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqluser/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/sql/v1beta1/sqluser/_http.log @@ -1,5 +1,5 @@ GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 404 Not Found Cache-Control: private @@ -30,7 +30,7 @@ X-Xss-Protection: 0 POST https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "MYSQL_5_7", @@ -78,7 +78,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -107,97 +107,8 @@ X-Xss-Protection: 0 --- -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}/users?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "items": [ - { - "etag": "abcdef0123A=", - "host": "", - "instance": "sqluser-dep-${uniqueId}", - "kind": "sql#user", - "name": "root", - "project": "${projectId}" - } - ], - "kind": "sql#usersList" -} - ---- - -DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}/users?alt=json&host=%25&name=root&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE_USER", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "PENDING", - "targetId": "sqluser-dep-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" -} - ---- - -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE_USER", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "sqluser-dep-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" -} - ---- - GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -367,6 +278,95 @@ X-Xss-Protection: 0 --- +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}/users?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "items": [ + { + "etag": "abcdef0123A=", + "host": "", + "instance": "sqluser-dep-${uniqueId}", + "kind": "sql#user", + "name": "root", + "project": "${projectId}" + } + ], + "kind": "sql#usersList" +} + +--- + +DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}/users?alt=json&name=root&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "insertTime": "2024-04-01T12:34:56.123456Z", + "kind": "sql#operation", + "name": "${operationID}", + "operationType": "DELETE_USER", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", + "status": "PENDING", + "targetId": "sqluser-dep-${uniqueId}", + "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}", + "targetProject": "${projectId}", + "user": "user@example.com" +} + +--- + +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "endTime": "2024-04-01T12:34:56.123456Z", + "insertTime": "2024-04-01T12:34:56.123456Z", + "kind": "sql#operation", + "name": "${operationID}", + "operationType": "DELETE_USER", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", + "status": "DONE", + "targetId": "sqluser-dep-${uniqueId}", + "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}", + "targetProject": "${projectId}", + "user": "user@example.com" +} + +--- + GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}/users?alt=json&prettyPrint=false User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager @@ -1291,7 +1291,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -1462,7 +1462,7 @@ X-Xss-Protection: 0 --- DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -1486,34 +1486,4 @@ X-Xss-Protection: 0 "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}", "targetProject": "${projectId}", "user": "user@example.com" -} - ---- - -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "sqluser-dep-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqluser-dep-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" } \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/iammemberreferences/sqlinstanceref/_http.log b/pkg/test/resourcefixture/testdata/iammemberreferences/sqlinstanceref/_http.log index e054363295..a44ee336e5 100644 --- a/pkg/test/resourcefixture/testdata/iammemberreferences/sqlinstanceref/_http.log +++ b/pkg/test/resourcefixture/testdata/iammemberreferences/sqlinstanceref/_http.log @@ -1,5 +1,5 @@ GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 404 Not Found Cache-Control: private @@ -30,7 +30,7 @@ X-Xss-Protection: 0 POST https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances?alt=json&prettyPrint=false Content-Type: application/json -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager { "databaseVersion": "MYSQL_5_7", @@ -78,7 +78,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -107,97 +107,8 @@ X-Xss-Protection: 0 --- -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}/users?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "items": [ - { - "etag": "abcdef0123A=", - "host": "", - "instance": "sqlinstance-${uniqueId}", - "kind": "sql#user", - "name": "root", - "project": "${projectId}" - } - ], - "kind": "sql#usersList" -} - ---- - -DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}/users?alt=json&host=%25&name=root&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE_USER", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "PENDING", - "targetId": "sqlinstance-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" -} - ---- - -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE_USER", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "sqlinstance-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" -} - ---- - GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -367,6 +278,95 @@ X-Xss-Protection: 0 --- +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}/users?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "items": [ + { + "etag": "abcdef0123A=", + "host": "", + "instance": "sqlinstance-${uniqueId}", + "kind": "sql#user", + "name": "root", + "project": "${projectId}" + } + ], + "kind": "sql#usersList" +} + +--- + +DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}/users?alt=json&name=root&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "insertTime": "2024-04-01T12:34:56.123456Z", + "kind": "sql#operation", + "name": "${operationID}", + "operationType": "DELETE_USER", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", + "status": "PENDING", + "targetId": "sqlinstance-${uniqueId}", + "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}", + "targetProject": "${projectId}", + "user": "user@example.com" +} + +--- + +GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false +User-Agent: kcc/controller-manager + +200 OK +Cache-Control: private +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "endTime": "2024-04-01T12:34:56.123456Z", + "insertTime": "2024-04-01T12:34:56.123456Z", + "kind": "sql#operation", + "name": "${operationID}", + "operationType": "DELETE_USER", + "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", + "status": "DONE", + "targetId": "sqlinstance-${uniqueId}", + "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}", + "targetProject": "${projectId}", + "user": "user@example.com" +} + +--- + GET https://pubsub.googleapis.com/v1/projects/${projectId}/topics/pubsubtopic-${uniqueId}?alt=json Content-Type: application/json User-Agent: Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager @@ -641,7 +641,7 @@ X-Xss-Protection: 0 --- GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -812,7 +812,7 @@ X-Xss-Protection: 0 --- DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager +User-Agent: kcc/controller-manager 200 OK Cache-Control: private @@ -836,34 +836,4 @@ X-Xss-Protection: 0 "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}", "targetProject": "${projectId}", "user": "user@example.com" -} - ---- - -GET https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}?alt=json&prettyPrint=false -User-Agent: google-api-go-client/0.5 Terraform/ (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google-beta/kcc/controller-manager - -200 OK -Cache-Control: private -Content-Type: application/json; charset=UTF-8 -Server: ESF -Vary: Origin -Vary: X-Origin -Vary: Referer -X-Content-Type-Options: nosniff -X-Frame-Options: SAMEORIGIN -X-Xss-Protection: 0 - -{ - "endTime": "2024-04-01T12:34:56.123456Z", - "insertTime": "2024-04-01T12:34:56.123456Z", - "kind": "sql#operation", - "name": "${operationID}", - "operationType": "DELETE", - "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/operations/${operationID}", - "status": "DONE", - "targetId": "sqlinstance-${uniqueId}", - "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/${projectId}/instances/sqlinstance-${uniqueId}", - "targetProject": "${projectId}", - "user": "user@example.com" } \ No newline at end of file diff --git a/scripts/generate-google3-docs/resource-reference/generated/resource-docs/cloudbuild/cloudbuildworkerpool.md b/scripts/generate-google3-docs/resource-reference/generated/resource-docs/cloudbuild/cloudbuildworkerpool.md index e4ef20ae6f..0e1683a3d0 100644 --- a/scripts/generate-google3-docs/resource-reference/generated/resource-docs/cloudbuild/cloudbuildworkerpool.md +++ b/scripts/generate-google3-docs/resource-reference/generated/resource-docs/cloudbuild/cloudbuildworkerpool.md @@ -168,7 +168,7 @@ resourceID: string

string

-

{% verbatim %}The compute network selflink of form "projects//global/networks/", when not managed by KCC.{% endverbatim %}

+

{% verbatim %}The compute network selflink of form "projects//global/networks/", when not managed by Config Connector.{% endverbatim %}

diff --git a/scripts/generate-google3-docs/resource-reference/generated/resource-docs/sql/sqlinstance.md b/scripts/generate-google3-docs/resource-reference/generated/resource-docs/sql/sqlinstance.md index 94f17cbac9..2ea411a0b9 100644 --- a/scripts/generate-google3-docs/resource-reference/generated/resource-docs/sql/sqlinstance.md +++ b/scripts/generate-google3-docs/resource-reference/generated/resource-docs/sql/sqlinstance.md @@ -242,7 +242,7 @@ settings:

string

-

{% verbatim %}Allowed value: The `selfLink` field of a `KMSCryptoKey` resource.{% endverbatim %}

+

{% verbatim %} If provided must be in the format `projects/[kms_project_id]/locations/[region]/keyRings/[key_ring_id]/cryptoKeys/[key]`.{% endverbatim %}

@@ -252,7 +252,7 @@ settings:

string

-

{% verbatim %}Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names{% endverbatim %}

+

{% verbatim %}The `name` field of a `KMSCryptoKey` resource.{% endverbatim %}

@@ -262,7 +262,7 @@ settings:

string

-

{% verbatim %}Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/{% endverbatim %}

+

{% verbatim %}The `metadata.namespace` field of a `KMSCryptoKey` resource.{% endverbatim %}

@@ -302,7 +302,7 @@ settings:

string

-

{% verbatim %}Allowed value: The `name` field of a `SQLInstance` resource.{% endverbatim %}

+

{% verbatim %}The SQLInstance selfLink, when not managed by Config Connector.{% endverbatim %}

@@ -312,7 +312,7 @@ settings:

string

-

{% verbatim %}Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names{% endverbatim %}

+

{% verbatim %}The `name` field of a `SQLInstance` resource.{% endverbatim %}

@@ -322,7 +322,7 @@ settings:

string

-

{% verbatim %}Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/{% endverbatim %}

+

{% verbatim %}The `namespace` field of a `SQLInstance` resource.{% endverbatim %}

@@ -642,8 +642,7 @@ settings:

list (string)

-

{% verbatim %}DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. -Specifying this field has no-ops; it's recommended to remove this field from your configuration.{% endverbatim %}

+

{% verbatim %}DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. Specifying this field has no-ops; it's recommended to remove this field from your configuration.{% endverbatim %}

@@ -663,12 +662,7 @@ Specifying this field has no-ops; it's recommended to remove this field from you

string

-

{% verbatim %}The availability type of the Cloud SQL instance, high availability -(REGIONAL) or single zone (ZONAL). For all instances, ensure that -settings.backup_configuration.enabled is set to true. -For MySQL instances, ensure that settings.backup_configuration.binary_log_enabled is set to true. -For Postgres instances, ensure that settings.backup_configuration.point_in_time_recovery_enabled -is set to true. Defaults to ZONAL.{% endverbatim %}

+

{% verbatim %}The availability type of the Cloud SQL instance, high availability (REGIONAL) or single zone (ZONAL). For all instances, ensure that settings.backup_configuration.enabled is set to true. For MySQL instances, ensure that settings.backup_configuration.binary_log_enabled is set to true. For Postgres instances, ensure that settings.backup_configuration.point_in_time_recovery_enabled is set to true. Defaults to ZONAL.{% endverbatim %}

@@ -798,8 +792,7 @@ is set to true. Defaults to ZONAL.{% endverbatim %}

boolean

-

{% verbatim %}DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. -Specifying this field has no-ops; it's recommended to remove this field from your configuration.{% endverbatim %}

+

{% verbatim %}DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. Specifying this field has no-ops; it's recommended to remove this field from your configuration.{% endverbatim %}

@@ -1129,7 +1122,7 @@ Specifying this field has no-ops; it's recommended to remove this field from you

string

-

{% verbatim %}Allowed value: The `selfLink` field of a `ComputeNetwork` resource.{% endverbatim %}

+

{% verbatim %}The compute network selflink of form "projects//global/networks/", when not managed by Config Connector.{% endverbatim %}

@@ -1139,7 +1132,7 @@ Specifying this field has no-ops; it's recommended to remove this field from you

string

-

{% verbatim %}Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names{% endverbatim %}

+

{% verbatim %}The `name` field of a `ComputeNetwork` resource.{% endverbatim %}

@@ -1149,7 +1142,7 @@ Specifying this field has no-ops; it's recommended to remove this field from you

string

-

{% verbatim %}Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/{% endverbatim %}

+

{% verbatim %}The `namespace` field of a `ComputeNetwork` resource.{% endverbatim %}

@@ -1389,8 +1382,7 @@ Specifying this field has no-ops; it's recommended to remove this field from you

string

-

{% verbatim %}DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. -Specifying this field has no-ops; it's recommended to remove this field from your configuration.{% endverbatim %}

+

{% verbatim %}DEPRECATED. This property is only applicable to First Generation instances, and First Generation instances are now deprecated. see https://cloud.google.com/sql/docs/mysql/deprecation-notice for information on how to upgrade to Second Generation instances. Specifying this field has no-ops; it's recommended to remove this field from your configuration.{% endverbatim %}

@@ -1420,7 +1412,7 @@ Specifying this field has no-ops; it's recommended to remove this field from you

string

-

{% verbatim %}Allowed value: The `url` field of a `StorageBucket` resource.{% endverbatim %}

+

{% verbatim %}The StorageBucket selfLink, when not managed by Config Connector.{% endverbatim %}

@@ -1430,7 +1422,7 @@ Specifying this field has no-ops; it's recommended to remove this field from you

string

-

{% verbatim %}Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names{% endverbatim %}

+

{% verbatim %}The `name` field of a `StorageBucket` resource.{% endverbatim %}

@@ -1440,7 +1432,7 @@ Specifying this field has no-ops; it's recommended to remove this field from you

string

-

{% verbatim %}Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/{% endverbatim %}

+

{% verbatim %}The `namespace` field of a `StorageBucket` resource.{% endverbatim %}

@@ -1548,7 +1540,7 @@ serviceAccountEmailAddress: string conditions

list (object)

-

{% verbatim %}Conditions represent the latest available observation of the resource's current state.{% endverbatim %}

+

{% verbatim %}Conditions represent the latest available observations of the SQLInstance's current state.{% endverbatim %}

diff --git a/scripts/github-actions/tests-e2e-fixtures b/scripts/github-actions/tests-e2e-fixtures index 32469d584b..368a7afd36 100755 --- a/scripts/github-actions/tests-e2e-fixtures +++ b/scripts/github-actions/tests-e2e-fixtures @@ -34,4 +34,5 @@ GOLDEN_OBJECT_CHECKS=1 \ GOLDEN_REQUEST_CHECKS=1 \ E2E_KUBE_TARGET=envtest \ E2E_GCP_TARGET=mock \ +KCC_USE_DIRECT_RECONCILERS="SQLInstance" \ go test -test.count=1 -timeout 3600s -v ./tests/e2e -run TestAllInSeries/fixtures \ No newline at end of file diff --git a/scripts/github-actions/tests-e2e-samples b/scripts/github-actions/tests-e2e-samples index a1e7229d9a..5aa602d6e3 100755 --- a/scripts/github-actions/tests-e2e-samples +++ b/scripts/github-actions/tests-e2e-samples @@ -29,4 +29,5 @@ echo "Running fixtures in tests/e2e..." RUN_E2E=1 \ E2E_KUBE_TARGET=envtest \ E2E_GCP_TARGET=mock \ +KCC_USE_DIRECT_RECONCILERS="SQLInstance" \ go test -test.count=1 -timeout 3600s -v ./tests/e2e -run TestAllInSeries/samples \ No newline at end of file