Пример #1
0
def find_and_configure_plugins(env_deployments):
    """Find and configure plugins that may have been declared.

    If the option 'plugins' is not defined, this function is a no-op.  If the
    plugins value is not a string or list, the an error is logged and the
    function just returns; i.e. misconfiguring the plugins option in the yaml
    file doesn't end the test.

    :param env_deployments: The enviroments that are doing to be run.
    :type env_deployments: List[EnvironmentDeploy]
    :raises Exception: a plugin may explode, which means this function can
        fail.
    """
    plugins = get_option("plugins")
    if plugins is None:
        return
    if isinstance(plugins, str):
        plugins = (plugins, )
    if not isinstance(plugins, Iterable):
        logger.error("Couldn't load plugins as it doesn't seem to be a list?")
        return
    for plugin_func in plugins:
        logger.info("Running plugin func %s()", plugin_func)
        try:
            utils.get_class(plugin_func)(env_deployments)
        except Exception as e:
            logger.error("Plugin func: '%s' failed with %s", plugin_func,
                         str(e))
            import traceback
            logger.error(traceback.format_exc())
            raise
Пример #2
0
def upload_collection_by_config(collection, context=None):
    """Upload a collection's events using a configured set of uploaders.

    :param collection: the collection whose logs to upload.
    :type collection: zaza.events.collection.Collection
    :param context: a context of dictionary keys for filling in values
    :type context: Optional[Dict[str, str]]
    """
    uploads = get_option('zaza-events.upload', [])
    if isinstance(uploads, str) or not isinstance(uploads, Iterable):
        logger.error("Config to upload logs is misconfigured? %s", uploads)
        return
    for upload in uploads:
        if not isinstance(upload, Mapping):
            logger.error(
                "Ignoring upload; it doesn't seem correcly formatted?", upload)
            continue
        try:
            upload_type = upload['type']
        except KeyError:
            logger.error("No type provided for upload, ignoring: %s", upload)
            continue
        if not isinstance(upload_type, str):
            logger.error("upload type is not a str, ignoring: %s", upload_type)
            continue

        upload_type = upload_type.lower()

        # TODO: this would be nicer as a dict lookup to make it more
        # flexible, but for the moment, we only support InfluxDB
        if upload_type == "influxdb":
            upload_influxdb(upload, collection, context)
        else:
            logger.error("Unknown type %s for uploading; ignoring",
                         upload_type)
Пример #3
0
    def __init__(self, env_deployments):
        """Initialise the Events Plugin.

        :param env_deployments: the deployments/tests that will happen.
        :type env_deployments: List[EnvironmentDeploy]
        """
        self.env_deployments = env_deployments

        keep_logs = get_option('zaza-events.keep-logs', False)
        if keep_logs:
            self.logs_dir_base = os.path.join(tempfile.gettempdir(),
                                              "zaza-events")
            Path(self.logs_dir_base).mkdir(parents=True, exist_ok=True)
            logger.debug("Ensuring logs base dir as: %s", self.logs_dir_base)
        else:
            # get a directory that will disappear at the end of the program.
            self.logs_dir_base = tempfile.TemporaryDirectory("-zaza-events")

        # Handle all notifications and turn them into zaza.events for the
        # timeseries event logging.
        subscribe(self.handle_notifications, event=None, when=NotifyType.BOTH)

        # Handle the BEFORE and AFTER bundle notifications to actually create
        # and finalise the events logger after each deployment.
        subscribe(self.handle_before_bundle,
                  event=NotifyEvents.BUNDLE,
                  when=NotifyType.BEFORE)
        subscribe(self.handle_after_bundle,
                  event=NotifyEvents.BUNDLE,
                  when=NotifyType.AFTER)
        logger.info("Configured EventsPlugin.")
 def test_get_option(self):
     options = {
         'key1': 'value1',
         'key2': 2,
         'key3': {
             'key3-1': 3,
             'key3-2': 4,
         },
         'key4': ['a', 'b', 'c', {
             "key4-3-1": 5
         }],
     }
     self.patch_object(g, '_options', new=options)
     self.assertEqual(g.get_option("key1"), "value1")
     self.assertEqual(g.get_option("key2"), 2)
     self.assertEqual(g.get_option("key3.key3-1"), 3)
     self.assertEqual(g.get_option("key3.key3-2"), 4)
     self.assertEqual(g.get_option("key4.3.key4-3-1"), 5)
Пример #5
0
def get_global_events_logging_manager():
    """Return the events logging manager (for the collection).

    This returns the logging manager for logging time-series events from within
    zaza tests.  The advantage of using this is that it taps into the
    global_options to get the 'right' one for the test.

    Note: if there are no zaza-events options configured the 'DEFAULT' event
    logging manager will be returned, which if nothing is configured, won't do
    anything with logs if a logger is requested and then used.

    :returns: the configured logging manager.
    :rtype: zaza.events.plugins.logging.LoggerPluginManager
    """
    name = get_option("zaza-events.modules.logging.logger-name", None)
    if name is None:
        name = get_option("zaza-events.collection-name", "DEFAULT")
    return get_plugin_manager(name)
