예제 #1
0
def register_lookup_handler(lookup_type, handler_or_path):
    """Register a lookup handler.

    Args:
        lookup_type (str): Name to register the handler under.
        handler_or_path (Union[Callable, str]): A function or a path to a
            handler.

    """
    handler = handler_or_path
    if isinstance(handler_or_path, string_types):
        handler = load_object_from_string(handler_or_path)
    CFNGIN_LOOKUP_HANDLERS[lookup_type] = handler
    if not isinstance(handler, type):
        # Hander is a not a new-style handler
        logger = logging.getLogger(__name__)
        logger.warning(
            "Registering lookup `%s`: Please upgrade to use the "
            "new style of Lookups.", lookup_type)
        warnings.warn(
            # For some reason, this does not show up...
            # Leaving it in anyway
            "Lookup `%s`: Please upgrade to use the new style of Lookups"
            "." % lookup_type,
            DeprecationWarning,
            stacklevel=2,
        )
예제 #2
0
def test_load_object_from_string():
    """Test load object from string."""
    tests = (("string.Template", string.Template),
             ("os.path.basename", os.path.basename), ("string.ascii_letters",
                                                      string.ascii_letters))
    for test in tests:
        assert load_object_from_string(test[0]) is test[1]
예제 #3
0
def test_load_object_from_string():
    """Test load object from string."""
    tests = (("string.Template", string.Template),
             ("os.path.basename", os.path.basename), ("string.ascii_letters",
                                                      string.ascii_letters))
    for test in tests:
        assert load_object_from_string(test[0]) is test[1]

    obj_path = 'tests.fixtures.mock_hooks.GLOBAL_VALUE'
    # check value from os.environ
    assert load_object_from_string(obj_path, try_reload=True) == 'us-east-1'

    with environ({'AWS_DEFAULT_REGION': 'us-west-2'}):
        # check value from os.environ after changing it to ensure reload
        assert load_object_from_string(obj_path,
                                       try_reload=True) == 'us-west-2'
예제 #4
0
    def blueprint(self):
        """Return the blueprint associated with this stack."""
        if not self._blueprint:
            kwargs = {}
            blueprint_class = None
            if self.definition.class_path:
                class_path = self.definition.class_path
                blueprint_class = load_object_from_string(class_path)
                if not hasattr(blueprint_class, "rendered"):
                    raise AttributeError("Stack class %s does not have a "
                                         "\"rendered\" "
                                         "attribute." % (class_path, ))
            elif self.definition.template_path:
                blueprint_class = RawTemplateBlueprint
                kwargs["raw_template_path"] = self.definition.template_path
            else:
                raise AttributeError("Stack does not have a defined class or "
                                     "template path.")

            self._blueprint = blueprint_class(
                name=self.name,
                context=self.context,
                mappings=self.mappings,
                description=self.definition.description,
                **kwargs)
        return self._blueprint
예제 #5
0
def register_lookup_handler(lookup_type, handler_or_path):
    # type: (str, Union[Type[LookupHandler], str]) -> None
    """Register a lookup handler.

    Args:
        lookup_type: Name to register the handler under
        handler_or_path: a function or a path to a handler

    """
    handler = handler_or_path
    if isinstance(handler_or_path, string_types):
        handler = load_object_from_string(handler_or_path)
    RUNWAY_LOOKUP_HANDLERS[lookup_type] = handler
예제 #6
0
def test_load_object_from_string_reload_conditions(mock_six):
    """Test load_object_from_string reload conditions."""
    mock_six.moves.reload_module.return_value = MagicMock()
    builtin_test = 'sys.version_info'
    mock_hook = 'tests.fixtures.mock_hooks.GLOBAL_VALUE'

    try:
        del sys.modules['tests.fixtures.mock_hooks']
    except:  # noqa pylint: disable=bare-except
        pass

    load_object_from_string(builtin_test, try_reload=False)
    mock_six.moves.reload_module.assert_not_called()

    load_object_from_string(builtin_test, try_reload=True)
    mock_six.moves.reload_module.assert_not_called()

    load_object_from_string(mock_hook, try_reload=True)
    mock_six.moves.reload_module.assert_not_called()

    load_object_from_string(mock_hook, try_reload=True)
    mock_six.moves.reload_module.assert_called_once()
예제 #7
0
            def __call__(self):  # pylint: disable=arguments-differ
                """Run when the class instance is called directly."""
                # Use the context property of the baseclass, if present.
                # If not, default to a basic context.
                try:
                    ctx = self.context
                except AttributeError:
                    ctx = Context(config=self.config,
                                  environment={"environment": "test"})

                configvars = self.stack.variables or {}
                variables = [
                    Variable(k, v, "cfngin") for k, v in configvars.items()
                ]

                blueprint_class = load_object_from_string(
                    self.stack.class_path)
                blueprint = blueprint_class(self.stack.name, ctx)
                blueprint.resolve_variables(variables or [])
                blueprint.setup_parameters()
                blueprint.create_template()
                self.assertRenderedBlueprint(blueprint)
예제 #8
0
def register_lookup_handler(lookup_type, handler_or_path):
    """Register a lookup handler.

    Args:
        lookup_type (str): Name to register the handler under.
        handler_or_path (Union[Callable, str]): A function or a path to a
            handler.

    """
    handler = handler_or_path
    LOGGER.debug("registering CFNgin lookup: %s=%s", lookup_type,
                 handler_or_path)
    if isinstance(handler_or_path, string_types):
        handler = load_object_from_string(handler_or_path)
    CFNGIN_LOOKUP_HANDLERS[lookup_type] = handler
    if not isinstance(handler, type):
        # Hander is a not a new-style handler
        LOGGER.warning(
            'lookup "%s" uses a deprecated format; to learn how to write '
            "lookups visit %s/page/cfngin/lookups.html#writing-a-custom-lookup",
            lookup_type,
            DOC_SITE,
        )
