def test_fetch_c_hybrid_plugins_installed(self): info = { "version": "1.6.0", "name": "FlirAX8", "config": { "asset": { "description": "Default asset name", "default": "flir", "displayName": "Asset Name", "type": "string" }, "plugin": { "description": "A Modbus connected Flir AX8 infrared camera", "default": "FlirAX8", "readonly": "true", "type": "string" } } } with patch.object(utils, "find_c_plugin_libs", return_value=[("FlirAX8", "json") ]) as patch_plugin_lib: with patch.object(common, "load_and_fetch_c_hybrid_plugin_info", return_value=info) as patch_hybrid_plugin_info: PluginDiscovery.fetch_c_plugins_installed('south', True) patch_hybrid_plugin_info.assert_called_once_with( info['name'], True) patch_plugin_lib.assert_called_once_with('south')
def test_bad_get_north_plugin_config(self, exc_name, log_exc_name, msg): with patch.object(_logger, log_exc_name) as patch_log_exc: with patch.object(common, 'load_and_fetch_python_plugin_info', side_effect=[exc_name]): PluginDiscovery.get_plugin_config("http", "north", False) assert 1 == patch_log_exc.call_count args, kwargs = patch_log_exc.call_args assert msg in args[0]
def test_fetch_c_plugins_installed(self, info, dir_name): with patch.object(utils, "find_c_plugin_libs", return_value=[info['name']]) as patch_plugin_lib: with patch.object(utils, "get_plugin_info", return_value=info) as patch_plugin_info: PluginDiscovery.fetch_c_plugins_installed(dir_name, True) patch_plugin_info.assert_called_once_with(info['name'], dir=dir_name) patch_plugin_lib.assert_called_once_with(dir_name)
def test_deprecated_python_plugins(self, info, warn_count, is_config=True): with patch.object(_logger, "warning") as patch_log_warn: with patch.object(common, 'load_and_fetch_python_plugin_info', side_effect=[info]): PluginDiscovery.get_plugin_config(info['name'], info['type'], is_config) assert warn_count == patch_log_warn.call_count if warn_count: args, kwargs = patch_log_warn.call_args assert '"{}" plugin is deprecated'.format(info['name']) == args[0]
def test_bad_get_north_plugin_config(self, exc_name, log_exc_name, msg): mock = MagicMock() attrs = {"plugin_info.side_effect": exc_name} mock.configure_mock(**attrs) with patch.object(_logger, log_exc_name) as patch_log_exc: with patch('builtins.__import__', return_value=mock): PluginDiscovery.get_plugin_config("http", "north", False) assert 1 == patch_log_exc.call_count args, kwargs = patch_log_exc.call_args assert msg in args[0]
def test_bad_fetch_c_north_plugin_installed(self, info, exc_count): with patch.object(_logger, "exception") as patch_log_exc: with patch.object(utils, "find_c_plugin_libs", return_value=["PI_Server"]) as patch_plugin_lib: with patch.object(utils, "get_plugin_info", return_value=info) as patch_plugin_info: PluginDiscovery.fetch_c_plugins_installed("north", False) patch_plugin_info.assert_called_once_with('PI_Server', dir='north') patch_plugin_lib.assert_called_once_with('north') assert exc_count == patch_log_exc.call_count
def test_bad_fetch_c_south_plugin_installed(self, info, exc_count): with patch.object(_logger, "exception") as patch_log_exc: with patch.object(utils, "find_c_plugin_libs", return_value=[("Random", "binary") ]) as patch_plugin_lib: with patch.object(utils, "get_plugin_info", return_value=info) as patch_plugin_info: PluginDiscovery.fetch_c_plugins_installed("south", False) patch_plugin_info.assert_called_once_with('Random', dir='south') patch_plugin_lib.assert_called_once_with('south') assert exc_count == patch_log_exc.call_count
async def get_plugins_installed(request): """ get list of installed plugins :Example: curl -X GET http://localhost:8081/foglamp/plugins/installed curl -X GET http://localhost:8081/foglamp/plugins/installed?config=true curl -X GET http://localhost:8081/foglamp/plugins/installed?type=north|south|filter|notificationDelivery|notificationRule curl -X 'GET http://localhost:8081/foglamp/plugins/installed?type=north&config=true' """ plugin_type = None is_config = False if 'type' in request.query and request.query['type'] != '': plugin_type = request.query['type'].lower() if request.query['type'] not in ['notificationDelivery', 'notificationRule'] else request.query['type'] if plugin_type is not None and plugin_type not in ['north', 'south', 'filter', 'notificationDelivery', 'notificationRule']: raise web.HTTPBadRequest(reason="Invalid plugin type. Must be 'north' or 'south' or 'filter' or 'notificationDelivery' or 'notificationRule'.") if 'config' in request.query: config = request.query['config'] if config not in ['true', 'false', True, False]: raise web.HTTPBadRequest(reason='Only "true", "false", true, false' ' are allowed for value of config.') is_config = True if ((type(config) is str and config.lower() in ['true']) or ( (type(config) is bool and config is True))) else False plugins_list = PluginDiscovery.get_plugins_installed(plugin_type, is_config) return web.json_response({"plugins": plugins_list})
def test_bad_get_plugin_config(self): mock_plugin_info = { 'name': "HTTP", 'version': "1.0.0", 'type': "north", 'interface': "1.0.0", 'config': { 'plugin': { 'description': "HTTP north plugin", 'type': 'string', 'default': 'http-north' } } } mock = MagicMock() attrs = {"plugin_info.side_effect": [mock_plugin_info]} mock.configure_mock(**attrs) with patch.object(_logger, "warning") as patch_log_warn: with patch('builtins.__import__', return_value=mock): actual = PluginDiscovery.get_plugin_config( "http-north", "south", False) assert actual is None patch_log_warn.assert_called_once_with( 'Plugin http-north is discarded due to invalid type')
def test_get_plugins_installed_type_south(self, mocker): @asyncio.coroutine def mock_folders(): yield TestPluginDiscovery.mock_south_folders @asyncio.coroutine def mock_c_folders(): yield TestPluginDiscovery.mock_c_south_folders mock_get_folders = mocker.patch.object(PluginDiscovery, "get_plugin_folders", return_value=next( mock_folders())) mock_get_plugin_config = mocker.patch.object( PluginDiscovery, "get_plugin_config", side_effect=TestPluginDiscovery.mock_plugins_south_config) mock_get_c_folders = mocker.patch.object(utils, "find_c_plugin_libs", return_value=next( mock_c_folders())) mock_get_c_plugin_config = mocker.patch.object( utils, "get_plugin_info", side_effect=TestPluginDiscovery.mock_c_plugins_south_config) plugins = PluginDiscovery.get_plugins_installed("south") expected_plugin = TestPluginDiscovery.mock_plugins_south_config expected_plugin.extend(TestPluginDiscovery.mock_c_plugins_south_config) # FIXME: ordering issue # assert expected_plugin == plugins assert 1 == mock_get_folders.call_count assert 2 == mock_get_plugin_config.call_count assert 1 == mock_get_c_folders.call_count assert 1 == mock_get_c_plugin_config.call_count
def test_get_plugin_config(self, info, expected, is_config): with patch.object(common, 'load_and_fetch_python_plugin_info', side_effect=[info]): actual = PluginDiscovery.get_plugin_config("modbus", "south", is_config) assert expected == actual
def test_deprecated_c_plugins_installed(self, info, dir_name): info['flag'] = api_utils.DEPRECATED_BIT_MASK_VALUE with patch.object(_logger, "warning") as patch_log_warn: with patch.object(utils, "find_c_plugin_libs", return_value=[(info['name'], "binary") ]) as patch_plugin_lib: with patch.object(utils, "get_plugin_info", return_value=info) as patch_plugin_info: PluginDiscovery.fetch_c_plugins_installed(dir_name, True) patch_plugin_info.assert_called_once_with(info['name'], dir=dir_name) patch_plugin_lib.assert_called_once_with(dir_name) assert 1 == patch_log_warn.call_count args, kwargs = patch_log_warn.call_args assert '"{}" plugin is deprecated'.format(info['name']) == args[0]
def test_get_plugin_config(self, info, expected, is_config): mock = MagicMock() attrs = {"plugin_info.side_effect": [info]} mock.configure_mock(**attrs) with patch('builtins.__import__', return_value=mock): actual = PluginDiscovery.get_plugin_config("modbus", "south", is_config) assert expected == actual
def test_get_plugin_folders(self, mocker): @asyncio.coroutine def mock_folders(): listdir = copy.deepcopy(TestPluginDiscovery.mock_north_folders) listdir.extend(["__init__", "empty", "common"]) yield listdir mocker.patch.object(os, "listdir", return_value=next(mock_folders())) mocker.patch.object(os.path, "isdir", return_value=True) plugin_folders = PluginDiscovery.get_plugin_folders("north") assert TestPluginDiscovery.mock_north_folders == plugin_folders
async def update_plugin(request: web.Request) -> web.Response: """ update plugin :Example: curl -X PUT http://localhost:8081/foglamp/plugins/south/sinusoid/update curl -X PUT http://localhost:8081/foglamp/plugins/north/http_north/update """ _type = request.match_info.get('type', None) name = request.match_info.get('name', None) try: # TODO: FOGL-3063, FOGL-3064 _type = _type.lower() if _type not in ['north', 'south']: raise ValueError("Invalid plugin type. Must be 'north' or 'south'") # Check requested plugin name is installed or not installed_plugins = PluginDiscovery.get_plugins_installed(_type, False) installed_plugin_name = [p_name["name"] for p_name in installed_plugins] if name not in installed_plugin_name: raise KeyError("{} plugin is not yet installed. So update is not possible.".format(name)) # Tracked plugins from asset tracker tracked_plugins = await _get_plugin_and_sch_name_from_asset_tracker(_type) sch_list = [] for p in tracked_plugins: if name == p['plugin']: sch_info = await _get_sch_id_and_enabled_by_name(p['service']) if sch_info[0]['enabled'] == 't': status, reason = await server.Server.scheduler.disable_schedule(uuid.UUID(sch_info[0]['id'])) if status: _logger.warning("{} {} instance is disabled as {} plugin is updating..".format( p['service'], _type, p['plugin'])) sch_list.append(sch_info[0]['id']) # Plugin update is running as a background task loop = request.loop request._type = _type request._name = name request._sch_list = sch_list loop.call_later(1, do_update, request) except KeyError as ex: raise web.HTTPNotFound(reason=ex) except ValueError as ex: raise web.HTTPBadRequest(reason=ex) except Exception as ex: raise web.HTTPInternalServerError(reason=ex) return web.json_response({"message": "{} plugin update in process. Wait for few minutes to complete.".format(name)})
def test_fetch_plugins_installed(self, mocker): @asyncio.coroutine def mock_folders(): yield TestPluginDiscovery.mock_north_folders mock_get_folders = mocker.patch.object(PluginDiscovery, "get_plugin_folders", return_value=next( mock_folders())) mock_get_plugin_config = mocker.patch.object( PluginDiscovery, "get_plugin_config", side_effect=TestPluginDiscovery.mock_plugins_north_config) plugins = PluginDiscovery.fetch_plugins_installed("north", False) # FIXME: below line is failing when in suite # assert TestPluginDiscovery.mock_plugins_north_config == plugins assert 1 == mock_get_folders.call_count assert 2 == mock_get_plugin_config.call_count
def test_get_c_rules_plugins_installed(self, mocker): @asyncio.coroutine def mock_rule_folders(): yield TestPluginDiscovery.mock_c_rule_folders mock_get_c_rule_folders = mocker.patch.object(utils, "find_c_plugin_libs", return_value=next( mock_rule_folders())) mock_get_c_rule_plugin_config = mocker.patch.object( utils, "get_plugin_info", side_effect=TestPluginDiscovery.mock_c_rule_config) plugins = PluginDiscovery.get_plugins_installed("rule") # expected_plugin = TestPluginDiscovery.mock_c_plugins_config[4] # FIXME: ordering issue # assert expected_plugin == plugins assert 1 == mock_get_c_rule_folders.call_count assert 1 == mock_get_c_rule_plugin_config.call_count
def test_bad_get_plugin_config(self): mock_plugin_info = { 'name': "HTTP", 'version': "1.0.0", 'type': "north", 'interface': "1.0.0", 'config': { 'plugin': { 'description': "HTTP north plugin", 'type': 'string', 'default': 'http-north' } } } with patch.object(_logger, "warning") as patch_log_warn: with patch.object(common, 'load_and_fetch_python_plugin_info', side_effect=[mock_plugin_info]): actual = PluginDiscovery.get_plugin_config( "http-north", "south", False) assert actual is None patch_log_warn.assert_called_once_with( 'Plugin http-north is discarded due to invalid type')
def _get_installed_plugins(): return PluginDiscovery.get_plugins_installed("north", False)