def test_struct(): data = {'hello': 'world'} struct = Struct(**data) assert struct.hello == 'world' assert struct.get('hello') == 'world' assert struct.get('unknown', default=42) == 42 assert repr(struct) == "<hello: 'world'>" assert struct.enum() == data
def test_struct(): data = {"hello": "world"} struct = Struct(**data) assert struct.hello == "world" assert struct.get("hello") == "world" assert struct.get("unknown", default=42) == 42 assert repr(struct) == "<hello: 'world'>" assert struct.enum() == data
def run_plugin(config=None, name=None, options=None): """ Run service plugins directly without the dispatching and transformation machinery. On the one hand, this might look like a bit of a hack. On the other hand, it shows very clearly how some of the innards of mqttwarn interact so it might also please newcomers as a "learning the guts of mqttwarn" example. :param config: The configuration object :param name: The name of the service plugin, e.g. "log" or "file" :param options: The data to be converged into an appropriate item Struct object instance """ # Bootstrap mqttwarn core # TODO: Optionally run w/o configuration. bootstrap(config=config) # Load designated service plugins load_services([name]) if '.' in name: service_logger_name = name else: service_logger_name = 'mqttwarn.services.{}'.format(name) srv = make_service(mqttc=None, name=service_logger_name) # Build a mimikry item instance for feeding to the service plugin item = Struct(**options) # TODO: Read configuration optionally from data. item.config = config.config('config:' + name) item.service = srv item.target = 'mqttwarn' item.data = {} # FIXME # Launch plugin module = service_plugins[name]['module'] response = module.plugin(srv, item) logger.info('Plugin response: {}'.format(response)) if response is False: sys.exit(1)
def processor(worker_id=None): """ Queue runner. Pull a job from the queue, find the module in charge of handling the service, and invoke the module's plugin to do so. """ while not exit_flag: logger.debug('Job queue has %s items to process' % q_in.qsize()) job = q_in.get() service = job.service section = job.section target = job.target topic = job.topic logger.debug("Processor #%s is handling: `%s' for %s" % (worker_id, service, target)) # Sanity checks. # If service configuration or targets can not be obtained successfully, # log a sensible error message, fail the job and carry on with the next job. try: service_config = context.get_service_config(service) service_targets = context.get_service_targets(service) if target not in service_targets: error_message = "Invalid configuration: Topic '{topic}' points to " \ "non-existing target '{target}' in service '{service}'".format(**locals()) raise KeyError(error_message) except Exception as ex: logger.error("Cannot handle service=%s, target=%s: %s\n%s" % (service, target, ex, exception_traceback())) q_in.task_done() continue item = { 'service' : service, 'section' : section, 'target' : target, 'config' : service_config, 'addrs' : service_targets[target], 'topic' : topic, 'payload' : job.payload, 'data' : None, 'title' : None, 'image' : None, 'message' : None, 'priority' : None } transform_data = job.data item['data'] = dict(list(transform_data.items())) item['title'] = xform(context.get_config(section, 'title'), SCRIPTNAME, transform_data) item['image'] = xform(context.get_config(section, 'image'), '', transform_data) item['message'] = xform(context.get_config(section, 'format'), job.payload, transform_data) try: item['priority'] = int(xform(context.get_config(section, 'priority'), 0, transform_data)) except Exception as e: item['priority'] = 0 logger.warning("Failed to determine the priority, defaulting to zero: %s" % e) if HAVE_JINJA is False and context.get_config(section, 'template'): logger.warning("Templating not possible because Jinja2 is not installed") if HAVE_JINJA is True: template = context.get_config(section, 'template') if template is not None: try: text = render_template(template, transform_data) if text is not None: item['message'] = text except Exception as e: logger.warning("Cannot render `%s' template: %s" % (template, e)) if item.get('message') is not None and len(item.get('message')) > 0: st = Struct(**item) notified = False try: # Fire the plugin in a separate thread and kill it if it doesn't return in 10s module = service_plugins[service]['module'] service_logger_name = 'mqttwarn.services.{}'.format(service) srv = make_service(mqttc=mqttc, name=service_logger_name) notified = timeout(module.plugin, (srv, st)) except Exception as e: logger.error("Cannot invoke service for `%s': %s" % (service, e)) if not notified: logger.warning("Notification of %s for `%s' FAILED or TIMED OUT" % (service, item.get('topic'))) else: logger.warning("Notification of %s for `%s' suppressed: text is empty" % (service, item.get('topic'))) q_in.task_done() logger.debug("Thread exiting...")