def setup_method(self): """ reset configuration table data for specific category_name/s, and clear data (if exists) in _registered_interests object""" asyncio.get_event_loop().run_until_complete(delete_from_configuration()) self.cf_mgr = ConfigurationManager(_storage) self.cf_mgr._registered_interests.clear()
def retrieve_configuration(_storage, _category_name, _default, _category_description): """Retrieves the configuration from the Category Manager for a category name Args: _storage: Reference to the Storage Client to be used _category_name: Category name to be retrieved _default: default values for the category _category_description: category description Returns: _config_from_manager: Retrieved configuration as a Dictionary Raises: """ _event_loop = asyncio.get_event_loop() cfg_manager = ConfigurationManager(_storage) _event_loop.run_until_complete( cfg_manager.create_category(_category_name, _default, _category_description)) _config_from_manager = _event_loop.run_until_complete( cfg_manager.get_category_all_items(_category_name)) return _config_from_manager
def set_configuration(self): """" set the default configuration for purge :return: Configuration information that was set for purge process """ cfg_manager = ConfigurationManager(self._storage) self.loop.run_until_complete( cfg_manager.create_category(self._CONFIG_CATEGORY_NAME, self._DEFAULT_PURGE_CONFIG, self._CONFIG_CATEGORY_DESCRIPTION)) return self.loop.run_until_complete( cfg_manager.get_category_all_items(self._CONFIG_CATEGORY_NAME))
def _fetch_configuration(self, cat_name=None, cat_desc=None, cat_config=None, cat_keep_original=False): """ Retrieves the configuration from the Configuration Manager""" SendingProcess._logger.debug("{0} - ".format("_fetch_configuration")) cfg_manager = ConfigurationManager(self._storage) try: self._event_loop.run_until_complete(cfg_manager.create_category(cat_name, cat_config, cat_desc, cat_keep_original)) _config_from_manager = self._event_loop.run_until_complete(cfg_manager.get_category_all_items(cat_name)) return _config_from_manager except Exception: _message = _MESSAGES_LIST["e000003"] SendingProcess._logger.error(_message) raise
async def get_filter_pipeline(request: web.Request) -> web.Response: """ GET filter pipeline :Example: curl -X GET http://localhost:8081/foglamp/filter/<user_name>/pipeline """ user_name = request.match_info.get('user_name', None) try: storage = connect.get_storage_async() cf_mgr = ConfigurationManager(storage) # Fetch the filter items: get category items category_info = await cf_mgr.get_category_all_items( category_name=user_name) if category_info is None: raise ValueError("No such '{}' category found.".format(user_name)) filter_value_from_storage = json.loads( category_info['filter']['value']) except KeyError: msg = "No filter pipeline exists for {}".format(user_name) _LOGGER.info(msg) raise web.HTTPNotFound(reason=msg) except StorageServerError as ex: _LOGGER.exception("Get pipeline: %s, caught exception: %s", user_name, str(ex.error)) raise web.HTTPInternalServerError(reason=str(ex.error)) except ValueError as ex: raise web.HTTPNotFound(reason=ex) except Exception as ex: raise web.HTTPInternalServerError(reason=ex) else: return web.json_response({'result': filter_value_from_storage})
async def delete_parent_category(request): """ Args: request: category_name Returns: remove the link b/w parent-child category for the parent :Example: curl -X DELETE http://localhost:8081/foglamp/category/{category_name}/parent """ category_name = request.match_info.get('category_name', None) category_name = urllib.parse.unquote( category_name) if category_name is not None else None cf_mgr = ConfigurationManager(connect.get_storage_async()) try: await cf_mgr.delete_parent_category(category_name) except TypeError as ex: raise web.HTTPBadRequest(reason=str(ex)) except ValueError as ex: raise web.HTTPNotFound(reason=str(ex)) return web.json_response({ "message": "Parent-child relationship for the parent-{} is deleted".format( category_name) })
async def get_category(request): """ Args: request: category_name is required Returns: the configuration items in the given category. :Example: curl -X GET http://localhost:8081/foglamp/category/PURGE_READ """ category_name = request.match_info.get('category_name', None) category_name = urllib.parse.unquote( category_name) if category_name is not None else None cf_mgr = ConfigurationManager(connect.get_storage_async()) category = await cf_mgr.get_category_all_items(category_name) if category is None: raise web.HTTPNotFound( reason="No such Category found for {}".format(category_name)) try: request.is_core_mgt except AttributeError: category = hide_password(category) return web.json_response(category)
async def test_dupe_category_name_add_service(self, client): mock_plugin_info = { 'name': "furnace4", 'version': "1.1", 'type': "south", 'interface': "1.0", 'mode': "async", 'config': { 'plugin': { 'description': "DHT11", 'type': 'string', 'default': 'dht11' } } } data = {"name": "furnace4", "type": "south", "plugin": "dht11"} storage_client_mock = MagicMock(StorageClientAsync) c_mgr = ConfigurationManager(storage_client_mock) with patch.object(common, 'load_and_fetch_python_plugin_info', side_effect=[mock_plugin_info]): with patch.object(connect, 'get_storage_async', return_value=storage_client_mock): with patch.object(c_mgr, 'get_category_all_items', return_value=self.async_mock( mock_plugin_info)) as patch_get_cat_info: resp = await client.post('/foglamp/service', data=json.dumps(data)) assert 400 == resp.status assert "The '{}' category already exists".format( data['name']) == resp.reason patch_get_cat_info.assert_called_once_with( category_name=data['name'])
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('/foglamp/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 get_category_item(request): """ Args: request: category_name & config_item are required Returns: the configuration item in the given category. :Example: curl -X GET http://localhost:8081/foglamp/category/PURGE_READ/age """ category_name = request.match_info.get('category_name', None) config_item = request.match_info.get('config_item', None) if not category_name or not config_item: raise web.HTTPBadRequest( reason="Both Category Name and Config items are required") # TODO: make it optimized and elegant cf_mgr = ConfigurationManager(connect.get_storage()) category_item = await cf_mgr.get_category_item(category_name, config_item) if category_item is None: raise web.HTTPNotFound(reason="No Category Item Found") return web.json_response(category_item)
async def _read_config(self): """Reads configuration""" default_config = { "max_running_tasks": { "description": "The maximum number of tasks that can be running at any given time", "type": "integer", "default": str(self._DEFAULT_MAX_RUNNING_TASKS) }, "max_completed_task_age_days": { "description": "The maximum age, in days (based on the start time), for a rows " "in the tasks table that do not have a status of running", "type": "integer", "default": str(self._DEFAULT_MAX_COMPLETED_TASK_AGE_DAYS) }, } cfg_manager = ConfigurationManager(self._storage) await cfg_manager.create_category('SCHEDULER', default_config, 'Scheduler configuration') config = await cfg_manager.get_category_all_items('SCHEDULER') self._max_running_tasks = int(config['max_running_tasks']['value']) self._max_completed_task_age = datetime.timedelta( seconds=int(config['max_completed_task_age_days']['value']) * self._DAY_SECONDS)
async def test_create_category_invalid_key(self, client, name="test_cat", desc="Test desc"): info = { 'info': { 'type': 'boolean', 'value': 'False', 'description': 'Test', 'default': 'False' } } payload = { "key": name, "description": desc, "value": info, "keep_original_items": "bla" } storage_client_mock = MagicMock(StorageClient) ConfigurationManager(storage_client_mock) with patch.object(connect, 'get_storage', return_value=storage_client_mock): resp = await client.post('/foglamp/category', data=json.dumps(payload)) assert 400 == resp.status assert "keep_original_items should be boolean true | false" == resp.reason
async def test_config_item_in_use_for_add_config_item(self, client): async def async_mock(): return { "info": { "default": "1", "description": "Test description", "type": "integer" } } category_name = 'cat' payload = { "default": "1", "description": "Test description", "type": "integer" } storage_client_mock = MagicMock(StorageClient) c_mgr = ConfigurationManager(storage_client_mock) with patch.object(connect, 'get_storage', return_value=storage_client_mock): with patch.object( c_mgr, 'get_category_all_items', return_value=async_mock()) as patch_get_all_items: resp = await client.post('/foglamp/category/{}/{}'.format( category_name, "info"), data=json.dumps(payload)) assert 400 == resp.status assert "'Config item is already in use for {}'".format( category_name) == resp.reason patch_get_all_items.assert_called_once_with(category_name)
async def test_set_config_item_not_found(self, client, category_name='rest_api', item_name='http_port'): async def async_mock(): return None payload = {"value": '8082'} storage_client_mock = MagicMock(StorageClient) c_mgr = ConfigurationManager(storage_client_mock) with patch.object(connect, 'get_storage', return_value=storage_client_mock): with patch.object(c_mgr, 'set_category_item_value_entry', return_value=async_mock()) as patch_set_entry: with patch.object( c_mgr, 'get_category_item', return_value=async_mock()) as patch_get_cat_item: resp = await client.put('/foglamp/category/{}/{}'.format( category_name, item_name), data=json.dumps(payload)) assert 404 == resp.status assert "No detail found for the category_name: {} and config_item: {}".format( category_name, item_name) == resp.reason patch_get_cat_item.assert_called_once_with( category_name, item_name) patch_set_entry.assert_called_once_with(category_name, item_name, payload['value'])
async def test_get_categories(self, client): async def async_mock(): return [('rest_api', 'User REST API'), ('service', 'Service configuration')] result = { 'categories': [{ 'key': 'rest_api', 'description': 'User REST API' }, { 'key': 'service', 'description': 'Service configuration' }] } storage_client_mock = MagicMock(StorageClient) c_mgr = ConfigurationManager(storage_client_mock) with patch.object(connect, 'get_storage', return_value=storage_client_mock): with patch.object( c_mgr, 'get_all_category_names', return_value=async_mock()) as patch_get_all_items: resp = await client.get('/foglamp/category') assert 200 == resp.status r = await resp.text() json_response = json.loads(r) assert result == json_response patch_get_all_items.assert_called_once_with()
async def get_category_item(request): """ Args: request: category_name & config_item are required Returns: the configuration item in the given category. :Example: curl -X GET http://localhost:8081/foglamp/category/PURGE_READ/age """ category_name = request.match_info.get('category_name', None) config_item = request.match_info.get('config_item', None) category_name = urllib.parse.unquote( category_name) if category_name is not None else None config_item = urllib.parse.unquote( config_item) if config_item is not None else None cf_mgr = ConfigurationManager(connect.get_storage_async()) category_item = await cf_mgr.get_category_item(category_name, config_item) if category_item is None: raise web.HTTPNotFound( reason="No such Category item found for {}".format(config_item)) return web.json_response(category_item)
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( '/foglamp/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
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('/foglamp/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
async def delete_configuration_item_value(request): """ Args: request: category_name, config_item are required Returns: set the configuration item value to empty string in the given category :Example: curl -X DELETE http://localhost:8081/foglamp/category/{category_name}/{config_item}/value For {category_name}=>PURGE delete value for {config_item}=>age curl -X DELETE http://localhost:8081/foglamp/category/PURGE_READ/age/value """ category_name = request.match_info.get('category_name', None) config_item = request.match_info.get('config_item', None) if not category_name or not config_item: raise web.HTTPBadRequest( reason="Both Category Name and Config items are required") # TODO: make it optimized and elegant cf_mgr = ConfigurationManager(connect.get_storage()) await cf_mgr.set_category_item_value_entry(category_name, config_item, '') result = await cf_mgr.get_category_item(category_name, config_item) if result is None: raise web.HTTPNotFound( reason= "No detail found for the category_name: {} and config_item: {}". format(category_name, config_item)) return web.json_response(result)
async def test_get_category(self, client, category_name='rest_api'): result = { 'httpPort': { 'default': '8081', 'value': '8081', 'type': 'integer', 'description': 'The port to accept HTTP connections on' }, 'certificateName': { 'default': 'foglamp', 'value': 'foglamp', 'type': 'string', 'description': 'Certificate file name' } } async def async_mock(): return result storage_client_mock = MagicMock(StorageClient) c_mgr = ConfigurationManager(storage_client_mock) with patch.object(connect, 'get_storage', return_value=storage_client_mock): with patch.object( c_mgr, 'get_category_all_items', return_value=async_mock()) as patch_get_all_items: resp = await client.get( '/foglamp/category/{}'.format(category_name)) assert 200 == resp.status r = await resp.text() json_response = json.loads(r) assert result == json_response patch_get_all_items.assert_called_once_with(category_name)
async def get_category(request): """ Args: request: category_name is required Returns: the configuration items in the given category. :Example: curl -X GET http://localhost:8081/foglamp/category/PURGE_READ """ category_name = request.match_info.get('category_name', None) if not category_name: raise web.HTTPBadRequest(reason="Category Name is required") # TODO: make it optimized and elegant cf_mgr = ConfigurationManager(connect.get_storage()) category = await cf_mgr.get_category_all_items(category_name) if category is None: raise web.HTTPNotFound( reason="No such Category Found for {}".format(category_name)) return web.json_response(category)
def _update_configuration(cls, age='72', retain_unsent='False') -> dict: """"Update the configuration table with the appropriate information regarding "PURE_READ" using pre-existing configuration_manager tools args: age: corresponds to the `age` value used for purging retainUnsent: corresponds to the `retainUnsent` value used for purging :return: The corresponding values set in the configuration for the purge process """ event_loop = asyncio.get_event_loop() cfg_manager = ConfigurationManager(cls._storage_client) event_loop.run_until_complete(cfg_manager.set_category_item_value_entry( cls._CONFIG_CATEGORY_NAME, 'age', age)) event_loop.run_until_complete(cfg_manager.set_category_item_value_entry( cls._CONFIG_CATEGORY_NAME, 'retainUnsent', retain_unsent)) return event_loop.run_until_complete(cfg_manager.get_category_all_items(cls._CONFIG_CATEGORY_NAME))
async def test_insert_scheduled_process_exception_add_service( self, client): data = {"name": "furnace4", "type": "south", "plugin": "dht11"} @asyncio.coroutine def q_result(*arg): return {'count': 0, 'rows': []} mock_plugin_info = { 'name': "furnace4", 'version': "1.1", 'type': "south", 'interface': "1.0", 'mode': "async", 'config': { 'plugin': { 'description': "DHT11", 'type': 'string', 'default': 'dht11' } } } mock = MagicMock() attrs = {"plugin_info.side_effect": [mock_plugin_info]} mock.configure_mock(**attrs) storage_client_mock = MagicMock(StorageClientAsync) c_mgr = ConfigurationManager(storage_client_mock) with patch('builtins.__import__', return_value=mock): with patch.object(_logger, 'exception') as ex_logger: with patch.object(connect, 'get_storage_async', return_value=storage_client_mock): with patch.object(c_mgr, 'get_category_all_items', return_value=self.async_mock( None)) as patch_get_cat_info: with patch.object(storage_client_mock, 'query_tbl_with_payload', side_effect=q_result) \ as query_table_patch: with patch.object(storage_client_mock, 'insert_into_tbl', side_effect=Exception()): resp = await client.post('/foglamp/service', data=json.dumps(data)) assert 500 == resp.status assert 'Failed to create service.' == resp.reason args1, kwargs1 = query_table_patch.call_args assert 'scheduled_processes' == args1[0] p2 = json.loads(args1[1]) assert { 'return': ['name'], 'where': { 'column': 'name', 'condition': '=', 'value': 'south_c' } } == p2 patch_get_cat_info.assert_called_once_with( category_name=data['name']) assert 1 == ex_logger.call_count
async def update_configuration_item_bulk(request): """ Bulk update config items :Example: curl -X PUT -H "Content-Type: application/json" -d '{"config_item_key": "<some value>", "config_item2_key": "<some value>" }' http://localhost:8081/foglamp/category/{category_name} """ category_name = request.match_info.get('category_name', None) category_name = urllib.parse.unquote( category_name) if category_name is not None else None try: data = await request.json() if not data: return web.HTTPBadRequest(reason='Nothing to update') cf_mgr = ConfigurationManager(connect.get_storage_async()) await cf_mgr.update_configuration_item_bulk(category_name, data) except (NameError, KeyError) as ex: raise web.HTTPNotFound(reason=ex) except (ValueError, TypeError) as ex: raise web.HTTPBadRequest(reason=ex) except Exception as ex: raise web.HTTPInternalServerError(reason=ex) else: result = await cf_mgr.get_category_all_items(category_name) return web.json_response(result)
async def get_notifications(request): """ GET list of notifications :Example: curl -X GET http://localhost:8081/foglamp/notification """ try: storage = connect.get_storage_async() config_mgr = ConfigurationManager(storage) all_notifications = await config_mgr._read_all_child_category_names("Notifications") notifications = [] for notification in all_notifications: notification_config = await config_mgr._read_category_val(notification['child']) notification = { "name": notification_config['name']['value'], "rule": notification_config['rule']['value'], "channel": notification_config['channel']['value'], "notificationType": notification_config['notification_type']['value'], "enable": notification_config['enable']['value'], } notifications.append(notification) except Exception as ex: raise web.HTTPInternalServerError(reason=ex) else: return web.json_response({'notifications': notifications})
async def delete_child_category(request): """ Args: request: category_name, child_category are required Returns: remove the link b/w child category and its parent :Example: curl -X DELETE http://localhost:8081/foglamp/category/{category_name}/children/{child_category} """ category_name = request.match_info.get('category_name', None) child_category = request.match_info.get('child_category', None) category_name = urllib.parse.unquote( category_name) if category_name is not None else None cf_mgr = ConfigurationManager(connect.get_storage_async()) try: result = await cf_mgr.delete_child_category(category_name, child_category) except TypeError as ex: raise web.HTTPBadRequest(reason=str(ex)) except ValueError as ex: raise web.HTTPNotFound(reason=str(ex)) return web.json_response({"children": result})
async def delete_category(request): """ Args: request: category_name required Returns: Success message on successful deletion Raises: TypeError/ValueError/Exception on error :Example: curl -X DELETE http://localhost:8081/foglamp/category/{category_name} """ category_name = request.match_info.get('category_name', None) category_name = urllib.parse.unquote( category_name) if category_name is not None else None try: cf_mgr = ConfigurationManager(connect.get_storage_async()) await cf_mgr.delete_category_and_children_recursively(category_name) except (ValueError, TypeError) as ex: raise web.HTTPBadRequest(reason=ex) except Exception as ex: raise web.HTTPInternalServerError(reason=ex) else: return web.json_response({ 'result': 'Category {} deleted successfully.'.format(category_name) })
async def test_delete_notification_exception(self, mocker, client): mocker.patch.object(ServiceRegistry, 'get', return_value=mock_registry) mocker.patch.object( notification, '_hit_get_url', return_value=mock_get_url("/foglamp/notification/plugin")) storage_client_mock = mocker.patch.object(connect, 'get_storage_async') mocker.patch.object(ConfigurationManager, '__init__', return_value=None) mocker.patch.object( ConfigurationManager, '_read_category_val', return_value=mock_read_category_val("Test Notification")) mocker.patch.object(AuditLogger, "__init__", return_value=None) audit_logger = mocker.patch.object(AuditLogger, "information", return_value=asyncio.sleep(.1)) c_mgr = ConfigurationManager(storage_client_mock) delete_configuration = mocker.patch.object( ConfigurationManager, "delete_category_and_children_recursively", return_value=asyncio.sleep(.1)) resp = await client.delete("/foglamp/notification") assert 405 == resp.status result = await resp.text() assert result.endswith(" Method Not Allowed")
async def _read_config(self): """Reads configuration""" default_config = { "sleep_interval": { "description": "The time (in seconds) to sleep between health checks. (must be greater than 5)", "type": "integer", "default": str(self._DEFAULT_SLEEP_INTERVAL) }, "ping_timeout": { "description": "Timeout for a response from any given microservice. (must be greater than 0)", "type": "integer", "default": str(self._DEFAULT_PING_TIMEOUT) }, } storage_client = connect.get_storage() cfg_manager = ConfigurationManager(storage_client) await cfg_manager.create_category('SMNTR', default_config, 'Service Monitor configuration') config = await cfg_manager.get_category_all_items('SMNTR') self._sleep_interval = int(config['sleep_interval']['value']) self._ping_timeout = int(config['ping_timeout']['value'])
async def create_child_category(request): """ Args: request: category_name is required and JSON object that defines the child category Returns: parent of the children being added :Example: curl -d '{"children": ["coap", "http", "sinusoid"]}' -X POST http://localhost:8081/foglamp/category/south/children """ cf_mgr = ConfigurationManager(connect.get_storage_async()) data = await request.json() if not isinstance(data, dict): raise ValueError('Data payload must be a dictionary') category_name = request.match_info.get('category_name', None) category_name = urllib.parse.unquote( category_name) if category_name is not None else None children = data.get('children') try: r = await cf_mgr.create_child_category(category_name, children) except TypeError as ex: raise web.HTTPBadRequest(reason=str(ex)) except ValueError as ex: raise web.HTTPNotFound(reason=str(ex)) return web.json_response(r)