def load_services(services): for service in services: service_plugins[service] = {} service_config = cf.config('config:' + service) if service_config is None: logger.error("Service `%s' has no config section" % service) sys.exit(1) service_plugins[service]['config'] = service_config module = cf.g('config:' + service, 'module', service) if '.' in module: try: service_plugins[service]['module'] = load_module_by_name(module) logger.info('Successfully loaded service "{}" from module "{}"'.format(service, module)) except Exception as ex: logger.exception('Unable to load service "{}" from module "{}": {}'.format(service, module, ex)) else: modulefile = resource_filename('mqttwarn.services', module + '.py') try: service_plugins[service]['module'] = load_module_from_file(modulefile) logger.info('Successfully loaded service "{}"'.format(service)) except Exception as ex: logger.exception('Unable to load service "{}" from file "{}": {}'.format(service, modulefile, ex))
def test_apprise_multi_basic_success(apprise_asset, apprise_mock, srv, caplog): with caplog.at_level(logging.DEBUG): module = load_module_by_name("mqttwarn.services.apprise_multi") item = Item( addrs=[ { "baseuri": "json://localhost:1234/mqtthook" }, { "baseuri": "json://daq.example.org:5555/foobar" }, ], title="⚽ Message title ⚽", message="⚽ Notification message ⚽", ) outcome = module.plugin(srv, item) assert apprise_mock.mock_calls == [ call(asset=mock.ANY), call().add("json://localhost:1234/mqtthook"), call().add("json://daq.example.org:5555/foobar"), call().notify(body="⚽ Notification message ⚽", title="⚽ Message title ⚽"), call().notify().__bool__(), ] assert outcome is True assert ( "Sending notification to Apprise. target=None, addresses=[{'baseuri': 'json://localhost:1234/mqtthook'}, {'baseuri': 'json://daq.example.org:5555/foobar'}]" in caplog.messages) assert "Successfully sent message using Apprise" in caplog.messages
def load_services(services): for service in services: service_plugins[service] = {} service_config = cf.config('config:' + service) if service_config is None: logger.error("Service `%s' has no config section" % service) sys.exit(1) service_plugins[service]['config'] = service_config module = cf.g('config:' + service, 'module', service) # Load external service from file. modulefile_candidates = [] if module.endswith(".py"): # Add two candidates: a) Use the file as given and b) treat the file as relative to # the directory of the configuration file. That retains backward compatibility. modulefile_candidates.append(module) modulefile_candidates.append(os.path.join(cf.configuration_path, module)) # Load external service with module specification. elif '.' in module: logger.debug('Trying to load service "{}" from module "{}"'.format(service, module)) try: service_plugins[service]['module'] = load_module_by_name(module) logger.info('Successfully loaded service "{}" from module "{}"'.format(service, module)) continue except Exception as ex: logger.exception('Unable to load service "{}" from module "{}": {}'.format(service, module, ex)) # Load built-in service module. else: # Backward-compatibility patch for honoring the renaming of the `http.py` module. if module == "http": module = "http_urllib" logger.debug('Trying to load built-in service "{}" from "{}"'.format(service, module)) modulefile_candidates = [ resource_filename('mqttwarn.services', module + '.py') ] success = False for modulefile in modulefile_candidates: if not os.path.isfile(modulefile): continue logger.debug('Trying to load service "{}" from file "{}"'.format(service, modulefile)) try: service_plugins[service]['module'] = load_module_from_file(modulefile) logger.info('Successfully loaded service "{}"'.format(service)) success = True except Exception as ex: logger.exception('Unable to load service "{}" from file "{}": {}'.format(service, modulefile, ex)) if not success: logger.critical('Unable to load service "{}"'.format(service)) sys.exit(1)
def test_apprise_multi_error(srv, caplog): with caplog.at_level(logging.DEBUG): mock_connection = mock.MagicMock() # Make the call to `notify` raise an exception. def error(*args, **kwargs): raise Exception("something failed") mock_connection.notify = error with mock.patch("apprise.Apprise", side_effect=[mock_connection], create=True) as mock_client: with mock.patch("apprise.AppriseAsset", create=True) as mock_asset: module = load_module_by_name("mqttwarn.services.apprise_multi") item = Item( addrs=[{ "baseuri": "json://localhost:1234/mqtthook" }], title="⚽ Message title ⚽", message="⚽ Notification message ⚽", ) outcome = module.plugin(srv, item) assert mock_client.mock_calls == [ mock.call(asset=mock.ANY), ] assert mock_connection.mock_calls == [ call.add("json://localhost:1234/mqtthook"), ] assert outcome is False assert ( "Sending notification to Apprise. target=None, addresses=[{'baseuri': 'json://localhost:1234/mqtthook'}]" in caplog.messages) assert ( "Sending message using Apprise failed. target=None, error=something failed" in caplog.messages)
def test_amqp_failure(srv, caplog): module = load_module_by_name("mqttwarn.services.amqp") exchange, routing_key = ["name_of_exchange", "my_routing_key"] item = Item( config={"uri": "amqp://*****:*****@localhost:5672/"}, target="test", addrs=[exchange, routing_key], message="⚽ Notification message ⚽", ) with caplog.at_level(logging.DEBUG): mock_connection = mock.MagicMock() # Make the call to `basic_publish` raise an exception. def error(*args, **kwargs): raise Exception("something failed") mock_connection.basic_publish = error with mock.patch("puka.Client", side_effect=[mock_connection], create=True) as mock_client: outcome = module.plugin(srv, item) assert mock_client.mock_calls == [ mock.call("amqp://*****:*****@localhost:5672/"), ] assert mock_connection.mock_calls == [ call.connect(), call.wait(mock.ANY), ] assert outcome is False assert ("AMQP publish to test [name_of_exchange/my_routing_key]" in caplog.text) assert ( "Error on AMQP publish to test [name_of_exchange/my_routing_key]: something failed" in caplog.text)
def test_amqp_success(mock_puka_client, srv, caplog): module = load_module_by_name("mqttwarn.services.amqp") exchange, routing_key = ["name_of_exchange", "my_routing_key"] item = Item( config={"uri": "amqp://*****:*****@localhost:5672/"}, target="test", addrs=[exchange, routing_key], message="⚽ Notification message ⚽", ) with caplog.at_level(logging.DEBUG): outcome = module.plugin(srv, item) assert mock_puka_client.mock_calls == [ mock.call("amqp://*****:*****@localhost:5672/"), call().connect(), call().wait(mock.ANY), call().basic_publish( exchange="name_of_exchange", routing_key="my_routing_key", headers={ "content_type": "text/plain", "x-agent": "mqttwarn", "delivery_mode": 1, }, body="⚽ Notification message ⚽", ), call().wait(mock.ANY), call().close(), ] assert outcome is True assert "AMQP publish to test [name_of_exchange/my_routing_key]" in caplog.text assert "Successfully published AMQP notification" in caplog.text
def test_apprise_multi_mailto_success(apprise_asset, apprise_mock, srv, caplog): with caplog.at_level(logging.DEBUG): module = load_module_by_name("mqttwarn.services.apprise_multi") item = Item( addrs=[{ "baseuri": "mailtos://*****:*****@mail.example.org", "recipients": ["*****@*****.**", "*****@*****.**"], "sender": "*****@*****.**", "sender_name": "Example Monitoring", }], title="⚽ Message title ⚽", message="⚽ Notification message ⚽", ) outcome = module.plugin(srv, item) assert apprise_mock.mock_calls == [ call(asset=mock.ANY), call().add( "mailtos://*****:*****@mail.example.org?to=foo%40example.org%2Cbar%40example.org&from=monitoring%40example.org&name=Example+Monitoring" ), call().notify(body="⚽ Notification message ⚽", title="⚽ Message title ⚽"), call().notify().__bool__(), ] assert outcome is True assert ( "Sending notification to Apprise. target=None, addresses=[{'baseuri': 'mailtos://*****:*****@mail.example.org', 'recipients': ['*****@*****.**', '*****@*****.**'], 'sender': '*****@*****.**', 'sender_name': 'Example Monitoring'}]" in caplog.messages) assert "Successfully sent message using Apprise" in caplog.messages
def test_load_module_by_name_bad(): with pytest.raises(ImportError) as excinfo: load_module_by_name("mqttwarn.services.unknown") assert str(excinfo.value) == "ImportError: No module named unknown"
def test_load_module_by_name_good(): module = load_module_by_name("mqttwarn.services.file") assert "plugin" in dir(module) assert module.plugin.__code__.co_argcount == 2 assert "srv" in module.plugin.__code__.co_varnames assert "item" in module.plugin.__code__.co_varnames
def test_load_module_by_name_good(): module = load_module_by_name('mqttwarn.services.file') assert 'plugin' in dir(module) assert module.plugin.__code__.co_argcount == 2 assert 'srv' in module.plugin.__code__.co_varnames assert 'item' in module.plugin.__code__.co_varnames