Commit abb34b7b authored by Sergio Gimenez's avatar Sergio Gimenez
Browse files

refactor: split federation create from zone subscription and fix provider fallback

parent e1ec809d
Loading
Loading
Loading
Loading
+44 −34
Original line number Diff line number Diff line
@@ -23,6 +23,29 @@ factory = FederationManagerClientFactory()
federation_client = factory.create_federation_client()


def _store_partner_zones(federation_context_id, provider, availability_zones, accepted_zone_ids=None):
    zones_to_insert = []
    accepted_zone_ids = set(accepted_zone_ids or [])
    for zone in availability_zones or []:
        zone_id = zone.get('zoneId') if isinstance(zone, dict) else None
        if not zone_id:
            continue
        if accepted_zone_ids and zone_id not in accepted_zone_ids:
            continue
        inserted_item = {
            '_id': zone_id,
            'edgeCloudProvider': provider,
            'edgeCloudZoneId': zone_id,
            'edgeCloudZoneName': zone.get('geographyDetails'),
            'edgeCloudZoneStatus': 'unknown',
            'isLocal': 'false',
            'fedContextId': federation_context_id,
        }
        zones_to_insert.append(inserted_item)
    if zones_to_insert:
        insert_zones(zones_to_insert)


def create_federation():
    """POST /partner - Create federation with partner OP."""