예제 #9
0
파일: utils.py 프로젝트: voodooGQ/runway
def handle_hooks(stage, hooks, provider, context):  # pylint: disable=too-many-statements
    """Handle pre/post_build hooks.

    These are pieces of code that we want to run before/after the builder
    builds the stacks.

    Args:
        stage (str): The current stage (pre_run, post_run, etc).
        hooks (List[:class:`runway.cfngin.config.Hook`]): Hooks to execute.
        provider (:class:`runway.cfngin.providers.base.BaseProvider`): Provider
            instance.
        context (:class:`runway.cfngin.context.Context`): Context instance.

    """
    if not hooks:
        LOGGER.debug("No %s hooks defined.", stage)
        return

    hook_paths = []
    for i, hook in enumerate(hooks):
        try:
            hook_paths.append(hook.path)
        except KeyError:
            raise ValueError("%s hook #%d missing path." % (stage, i))

    LOGGER.info("Executing %s hooks: %s", stage, ", ".join(hook_paths))
    stage = stage.replace('build', 'deploy')  # TODO remove after full rename
    for hook in hooks:
        data_key = hook.data_key
        required = hook.required

        if not hook.enabled:
            LOGGER.debug("hook with method %s is disabled, skipping",
                         hook.path)
            continue

        try:
            method = load_object_from_string(hook.path, try_reload=True)
        except (AttributeError, ImportError):
            LOGGER.exception("Unable to load method at %s:", hook.path)
            if required:
                raise
            continue

        if isinstance(hook.args, dict):
            args = [Variable(k, v) for k, v in hook.args.items()]
            try:  # handling for output or similar being used in pre_build
                resolve_variables(args, context, provider)
            except FailedVariableLookup:
                if 'pre' in stage:
                    LOGGER.error('Lookups that change the order of '
                                 'execution, like "output", can only be '
                                 'used in "post_*" hooks. Please '
                                 'ensure that the hook being used does '
                                 'not rely on a stack, hook_data, or '
                                 'context that does not exist yet.')
                raise
            kwargs = {v.name: v.value for v in args}
        else:
            kwargs = hook.args or {}

        try:
            if isinstance(method, FunctionType):
                result = method(context=context, provider=provider, **kwargs)
            else:
                result = getattr(
                    method(context=context, provider=provider, **kwargs),
                    stage)()
        except Exception:  # pylint: disable=broad-except
            LOGGER.exception("Method %s threw an exception:", hook.path)
            if required:
                raise
            continue

        if not result:
            if required:
                LOGGER.error("Required hook %s failed. Return value: %s",
                             hook.path, result)
                sys.exit(1)
            LOGGER.warning("Non-required hook %s failed. Return value: %s",
                           hook.path, result)
        else:
            if isinstance(result, collections.Mapping):
                if data_key:
                    LOGGER.debug(
                        "Adding result for hook %s to context in "
                        "data_key %s.", hook.path, data_key)
                    context.set_hook_data(data_key, result)
                else:
                    LOGGER.debug(
                        "Hook %s returned result data, but no data "
                        "key set, so ignoring.", hook.path)
예제 #10
0
파일: utils.py 프로젝트: cmilam87/runway
def handle_hooks(stage, hooks, provider, context):
    """Handle pre/post_build hooks.

    These are pieces of code that we want to run before/after the builder
    builds the stacks.

    Args:
        stage (str): The current stage (pre_run, post_run, etc).
        hooks (List[:class:`runway.cfngin.config.Hook`]): Hooks to execute.
        provider (:class:`runway.cfngin.providers.base.BaseProvider`): Provider
            instance.
        context (:class:`runway.cfngin.context.Context`): Context instance.

    """
    if not hooks:
        LOGGER.debug("No %s hooks defined.", stage)
        return

    hook_paths = []
    for i, hook in enumerate(hooks):
        try:
            hook_paths.append(hook.path)
        except KeyError:
            raise ValueError("%s hook #%d missing path." % (stage, i))

    LOGGER.info("Executing %s hooks: %s", stage, ", ".join(hook_paths))
    for hook in hooks:
        data_key = hook.data_key
        required = hook.required
        kwargs = hook.args or {}
        enabled = hook.enabled
        if not enabled:
            LOGGER.debug("hook with method %s is disabled, skipping",
                         hook.path)
            continue
        try:
            method = load_object_from_string(hook.path)
        except (AttributeError, ImportError):
            LOGGER.exception("Unable to load method at %s:", hook.path)
            if required:
                raise
            continue
        try:
            result = method(context=context, provider=provider, **kwargs)
        except Exception:  # pylint: disable=broad-except
            LOGGER.exception("Method %s threw an exception:", hook.path)
            if required:
                raise
            continue
        if not result:
            if required:
                LOGGER.error("Required hook %s failed. Return value: %s",
                             hook.path, result)
                sys.exit(1)
            LOGGER.warning("Non-required hook %s failed. Return value: %s",
                           hook.path, result)
        else:
            if isinstance(result, collections.Mapping):
                if data_key:
                    LOGGER.debug(
                        "Adding result for hook %s to context in "
                        "data_key %s.", hook.path, data_key)
                    context.set_hook_data(data_key, result)
                else:
                    LOGGER.debug(
                        "Hook %s returned result data, but no data "
                        "key set, so ignoring.", hook.path)