Exemple #1
0
 def test_constructor_configuration_manager_defined_no_configuration_manager_passed(
         self, reset_singleton):
     configuration_manager_mock = MagicMock(spec=ConfigurationManager)
     i_reg = InterestRegistry(configuration_manager_mock)
     # second time initializing InterestRegistry without configuration manager
     i_reg2 = InterestRegistry()
     assert hasattr(i_reg2, '_configuration_manager')
     assert isinstance(i_reg2._configuration_manager, ConfigurationManager)
     assert hasattr(i_reg2, '_registered_interests')
     assert len(i_reg._registered_interests) == 0
Exemple #2
0
 def test_constructor_configuration_manager_defined_configuration_manager_passed(
         self, reset_singleton):
     configuration_manager_mock = MagicMock(spec=ConfigurationManager)
     # second time initializing InterestRegistry with new configuration manager
     # works
     configuration_manager_mock2 = MagicMock(spec=ConfigurationManager)
     i_reg = InterestRegistry(configuration_manager_mock)
     i_reg2 = InterestRegistry(configuration_manager_mock2)
     assert hasattr(i_reg2, '_configuration_manager')
     # ignore new configuration manager
     assert isinstance(i_reg2._configuration_manager, ConfigurationManager)
     assert hasattr(i_reg2, '_registered_interests')
    async def test_run_general_exception(self):
        storage_client_mock = MagicMock(spec=StorageClientAsync)
        cfg_mgr = ConfigurationManager(storage_client_mock)

        with patch.object(ServiceRegistry._logger, 'info') as log_info:
            s_id_1 = ServiceRegistry.register('sname1', 'Storage', 'saddress1',
                                              1, 1, 'http')
        assert 1 == log_info.call_count
        args, kwargs = log_info.call_args
        assert args[0].startswith('Registered service instance id=')
        assert args[0].endswith(
            ': <sname1, type=Storage, protocol=http, address=saddress1, service port=1, management port=1, status=1>'
        )

        i_reg = InterestRegistry(cfg_mgr)
        i_reg.register(s_id_1, 'catname1')

        # used to mock client session context manager
        async def async_mock(return_value):
            return return_value

        class AsyncSessionContextManagerMock(MagicMock):
            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)

            async def __aenter__(self):
                raise Exception

            async def __aexit__(self, *args):
                return None

        with patch.object(ConfigurationManager,
                          'get_category_all_items',
                          return_value=async_mock(None)) as cm_get_patch:
            with patch.object(aiohttp.ClientSession,
                              'post',
                              return_value=AsyncSessionContextManagerMock()
                              ) as post_patch:
                with patch.object(cb._LOGGER, 'exception') as exception_patch:
                    await cb.run('catname1')
                exception_patch.assert_called_once_with(
                    'Unable to notify microservice with uuid %s due to exception: %s',
                    s_id_1, '')
            post_patch.assert_has_calls([
                call('http://saddress1:1/fledge/change',
                     data='{"category": "catname1", "items": null}',
                     headers={'content-type': 'application/json'})
            ])
        cm_get_patch.assert_called_once_with('catname1')
Exemple #4
0
 def test_constructor_no_configuration_manager_defined_no_configuration_manager_passed(
         self, reset_singleton):
     # first time initializing InterestRegistry without configuration manager
     # produces error
     with pytest.raises(TypeError) as excinfo:
         InterestRegistry()
     assert 'Must be a valid ConfigurationManager object' in str(
         excinfo.value)
