Commit bea140ca authored by George Papathanail's avatar George Papathanail Committed by Dimitrios Gogos
Browse files

fix: align TrafficInfluence delete flow with QoD's delete_session pattern

parent 1315c336
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ def build_activate_command(
    correlation_id: str,
    requested_at: str,
    service_specification_id: UUID,
    service_instance_id: UUID,
    app_provider_id: str,
    zone_id: str | None,
) -> SRMNetworkCapabilityActivateCommand:
@@ -37,6 +38,7 @@ def build_activate_command(
        correlation_id=correlation_id,
        requested_at=requested_at,
        app_provider_id=app_provider_id,
        service_instance_id=str(service_instance_id),
        service_specification_id=str(service_specification_id),
        zone_id=zone_id,
        network_capability=NetworkCapabilityPayload(
@@ -57,7 +59,7 @@ def build_activate_command(


def build_deactivate_command(
    external_ref: str,
    service_instance_id: UUID,
    operation_id: UUID,
    correlation_id: str,
    requested_at: str,
@@ -70,7 +72,7 @@ def build_deactivate_command(
        requested_at=requested_at,
        app_provider_id=app_provider_id,
        network_capability=NetworkCapabilityDeactivateTarget(
            external_ref=external_ref,
            service_instance_id=str(service_instance_id),
            grace_period_seconds=grace_period_seconds,
        ),
    )
+9 −7
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ class TrafficInfluenceService:
            # (srm/interface-contract.md §E.4, ADR-0011) -- unlike QoD, which mints a
            # throwaway id because its sessions aren't tied to an onboarded catalog entry.
            service_specification_id=request.appId,
            service_instance_id=traffic_influence_id,
            app_provider_id=app_provider_id,
            zone_id=zone_id,
        )
@@ -399,12 +400,12 @@ class TrafficInfluenceService:
            raise RuntimeError("Operation/TrafficInfluence repositories are not available")

        traffic_influence = await self._traffic_influence_repo.get_by_id(UUID(traffic_influence_id))
        if traffic_influence is None or traffic_influence.external_ref is None:
        if traffic_influence is None:
            raise NotFoundException(message=f"Traffic influence {traffic_influence_id} not found")

        operation_id, correlation_id, requested_at = self._new_operation_metadata(x_correlator)
        command = build_deactivate_command(
            external_ref=traffic_influence.external_ref,
            service_instance_id=traffic_influence.traffic_influence_id,
            operation_id=operation_id,
            correlation_id=correlation_id,
            requested_at=requested_at,
@@ -423,14 +424,15 @@ class TrafficInfluenceService:
                metadata={"traffic_influence_id": str(traffic_influence_id)},
            )
        )
        await self._traffic_influence_repo.save(
            traffic_influence.model_copy(
                update={"state": RecordTrafficInfluenceState.DELETION_IN_PROGRESS}
            )
        )

        await self._publish(
            Subject.TASK_DEACTIVATE,
            command,
            "Failed to publish traffic influence deactivation",
        )

        await self._traffic_influence_repo.save(
            traffic_influence.model_copy(
                update={"state": RecordTrafficInfluenceState.DELETION_IN_PROGRESS}
            )
        )
+3 −1
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ class SRMNetworkCapabilityActivateCommand(BaseModel):
    requested_at: str
    app_provider_id: str
    source: str = "nbi_camara"
    service_instance_id: str
    service_specification_id: str
    zone_id: str | None = None
    domain_id: str | None = None
@@ -58,7 +59,8 @@ class SRMNetworkCapabilityActivateCommand(BaseModel):

class NetworkCapabilityDeactivateTarget(BaseModel):
    capability_type: str = "traffic_influence"
    external_ref: str
    service_instance_id: str | None = None
    external_ref: str | None = None
    grace_period_seconds: int = 0


+15 −7
Original line number Diff line number Diff line
@@ -64,7 +64,8 @@ class TestTrafficInfluenceCreateFlow:
    def test_srm_receives_a_valid_activate_command(
        self, api_client: TestClient, fake_bus: FakeDataBus
    ) -> None:
        api_client.post(f"{TI_BASE}/traffic-influences", json=TI_BODY)
        response = api_client.post(f"{TI_BASE}/traffic-influences", json=TI_BODY)
        traffic_influence_id = response.json()["trafficInfluenceID"]

        activates = [p for s, p in fake_bus.published if s == Subject.TASK_ACTIVATE]
        assert len(activates) == 1
@@ -82,6 +83,7 @@ class TestTrafficInfluenceCreateFlow:
        assert destination.protocol == "TCP"
        assert command.zone_id == TI_BODY["edgeCloudZoneId"]
        assert command.service_specification_id == TI_BODY["appId"]
        assert command.service_instance_id == traffic_influence_id
        assert command.source == "nbi_camara"

    def test_persists_operation_and_traffic_influence_rows(
@@ -200,17 +202,23 @@ class TestTrafficInfluenceGetFlow:


class TestTrafficInfluenceDeleteFlow:
    def test_delete_returns_404_before_activation_confirmed(self, api_client: TestClient) -> None:
        """A resource with no confirmed external_ref yet (still ORDERED) has nothing
        for a deactivate command to key on, so deletion 404s rather than silently
        no-op-ing or guessing at an id SRM never confirmed."""
    def test_delete_succeeds_before_activation_confirmed(
        self, api_client: TestClient, fake_bus: FakeDataBus
    ) -> None:
        """The deactivate command is keyed on OEG's own trafficInfluenceID (sent to SRM
        as service_instance_id at activation time), same as QoD's delete_session -- so
        deletion doesn't need to wait for SRM's external_ref to come back."""
        traffic_influence_id = api_client.post(
            f"{TI_BASE}/traffic-influences", json=TI_BODY
        ).json()["trafficInfluenceID"]

        response = api_client.delete(f"{TI_BASE}/traffic-influences/{traffic_influence_id}")

        assert response.status_code == 404
        assert response.status_code == 202
        deactivates = [p for s, p in fake_bus.published if s == Subject.TASK_DEACTIVATE]
        assert len(deactivates) == 1
        command = SRMNetworkCapabilityDeactivateCommand.model_validate(deactivates[0])
        assert command.network_capability.service_instance_id == traffic_influence_id

    def test_delete_returns_404_when_unknown(self, api_client: TestClient) -> None:
        response = api_client.delete(f"{TI_BASE}/traffic-influences/{uuid4()}")
@@ -250,7 +258,7 @@ class TestTrafficInfluenceDeleteFlow:
        deactivates = [p for s, p in fake_bus.published if s == Subject.TASK_DEACTIVATE]
        assert len(deactivates) == 1
        command = SRMNetworkCapabilityDeactivateCommand.model_validate(deactivates[0])
        assert command.network_capability.external_ref == "traffic-policy-456"
        assert command.network_capability.service_instance_id == str(traffic_influence_id)
        assert (
            traffic_influence_repo.rows[traffic_influence_id].state
            == TrafficInfluenceState.DELETION_IN_PROGRESS