diff --git a/apis/secretmanager/v1beta1/secret_types.go b/apis/secretmanager/v1beta1/secret_types.go index e98f8a84da..6c5cbd4362 100644 --- a/apis/secretmanager/v1beta1/secret_types.go +++ b/apis/secretmanager/v1beta1/secret_types.go @@ -197,6 +197,7 @@ type SecretManagerSecretStatus struct { // SecretManagerSecretSpec defines the desired state of SecretManagerSecret // +kcc:proto=google.cloud.secretmanager.v1.Secret type SecretManagerSecretObservedState struct { + VersionAliases map[string]string `json:"versionAliases,omitempty"` } // +genclient diff --git a/apis/secretmanager/v1beta1/zz_generated.deepcopy.go b/apis/secretmanager/v1beta1/zz_generated.deepcopy.go index c7ce491492..06fdd58052 100644 --- a/apis/secretmanager/v1beta1/zz_generated.deepcopy.go +++ b/apis/secretmanager/v1beta1/zz_generated.deepcopy.go @@ -465,6 +465,13 @@ func (in *SecretManagerSecretList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecretManagerSecretObservedState) DeepCopyInto(out *SecretManagerSecretObservedState) { *out = *in + if in.VersionAliases != nil { + in, out := &in.VersionAliases, &out.VersionAliases + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretManagerSecretObservedState. @@ -563,7 +570,7 @@ func (in *SecretManagerSecretStatus) DeepCopyInto(out *SecretManagerSecretStatus if in.ObservedState != nil { in, out := &in.ObservedState, &out.ObservedState *out = new(SecretManagerSecretObservedState) - **out = **in + (*in).DeepCopyInto(*out) } } diff --git a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_secretmanagersecrets.secretmanager.cnrm.cloud.google.com.yaml b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_secretmanagersecrets.secretmanager.cnrm.cloud.google.com.yaml index 4d95f98f4d..e6d511c1b4 100644 --- a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_secretmanagersecrets.secretmanager.cnrm.cloud.google.com.yaml +++ b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_secretmanagersecrets.secretmanager.cnrm.cloud.google.com.yaml @@ -383,6 +383,11 @@ spec: observedState: description: ObservedState is the state of the resource as most recently observed in GCP. + properties: + versionAliases: + additionalProperties: + type: string + type: object type: object type: object type: object diff --git a/pkg/controller/direct/secretmanager/secret_controller.go b/pkg/controller/direct/secretmanager/secret_controller.go index d8927f1863..aecfc7731c 100644 --- a/pkg/controller/direct/secretmanager/secret_controller.go +++ b/pkg/controller/direct/secretmanager/secret_controller.go @@ -183,7 +183,8 @@ func (a *Adapter) Create(ctx context.Context, op *directbase.CreateOperation) er } resource.Annotations = ComputeAnnotations(desired) resource.Labels = common.ComputeGCPLabels(desired.GetLabels()) - + // GCP service does not allow setting version aliases during Secret creation. + resource.VersionAliases = nil req := &secretmanagerpb.CreateSecretRequest{ Parent: a.id.Parent().String(), SecretId: a.id.ID(), @@ -203,7 +204,14 @@ func (a *Adapter) Create(ctx context.Context, op *directbase.CreateOperation) er external := a.id.String() status.ExternalRef = &external status.Name = created.Name - return op.UpdateStatus(ctx, status, nil) + if err = op.UpdateStatus(ctx, status, nil); err != nil { + return err + } + // VersionAliases cannot be set in Creation, requeing the result to update the versionAlias without waiting for the reconciliation interval. + if a.desired.Spec.VersionAliases != nil { + op.RequeueRequested = true + } + return nil } func topicsEqual(desired []*krm.TopicRef, actual []*secretmanagerpb.Topic) bool { diff --git a/pkg/controller/direct/secretmanager/secret_mapping.go b/pkg/controller/direct/secretmanager/secret_mapping.go index 4593ac30e5..c96dd24cfa 100644 --- a/pkg/controller/direct/secretmanager/secret_mapping.go +++ b/pkg/controller/direct/secretmanager/secret_mapping.go @@ -15,6 +15,8 @@ package secretmanager import ( + "strconv" + krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/secretmanager/v1beta1" pb "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb" @@ -23,7 +25,12 @@ import ( ) func SecretManagerSecretStatusObservedState_FromProto(mapCtx *direct.MapContext, in *pb.Secret) *krm.SecretManagerSecretObservedState { - return &krm.SecretManagerSecretObservedState{} + if in == nil { + return nil + } + out := &krm.SecretManagerSecretObservedState{} + out.VersionAliases = MapStringInt64_ToMapStringString(mapCtx, in.VersionAliases) + return out } func CustomerManagedEncryption_FromProto(mapCtx *direct.MapContext, in *pb.CustomerManagedEncryption) *krm.CustomerManagedEncryption { @@ -96,8 +103,7 @@ func SecretManagerSecretSpec_ToProto(mapCtx *direct.MapContext, in *krm.SecretMa } // MISSING: Etag out.Rotation = Rotation_ToProto(mapCtx, in.Rotation) - // MISSING: VersionAliases - // out.VersionAliases = in.VersionAliases + out.VersionAliases = MapStringString_ToMapStringInt64(mapCtx, in.VersionAliases) out.Annotations = in.Annotations // MISSING: Labels // MISSING: VersionDestroyTtl @@ -122,3 +128,23 @@ func Topic_ToProto(mapCtx *direct.MapContext, in *krm.Topic) *pb.Topic { out.Name = direct.ValueOf(in.Name) return out } + +func MapStringString_ToMapStringInt64(mapCtx *direct.MapContext, in map[string]string) map[string]int64 { + out := map[string]int64{} + for k, v := range in { + stringV, err := strconv.ParseInt(v, 10, 64) + if err != nil { + mapCtx.Errorf("%s has invalid value, expect int64, got %s", k, v) + } + out[k] = stringV + } + return out +} + +func MapStringInt64_ToMapStringString(mapCtx *direct.MapContext, in map[string]int64) map[string]string { + out := map[string]string{} + for k, v := range in { + out[k] = strconv.FormatInt(v, 10) + } + return out +} diff --git a/pkg/controller/direct/secretmanager/secretversion_controller.go b/pkg/controller/direct/secretmanager/secretversion_controller.go index 198c4a2682..d87ceef60f 100644 --- a/pkg/controller/direct/secretmanager/secretversion_controller.go +++ b/pkg/controller/direct/secretmanager/secretversion_controller.go @@ -280,6 +280,9 @@ func (a *SecretVersionAdapter) Delete(ctx context.Context, deleteOp *directbase. Name: a.id.String(), Etag: a.actual.Etag} _, err := a.gcpClient.DestroySecretVersion(ctx, req) if err != nil { + if direct.IsNotFound(err) { + return false, nil + } return false, fmt.Errorf("deleting SecretVersion %s: %w", a.id, err) } log.Info("destroyed SecretVersion", "name", a.id) diff --git a/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/basicsecretmanagersecret/_generated_export_basicsecretmanagersecret.golden b/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/basicsecretmanagersecret/_generated_export_basicsecretmanagersecret.golden new file mode 100644 index 0000000000..ce0682d68a --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/basicsecretmanagersecret/_generated_export_basicsecretmanagersecret.golden @@ -0,0 +1,16 @@ +apiVersion: secretmanager.cnrm.cloud.google.com/v1beta1 +kind: SecretManagerSecret +metadata: + annotations: + cnrm.cloud.google.com/project-id: ${projectId} + labels: + cnrm-test: "true" + label-one: value-one + managed-by-cnrm: "true" + name: secretmanagersecret-${uniqueId} +spec: + replication: + userManaged: + replicas: + - location: us-central1 + resourceID: secretmanagersecret-${uniqueId} \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/basicsecretmanagersecret/_http.log b/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/basicsecretmanagersecret/_http.log index 640bf8882a..2092535749 100644 --- a/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/basicsecretmanagersecret/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/basicsecretmanagersecret/_http.log @@ -79,6 +79,43 @@ X-Xss-Protection: 0 --- +GET https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/secretmanagersecret-${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 + +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", + "etag": "abcdef0123A=", + "labels": { + "cnrm-test": "true", + "label-one": "value-one", + "managed-by-cnrm": "true" + }, + "name": "projects/${projectNumber}/secrets/secretmanagersecret-${uniqueId}", + "replication": { + "userManaged": { + "replicas": [ + { + "location": "us-central1" + } + ] + } + } +} + +--- + GET https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/secretmanagersecret-${uniqueId}?%24alt=json%3Benum-encoding%3Dint Content-Type: application/json User-Agent: kcc/controller-manager diff --git a/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/fullsecretmanagersecret/_generated_export_fullsecretmanagersecret.golden b/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/fullsecretmanagersecret/_generated_export_fullsecretmanagersecret.golden new file mode 100644 index 0000000000..291ddcefb5 --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/fullsecretmanagersecret/_generated_export_fullsecretmanagersecret.golden @@ -0,0 +1,28 @@ +apiVersion: secretmanager.cnrm.cloud.google.com/v1beta1 +kind: SecretManagerSecret +metadata: + annotations: + cnrm.cloud.google.com/project-id: ${projectId} + labels: + cnrm-test: "true" + label-one: value-one + label-two: value-two + managed-by-cnrm: "true" + name: secretmanagersecret-${uniqueId} +spec: + annotations: + bar: secretmanagersecret-bar + foo: secretmanagersecret + expireTime: "2025-10-03T15:01:23Z" + replication: + auto: + customerManagedEncryption: + kmsKeyRef: + external: projects/${projectId}/locations/global/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId} + resourceID: secretmanagersecret-${uniqueId} + rotation: + nextRotationTime: "2025-10-03T15:01:23Z" + rotationPeriod: 7200s + topics: + - topicRef: + external: projects/${projectId}/topics/topic-2-${uniqueId} \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/fullsecretmanagersecret/_http.log b/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/fullsecretmanagersecret/_http.log index 86879e8794..a1d0b8bdba 100644 --- a/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/fullsecretmanagersecret/_http.log +++ b/pkg/test/resourcefixture/testdata/basic/secretmanager/v1beta1/fullsecretmanagersecret/_http.log @@ -892,6 +892,56 @@ X-Xss-Protection: 0 --- +GET https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/secretmanagersecret-${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 + +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 + +{ + "annotations": { + "bar": "secretmanagersecret-bar", + "foo": "secretmanagersecret" + }, + "createTime": "2024-04-01T12:34:56.123456Z", + "etag": "abcdef0123A=", + "expireTime": "2025-10-03T15:01:23Z", + "labels": { + "cnrm-test": "true", + "label-one": "value-one", + "label-two": "value-two", + "managed-by-cnrm": "true" + }, + "name": "projects/${projectNumber}/secrets/secretmanagersecret-${uniqueId}", + "replication": { + "automatic": { + "customerManagedEncryption": { + "kmsKeyName": "projects/${projectId}/locations/global/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}" + } + } + }, + "rotation": { + "nextRotationTime": "2025-10-03T15:01:23Z", + "rotationPeriod": "7200s" + }, + "topics": [ + { + "name": "projects/${projectId}/topics/topic-2-${uniqueId}" + } + ] +} + +--- + GET https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/secretmanagersecret-${uniqueId}?%24alt=json%3Benum-encoding%3Dint Content-Type: application/json User-Agent: kcc/controller-manager diff --git a/scripts/generate-google3-docs/resource-reference/generated/resource-docs/secretmanager/secretmanagersecret.md b/scripts/generate-google3-docs/resource-reference/generated/resource-docs/secretmanager/secretmanagersecret.md index a0dc5ac504..62543b7172 100644 --- a/scripts/generate-google3-docs/resource-reference/generated/resource-docs/secretmanager/secretmanagersecret.md +++ b/scripts/generate-google3-docs/resource-reference/generated/resource-docs/secretmanager/secretmanagersecret.md @@ -555,7 +555,9 @@ conditions: externalRef: string name: string observedGeneration: integer -observedState: {} +observedState: + versionAliases: + string: string ``` @@ -642,6 +644,13 @@ observedState: {}

{% verbatim %}ObservedState is the state of the resource as most recently observed in GCP.{% endverbatim %}

+ + + +
observedState.versionAliases +

map (key: string, value: string)

+

{% verbatim %}{% endverbatim %}

+
diff --git a/tests/e2e/export.go b/tests/e2e/export.go index 44ffc7d011..1945b680ad 100644 --- a/tests/e2e/export.go +++ b/tests/e2e/export.go @@ -68,6 +68,9 @@ func exportResource(h *create.Harness, obj *unstructured.Unstructured, expectati case schema.GroupKind{Group: "cloudbuild.cnrm.cloud.google.com", Kind: "CloudBuildWorkerPool"}: exportURI = "//cloudbuild.googleapis.com/projects/" + projectID + "/locations/" + location + "/workerPools/" + resourceID + case schema.GroupKind{Group: "secretmanager.cnrm.cloud.google.com", Kind: "SecretManagerSecret"}: + exportURI = "//secretmanager.googleapis.com/projects/" + projectID + "/secrets/" + resourceID + } if exportURI == "" { @@ -103,7 +106,6 @@ func exportResource(h *create.Harness, obj *unstructured.Unstructured, expectati } exportURI = strings.ReplaceAll(exportURI, "{.spec.collection}", collection) } - exportParams := h.ExportParams() exportParams.IAMFormat = "partialpolicy" exportParams.ResourceFormat = "krm" @@ -111,9 +113,17 @@ func exportResource(h *create.Harness, obj *unstructured.Unstructured, expectati outputPath := filepath.Join(outputDir, "export.yaml") exportParams.Output = outputPath exportParams.URI = exportURI - if err := export.Execute(h.Ctx, &exportParams); err != nil { - h.Errorf("error from export.Execute: %v", err) - return "" + switch gvk.Kind { + case "SecretManagerSecretVersion": + // Skip run export.Execute because the SecretVersion servicemappings has a broken marker + // that the `idTemplateCanBeUsedToMatchResourceName` is false so the Execute always fails. + // https://github.com/GoogleCloudPlatform/k8s-config-connector/blob/3530c83a5e0d331640ec2160675d80336fad9c53/config/servicemappings/secretmanager.yaml#L79 + break + default: + if err := export.Execute(h.Ctx, &exportParams); err != nil { + h.Errorf("error from export.Execute: %v", err) + return "" + } } output := h.MustReadFile(outputPath) diff --git a/tests/e2e/testdata/scenarios/secretmanagerversionalias/_export0.yaml b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_export0.yaml new file mode 100644 index 0000000000..6623042f4a --- /dev/null +++ b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_export0.yaml @@ -0,0 +1,12 @@ +apiVersion: secretmanager.cnrm.cloud.google.com/v1beta1 +kind: SecretManagerSecret +metadata: + annotations: + cnrm.cloud.google.com/project-id: ${projectId} + name: secret-${uniqueId} +spec: + replication: + userManaged: + replicas: + - location: us-central1 + resourceID: secret-${uniqueId} \ No newline at end of file diff --git a/tests/e2e/testdata/scenarios/secretmanagerversionalias/_export3.yaml b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_export3.yaml new file mode 100644 index 0000000000..3fe609aa8b --- /dev/null +++ b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_export3.yaml @@ -0,0 +1,14 @@ +apiVersion: secretmanager.cnrm.cloud.google.com/v1beta1 +kind: SecretManagerSecret +metadata: + annotations: + cnrm.cloud.google.com/project-id: ${projectId} + name: secret-${uniqueId} +spec: + replication: + userManaged: + replicas: + - location: us-central1 + resourceID: secret-${uniqueId} + versionAliases: + foo: "1" \ No newline at end of file diff --git a/tests/e2e/testdata/scenarios/secretmanagerversionalias/_http00.log b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_http00.log new file mode 100644 index 0000000000..ff4c96167e --- /dev/null +++ b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_http00.log @@ -0,0 +1,106 @@ +GET https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/secret-${uniqueId}?%24alt=json%3Benum-encoding%3Dint +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: name=projects%2F${projectId}%2Fsecrets%2Fsecret-${uniqueId} + +404 Not Found +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 + +{ + "error": { + "code": 404, + "details": [ + { + "@type": "type.googleapis.com/google.rpc.DebugInfo", + "detail": "[ORIGINAL ERROR] generic::not_found: Secret [projects/${projectNumber}/secrets/secret-${uniqueId}] not found. [google.rpc.error_details_ext] { message: \"Secret [projects/${projectNumber}/secrets/secret-${uniqueId}] not found.\" }" + } + ], + "message": "Secret [projects/${projectNumber}/secrets/secret-${uniqueId}] not found.", + "status": "NOT_FOUND" + } +} + +--- + +POST https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets?%24alt=json%3Benum-encoding%3Dint&secretId=secret-${uniqueId} +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: parent=projects%2F${projectId} + +{ + "replication": { + "userManaged": { + "replicas": [ + { + "location": "us-central1" + } + ] + } + } +} + +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", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}/secrets/secret-${uniqueId}", + "replication": { + "userManaged": { + "replicas": [ + { + "location": "us-central1" + } + ] + } + } +} + +--- + +GET https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/secret-${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 + +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", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}/secrets/secret-${uniqueId}", + "replication": { + "userManaged": { + "replicas": [ + { + "location": "us-central1" + } + ] + } + } +} \ No newline at end of file diff --git a/tests/e2e/testdata/scenarios/secretmanagerversionalias/_http02.log b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_http02.log new file mode 100644 index 0000000000..e601f4a707 --- /dev/null +++ b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_http02.log @@ -0,0 +1,38 @@ +POST https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/secret-${uniqueId}:addVersion?%24alt=json%3Benum-encoding%3Dint +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: parent=projects%2F${projectId}%2Fsecrets%2Fsecret-${uniqueId} + +{ + "parent": "projects/${projectId}/secrets/secret-${uniqueId}", + "payload": { + "data": "SSBhbHdheXMgbG92ZWQgc3BhcnJpbmcgd2l0aCBnaWFudCBjYW5keSBzd29yZHMsIGJ1dCBJIGhhZCBubyBpZGVhIHRoYXQgd2FzIG15IHN1cGVyIHNlY3JldCBpbmZvcm1hdGlvbiE=" + } +} + +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", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}/secrets/secret-${uniqueId}/versions/1", + "replicationStatus": { + "userManaged": { + "replicas": [ + { + "location": "us-central1" + } + ] + } + }, + "state": 1 +} \ No newline at end of file diff --git a/tests/e2e/testdata/scenarios/secretmanagerversionalias/_http03.log b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_http03.log new file mode 100644 index 0000000000..753cd936ab --- /dev/null +++ b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_http03.log @@ -0,0 +1,118 @@ +GET https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/secret-${uniqueId}?%24alt=json%3Benum-encoding%3Dint +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: name=projects%2F${projectId}%2Fsecrets%2Fsecret-${uniqueId} + +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", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}/secrets/secret-${uniqueId}", + "replication": { + "userManaged": { + "replicas": [ + { + "location": "us-central1" + } + ] + } + } +} + +--- + +PATCH https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/secret-${uniqueId}?%24alt=json%3Benum-encoding%3Dint&updateMask=versionAliases +Content-Type: application/json +User-Agent: kcc/controller-manager +x-goog-request-params: secret.name=projects%2F${projectId}%2Fsecrets%2Fsecret-${uniqueId} + +{ + "etag": "abcdef0123A=", + "name": "projects/${projectId}/secrets/secret-${uniqueId}", + "replication": { + "userManaged": { + "replicas": [ + { + "location": "us-central1" + } + ] + } + }, + "versionAliases": { + "foo": "1" + } +} + +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", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}/secrets/secret-${uniqueId}", + "replication": { + "userManaged": { + "replicas": [ + { + "location": "us-central1" + } + ] + } + }, + "versionAliases": { + "foo": "1" + } +} + +--- + +GET https://secretmanager.googleapis.com/v1/projects/${projectId}/secrets/secret-${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 + +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", + "etag": "abcdef0123A=", + "name": "projects/${projectNumber}/secrets/secret-${uniqueId}", + "replication": { + "userManaged": { + "replicas": [ + { + "location": "us-central1" + } + ] + } + }, + "versionAliases": { + "foo": "1" + } +} \ No newline at end of file diff --git a/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object00.yaml b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object00.yaml new file mode 100644 index 0000000000..9cc8d72e7f --- /dev/null +++ b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object00.yaml @@ -0,0 +1,29 @@ +apiVersion: secretmanager.cnrm.cloud.google.com/v1beta1 +kind: SecretManagerSecret +metadata: + annotations: + alpha.cnrm.cloud.google.com/reconciler: direct + cnrm.cloud.google.com/management-conflict-prevention-policy: none + cnrm.cloud.google.com/project-id: ${projectId} + finalizers: + - cnrm.cloud.google.com/finalizer + - cnrm.cloud.google.com/deletion-defender + generation: 1 + name: secret-${uniqueId} + namespace: ${projectId} +spec: + replication: + userManaged: + replicas: + - location: us-central1 +status: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: The resource is up to date + reason: UpToDate + status: "True" + type: Ready + externalRef: projects/${projectId}/secrets/secret-${uniqueId} + name: projects/${projectNumber}/secrets/secret-${uniqueId} + observedGeneration: 1 + observedState: {} diff --git a/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object01.yaml b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object01.yaml new file mode 100644 index 0000000000..9a25f8a10f --- /dev/null +++ b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object01.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +data: + secretData: SSBhbHdheXMgbG92ZWQgc3BhcnJpbmcgd2l0aCBnaWFudCBjYW5keSBzd29yZHMsIGJ1dCBJIGhhZCBubyBpZGVhIHRoYXQgd2FzIG15IHN1cGVyIHNlY3JldCBpbmZvcm1hdGlvbiE= +kind: Secret +metadata: + annotations: + cnrm.cloud.google.com/project-id: ${projectId} + name: secret-dep-${uniqueId} + namespace: ${projectId} +type: Opaque diff --git a/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object02.yaml b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object02.yaml new file mode 100644 index 0000000000..06b1fa2451 --- /dev/null +++ b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object02.yaml @@ -0,0 +1,40 @@ +apiVersion: secretmanager.cnrm.cloud.google.com/v1beta1 +kind: SecretManagerSecretVersion +metadata: + annotations: + cnrm.cloud.google.com/management-conflict-prevention-policy: none + cnrm.cloud.google.com/project-id: ${projectId} + finalizers: + - cnrm.cloud.google.com/finalizer + - cnrm.cloud.google.com/deletion-defender + generation: 1 + name: secretversion-${uniqueId} + namespace: ${projectId} +spec: + enabled: true + secretData: + valueFrom: + secretKeyRef: + key: secretData + name: secret-dep-${uniqueId} + secretRef: + name: secret-${uniqueId} +status: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: The resource is up to date + reason: UpToDate + status: "True" + type: Ready + createTime: "1970-01-01T00:00:00Z" + externalRef: projects/${projectId}/secrets/secret-${uniqueId}/versions/1 + name: projects/${projectNumber}/secrets/secret-${uniqueId}/versions/1 + observedGeneration: 1 + observedState: + createTime: "1970-01-01T00:00:00Z" + name: projects/${projectNumber}/secrets/secret-${uniqueId}/versions/1 + replicationStatus: + userManaged: + replicas: + - location: us-central1 + version: "1" diff --git a/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object03.yaml b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object03.yaml new file mode 100644 index 0000000000..7308e8d9d8 --- /dev/null +++ b/tests/e2e/testdata/scenarios/secretmanagerversionalias/_object03.yaml @@ -0,0 +1,33 @@ +apiVersion: secretmanager.cnrm.cloud.google.com/v1beta1 +kind: SecretManagerSecret +metadata: + annotations: + alpha.cnrm.cloud.google.com/reconciler: direct + cnrm.cloud.google.com/management-conflict-prevention-policy: none + cnrm.cloud.google.com/project-id: ${projectId} + finalizers: + - cnrm.cloud.google.com/finalizer + - cnrm.cloud.google.com/deletion-defender + generation: 2 + name: secret-${uniqueId} + namespace: ${projectId} +spec: + replication: + userManaged: + replicas: + - location: us-central1 + versionAliases: + foo: "1" +status: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: The resource is up to date + reason: UpToDate + status: "True" + type: Ready + externalRef: projects/${projectId}/secrets/secret-${uniqueId} + name: projects/${projectNumber}/secrets/secret-${uniqueId} + observedGeneration: 2 + observedState: + versionAliases: + foo: "1" diff --git a/tests/e2e/testdata/scenarios/secretmanagerversionalias/script.yaml b/tests/e2e/testdata/scenarios/secretmanagerversionalias/script.yaml new file mode 100644 index 0000000000..adf902598a --- /dev/null +++ b/tests/e2e/testdata/scenarios/secretmanagerversionalias/script.yaml @@ -0,0 +1,64 @@ +# 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: secretmanager.cnrm.cloud.google.com/v1beta1 +kind: SecretManagerSecret +metadata: + annotations: + cnrm.cloud.google.com/project-id: ${projectId} + alpha.cnrm.cloud.google.com/reconciler: "direct" + name: secret-${uniqueId} +spec: + replication: + userManaged: + replicas: + - location: us-central1 +--- +apiVersion: v1 +kind: Secret +metadata: + name: secret-dep-${uniqueId} +data: + secretData: SSBhbHdheXMgbG92ZWQgc3BhcnJpbmcgd2l0aCBnaWFudCBjYW5keSBzd29yZHMsIGJ1dCBJIGhhZCBubyBpZGVhIHRoYXQgd2FzIG15IHN1cGVyIHNlY3JldCBpbmZvcm1hdGlvbiE= +--- +apiVersion: secretmanager.cnrm.cloud.google.com/v1beta1 +kind: SecretManagerSecretVersion +metadata: + annotations: + cnrm.cloud.google.com/project-id: ${projectId} + name: secretversion-${uniqueId} +spec: + enabled: true + secretData: + valueFrom: + secretKeyRef: + key: secretData + name: secret-dep-${uniqueId} + secretRef: + name: secret-${uniqueId} +--- +# Verify the versionAliases has been updated +apiVersion: secretmanager.cnrm.cloud.google.com/v1beta1 +kind: SecretManagerSecret +metadata: + annotations: + cnrm.cloud.google.com/project-id: ${projectId} + alpha.cnrm.cloud.google.com/reconciler: "direct" + name: secret-${uniqueId} +spec: + replication: + userManaged: + replicas: + - location: us-central1 + versionAliases: + "foo": "1" \ No newline at end of file