Skip to content

Commit 142f61b

Browse files
authored
feat: add --set-secrets option to deploy command (GoogleCloudPlatform#734)
* feat: add --set-secrets option to deploy command Add support for Secret Manager secrets in Agent Engine deployments: - New --set-secrets option accepts ENV_VAR=SECRET_ID or ENV_VAR=SECRET_ID:VERSION - Secrets displayed as [secret:ID:VERSION] in deployment logs - Refactored parse_secrets to reuse parse_key_value_pairs - Added format_env_value helper for consistent display * fix: address code review feedback for secret parsing - Check for colon existence before using rpartition in parse_secrets - Add version key check in format_env_value to prevent KeyError - Add type ignore comment for env_vars.update(secrets)
1 parent 3734bd5 commit 142f61b

File tree

3 files changed

+1407
-3
lines changed

3 files changed

+1407
-3
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
c# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
steps:
16+
17+
- name: "gcr.io/cloud-builders/gcloud-slim"
18+
id: trigger-deployment
19+
entrypoint: gcloud
20+
args:
21+
- "run"
22+
- "deploy"
23+
- "{{cookiecutter.project_name}}"
24+
- "--image"
25+
- "$_REGION-docker.pkg.dev/$PROJECT_ID/$_ARTIFACT_REGISTRY_REPO_NAME/$_CONTAINER_NAME"
26+
- "--region"
27+
- "$_REGION"
28+
- "--project"
29+
- $_PROD_PROJECT_ID
30+
31+
substitutions:
32+
_PROD_PROJECT_ID: YOUR_PROD_PROJECT_ID
33+
_REGION: us-central1
34+
35+
logsBucket: gs://${PROJECT_ID}-{{cookiecutter.project_name}}-logs/build-logs
36+
options:
37+
substitutionOption: ALLOW_LOOSE
38+
defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET

agent_starter_pack/deployment_targets/agent_engine/python/{{cookiecutter.agent_directory}}/app_utils/deploy.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,26 @@ def parse_key_value_pairs(kv_string: str | None) -> dict[str, str]:
7979
return result
8080

8181

82+
def parse_secrets(secrets_string: str | None) -> dict[str, dict[str, str]]:
83+
"""Parse secrets from ENV_VAR=SECRET_ID or ENV_VAR=SECRET_ID:VERSION format."""
84+
raw = parse_key_value_pairs(secrets_string)
85+
result: dict[str, dict[str, str]] = {}
86+
for key, spec in raw.items():
87+
if ":" not in spec:
88+
secret_id, version = spec, "latest"
89+
else:
90+
secret_id, _, version = spec.rpartition(":")
91+
result[key] = {"secret": secret_id, "version": version}
92+
return result
93+
94+
95+
def format_env_value(value: Any) -> str:
96+
"""Format an env var value for display, masking secrets."""
97+
if isinstance(value, dict) and "secret" in value and "version" in value:
98+
return f"[secret:{value['secret']}:{value['version']}]"
99+
return str(value)
100+
101+
82102
def write_deployment_metadata(
83103
remote_agent: Any,
84104
metadata_file: str = "deployment_metadata.json",
@@ -219,6 +239,11 @@ def setup_agent_identity(client: Any, project: str, display_name: str) -> Any:
219239
default=None,
220240
help="Comma-separated list of environment variables in KEY=VALUE format",
221241
)
242+
@click.option(
243+
"--set-secrets",
244+
default=None,
245+
help="Comma-separated secrets: ENV_VAR=SECRET_ID or ENV_VAR=SECRET_ID:VERSION",
246+
)
222247
@click.option(
223248
"--labels",
224249
default=None,
@@ -279,6 +304,7 @@ def deploy_agent_engine_app(
279304
entrypoint_object: str,
280305
requirements_file: str,
281306
set_env_vars: str | None,
307+
set_secrets: str | None,
282308
labels: str | None,
283309
service_account: str | None,
284310
min_instances: int,
@@ -294,10 +320,14 @@ def deploy_agent_engine_app(
294320
logging.basicConfig(level=logging.INFO)
295321
logging.getLogger("httpx").setLevel(logging.WARNING)
296322

297-
# Parse CLI environment variables and labels
298-
env_vars = parse_key_value_pairs(set_env_vars)
323+
# Parse CLI environment variables, secrets, and labels
324+
env_vars: dict[str, Any] = parse_key_value_pairs(set_env_vars)
325+
secrets = parse_secrets(set_secrets)
299326
labels_dict = parse_key_value_pairs(labels)
300327

328+
# Merge secrets into env_vars (secrets override plain env vars)
329+
env_vars.update(secrets) # type: ignore[arg-type]
330+
301331
# Set deployment-specific environment variables
302332
env_vars["GOOGLE_CLOUD_REGION"] = location
303333
env_vars["NUM_WORKERS"] = str(num_workers)
@@ -338,7 +368,7 @@ def deploy_agent_engine_app(
338368
if env_vars:
339369
click.echo("\n🌍 Environment Variables:")
340370
for key, value in sorted(env_vars.items()):
341-
click.echo(f" {key}: {value}")
371+
click.echo(f" {key}: {format_env_value(value)}")
342372

343373
source_packages_list = list(source_packages)
344374

0 commit comments

Comments
 (0)