diff --git a/libs/cli/langgraph_cli/deploy.py b/libs/cli/langgraph_cli/deploy.py index f04e9b31a..7507482c1 100644 --- a/libs/cli/langgraph_cli/deploy.py +++ b/libs/cli/langgraph_cli/deploy.py @@ -2518,6 +2518,13 @@ def deploy_listeners() -> None: @OPT_HOST_API_KEY @OPT_HOST_URL +@click.option( + "--json", + "json_output", + is_flag=True, + default=False, + help="Emit the listeners as a JSON array instead of a table.", +) @deploy_listeners.command( "list", help=( @@ -2526,11 +2533,16 @@ def deploy_listeners() -> None: "--listener-id ` to deploy through it." ), ) -def deploy_listeners_list(api_key: str | None, host_url: str | None) -> None: +def deploy_listeners_list( + api_key: str | None, host_url: str | None, json_output: bool +) -> None: client = _create_host_backend_client(host_url, api_key) listeners = _call_host_backend_with_optional_tenant( client, lambda c: c.list_listeners() ) + if json_output: + click.echo(json_mod.dumps(listeners)) + return if not listeners: click.echo("No listeners found for this workspace.") return diff --git a/libs/cli/tests/unit_tests/cli/test_cli.py b/libs/cli/tests/unit_tests/cli/test_cli.py index 7b3441877..01838dec2 100644 --- a/libs/cli/tests/unit_tests/cli/test_cli.py +++ b/libs/cli/tests/unit_tests/cli/test_cli.py @@ -535,6 +535,79 @@ def test_deploy_listeners_list_command_no_results(monkeypatch) -> None: assert result.output.strip() == "No listeners found for this workspace." +def test_deploy_listeners_list_command_json(monkeypatch) -> None: + runner = CliRunner() + + listeners = [ + { + "id": "listener-1", + "compute_id": "prod-cluster", + "compute_config": {"k8s_namespaces": ["agents"]}, + }, + { + "id": "listener-2", + "compute_id": "multi-cluster", + "compute_config": {"k8s_namespaces": ["agents", "agents-staging"]}, + }, + ] + + class FakeClient: + def __init__(self, host_url: str, api_key: str, tenant_id: str | None = None): + pass + + def list_listeners(self): + return listeners + + monkeypatch.setattr(deploy_module, "HostBackendClient", FakeClient) + + result = runner.invoke( + cli, + [ + "deploy", + "listeners", + "list", + "--json", + "--api-key", + "test-key", + "--host-url", + "https://api.example.com", + ], + ) + + assert result.exit_code == 0, result.output + assert json.loads(result.output) == listeners + + +def test_deploy_listeners_list_command_json_no_results(monkeypatch) -> None: + runner = CliRunner() + + class FakeClient: + def __init__(self, host_url: str, api_key: str, tenant_id: str | None = None): + pass + + def list_listeners(self): + return [] + + monkeypatch.setattr(deploy_module, "HostBackendClient", FakeClient) + + result = runner.invoke( + cli, + [ + "deploy", + "listeners", + "list", + "--json", + "--api-key", + "test-key", + "--host-url", + "https://api.example.com", + ], + ) + + assert result.exit_code == 0, result.output + assert json.loads(result.output) == [] + + def test_deploy_revisions_list_command(monkeypatch) -> None: runner = CliRunner() captured: dict[str, str] = {}