Example #1
0
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
Example #2
0
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
Example #3
0
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)
Example #4
0
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...")