Пример #6
0
def get_conncheck_manager():
    """Get the conncheck manager that's most like to be useful.

    If zaza-events.modules.conncheck.manager-name is defined, then use that to
    return the manager, otherwise, use the DEFAULT.

    :returns: a conncheck manager
    :rtype: ConnCheckPluginManager
    """
    name = get_option('zaza-events.modules.conncheck.manager-name', "DEFAULT")
    return get_plugin_manager(name)
Пример #7
0
def configure(env_deployments):
    """Configure the event plugin for events.

    If the 'zaza-events' config option is available, this configures the
    EventsPlugin that then glues zaza.notifications published events into
    zaza.events time-series notifications.

    :param env_deployments: the deployments/tests that will happen.
    :type env_deployments: List[EnvironmentDeploy]
    """
    config = get_option("zaza-events", raise_exception=False)
    if config is None:
        logger.error(
            "zaza.events.configure called, but no configuration found")
        return

    # Note that the subscriptions in the __init__() will keep events_plugin
    # around until the end of the program run.
    EventsPlugin(env_deployments)
Пример #8
0
def get_collection(name=None):
    """Return a collection by name.

    Collections are available globally, and typically only one will be needed
    per test.  If the global options 'zaza-events.collection-name' is defined,
    then that collection name is used for the collection.  This is so a global
    collection can be used within tests if wanted.  Obviously, overriding
    :param:`name` will force a particular collection to be returned.

    This returns a named collection (a.k.a logging) for use in a module.

    :returns: the colection named, or creates a new one of that name.
    :rtype: Collection
    """
    global _collections
    if name is None:
        name = get_option("zaza-events.collection-name", "DEFAULT")
    try:
        return _collections[name]
    except KeyError:
        pass
    _collections[name] = Collection(name=name)
    return _collections[name]
Пример #9
0
    def handle_before_bundle(self,
                             event,
                             when,
                             *args,
                             env_deployment=None,
                             **kwargs):
        """Handle when a new bundle is about to be performed.

        This resets/configures the collection. This allows a complete test run
        be a bundle that gets all its logs collected and then saved "somewhere"
        according to the config.

        :param event: This must be NotifyEvents.BUNDLE
        :type event: NotifyEvents
        :param when: This must be NotifyType.BEFORE
        :type when: NotifyType
        :param *args: Any additional args passed; these are ignored.
        :type *args: Tuple(ANY)
        :param env_deployment: The deployment details for this model.
        :type env_deployment: EnvironmentDeploy
        :param **kwargs: Any additional kwargs; these are ignored.
        :type **kwargs: Dict[str, ANY]
        """
        logger.info("handle_before_bundle() called for env_deployment:%s",
                    env_deployment)
        assert event is NotifyEvents.BUNDLE
        assert when is NotifyType.BEFORE
        assert env_deployment is not None
        # Note that get_collection gets a zaza-events.* configured collection
        # if the collection-name key is present.
        collection = ze_collection.get_collection()
        collection.reset()
        context = event_context_vars(env_deployment)
        log_collection_name = expand_vars(
            context,
            get_option('zaza-events.log-collection-name', env_deployment.name))
        description = get_option('zaza-events.collection-description')
        logs_dir_name = expand_vars(context, "{bundle}-{date}")
        try:
            logs_dir_base = self.logs_dir_base.name
        except AttributeError:
            logs_dir_base = self.logs_dir_base
        logs_dir = os.path.join(logs_dir_base, logs_dir_name)
        Path(logs_dir).mkdir(parents=True, exist_ok=True)
        collection.configure(collection=log_collection_name,
                             description=description,
                             logs_dir=logs_dir)

        # Now configure any additional modules automagically
        modules = get_option('zaza-events.modules', [])
        if isinstance(modules, str) or not isinstance(modules, Iterable):
            logger.error("Option zaza-events.module isn't a list? %s", modules)
            return
        for module_spec in modules:
            # if module is a dictionary then it's a key: spec, otherwise there
            # is no spec for the module.
            if isinstance(module_spec, dict):
                if len(module_spec.keys()) != 1:
                    logger.error(
                        "Module key %s is not formatted as a single-key "
                        "dictionary", module_spec)
                    continue
                module, config = list(module_spec.items())[0]
                if not isinstance(config, dict):
                    logger.error("Module key %s has invalid config %s", module,
                                 config)
                    continue
            elif isinstance(module_spec, str):
                module, config = (module_spec, {})
            else:
                logger.error("Can configure with %s.", module_spec)
                continue
            configure_func = (
                "zaza.events.plugins.{}.auto_configure_with_collection".format(
                    module))
            try:
                logger.info("Running autoconfigure for zaza-events func %s()",
                            configure_func)
                utils.get_class(configure_func)(collection, config)
            except Exception as e:
                logger.error(
                    "Error running autoconfigure for zaza-events %s: %s",
                    configure_func, str(e))
                if get_option('zaza-events.raise-exceptions', False):
                    raise

        # events = logging_manager.get_global_event_logger_instance()
        events = get_global_event_logger_instance()
        events.log(Events.START_TEST,
                   comment="Starting {}".format(log_collection_name))