Loading edge_cloud_management_api/controllers/federation_manager_controller.py +44 −34 Original line number Diff line number Diff line Loading @@ -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.""" Loading @@ -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): Loading Loading @@ -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): Loading tests/unit/controllers/test_federation_manager_controller.py +38 −8 Original line number Diff line number Diff line Loading @@ -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", Loading @@ -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() Loading @@ -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 Loading Loading @@ -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 Loading Loading
edge_cloud_management_api/controllers/federation_manager_controller.py +44 −34 Original line number Diff line number Diff line Loading @@ -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.""" Loading @@ -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): Loading Loading @@ -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): Loading
tests/unit/controllers/test_federation_manager_controller.py +38 −8 Original line number Diff line number Diff line Loading @@ -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", Loading @@ -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() Loading @@ -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 Loading Loading @@ -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 Loading