mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-23 18:15:08 +02:00
refactor(cli): drop listeners without an id and name the source arguments
This commit is contained in:
@@ -157,7 +157,10 @@ class Listener:
|
||||
namespaces: tuple[str, ...]
|
||||
|
||||
@classmethod
|
||||
def from_resource(cls, resource: Mapping[str, object]) -> "Listener":
|
||||
def from_resource(cls, resource: Mapping[str, object]) -> "Listener | None":
|
||||
identifier = str(resource.get("id") or "")
|
||||
if not identifier:
|
||||
return None
|
||||
compute_config = resource.get("compute_config")
|
||||
namespaces = (
|
||||
compute_config.get("k8s_namespaces")
|
||||
@@ -165,7 +168,7 @@ class Listener:
|
||||
else None
|
||||
)
|
||||
return cls(
|
||||
str(resource.get("id", "")),
|
||||
identifier,
|
||||
str(resource.get("compute_id", "")),
|
||||
tuple(str(namespace) for namespace in namespaces)
|
||||
if isinstance(namespaces, list)
|
||||
@@ -1445,7 +1448,8 @@ def _available_listeners(client: HostBackendClient) -> tuple[Listener, ...]:
|
||||
resources = _call_host_backend_with_optional_tenant(
|
||||
client, lambda c: c.list_listeners()
|
||||
)
|
||||
return tuple(Listener.from_resource(resource) for resource in resources)
|
||||
listeners = (Listener.from_resource(resource) for resource in resources)
|
||||
return tuple(listener for listener in listeners if listener is not None)
|
||||
|
||||
|
||||
def _ensure_customer_registry_source(existing: ExistingDeployment) -> None:
|
||||
@@ -1510,7 +1514,7 @@ class RemoteBuildSource:
|
||||
class CustomerRegistrySource:
|
||||
reference: ImageReference
|
||||
prebuilt_image: str | None
|
||||
placement: RequestedPlacement = RequestedPlacement()
|
||||
placement: RequestedPlacement
|
||||
|
||||
def run(self, ctx: DeployContext) -> DeployOutcome:
|
||||
if isinstance(ctx.selector, ById):
|
||||
@@ -1648,7 +1652,9 @@ def _select_source(
|
||||
reference = _push_reference(push_to, tag)
|
||||
if image is None:
|
||||
_require_local_docker()
|
||||
return CustomerRegistrySource(reference, image, placement)
|
||||
return CustomerRegistrySource(
|
||||
reference=reference, prebuilt_image=image, placement=placement
|
||||
)
|
||||
if image and remote_build_flag is True:
|
||||
raise click.UsageError("--image cannot be combined with --remote builds.")
|
||||
use_remote_build, local_build_error = _resolve_build_mode(
|
||||
|
||||
@@ -280,7 +280,8 @@ class HostBackendClient:
|
||||
return _resources(
|
||||
self._request(
|
||||
"GET",
|
||||
f"/v2/deployments/{deployment_id}/revisions?limit={limit}",
|
||||
f"/v2/deployments/{deployment_id}/revisions",
|
||||
params={"limit": limit},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -914,3 +914,21 @@ def test_a_truncated_listener_page_says_so(deploy_project: DeployProject) -> Non
|
||||
|
||||
assert result.exit_code != 0
|
||||
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"},
|
||||
}
|
||||
|
||||
@@ -626,7 +626,9 @@ class TestSelectSource:
|
||||
{"push_to": REPOSITORY},
|
||||
True,
|
||||
CustomerRegistrySource(
|
||||
ImageReference(REPOSITORY, "latest"), prebuilt_image=None
|
||||
reference=ImageReference(REPOSITORY, "latest"),
|
||||
prebuilt_image=None,
|
||||
placement=RequestedPlacement(),
|
||||
),
|
||||
id="push_to_selects_the_external_source_with_the_default_tag",
|
||||
),
|
||||
@@ -634,7 +636,9 @@ class TestSelectSource:
|
||||
{"push_to": f"{REPOSITORY}:v2"},
|
||||
True,
|
||||
CustomerRegistrySource(
|
||||
ImageReference(REPOSITORY, "v2"), prebuilt_image=None
|
||||
reference=ImageReference(REPOSITORY, "v2"),
|
||||
prebuilt_image=None,
|
||||
placement=RequestedPlacement(),
|
||||
),
|
||||
id="push_to_keeps_a_tag_given_in_the_reference",
|
||||
),
|
||||
@@ -642,7 +646,9 @@ class TestSelectSource:
|
||||
{"push_to": REPOSITORY, "tag": "v3"},
|
||||
True,
|
||||
CustomerRegistrySource(
|
||||
ImageReference(REPOSITORY, "v3"), prebuilt_image=None
|
||||
reference=ImageReference(REPOSITORY, "v3"),
|
||||
prebuilt_image=None,
|
||||
placement=RequestedPlacement(),
|
||||
),
|
||||
id="tag_flag_composes_with_push_to",
|
||||
),
|
||||
@@ -650,7 +656,9 @@ class TestSelectSource:
|
||||
{"push_to": REPOSITORY, "image": "app:dev"},
|
||||
False,
|
||||
CustomerRegistrySource(
|
||||
ImageReference(REPOSITORY, "latest"), prebuilt_image="app:dev"
|
||||
reference=ImageReference(REPOSITORY, "latest"),
|
||||
prebuilt_image="app:dev",
|
||||
placement=RequestedPlacement(),
|
||||
),
|
||||
id="prebuilt_image_is_retagged_for_push_to_without_docker_checks",
|
||||
),
|
||||
@@ -661,9 +669,9 @@ class TestSelectSource:
|
||||
},
|
||||
True,
|
||||
CustomerRegistrySource(
|
||||
ImageReference(REPOSITORY, "latest"),
|
||||
None,
|
||||
RequestedPlacement("listener-1", "agents"),
|
||||
reference=ImageReference(REPOSITORY, "latest"),
|
||||
prebuilt_image=None,
|
||||
placement=RequestedPlacement("listener-1", "agents"),
|
||||
),
|
||||
id="push_to_carries_the_requested_placement",
|
||||
),
|
||||
@@ -952,6 +960,8 @@ 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):
|
||||
|
||||
Reference in New Issue
Block a user