diff --git a/secretmanager/create_secret_with_delayed_destroy.go b/secretmanager/create_secret_with_delayed_destroy.go new file mode 100644 index 0000000000..86b621a29e --- /dev/null +++ b/secretmanager/create_secret_with_delayed_destroy.go @@ -0,0 +1,68 @@ +// Copyright 2025 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 +// +// https://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 secretmanager + +// [START secretmanager_create_secret_with_delayed_destroy] +import ( + "context" + "fmt" + "io" + "time" + + secretmanager "cloud.google.com/go/secretmanager/apiv1" + "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb" + "google.golang.org/protobuf/types/known/durationpb" +) + +// createSecretWithDelayedDestroy creates a new secret with the given name +// and version destroy ttl. A secret is a logical wrapper around a collection +// of secret versions. Secret versions hold the actual secret material. +func createSecretWithDelayedDestroy(w io.Writer, parent, secretID string, versionDestroyTtl int) error { + // parent := "projects/my-project" + // secretID := "my-secret" + // versionDestroyTtl := 86400 + + // Create the client. + ctx := context.Background() + client, err := secretmanager.NewClient(ctx) + if err != nil { + return fmt.Errorf("failed to create secretmanager client: %w", err) + } + defer client.Close() + + // Build the request. + req := &secretmanagerpb.CreateSecretRequest{ + Parent: parent, + SecretId: secretID, + Secret: &secretmanagerpb.Secret{ + Replication: &secretmanagerpb.Replication{ + Replication: &secretmanagerpb.Replication_Automatic_{ + Automatic: &secretmanagerpb.Replication_Automatic{}, + }, + }, + VersionDestroyTtl: durationpb.New(time.Duration(versionDestroyTtl) * time.Second), + }, + } + + // Call the API. + result, err := client.CreateSecret(ctx, req) + if err != nil { + return fmt.Errorf("failed to create secret: %w", err) + } + fmt.Fprintf(w, "Created secret with version destroy ttl: %s\n", result.Name) + return nil +} + +// [END secretmanager_create_secret_with_delayed_destroy] diff --git a/secretmanager/disable_secret_delayed_destroy.go b/secretmanager/disable_secret_delayed_destroy.go new file mode 100644 index 0000000000..4dcede0584 --- /dev/null +++ b/secretmanager/disable_secret_delayed_destroy.go @@ -0,0 +1,61 @@ +// Copyright 2025 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 +// +// https://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 secretmanager + +// [START secretmanager_disable_secret_delayed_destroy] +import ( + "context" + "fmt" + "io" + + secretmanager "cloud.google.com/go/secretmanager/apiv1" + "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb" + "google.golang.org/genproto/protobuf/field_mask" +) + +// disableSecretDelayedDestroy disables the delayed destroy configuration on an +// existing secret. When disabled, secret versions are destroyed immediately +// upon deletion. +func disableSecretDelayedDestroy(w io.Writer, name string) error { + // name := "projects/my-project/secrets/my-secret" + + // Create the client. + ctx := context.Background() + client, err := secretmanager.NewClient(ctx) + if err != nil { + return fmt.Errorf("failed to create secretmanager client: %w", err) + } + defer client.Close() + + // Build the request. + req := &secretmanagerpb.UpdateSecretRequest{ + Secret: &secretmanagerpb.Secret{ + Name: name, + }, + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"version_destroy_ttl"}, + }, + } + + // Call the API. + result, err := client.UpdateSecret(ctx, req) + if err != nil { + return fmt.Errorf("failed to update secret: %w", err) + } + fmt.Fprintf(w, "Updated secret: %s\n", result.Name) + return nil +} + +// [END secretmanager_disable_secret_delayed_destroy] diff --git a/secretmanager/regional_samples/create_regional_secret_with_delayed_destroy.go b/secretmanager/regional_samples/create_regional_secret_with_delayed_destroy.go new file mode 100644 index 0000000000..03fd56a169 --- /dev/null +++ b/secretmanager/regional_samples/create_regional_secret_with_delayed_destroy.go @@ -0,0 +1,68 @@ +// Copyright 2025 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 +// +// https://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 regional_secretmanager + +// [START secretmanager_create_regional_secret_with_delayed_destroy] +import ( + "context" + "fmt" + "io" + "time" + + secretmanager "cloud.google.com/go/secretmanager/apiv1" + "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb" + "google.golang.org/api/option" + "google.golang.org/protobuf/types/known/durationpb" +) + +// createRegionalSecretWithDelayedDestroy creates a new secret with the given name +// and version destroy ttl. A secret is a logical wrapper around a collection +// of secret versions. Secret versions hold the actual secret material. +func createRegionalSecretWithDelayedDestroy(w io.Writer, projectID, locationID, secretID string, versionDestroyTtl int) error { + // projectID := "my-project" + // locationID := "us-central1" + // secretID := "my-secret" + // versionDestroyTtl := 86400 + + // Create the client. + ctx := context.Background() + endpoint := fmt.Sprintf("secretmanager.%s.rep.googleapis.com:443", locationID) + client, err := secretmanager.NewClient(ctx, option.WithEndpoint(endpoint)) + if err != nil { + return fmt.Errorf("failed to create secretmanager client: %w", err) + } + defer client.Close() + + parent := fmt.Sprintf("projects/%s/locations/%s", projectID, locationID) + + // Build the request. + req := &secretmanagerpb.CreateSecretRequest{ + Parent: parent, + SecretId: secretID, + Secret: &secretmanagerpb.Secret{ + VersionDestroyTtl: durationpb.New(time.Duration(versionDestroyTtl) * time.Second), + }, + } + + // Call the API. + result, err := client.CreateSecret(ctx, req) + if err != nil { + return fmt.Errorf("failed to create secret: %w", err) + } + fmt.Fprintf(w, "Created secret with version destroy ttl: %s\n", result.Name) + return nil +} + +// [END secretmanager_create_regional_secret_with_delayed_destroy] diff --git a/secretmanager/regional_samples/disable_regional_secret_delayed_destroy.go b/secretmanager/regional_samples/disable_regional_secret_delayed_destroy.go new file mode 100644 index 0000000000..e61bff3c4a --- /dev/null +++ b/secretmanager/regional_samples/disable_regional_secret_delayed_destroy.go @@ -0,0 +1,67 @@ +// Copyright 2025 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 +// +// https://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 regional_secretmanager + +// [START secretmanager_disable_regional_secret_delayed_destroy] +import ( + "context" + "fmt" + "io" + + secretmanager "cloud.google.com/go/secretmanager/apiv1" + "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb" + "google.golang.org/api/option" + "google.golang.org/genproto/protobuf/field_mask" +) + +// disableRegionalSecretDelayedDestroy disables the delayed destroy configuration on an +// existing regional secret. When disabled, secret versions are destroyed +// immediately upon deletion. +func disableRegionalSecretDelayedDestroy(w io.Writer, projectID, locationID, secretID string) error { + // projectID := "my-project" + // locationID := "us-central1" + // secretID := "my-secret" + + // Create the client. + ctx := context.Background() + endpoint := fmt.Sprintf("secretmanager.%s.rep.googleapis.com:443", locationID) + client, err := secretmanager.NewClient(ctx, option.WithEndpoint(endpoint)) + if err != nil { + return fmt.Errorf("failed to create secretmanager client: %w", err) + } + defer client.Close() + + name := fmt.Sprintf("projects/%s/locations/%s/secrets/%s", projectID, locationID, secretID) + + // Build the request. + req := &secretmanagerpb.UpdateSecretRequest{ + Secret: &secretmanagerpb.Secret{ + Name: name, + }, + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"version_destroy_ttl"}, + }, + } + + // Call the API. + result, err := client.UpdateSecret(ctx, req) + if err != nil { + return fmt.Errorf("failed to update secret: %w", err) + } + fmt.Fprintf(w, "Updated secret: %s\n", result.Name) + return nil +} + +// [END secretmanager_disable_regional_secret_delayed_destroy] diff --git a/secretmanager/regional_samples/regional_secretmanager_test.go b/secretmanager/regional_samples/regional_secretmanager_test.go index 0f41e74ed7..b624cb12d4 100644 --- a/secretmanager/regional_samples/regional_secretmanager_test.go +++ b/secretmanager/regional_samples/regional_secretmanager_test.go @@ -33,9 +33,7 @@ import ( "github.com/gofrs/uuid" "google.golang.org/api/option" "google.golang.org/grpc/codes" - grpccodes "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - grpcstatus "google.golang.org/grpc/status" ) func testLocation(tb testing.TB) string { @@ -110,7 +108,7 @@ func testCleanupRegionalSecret(tb testing.TB, name string) { if err := client.DeleteSecret(ctx, &secretmanagerpb.DeleteSecretRequest{ Name: name, }); err != nil { - if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { + if terr, ok := status.FromError(err); !ok || terr.Code() != codes.NotFound { tb.Fatalf("testCleanupSecret: failed to delete regional secret: %v", err) } } @@ -132,6 +130,20 @@ func TestCreateRegionalSecretWithLabels(t *testing.T) { } } +func testGetRegionalSecret(tb testing.TB, name string) *secretmanagerpb.Secret { + tb.Helper() + + client, ctx := testRegionalClient(tb) + + secret, err := client.GetSecret(ctx, &secretmanagerpb.GetSecretRequest{ + Name: name, + }) + if err != nil { + tb.Fatalf("testGetRegionalSecret: failed to get secret: %v", err) + } + return secret +} + func TestDeleteRegionalSecretLabel(t *testing.T) { tc := testutil.SystemTest(t) @@ -481,3 +493,74 @@ func TestCreateRegionalSecretWithTags(t *testing.T) { t.Errorf("createRegionalSecretWithTags: expected %q to contain %q", got, want) } } + +func TestCreateRegionalSecretWithDelayedDestroy(t *testing.T) { + tc := testutil.SystemTest(t) + + secretID := testName(t) + locationID := testLocation(t) + + var b bytes.Buffer + if err := createRegionalSecretWithDelayedDestroy(&b, tc.ProjectID, locationID, secretID, 86400); err != nil { + t.Fatal(err) + } + + name := fmt.Sprintf("projects/%s/locations/%s/secrets/%s", tc.ProjectID, locationID, secretID) + defer testCleanupRegionalSecret(t, name) + + if got, want := b.String(), "Created secret with version destroy ttl:"; !strings.Contains(got, want) { + t.Errorf("createRegionalSecretWithDelayedDestroy: expected %q to contain %q", got, want) + } + + secret := testGetRegionalSecret(t, name) + + if got, want := secret.VersionDestroyTtl.Seconds, int64(86400); got != want { + t.Errorf("createRegionalSecretWithDelayedDestroy: expected %v to be %v", got, want) + } +} + +func TestUpdateRegionalSecretWithDelayedDestroy(t *testing.T) { + tc := testutil.SystemTest(t) + + secret, secretID := testRegionalSecret(t, tc.ProjectID) + locationID := testLocation(t) + + var b bytes.Buffer + if err := updateRegionalSecretWithDelayedDestroy(&b, tc.ProjectID, locationID, secretID, 86400); err != nil { + t.Fatal(err) + } + defer testCleanupRegionalSecret(t, secret.Name) + + if got, want := b.String(), "Updated secret:"; !strings.Contains(got, want) { + t.Errorf("updateRegionalSecretWithDelayedDestroy: expected %q to contain %q", got, want) + } + + updatedSecret := testGetRegionalSecret(t, secret.Name) + + if got, want := updatedSecret.VersionDestroyTtl.Seconds, int64(86400); got != want { + t.Errorf("updateRegionalSecretWithDelayedDestroy: expected %v to be %v", got, want) + } +} + +func TestDisableRegionalSecretDelayedDestroy(t *testing.T) { + tc := testutil.SystemTest(t) + + secret, secretID := testRegionalSecret(t, tc.ProjectID) + locationID := testLocation(t) + + var b bytes.Buffer + if err := disableRegionalSecretDelayedDestroy(&b, tc.ProjectID, locationID, secretID); err != nil { + t.Fatal(err) + } + defer testCleanupRegionalSecret(t, secret.Name) + + if got, want := b.String(), "Updated secret:"; !strings.Contains(got, want) { + t.Errorf("disableRegionalSecretDelayedDestroy: expected %q to contain %q", got, want) + } + + updatedSecret := testGetRegionalSecret(t, secret.Name) + + if updatedSecret.VersionDestroyTtl != nil { + t.Errorf("disableRegionalSecretDelayedDestroy: expected VersionDestroyTtl to be nil, got non-nil") + } +} diff --git a/secretmanager/regional_samples/update_regional_secret_with_delayed_destroy.go b/secretmanager/regional_samples/update_regional_secret_with_delayed_destroy.go new file mode 100644 index 0000000000..9edc59779e --- /dev/null +++ b/secretmanager/regional_samples/update_regional_secret_with_delayed_destroy.go @@ -0,0 +1,70 @@ +// Copyright 2025 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 +// +// https://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 regional_secretmanager + +// [START secretmanager_update_regional_secret_with_delayed_destroy] +import ( + "context" + "fmt" + "io" + "time" + + secretmanager "cloud.google.com/go/secretmanager/apiv1" + "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb" + "google.golang.org/api/option" + "google.golang.org/genproto/protobuf/field_mask" + "google.golang.org/protobuf/types/known/durationpb" +) + +// updateRegionalSecretWithDelayedDestroy updates the version destroy TTL on an +// existing regional secret. +func updateRegionalSecretWithDelayedDestroy(w io.Writer, projectID, locationID, secretID string, versionDestroyTtl int) error { + // projectID := "my-project" + // locationID := "us-central1" + // secretID := "my-secret" + // versionDestroyTtl := 86400 + + // Create the client. + ctx := context.Background() + endpoint := fmt.Sprintf("secretmanager.%s.rep.googleapis.com:443", locationID) + client, err := secretmanager.NewClient(ctx, option.WithEndpoint(endpoint)) + if err != nil { + return fmt.Errorf("failed to create secretmanager client: %w", err) + } + defer client.Close() + + name := fmt.Sprintf("projects/%s/locations/%s/secrets/%s", projectID, locationID, secretID) + + // Build the request. + req := &secretmanagerpb.UpdateSecretRequest{ + Secret: &secretmanagerpb.Secret{ + Name: name, + VersionDestroyTtl: durationpb.New(time.Duration(versionDestroyTtl) * time.Second), + }, + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"version_destroy_ttl"}, + }, + } + + // Call the API. + result, err := client.UpdateSecret(ctx, req) + if err != nil { + return fmt.Errorf("failed to update secret: %w", err) + } + fmt.Fprintf(w, "Updated secret: %s\n", result.Name) + return nil +} + +// [END secretmanager_update_regional_secret_with_delayed_destroy] diff --git a/secretmanager/secretmanager_test.go b/secretmanager/secretmanager_test.go index 3477b04f94..ecf2cf1592 100644 --- a/secretmanager/secretmanager_test.go +++ b/secretmanager/secretmanager_test.go @@ -34,9 +34,7 @@ import ( "github.com/gofrs/uuid" "google.golang.org/api/option" "google.golang.org/grpc/codes" - grpccodes "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - grpcstatus "google.golang.org/grpc/status" ) func testLocation(tb testing.TB) string { @@ -202,6 +200,20 @@ func testRegionalSecretVersion(tb testing.TB, parent string, payload []byte) *se return version } +func testGetSecret(tb testing.TB, name string) *secretmanagerpb.Secret { + tb.Helper() + + client, ctx := testClient(tb) + + secret, err := client.GetSecret(ctx, &secretmanagerpb.GetSecretRequest{ + Name: name, + }) + if err != nil { + tb.Fatalf("testGetSecret: failed to get secret: %v", err) + } + return secret +} + func testCleanupSecret(tb testing.TB, name string) { tb.Helper() @@ -210,7 +222,7 @@ func testCleanupSecret(tb testing.TB, name string) { if err := client.DeleteSecret(ctx, &secretmanagerpb.DeleteSecretRequest{ Name: name, }); err != nil { - if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { + if terr, ok := status.FromError(err); !ok || terr.Code() != codes.NotFound { tb.Fatalf("testCleanupSecret: failed to delete secret: %v", err) } } @@ -224,7 +236,7 @@ func testCleanupRegionalSecret(tb testing.TB, name string) { if err := client.DeleteSecret(ctx, &secretmanagerpb.DeleteSecretRequest{ Name: name, }); err != nil { - if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { + if terr, ok := status.FromError(err); !ok || terr.Code() != codes.NotFound { tb.Fatalf("testCleanupSecret: failed to delete regional secret: %v", err) } } @@ -456,7 +468,7 @@ func TestDeleteSecret(t *testing.T) { _, err := client.GetSecret(ctx, &secretmanagerpb.GetSecretRequest{ Name: secret.Name, }) - if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { + if terr, ok := status.FromError(err); !ok || terr.Code() != codes.NotFound { t.Errorf("deleteSecret: expected %v to be not found", err) } } @@ -501,7 +513,7 @@ func TestDeleteRegionalSecret(t *testing.T) { _, err := client.GetSecret(ctx, &secretmanagerpb.GetSecretRequest{ Name: secret.Name, }) - if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { + if terr, ok := status.FromError(err); !ok || terr.Code() != codes.NotFound { t.Errorf("deleteRegionalSecret: expected %v to be not found", err) } @@ -521,7 +533,7 @@ func TestDeleteSecretWithEtag(t *testing.T) { _, err := client.GetSecret(ctx, &secretmanagerpb.GetSecretRequest{ Name: secret.Name, }) - if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { + if terr, ok := status.FromError(err); !ok || terr.Code() != codes.NotFound { t.Errorf("deleteSecret: expected %v to be not found", err) } } @@ -542,7 +554,7 @@ func TestDeleteRegionalSecretWithEtag(t *testing.T) { _, err := client.GetSecret(ctx, &secretmanagerpb.GetSecretRequest{ Name: secret.Name, }) - if terr, ok := grpcstatus.FromError(err); !ok || terr.Code() != grpccodes.NotFound { + if terr, ok := status.FromError(err); !ok || terr.Code() != codes.NotFound { t.Errorf("deleteRegionalSecret: expected %v to be not found", err) } } @@ -1675,3 +1687,74 @@ func TestCreateSecretWithTags(t *testing.T) { } } + +func TestCreateSecretWithDelayedDestroy(t *testing.T) { + tc := testutil.SystemTest(t) + + secretID := testName(t) + parent := fmt.Sprintf("projects/%s", tc.ProjectID) + + var b bytes.Buffer + if err := createSecretWithDelayedDestroy(&b, parent, secretID, 86400); err != nil { + t.Fatal(err) + } + + name := fmt.Sprintf("projects/%s/secrets/%s", tc.ProjectID, secretID) + defer testCleanupSecret(t, name) + + if got, want := b.String(), "Created secret with version destroy ttl:"; !strings.Contains(got, want) { + t.Errorf("createSecretWithDelayedDestroy: expected %q to contain %q", got, want) + } + + secret := testGetSecret(t, name) + + if got, want := secret.VersionDestroyTtl.Seconds, int64(86400); got != want { + t.Errorf("createSecretWithDelayedDestroy: expected %v to be %v", got, want) + } +} + +func TestUpdateSecretWithDelayedDestroy(t *testing.T) { + tc := testutil.SystemTest(t) + + secret := testSecret(t, tc.ProjectID) + secretID := secret.Name + + var b bytes.Buffer + if err := updateSecretWithDelayedDestroy(&b, secretID, 86400); err != nil { + t.Fatal(err) + } + defer testCleanupSecret(t, secretID) + + if got, want := b.String(), "Updated secret:"; !strings.Contains(got, want) { + t.Errorf("updateSecretWithDelayedDestroy: expected %q to contain %q", got, want) + } + + updatedSecret := testGetSecret(t, secretID) + + if got, want := updatedSecret.VersionDestroyTtl.Seconds, int64(86400); got != want { + t.Errorf("updateSecretWithDelayedDestroy: expected %v to be %v", got, want) + } +} + +func TestDisableSecretDelayedDestroy(t *testing.T) { + tc := testutil.SystemTest(t) + + secret := testSecret(t, tc.ProjectID) + secretID := secret.Name + + var b bytes.Buffer + if err := disableSecretDelayedDestroy(&b, secretID); err != nil { + t.Fatal(err) + } + defer testCleanupSecret(t, secretID) + + if got, want := b.String(), "Updated secret:"; !strings.Contains(got, want) { + t.Errorf("disableSecretDelayedDestroy: expected %q to contain %q", got, want) + } + + updatedSecret := testGetSecret(t, secretID) + + if updatedSecret.VersionDestroyTtl != nil { + t.Errorf("disableSecretDelayedDestroy: expected VersionDestroyTtl to be nil, got non-nil") + } +} diff --git a/secretmanager/update_secret_with_delayed_destroy.go b/secretmanager/update_secret_with_delayed_destroy.go new file mode 100644 index 0000000000..44c1726084 --- /dev/null +++ b/secretmanager/update_secret_with_delayed_destroy.go @@ -0,0 +1,64 @@ +// Copyright 2025 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 +// +// https://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 secretmanager + +// [START secretmanager_update_secret_with_delayed_destroy] +import ( + "context" + "fmt" + "io" + "time" + + secretmanager "cloud.google.com/go/secretmanager/apiv1" + "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb" + "google.golang.org/genproto/protobuf/field_mask" + "google.golang.org/protobuf/types/known/durationpb" +) + +// updateSecretWithDelayedDestroy updates the version destroy TTL on an +// existing secret. +func updateSecretWithDelayedDestroy(w io.Writer, name string, versionDestroyTtl int) error { + // name := "projects/my-project/secrets/my-secret" + // versionDestroyTtl := 86400 + + // Create the client. + ctx := context.Background() + client, err := secretmanager.NewClient(ctx) + if err != nil { + return fmt.Errorf("failed to create secretmanager client: %w", err) + } + defer client.Close() + + // Build the request. + req := &secretmanagerpb.UpdateSecretRequest{ + Secret: &secretmanagerpb.Secret{ + Name: name, + VersionDestroyTtl: durationpb.New(time.Duration(versionDestroyTtl) * time.Second), + }, + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"version_destroy_ttl"}, + }, + } + + // Call the API. + result, err := client.UpdateSecret(ctx, req) + if err != nil { + return fmt.Errorf("failed to update secret: %w", err) + } + fmt.Fprintf(w, "Updated secret: %s\n", result.Name) + return nil +} + +// [END secretmanager_update_secret_with_delayed_destroy]