mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-23 01:55:06 +02:00
fix(cli): refuse a malformed listener instead of dropping it
This commit is contained in:
@@ -157,10 +157,12 @@ class Listener:
|
||||
namespaces: tuple[str, ...]
|
||||
|
||||
@classmethod
|
||||
def from_resource(cls, resource: Mapping[str, object]) -> "Listener | None":
|
||||
def from_resource(cls, resource: Mapping[str, object]) -> "Listener":
|
||||
identifier = str(resource.get("id") or "")
|
||||
if not identifier:
|
||||
return None
|
||||
raise HostBackendError(
|
||||
"The control plane returned a listener without an id."
|
||||
)
|
||||
compute_config = resource.get("compute_config")
|
||||
namespaces = (
|
||||
compute_config.get("k8s_namespaces")
|
||||
@@ -1467,8 +1469,7 @@ def _available_listeners(client: HostBackendClient) -> tuple[Listener, ...]:
|
||||
resources = _call_host_backend_with_optional_tenant(
|
||||
client, lambda c: c.list_listeners()
|
||||
)
|
||||
listeners = (Listener.from_resource(resource) for resource in resources)
|
||||
return tuple(listener for listener in listeners if listener is not None)
|
||||
return tuple(Listener.from_resource(resource) for resource in resources)
|
||||
|
||||
|
||||
def _ensure_customer_registry_source(existing: ExistingDeployment) -> None:
|
||||
|
||||
@@ -918,24 +918,6 @@ def test_a_truncated_listener_page_says_so(deploy_project: DeployProject) -> Non
|
||||
assert "first 100" in result.output
|
||||
|
||||
|
||||
def test_a_listener_without_an_id_is_ignored(deploy_project: DeployProject) -> None:
|
||||
deploy_project.control_plane.listeners = [
|
||||
{"compute_id": "broken", "compute_config": {"k8s_namespaces": ["agents"]}},
|
||||
LISTENER,
|
||||
]
|
||||
|
||||
result = deploy_project.run(
|
||||
"--push-to", PUSH_REPOSITORY, host_url=CLOUD_CONTROL_PLANE_URL
|
||||
)
|
||||
|
||||
assert result.exit_code == 0, result.output
|
||||
assert deploy_project.control_plane.bodies[CREATE_DEPLOYMENT]["source_config"] == {
|
||||
"resource_spec": {},
|
||||
"listener_id": "listener-1",
|
||||
"listener_config": {"k8s_namespace": "agents"},
|
||||
}
|
||||
|
||||
|
||||
def test_a_managed_build_in_a_listener_workspace_points_at_push_to(
|
||||
deploy_project: DeployProject,
|
||||
) -> None:
|
||||
@@ -949,3 +931,34 @@ def test_a_managed_build_in_a_listener_workspace_points_at_push_to(
|
||||
assert result.exit_code != 0
|
||||
assert "--push-to" in result.output
|
||||
assert deploy_project.docker.verbs() == []
|
||||
|
||||
|
||||
def test_a_managed_control_plane_without_listeners_creates_as_before(
|
||||
deploy_project: DeployProject,
|
||||
) -> None:
|
||||
result = deploy_project.run(
|
||||
"--push-to", PUSH_REPOSITORY, host_url=CLOUD_CONTROL_PLANE_URL
|
||||
)
|
||||
|
||||
assert result.exit_code == 0, result.output
|
||||
assert deploy_project.control_plane.bodies[CREATE_DEPLOYMENT]["source_config"] == {
|
||||
"resource_spec": {}
|
||||
}
|
||||
assert deploy_project.timeline.count(LIST_LISTENERS) == 1
|
||||
|
||||
|
||||
def test_a_listener_without_an_id_is_reported_rather_than_ignored(
|
||||
deploy_project: DeployProject,
|
||||
) -> None:
|
||||
deploy_project.control_plane.listeners = [
|
||||
{"compute_id": "broken", "compute_config": {"k8s_namespaces": ["agents"]}},
|
||||
LISTENER,
|
||||
]
|
||||
|
||||
result = deploy_project.run(
|
||||
"--push-to", PUSH_REPOSITORY, host_url=CLOUD_CONTROL_PLANE_URL
|
||||
)
|
||||
|
||||
assert result.exit_code != 0
|
||||
assert "without an id" in result.output
|
||||
assert deploy_project.docker.verbs() == []
|
||||
|
||||
@@ -960,8 +960,6 @@ class TestListener:
|
||||
Listener("listener-1", "", ()),
|
||||
id="only_an_id",
|
||||
),
|
||||
pytest.param({"compute_id": "c"}, None, id="no_id_is_not_a_listener"),
|
||||
pytest.param({"id": ""}, None, id="empty_id_is_not_a_listener"),
|
||||
],
|
||||
)
|
||||
def test_from_resource_reads_the_control_plane_shape(self, resource, expected):
|
||||
@@ -1179,3 +1177,15 @@ def test_a_partial_page_without_a_match_means_the_name_is_free():
|
||||
)
|
||||
|
||||
assert find_deployment_by_name(client, "brand-new-agent") is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"resource",
|
||||
[
|
||||
pytest.param({"compute_id": "c"}, id="no_id"),
|
||||
pytest.param({"id": ""}, id="empty_id"),
|
||||
],
|
||||
)
|
||||
def test_a_listener_without_an_id_is_refused(resource):
|
||||
with pytest.raises(HostBackendError, match="without an id"):
|
||||
Listener.from_resource(resource)
|
||||
|
||||
Reference in New Issue
Block a user