Exemple #5
0
    def test_register(self, reset_singleton):
        configuration_manager_mock = MagicMock(spec=ConfigurationManager)
        i_reg = InterestRegistry(configuration_manager_mock)
        # register the first interest
        microservice_uuid = 'muuid'
        category_name = 'catname'
        ret_val = i_reg.register(microservice_uuid, category_name)
        assert ret_val is not None
        assert len(i_reg._registered_interests) is 1
        assert isinstance(i_reg._registered_interests[0], InterestRecord)
        assert i_reg._registered_interests[0]._registration_id is ret_val
        assert i_reg._registered_interests[
            0]._microservice_uuid is microservice_uuid
        assert i_reg._registered_interests[0]._category_name is category_name
        str_val = 'interest registration id={}: <microservice uuid={}, category_name={}>'.format(
            ret_val, microservice_uuid, category_name)
        assert str(i_reg._registered_interests[0]) == str_val

        # register an existing interest
        with pytest.raises(interest_registry_exceptions.
                           ErrorInterestRegistrationAlreadyExists) as excinfo:
            ret_val = i_reg.register(microservice_uuid, category_name)
        assert ret_val is not None
        assert len(i_reg._registered_interests) is 1
        assert isinstance(i_reg._registered_interests[0], InterestRecord)
        assert i_reg._registered_interests[0]._registration_id is ret_val
        assert i_reg._registered_interests[
            0]._microservice_uuid is microservice_uuid
        assert i_reg._registered_interests[0]._category_name is category_name
        str_val = 'interest registration id={}: <microservice uuid={}, category_name={}>'.format(
            ret_val, microservice_uuid, category_name)
        assert str(i_reg._registered_interests[0]) == str_val

        # register a second interest
        category_name2 = 'catname2'
        ret_val = i_reg.register(microservice_uuid, category_name2)
        assert ret_val is not None
        assert len(i_reg._registered_interests) is 2
        assert isinstance(i_reg._registered_interests[1], InterestRecord)
        assert i_reg._registered_interests[1]._registration_id is ret_val
        assert i_reg._registered_interests[
            1]._microservice_uuid is microservice_uuid
        assert i_reg._registered_interests[1]._category_name is category_name2
        str_val = 'interest registration id={}: <microservice uuid={}, category_name={}>'.format(
            ret_val, microservice_uuid, category_name2)
        assert str(i_reg._registered_interests[1]) == str_val
Exemple #6
0
    def _expunge(cls, service_id, service_status):
        """ removes the service instance from action

        :param service_id: a uuid of registered service
        :param service_status: service status to be marked
        :return: service_id on successful deregistration
        """
        services = cls.get(idx=service_id)
        service_name = services[0]._name
        services[0]._status = service_status
        cls._remove_from_scheduler_records(service_name)

        # Remove interest registry records, if any
        interest_recs = InterestRegistry().get(microservice_uuid=service_id)
        for interest_rec in interest_recs:
            InterestRegistry().unregister(interest_rec._registration_id)

        return services[0]
Exemple #7
0
 def test_constructor_no_configuration_manager_defined_configuration_manager_passed(
         self, reset_singleton):
     # first time initializing InterestRegistry with configuration manager
     # works
     configuration_manager_mock = MagicMock(spec=ConfigurationManager)
     i_reg = InterestRegistry(configuration_manager_mock)
     assert hasattr(i_reg, '_configuration_manager')
     assert isinstance(i_reg._configuration_manager, ConfigurationManager)
     assert hasattr(i_reg, '_registered_interests')
Exemple #8
0
    def test_get(self, reset_singleton):
        configuration_manager_mock = MagicMock(spec=ConfigurationManager)
        i_reg = InterestRegistry(configuration_manager_mock)

        # get when empty
        microservice_uuid = 'muuid'
        category_name = 'catname'
        with pytest.raises(
                interest_registry_exceptions.DoesNotExist) as excinfo:
            i_reg.get(microservice_uuid=microservice_uuid,
                      category_name=category_name)

        # get when there is a result (use patch on 'get')
        with patch.object(InterestRegistry, 'and_filter', return_value=[1]):
            ret_val = i_reg.get(microservice_uuid=microservice_uuid,
                                category_name=category_name)
        assert ret_val is not None
        assert ret_val == [1]
Exemple #9
0
 async def test_get_interest_exception(self, client, params, message, expected_kwargs):
     Server._storage_client = MagicMock(StorageClientAsync)
     Server._configuration_manager = ConfigurationManager(Server._storage_client)
     Server._interest_registry = InterestRegistry(Server._configuration_manager)
     with patch.object(Server._interest_registry, 'get', side_effect=interest_registry_exceptions.DoesNotExist) as patch_get_interest_reg:
         resp = await client.get('/fledge/interest{}'.format(params))
         assert 404 == resp.status
         assert message == resp.reason
     args, kwargs = patch_get_interest_reg.call_args
     assert expected_kwargs == kwargs
