Commit 51ce03bd authored by Sergio Gimenez's avatar Sergio Gimenez
Browse files

fix(fm): keep the requested name of a partner-hosted instance

SRM hands FM the whole deploy command, instance_name included, when the
target zone belongs to a partner. FM dropped the name and answered
/internal/federated-service-instances with ref "federated:<id>", so the
portal listed every partner-hosted instance by its UUID.

Keep instance_name in the InstallApp transaction summary and return it
as ref, falling back to the instance id: the same rule SRM applies to a
local instance. The summary is JSON already, so no migration.

Co-Authored-By: default avatarClaude Opus 5.5 <noreply@anthropic.com>
parent f61c6ea7
Loading
Loading
Loading
Loading
Loading
+2 −2
Changes for src/federation_manager/api/internal/service_instances.py: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -47,8 +47,8 @@ class FederatedServiceInstanceView(BaseModel):
            id=instance.service_instance_id,
            service_specification_id=instance.service_specification_id,
            zone_id=instance.zone_id,
            # the partner's appInstIdentifier stays with FM, as its zone ids do
            ref=f"federated:{instance.service_instance_id}",
            # SRM's own rule for a local instance; the partner's appInstIdentifier stays with FM
            ref=instance.name or str(instance.service_instance_id),
            state=instance.state,
            app_provider_id=instance.app_provider_id,
            metadata={"provider": "federation", "partner_op_id": str(instance.partner_op_id)},
+1 −0
Changes for src/federation_manager/application/federated_handoff.py: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ class FederatedDeployHandler:
                command.correlation_id,
                service_instance_id,
                command.app_provider_id,
                command.deploy.instance_name,
            ),
        )

+3 −0
Changes for src/federation_manager/application/federated_instances.py: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ class FederatedInstance:
    service_specification_id: UUID
    zone_id: UUID
    app_provider_id: str
    # the name the App Provider asked for, if any
    name: str | None
    partner_op_id: UUID
    state: State
    created_at: datetime
@@ -76,6 +78,7 @@ class FederatedInstanceQueries:
            service_specification_id=UUID(str(summary["service_specification_id"])),
            zone_id=UUID(str(summary["zone_id"])),
            app_provider_id=str(summary["app_provider_id"]),
            name=str(summary["instance_name"]) if summary.get("instance_name") else None,
            partner_op_id=install.partner_op_id,
            state=state,
            created_at=install.started_at,
+6 −0
Changes for src/federation_manager/application/outbound_deploy.py: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ class SrmHandOff:
    correlation_id: str
    service_instance_id: UUID
    app_provider_id: str
    instance_name: str | None = None


@dataclass(frozen=True)
@@ -197,6 +198,11 @@ class OutboundDeploymentService:
                        if hand_off
                        else {}
                    ),
                    **(
                        {"instance_name": hand_off.instance_name}
                        if hand_off and hand_off.instance_name
                        else {}
                    ),
                },
                started_at=self._clock(),
            )
+19 −0
Changes for tests/test_federated_service_instances.py: 19 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -69,6 +69,25 @@ async def test_a_handed_off_deploy_is_listed_for_its_app_provider() -> None:
    assert set(instance) <= SRM_SERVICE_INSTANCE_FIELDS


async def test_the_requested_name_is_the_ref() -> None:
    h = TerminateHarness()
    command = _command()
    command["deploy"] = {"instance_name": "podinfo-paris"}
    await h.handler.handle(command)

    instance = _client(h).get(f"{INSTANCES}/{INSTANCE}").json()

    assert instance["ref"] == "podinfo-paris"


async def test_without_a_requested_name_the_ref_is_the_instance_id() -> None:
    h = await _deployed()

    instance = _client(h).get(f"{INSTANCES}/{INSTANCE}").json()

    assert instance["ref"] == str(INSTANCE)


async def test_another_app_provider_sees_none_of_them() -> None:
    h = await _deployed()