fix: gate --sandbox-launcher behind gcloud beta run deploy
Merge https://github.com/google/adk-python/pull/6514 Closes #6511 PiperOrigin-RevId: 960588457
This commit is contained in:
@@ -665,6 +665,7 @@ def to_cloud_run(
|
||||
a2a: bool = False,
|
||||
trigger_sources: Optional[str] = None,
|
||||
extra_gcloud_args: Optional[tuple[str, ...]] = None,
|
||||
with_cloud_run_sandbox: bool = False,
|
||||
) -> None:
|
||||
"""Deploys an agent to Google Cloud Run.
|
||||
|
||||
@@ -701,6 +702,8 @@ def to_cloud_run(
|
||||
artifact_service_uri: The URI of the artifact service.
|
||||
memory_service_uri: The URI of the memory service.
|
||||
use_local_storage: Whether to use local .adk storage in the container.
|
||||
with_cloud_run_sandbox: Whether to enable the Cloud Run sandbox for code
|
||||
execution.
|
||||
"""
|
||||
app_name = app_name or os.path.basename(agent_folder)
|
||||
if parse(adk_version) >= parse('1.3.0') and not use_local_storage:
|
||||
@@ -780,14 +783,18 @@ def to_cloud_run(
|
||||
adk_managed_args = {'--source', '--project', '--port', '--verbosity'}
|
||||
if region:
|
||||
adk_managed_args.add('--region')
|
||||
if with_cloud_run_sandbox:
|
||||
adk_managed_args.add('--sandbox-launcher')
|
||||
|
||||
# Validate that extra gcloud args don't conflict with ADK-managed args
|
||||
_validate_gcloud_extra_args(extra_gcloud_args, adk_managed_args)
|
||||
|
||||
# Build the command with extra gcloud args
|
||||
gcloud_cmd = [
|
||||
_GCLOUD_CMD,
|
||||
'beta',
|
||||
gcloud_cmd = [_GCLOUD_CMD]
|
||||
if with_cloud_run_sandbox:
|
||||
# --sandbox-launcher is only supported on the beta release track.
|
||||
gcloud_cmd.append('beta')
|
||||
gcloud_cmd += [
|
||||
'run',
|
||||
'deploy',
|
||||
service_name,
|
||||
@@ -800,8 +807,9 @@ def to_cloud_run(
|
||||
str(port),
|
||||
'--verbosity',
|
||||
log_level.lower() if log_level else verbosity,
|
||||
'--sandbox-launcher',
|
||||
]
|
||||
if with_cloud_run_sandbox:
|
||||
gcloud_cmd.append('--sandbox-launcher')
|
||||
|
||||
# Handle labels specially - merge user labels with ADK label
|
||||
user_labels = []
|
||||
|
||||
@@ -2315,6 +2315,16 @@ def cli_api_server(
|
||||
default=False,
|
||||
help="Optional. Whether to enable A2A endpoint.",
|
||||
)
|
||||
@click.option(
|
||||
"--with_cloud_run_sandbox",
|
||||
is_flag=True,
|
||||
show_default=True,
|
||||
default=False,
|
||||
help=(
|
||||
"Optional. Whether to enable the Cloud Run sandbox for code"
|
||||
" execution. Requires the 'gcloud beta run deploy' release track."
|
||||
),
|
||||
)
|
||||
# Kept as raw str (not parsed to list) — interpolated directly into Dockerfile CMD.
|
||||
@click.option(
|
||||
"--trigger_sources",
|
||||
@@ -2359,6 +2369,7 @@ def cli_deploy_cloud_run(
|
||||
use_local_storage: bool = False,
|
||||
a2a: bool = False,
|
||||
trigger_sources: str | None = None,
|
||||
with_cloud_run_sandbox: bool = False,
|
||||
):
|
||||
"""Deploys an agent to Cloud Run.
|
||||
|
||||
@@ -2383,6 +2394,7 @@ def cli_deploy_cloud_run(
|
||||
|
||||
cli_deploy.to_cloud_run(
|
||||
agent_folder=agent,
|
||||
with_cloud_run_sandbox=with_cloud_run_sandbox,
|
||||
project=project,
|
||||
region=region,
|
||||
service_name=service_name,
|
||||
|
||||
@@ -175,7 +175,6 @@ def test_to_cloud_run_happy_path(
|
||||
|
||||
expected_gcloud_command = [
|
||||
cli_deploy._GCLOUD_CMD,
|
||||
"beta",
|
||||
"run",
|
||||
"deploy",
|
||||
"svc",
|
||||
@@ -189,7 +188,6 @@ def test_to_cloud_run_happy_path(
|
||||
"8080",
|
||||
"--verbosity",
|
||||
"info",
|
||||
"--sandbox-launcher",
|
||||
"--labels",
|
||||
"created-by=adk",
|
||||
]
|
||||
@@ -276,6 +274,85 @@ def test_to_cloud_run_cleans_temp_dir_on_failure(
|
||||
assert str(rmtree_recorder.get_last_call_args()[0]) == str(tmp_dir)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("with_cloud_run_sandbox", [True, False])
|
||||
def test_to_cloud_run_with_sandbox(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
agent_dir: AgentDirFixture,
|
||||
tmp_path: Path,
|
||||
with_cloud_run_sandbox: bool,
|
||||
) -> None:
|
||||
"""Verify --sandbox-launcher and beta release track based on with_cloud_run_sandbox."""
|
||||
src_dir = agent_dir(include_requirements=False, include_env=False)
|
||||
run_recorder = _Recorder()
|
||||
|
||||
monkeypatch.setattr(subprocess, "run", run_recorder)
|
||||
monkeypatch.setattr(shutil, "rmtree", lambda _x: None)
|
||||
|
||||
cli_deploy.to_cloud_run(
|
||||
agent_folder=str(src_dir),
|
||||
project="proj",
|
||||
region="us-central1",
|
||||
service_name="svc",
|
||||
app_name="app",
|
||||
temp_folder=str(tmp_path),
|
||||
port=8080,
|
||||
trace_to_cloud=False,
|
||||
otel_to_cloud=False,
|
||||
with_ui=False,
|
||||
log_level="info",
|
||||
verbosity="info",
|
||||
adk_version="1.0.0",
|
||||
with_cloud_run_sandbox=with_cloud_run_sandbox,
|
||||
)
|
||||
|
||||
assert len(run_recorder.calls) == 1
|
||||
gcloud_cmd = run_recorder.get_last_call_args()[0]
|
||||
|
||||
if with_cloud_run_sandbox:
|
||||
# 'beta' is inserted right after the gcloud command
|
||||
assert gcloud_cmd[1] == "beta"
|
||||
assert gcloud_cmd[2] == "run"
|
||||
assert "--sandbox-launcher" in gcloud_cmd
|
||||
else:
|
||||
assert gcloud_cmd[1] == "run"
|
||||
assert "--sandbox-launcher" not in gcloud_cmd
|
||||
assert "beta" not in gcloud_cmd
|
||||
|
||||
|
||||
def test_to_cloud_run_sandbox_conflict(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
agent_dir: AgentDirFixture,
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
"""Verify that --sandbox-launcher in extra_gcloud_args raises an error when with_cloud_run_sandbox is True."""
|
||||
src_dir = agent_dir(include_requirements=False, include_env=False)
|
||||
run_recorder = _Recorder()
|
||||
|
||||
monkeypatch.setattr(subprocess, "run", run_recorder)
|
||||
monkeypatch.setattr(shutil, "rmtree", lambda _x: None)
|
||||
|
||||
with pytest.raises(click.ClickException) as exc_info:
|
||||
cli_deploy.to_cloud_run(
|
||||
agent_folder=str(src_dir),
|
||||
project="proj",
|
||||
region="us-central1",
|
||||
service_name="svc",
|
||||
app_name="app",
|
||||
temp_folder=str(tmp_path),
|
||||
port=8080,
|
||||
trace_to_cloud=False,
|
||||
otel_to_cloud=False,
|
||||
with_ui=False,
|
||||
log_level="info",
|
||||
verbosity="info",
|
||||
adk_version="1.0.0",
|
||||
with_cloud_run_sandbox=True,
|
||||
extra_gcloud_args=("--sandbox-launcher",),
|
||||
)
|
||||
|
||||
assert "conflicts with ADK's automatic configuration" in str(exc_info.value)
|
||||
|
||||
|
||||
# Label merging tests
|
||||
@pytest.mark.parametrize(
|
||||
"extra_gcloud_args, expected_labels",
|
||||
|
||||
@@ -1090,6 +1090,29 @@ def test_cli_deploy_cloud_run_allows_empty_gcloud_args(
|
||||
assert extra_args == ()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("with_sandbox", [True, False])
|
||||
def test_cli_deploy_cloud_run_sandbox(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, with_sandbox: bool
|
||||
) -> None:
|
||||
"""Verify --with_cloud_run_sandbox parameter gets forwarded to to_cloud_run."""
|
||||
rec = _Recorder()
|
||||
monkeypatch.setattr("google.adk.cli.cli_deploy.to_cloud_run", rec)
|
||||
|
||||
agent_dir = tmp_path / "agent_sandbox"
|
||||
agent_dir.mkdir()
|
||||
runner = CliRunner()
|
||||
args = ["deploy", "cloud_run", str(agent_dir)]
|
||||
if with_sandbox:
|
||||
args.append("--with_cloud_run_sandbox")
|
||||
result = runner.invoke(
|
||||
cli_tools_click.main,
|
||||
args,
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert rec.calls, "cli_deploy.to_cloud_run must be invoked"
|
||||
assert rec.calls[0][1].get("with_cloud_run_sandbox") == with_sandbox
|
||||
|
||||
|
||||
def test_cli_deploy_cloud_run_interspersed_options(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user