Exemple #10
0
async def run(category_name):
    """ Callback run by configuration category to notify changes to interested microservices

    Note: this method is async as needed

    Args:
        configuration_name (str): name of category that was changed
    """

    # get all interest records regarding category_name
    cfg_mgr = ConfigurationManager()
    interest_registry = InterestRegistry(cfg_mgr)
    try:
        interest_records = interest_registry.get(category_name=category_name)
    except interest_registry_exceptions.DoesNotExist:
        return

    category_value = await cfg_mgr.get_category_all_items(category_name)
    payload = {"category" : category_name, "items" : category_value}
    headers = {'content-type': 'application/json'}

    # for each microservice interested in category_name, notify change
    for i in interest_records:
        # get microservice management server info of microservice through service registry
        try: 
            service_record = ServiceRegistry.get(idx=i._microservice_uuid)[0]
        except service_registry_exceptions.DoesNotExist:
            _LOGGER.exception("Unable to notify microservice with uuid %s as it is not found in the service registry", i._microservice_uuid)
            continue
        url = "{}://{}:{}/fledge/change".format(service_record._protocol, service_record._address, service_record._management_port)
        async with aiohttp.ClientSession() as session:
            try:
                async with session.post(url, data=json.dumps(payload, sort_keys=True), headers=headers) as resp:
                    result = await resp.text()
                    status_code = resp.status
                    if status_code in range(400, 500):
                        _LOGGER.error("Bad request error code: %d, reason: %s", status_code, resp.reason)
                    if status_code in range(500, 600):
                        _LOGGER.error("Server error code: %d, reason: %s", status_code, resp.reason)
            except Exception as ex:
                _LOGGER.exception("Unable to notify microservice with uuid %s due to exception: %s", i._microservice_uuid, str(ex))
                continue
Exemple #11
0
    async def test_unregister_interest_exception(self, client):
        Server._storage_client = MagicMock(StorageClientAsync)
        Server._configuration_manager = ConfigurationManager(Server._storage_client)
        Server._interest_registry = InterestRegistry(Server._configuration_manager)

        reg_id = 'c6bbf3c8-f43c-4b0f-ac48-f597f510da0b'
        with patch.object(Server._interest_registry, 'get', side_effect=interest_registry_exceptions.DoesNotExist) as patch_get_interest_reg:
            resp = await client.delete('/fledge/interest/{}'.format(reg_id))
            assert 404 == resp.status
            assert 'InterestRecord with registration_id {} does not exist'.format(reg_id) == resp.reason
        args, kwargs = patch_get_interest_reg.call_args
        assert {'registration_id': reg_id} == kwargs
Exemple #12
0
    async def test_register_interest_exceptions(self, client):
        Server._storage_client = MagicMock(StorageClientAsync)
        Server._configuration_manager = ConfigurationManager(Server._storage_client)
        Server._interest_registry = InterestRegistry(Server._configuration_manager)

        request_data = {"category": "COAP", "service": "c6bbf3c8-f43c-4b0f-ac48-f597f510da0b"}
        with patch.object(Server._interest_registry, 'register', side_effect=interest_registry_exceptions.ErrorInterestRegistrationAlreadyExists) as patch_reg_interest_reg:
            resp = await client.post('/fledge/interest', data=json.dumps(request_data))
            assert 400 == resp.status
            assert 'An InterestRecord already exists by microservice_uuid {} for category_name {}'.format(request_data['service'], request_data['category']) == resp.reason
        args, kwargs = patch_reg_interest_reg.call_args
        assert (request_data['service'], request_data['category']) == args
Exemple #13
0
    async def test_bad_register_interest(self, client):
        Server._storage_client = MagicMock(StorageClientAsync)
        Server._configuration_manager = ConfigurationManager(Server._storage_client)
        Server._interest_registry = InterestRegistry(Server._configuration_manager)

        request_data = {"category": "COAP", "service": "c6bbf3c8-f43c-4b0f-ac48-f597f510da0b"}
        with patch.object(Server._interest_registry, 'register', return_value=None) as patch_reg_interest_reg:
            resp = await client.post('/fledge/interest', data=json.dumps(request_data))
            assert 400 == resp.status
            assert 'Interest by microservice_uuid {} for category_name {} could not be registered'.format(request_data['service'], request_data['category']) == resp.reason
        args, kwargs = patch_reg_interest_reg.call_args
        assert (request_data['service'], request_data['category']) == args