@@ -31,42 +54,13 @@ def create_federation():
    if not token:
        return jsonify({"error": "Unable to obtain access token"}), 500
    response, code = federation_client.post_partner(body, token)
    fed = {'_id': response.get('federationContextId'), 'token': token}
    if code==200:
        provider = response.get('partnerOPFederationId')
        av_zones = response.get('offeredAvailabilityZones')
        zones_to_insert = []
        for zone in av_zones:
            inserted_item = {'_id': zone.get('zoneId'), 
                             'edgeCloudProvider': provider, 
                             'edgeCloudZoneId': zone.get('zoneId'), 
                             'edgeCloudZoneName': zone.get('geographyDetails'), 
                             'edgeCloudZoneStatus': 'unknown',
                             'isLocal': 'false',
                             'fedContextId': response.get('federationContextId')
    fed = {
        '_id': response.get('federationContextId'),
        'token': token,
        'partnerOPFederationId': response.get('partnerOPFederationId'),
    }
            zones_to_insert.append(inserted_item)
        insert_zones(zones_to_insert)    
    if code==200:
        insert_federation(fed)

        avail_zone_notif_link = config.AVAIL_ZONE_NOTIF_LINK or body.get("availZoneNotifLink")
        accepted_availability_zones = []
        for zone in av_zones or []:
            if isinstance(zone, dict) and zone.get("zoneId"):
                accepted_availability_zones.append(zone.get("zoneId"))
        if accepted_availability_zones:
            zone_response, zone_code = federation_client.subscribe_to_zones(
                response.get("federationContextId"),
                accepted_availability_zones,
                token,
                avail_zone_notif_link,
            )
            if zone_code != 200:
                logger.warning(
                    "Zone subscription returned non-200: %s - %s",
                    zone_code,
                    zone_response,
                )
    return response, code

def get_federation(federationContextId):
@@ -135,6 +129,22 @@ def request_zone_synch(federationContextId):
    response, code = federation_client.request_zone_sync(
        federation_context_id=federationContextId, body=body, token=token
    )
    if code == 200:
        federation_response, federation_code = federation_client.get_partner(federationContextId, token)
        if federation_code == 200:
            fed = get_fed(federationContextId) or {}
            _store_partner_zones(
                federationContextId,
                federation_response.get('partnerOPFederationId') or fed.get('partnerOPFederationId'),
                federation_response.get('offeredAvailabilityZones'),
                body.get('acceptedAvailabilityZones'),
            )
        else:
            logger.warning(
                "Unable to refresh partner zones after subscription: %s - %s",
                federation_code,
                federation_response,
            )
    return jsonify(response), code

def get_zone_resource_info(federationContextId, zoneId):
+38 −8
Original line number Diff line number Diff line
@@ -13,8 +13,11 @@ def test_app():


@pytest.mark.component
@patch("edge_cloud_management_api.controllers.federation_manager_controller.FederationManagerClientFactory")
def test_create_federation(mock_factory_class, test_app: Flask):
@patch("edge_cloud_management_api.controllers.federation_manager_controller.insert_federation")
@patch("edge_cloud_management_api.controllers.federation_manager_controller.insert_zones")
@patch("edge_cloud_management_api.controllers.federation_manager_controller.__get_token", return_value="token")
@patch("edge_cloud_management_api.controllers.federation_manager_controller.federation_client")
def test_create_federation(mock_federation_client, _mock_get_token, mock_insert_zones, mock_insert_federation, test_app: Flask):
    """Test create_federation returns federation data"""
    body = {
        "origOPFederationId": "orig-123",
@@ -22,9 +25,10 @@ def test_create_federation(mock_factory_class, test_app: Flask):
        "partnerStatusLink": "https://callback.example.com/status"
    }

    mock_client = MagicMock()
    mock_client.post_partner.return_value = {"federationContextId": "abc", "partnerOPFederationId": "partner-xyz"}
    mock_factory_class.return_value.create_federation_client.return_value = mock_client
    mock_federation_client.post_partner.return_value = (
        {"federationContextId": "abc", "partnerOPFederationId": "partner-xyz"},
        200,
    )

    with test_app.test_request_context(json=body):
        response, status = federation_manager_controller.create_federation()
@@ -34,6 +38,12 @@ def test_create_federation(mock_factory_class, test_app: Flask):
    assert data is not None
    assert "federationContextId" in data
    assert data["federationContextId"] == "abc"
    mock_insert_federation.assert_called_once_with({
        "_id": "abc",
        "token": "token",
        "partnerOPFederationId": "partner-xyz",
    })
    mock_insert_zones.assert_not_called()


@pytest.mark.component
@@ -84,21 +94,41 @@ def test_get_federation_context_ids(mock_factory_class, test_app: Flask):

@pytest.mark.component
@patch("edge_cloud_management_api.controllers.federation_manager_controller.__get_token", return_value="token")
@patch("edge_cloud_management_api.controllers.federation_manager_controller.get_fed", return_value={"partnerOPFederationId": "partner-xyz"})
@patch("edge_cloud_management_api.controllers.federation_manager_controller.federation_client")
def test_request_zone_synch(mock_federation_client, _mock_get_token, test_app: Flask):
def test_request_zone_synch(mock_federation_client, _mock_get_fed, _mock_get_token, test_app: Flask):
    federation_context_id = "ctx-123"
    body = {
        "acceptedAvailabilityZones": ["zone-1"],
        "availZoneNotifLink": "http://callback.local"
    }
    mock_federation_client.request_zone_sync.return_value = ({"status": "ok"}, 200)

    mock_federation_client.get_partner.return_value = ({
        "offeredAvailabilityZones": [
            {"zoneId": "zone-1", "geographyDetails": "Zone 1"},
            {"zoneId": "zone-2", "geographyDetails": "Zone 2"},
        ],
    }, 200)

    with patch("edge_cloud_management_api.controllers.federation_manager_controller.insert_zones") as mock_insert_zones:
        with test_app.test_request_context(json=body):
            response, status = federation_manager_controller.request_zone_synch(federation_context_id)

    assert status == 200
    assert response.get_json() == {"status": "ok"}
    mock_federation_client.request_zone_sync.assert_called_once()
    mock_federation_client.get_partner.assert_called_once_with(federation_context_id, "token")
    mock_insert_zones.assert_called_once_with([
        {
            "_id": "zone-1",
            "edgeCloudProvider": "partner-xyz",
            "edgeCloudZoneId": "zone-1",
            "edgeCloudZoneName": "Zone 1",
            "edgeCloudZoneStatus": "unknown",
            "isLocal": "false",
            "fedContextId": federation_context_id,
        }
    ])


@pytest.mark.component