Skip to content

Commit f456dc4

Browse files
authored
chore(secretmanager): Add regional samples for delayed destory (#13317)
1 parent 286361a commit f456dc4

File tree

4 files changed

+330
-0
lines changed

4 files changed

+330
-0
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2025 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
"""
16+
Command line application and sample code for creating a new secret with
17+
delayed destroy.
18+
"""
19+
20+
import argparse
21+
22+
# [START secretmanager_create_regional_secret_with_delayed_destroy]
23+
24+
# Import the Secret Manager client library.
25+
from google.cloud import secretmanager_v1
26+
from google.protobuf.duration_pb2 import Duration
27+
28+
29+
def create_regional_secret_with_delayed_destroy(
30+
project_id: str,
31+
location_id: str,
32+
secret_id: str,
33+
version_destroy_ttl: int,
34+
) -> secretmanager_v1.Secret:
35+
"""
36+
Create a new secret with the given name and version_destroy_ttl. A secret is a logical wrapper
37+
around a collection of secret versions. Secret versions hold the actual
38+
secret material.
39+
40+
Args:
41+
project_id: Parent project id
42+
location_id: Location of the secret
43+
secret_id: ID of the secret or fully qualified identifier for the secret
44+
version_destroy_ttl: Secret Version TTL after destruction request
45+
46+
Returns:
47+
Regional secret with delayed destroy
48+
"""
49+
50+
# Endpoint to call the regional secret manager sever
51+
api_endpoint = f"secretmanager.{location_id}.rep.googleapis.com"
52+
53+
# Create the Secret Manager client.
54+
client = secretmanager_v1.SecretManagerServiceClient(
55+
client_options={"api_endpoint": api_endpoint},
56+
)
57+
58+
# Build the resource name of the parent project.
59+
parent = f"projects/{project_id}/locations/{location_id}"
60+
61+
# Create the secret.
62+
response = client.create_secret(
63+
request={
64+
"parent": parent,
65+
"secret_id": secret_id,
66+
"secret": {"version_destroy_ttl": Duration(seconds=version_destroy_ttl)},
67+
}
68+
)
69+
70+
# Print the new secret name.
71+
print(f"Created secret: {response.name}")
72+
73+
return response
74+
75+
# [END secretmanager_create_regional_secret_with_delayed_destroy]
76+
77+
78+
if __name__ == "__main__":
79+
parser = argparse.ArgumentParser(
80+
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
81+
)
82+
parser.add_argument("project_id", help="id of the GCP project")
83+
parser.add_argument(
84+
"location_id", help="id of the location where secret is to be created"
85+
)
86+
parser.add_argument("secret_id", help="id of the secret to create")
87+
parser.add_argument(
88+
"version_destroy_ttl", help="version_destroy_ttl you want to add (in seconds)"
89+
)
90+
args = parser.parse_args()
91+
92+
create_regional_secret_with_delayed_destroy(
93+
args.project_id, args.location_id, args.secret_id, int(args.version_destroy_ttl)
94+
)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2025 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
16+
import argparse
17+
18+
# [START secretmanager_disable_regional_secret_delayed_destroy]
19+
20+
# Import the Secret Manager client library.
21+
from google.cloud import secretmanager_v1
22+
23+
24+
def disable_regional_secret_delayed_destroy(
25+
project_id: str, location_id: str, secret_id: str
26+
) -> secretmanager_v1.Secret:
27+
"""
28+
Disable delayed destroy on an existing secret with a version destroy ttl.
29+
30+
Args:
31+
project_id: Parent project id
32+
location_id: Location of the secret
33+
secret_id: ID of the secret or fully qualified identifier for the secret
34+
35+
Returns:
36+
Regional secret with disabled delayed destroy
37+
"""
38+
39+
# Endpoint to call the regional secret manager sever
40+
api_endpoint = f"secretmanager.{location_id}.rep.googleapis.com"
41+
42+
# Create the Secret Manager client.
43+
client = secretmanager_v1.SecretManagerServiceClient(
44+
client_options={"api_endpoint": api_endpoint},
45+
)
46+
47+
# Build the resource name.
48+
name = f"projects/{project_id}/locations/{location_id}/secrets/{secret_id}"
49+
50+
# Disable delayed destroy on secret
51+
secret = {"name": name}
52+
update_mask = {"paths": ["version_destroy_ttl"]}
53+
response = client.update_secret(
54+
request={"secret": secret, "update_mask": update_mask}
55+
)
56+
57+
# Print the new secret name.
58+
print(f"Disabled delayed destroy on secret: {response.name}")
59+
60+
return response
61+
62+
# [END secretmanager_disable_regional_secret_delayed_destroy]
63+
64+
65+
if __name__ == "__main__":
66+
parser = argparse.ArgumentParser(
67+
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
68+
)
69+
parser.add_argument("project_id", help="id of the GCP project")
70+
parser.add_argument(
71+
"location_id", help="id of the location where secret is to be created"
72+
)
73+
parser.add_argument("secret_id", help="id of the secret to act on")
74+
args = parser.parse_args()
75+
76+
disable_regional_secret_delayed_destroy(
77+
args.project_id, args.location_id, args.secret_id
78+
)

secretmanager/snippets/regional_samples/snippets_test.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,29 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313

14+
from datetime import timedelta
1415
import os
1516
import time
1617
from typing import Iterator, Tuple, Union
1718
import uuid
1819

1920
from google.api_core import exceptions, retry
2021
from google.cloud import secretmanager_v1
22+
from google.protobuf.duration_pb2 import Duration
2123
import pytest
2224

2325
from regional_samples import access_regional_secret_version
2426
from regional_samples import add_regional_secret_version
2527
from regional_samples import create_regional_secret
2628
from regional_samples import create_regional_secret_with_annotations
29+
from regional_samples import create_regional_secret_with_delayed_destroy
2730
from regional_samples import create_regional_secret_with_labels
2831
from regional_samples import delete_regional_secret
2932
from regional_samples import delete_regional_secret_label
3033
from regional_samples import delete_regional_secret_with_etag
3134
from regional_samples import destroy_regional_secret_version
3235
from regional_samples import destroy_regional_secret_version_with_etag
36+
from regional_samples import disable_regional_secret_delayed_destroy
3337
from regional_samples import disable_regional_secret_version
3438
from regional_samples import disable_regional_secret_version_with_etag
3539
from regional_samples import edit_regional_secret_annotations
@@ -46,6 +50,7 @@
4650
from regional_samples import list_regional_secrets_with_filter
4751
from regional_samples import regional_quickstart
4852
from regional_samples import update_regional_secret
53+
from regional_samples import update_regional_secret_with_delayed_destroy
4954
from regional_samples import update_regional_secret_with_etag
5055
from regional_samples import view_regional_secret_annotations
5156
from regional_samples import view_regional_secret_labels
@@ -99,6 +104,11 @@ def annotation_value() -> str:
99104
return "annotationvalue"
100105

101106

107+
@pytest.fixture()
108+
def version_destroy_ttl() -> int:
109+
return 604800 # 7 days in seconds
110+
111+
102112
@retry.Retry()
103113
def retry_client_create_regional_secret(
104114
regional_client: secretmanager_v1.SecretManagerServiceClient,
@@ -201,6 +211,33 @@ def regional_secret(
201211
yield secret_id, regional_secret.etag
202212

203213

214+
@pytest.fixture()
215+
def regional_secret_with_delayed_destroy(
216+
regional_client: secretmanager_v1.SecretManagerServiceClient,
217+
project_id: str,
218+
location_id: str,
219+
secret_id: str,
220+
version_destroy_ttl: int,
221+
) -> Iterator[str]:
222+
print("creating secret with given secret id.")
223+
224+
parent = f"projects/{project_id}/locations/{location_id}"
225+
time.sleep(5)
226+
retry_client_create_regional_secret(
227+
regional_client,
228+
request={
229+
"parent": parent,
230+
"secret_id": secret_id,
231+
"secret": {
232+
"version_destroy_ttl": Duration(seconds=version_destroy_ttl),
233+
},
234+
},
235+
)
236+
print("debug")
237+
238+
yield secret_id
239+
240+
204241
def test_regional_quickstart(project_id: str, location_id: str, secret_id: str) -> None:
205242
regional_quickstart.regional_quickstart(project_id, location_id, secret_id)
206243

@@ -259,6 +296,18 @@ def test_create_regional_secret_with_annotations(
259296
assert secret_id in secret.name
260297

261298

299+
def test_create_regional_secret_with_delayed_destroy(
300+
regional_client: secretmanager_v1.SecretManagerServiceClient,
301+
project_id: str,
302+
location_id: str,
303+
secret_id: str,
304+
version_destroy_ttl: int,
305+
) -> None:
306+
secret = create_regional_secret_with_delayed_destroy.create_regional_secret_with_delayed_destroy(project_id, location_id, secret_id, version_destroy_ttl)
307+
assert secret_id in secret.name
308+
assert timedelta(seconds=version_destroy_ttl) == secret.version_destroy_ttl
309+
310+
262311
def test_create_regional_secret_with_label(
263312
regional_client: secretmanager_v1.SecretManagerServiceClient,
264313
project_id: str,
@@ -336,6 +385,17 @@ def test_destroy_regional_secret_version_with_etag(
336385
assert version.destroy_time
337386

338387

388+
def test_disable_regional_secret_delayed_destroy(
389+
regional_client: secretmanager_v1.SecretManagerServiceClient,
390+
regional_secret_with_delayed_destroy: str,
391+
project_id: str,
392+
location_id: str,
393+
) -> None:
394+
secret_id = regional_secret_with_delayed_destroy
395+
updated_secret = disable_regional_secret_delayed_destroy.disable_regional_secret_delayed_destroy(project_id, location_id, secret_id)
396+
assert updated_secret.version_destroy_ttl == timedelta(0)
397+
398+
339399
def test_enable_disable_regional_secret_version(
340400
regional_client: secretmanager_v1.SecretManagerServiceClient,
341401
regional_secret_version: Tuple[str, str, str],
@@ -612,6 +672,18 @@ def test_update_regional_secret(
612672
assert updated_regional_secret.labels["secretmanager"] == "rocks"
613673

614674

675+
def test_update_regional_secret_with_delayed_destroy(
676+
regional_secret_with_delayed_destroy: str,
677+
project_id: str,
678+
location_id: str,
679+
version_destroy_ttl: int
680+
) -> None:
681+
secret_id = regional_secret_with_delayed_destroy
682+
updated_version_delayed_destroy = 118400
683+
updated_secret = update_regional_secret_with_delayed_destroy.update_regional_secret_with_delayed_destroy(project_id, location_id, secret_id, updated_version_delayed_destroy)
684+
assert updated_secret.version_destroy_ttl == timedelta(seconds=updated_version_delayed_destroy)
685+
686+
615687
def test_view_regional_secret_labels(
616688
capsys: pytest.LogCaptureFixture,
617689
project_id: str,

0 commit comments

Comments
 (0)