Exemple #14
0
 async def test_get_interest_with_filter(self, client, params, expected_kwargs):
     Server._storage_client = MagicMock(StorageClientAsync)
     Server._configuration_manager = ConfigurationManager(Server._storage_client)
     Server._interest_registry = InterestRegistry(Server._configuration_manager)
     with patch.object(Server._interest_registry, 'get', return_value=[]) as patch_get_interest_reg:
         resp = await client.get('/fledge/interest{}'.format(params))
         assert 200 == resp.status
         r = await resp.text()
         json_response = json.loads(r)
         assert {'interests': []} == json_response
     args, kwargs = patch_get_interest_reg.call_args
     assert expected_kwargs == kwargs
Exemple #15
0
    async def test_register_interest(self, client):
        Server._storage_client = MagicMock(StorageClientAsync)
        Server._configuration_manager = ConfigurationManager(Server._storage_client)
        Server._interest_registry = InterestRegistry(Server._configuration_manager)

        request_data = {"category": "COAP", "service": "c6bbf3c8-f43c-4b0f-ac48-f597f510da0b"}
        reg_id = 'a404852d-d91c-47bd-8860-d4ff81b6e8cb'
        with patch.object(Server._interest_registry, 'register', return_value=reg_id) as patch_reg_interest_reg:
            resp = await client.post('/fledge/interest', data=json.dumps(request_data))
            assert 200 == resp.status
            r = await resp.text()
            json_response = json.loads(r)
            assert {'id': reg_id, 'message': 'Interest registered successfully'} == json_response
        args, kwargs = patch_reg_interest_reg.call_args
        assert (request_data['service'], request_data['category']) == args
Exemple #16
0
    def test_get_with_and_filter(self, reset_singleton):
        configuration_manager_mock = MagicMock(spec=ConfigurationManager)
        i_reg = InterestRegistry(configuration_manager_mock)
        # register some interts
        id_1_1 = i_reg.register('muuid1', 'catname1')
        id_1_2 = i_reg.register('muuid1', 'catname2')
        id_2_1 = i_reg.register('muuid2', 'catname1')
        id_2_2 = i_reg.register('muuid2', 'catname2')
        id_3_3 = i_reg.register('muuid3', 'catname3')

        ret_val = i_reg.get(microservice_uuid='muuid1')
        assert len(ret_val) is 2
        for i in ret_val:
            assert isinstance(i, InterestRecord)
        assert ret_val[0]._registration_id is id_1_1
        assert ret_val[0]._microservice_uuid is 'muuid1'
        assert ret_val[0]._category_name is 'catname1'
        assert ret_val[1]._registration_id is id_1_2
        assert ret_val[1]._microservice_uuid is 'muuid1'
        assert ret_val[1]._category_name is 'catname2'

        ret_val = i_reg.get(category_name='catname2')
        assert len(ret_val) is 2
        for i in ret_val:
            assert isinstance(i, InterestRecord)
        assert ret_val[0]._registration_id is id_1_2
        assert ret_val[0]._microservice_uuid is 'muuid1'
        assert ret_val[0]._category_name is 'catname2'
        assert ret_val[1]._registration_id is id_2_2
        assert ret_val[1]._microservice_uuid is 'muuid2'
        assert ret_val[1]._category_name is 'catname2'

        ret_val = i_reg.get(category_name='catname2',
                            microservice_uuid='muuid2')
        assert len(ret_val) is 1
        for i in ret_val:
            assert isinstance(i, InterestRecord)
        assert ret_val[0]._registration_id is id_2_2
        assert ret_val[0]._microservice_uuid is 'muuid2'
        assert ret_val[0]._category_name is 'catname2'
Exemple #17
0
    async def test_get_interest(self, client):
        Server._storage_client = MagicMock(StorageClientAsync)
        Server._configuration_manager = ConfigurationManager(Server._storage_client)
        Server._interest_registry = InterestRegistry(Server._configuration_manager)

        data = []
        category_name = 'test_Cat'
        muuid = '0c501cd3-c45a-439a-bec6-fc08d13f9699'
        reg_id = 'c6bbf3c8-f43c-4b0f-ac48-f597f510da0b'
        record = InterestRecord(reg_id, muuid, category_name)
        data.append(record)

        with patch.object(Server._interest_registry, 'get', return_value=data) as patch_get_interest_reg:
            resp = await client.get('/fledge/interest')
            assert 200 == resp.status
            r = await resp.text()
            json_response = json.loads(r)
            assert {'interests': [{'category': category_name, 'microserviceId': muuid, 'registrationId': reg_id}]} == json_response
        args, kwargs = patch_get_interest_reg.call_args
        assert {} == kwargs
    async def test_run_empty_interests(self):
        storage_client_mock = MagicMock(spec=StorageClientAsync)
        cfg_mgr = ConfigurationManager(storage_client_mock)

        with patch.object(ServiceRegistry._logger, 'info') as log_info:
            ServiceRegistry.register('sname1', 'Storage', 'saddress1', 1, 1,
                                     'http')
            ServiceRegistry.register('sname2', 'Southbound', 'saddress2', 2, 2,
                                     'http')
            ServiceRegistry.register('sname3', 'Southbound', 'saddress3', 3, 3,
                                     'http')
        assert 3 == log_info.call_count
        InterestRegistry(cfg_mgr)

        # used to mock client session context manager
        async def async_mock(return_value):
            return return_value

        class AsyncSessionContextManagerMock(MagicMock):
            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)

            async def __aenter__(self):
                client_response_mock = MagicMock(spec=aiohttp.ClientResponse)
                client_response_mock.text.side_effect = [async_mock(None)]
                status_mock = Mock()
                status_mock.side_effect = [200]
                client_response_mock.status = status_mock()
                return client_response_mock

            async def __aexit__(self, *args):
                return None

        with patch.object(ConfigurationManager,
                          'get_category_all_items') as cm_get_patch:
            with patch.object(aiohttp.ClientSession, 'post') as post_patch:
                await cb.run('catname1')
            post_patch.assert_not_called()
        cm_get_patch.assert_not_called()
Exemple #19
0
    async def test_unregister_interest(self, client):
        Server._storage_client = MagicMock(StorageClientAsync)
        Server._configuration_manager = ConfigurationManager(Server._storage_client)
        Server._interest_registry = InterestRegistry(Server._configuration_manager)

        data = []
        category_name = 'test_Cat'
        muuid = '0c501cd3-c45a-439a-bec6-fc08d13f9699'
        reg_id = 'c6bbf3c8-f43c-4b0f-ac48-f597f510da0b'
        record = InterestRecord(reg_id, muuid, category_name)
        data.append(record)

        with patch.object(Server._interest_registry, 'get', return_value=data) as patch_get_interest_reg:
            with patch.object(Server._interest_registry, 'unregister', return_value=[]) as patch_unregister_interest:
                resp = await client.delete('/fledge/interest/{}'.format(reg_id))
                assert 200 == resp.status
                r = await resp.text()
                json_response = json.loads(r)
                assert {'id': reg_id, 'message': 'Interest unregistered'} == json_response
            args, kwargs = patch_unregister_interest.call_args
            assert (reg_id,) == args
        args1, kwargs1 = patch_get_interest_reg.call_args
        assert {'registration_id': reg_id} == kwargs1
Exemple #20
0
    def test_unregister(self, reset_singleton):
        configuration_manager_mock = MagicMock(spec=ConfigurationManager)
        i_reg = InterestRegistry(configuration_manager_mock)
        # unregister when no items exists
        fake_uuid = 'bla'
        with pytest.raises(
                interest_registry_exceptions.DoesNotExist) as excinfo:
            ret_val = i_reg.unregister(fake_uuid)

        # register 2 interests, then unregister 1
        id_1_1 = i_reg.register('muuid1', 'catname1')
        id_1_2 = i_reg.register('muuid1', 'catname2')
        ret_val = i_reg.unregister(id_1_1)
        assert ret_val == id_1_1
        assert len(i_reg._registered_interests) is 1
        assert isinstance(i_reg._registered_interests[0], InterestRecord)
        assert i_reg._registered_interests[0]._registration_id is id_1_2
        assert i_reg._registered_interests[0]._microservice_uuid is 'muuid1'
        assert i_reg._registered_interests[0]._category_name is 'catname2'

        # unregister the second one
        ret_val = i_reg.unregister(id_1_2)
        assert ret_val == id_1_2
        assert len(i_reg._registered_interests) is 0
    async def test_run_good(self):
        storage_client_mock = MagicMock(spec=StorageClientAsync)
        cfg_mgr = ConfigurationManager(storage_client_mock)

        with patch.object(ServiceRegistry._logger, 'info') as log_info:
            s_id_1 = ServiceRegistry.register('sname1', 'Storage', 'saddress1',
                                              1, 1, 'http')
            s_id_2 = ServiceRegistry.register('sname2', 'Southbound',
                                              'saddress2', 2, 2, 'http')
            s_id_3 = ServiceRegistry.register('sname3', 'Southbound',
                                              'saddress3', 3, 3, 'http')
        assert 3 == log_info.call_count
        i_reg = InterestRegistry(cfg_mgr)
        i_reg.register(s_id_1, 'catname1')
        i_reg.register(s_id_1, 'catname2')
        i_reg.register(s_id_2, 'catname1')
        i_reg.register(s_id_2, 'catname2')
        i_reg.register(s_id_3, 'catname3')

        # used to mock client session context manager
        async def async_mock(return_value):
            return return_value

        class AsyncSessionContextManagerMock(MagicMock):
            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)

            async def __aenter__(self):
                client_response_mock = MagicMock(spec=aiohttp.ClientResponse)
                client_response_mock.text.side_effect = [async_mock(None)]
                status_mock = Mock()
                status_mock.side_effect = [200]
                client_response_mock.status = status_mock()
                return client_response_mock

            async def __aexit__(self, *args):
                return None

        with patch.object(ConfigurationManager,
                          'get_category_all_items',
                          return_value=async_mock(None)) as cm_get_patch:
            with patch.object(aiohttp.ClientSession,
                              'post',
                              return_value=AsyncSessionContextManagerMock()
                              ) as post_patch:
                await cb.run('catname1')
            post_patch.assert_has_calls([
                call('http://saddress1:1/fledge/change',
                     data='{"category": "catname1", "items": null}',
                     headers={'content-type': 'application/json'}),
                call('http://saddress2:2/fledge/change',
                     data='{"category": "catname1", "items": null}',
                     headers={'content-type': 'application/json'})
            ])
        cm_get_patch.assert_called_once_with('catname1')

        with patch.object(ConfigurationManager,
                          'get_category_all_items',
                          return_value=async_mock(None)) as cm_get_patch:
            with patch.object(aiohttp.ClientSession,
                              'post',
                              return_value=AsyncSessionContextManagerMock()
                              ) as post_patch:
                await cb.run('catname2')
            post_patch.assert_has_calls([
                call('http://saddress1:1/fledge/change',
                     data='{"category": "catname2", "items": null}',
                     headers={'content-type': 'application/json'}),
                call('http://saddress2:2/fledge/change',
                     data='{"category": "catname2", "items": null}',
                     headers={'content-type': 'application/json'})
            ])
        cm_get_patch.assert_called_once_with('catname2')

        with patch.object(ConfigurationManager,
                          'get_category_all_items',
                          return_value=async_mock(None)) as cm_get_patch:
            with patch.object(aiohttp.ClientSession,
                              'post',
                              return_value=AsyncSessionContextManagerMock()
                              ) as post_patch:
                await cb.run('catname3')
            post_patch.assert_called_once_with(
                'http://saddress3:3/fledge/change',
                data='{"category": "catname3", "items": null}',
                headers={'content-type': 'application/json'})
        cm_get_patch.assert_called_once_with('catname3')