Example #1
0
    def resolve_stacks(self, stack_map):
        """
        Transforms map of Stacks into a set of Stacks, transforms dependencies
        from a list of Strings (stack names) to a list of Stacks.

        :param stack_map: Map of stacks, containing dependencies as list of Strings.
        :type base_config: dict
        :returns: Set of stacks, containing dependencies as list of Stacks.
        :rtype: set
        :raises: sceptre.exceptions.DependencyDoesNotExistError
        """
        stacks = set()
        for stack in stack_map.values():
            if not self.context.ignore_dependencies:
                for i, dep in enumerate(stack.dependencies):
                    try:
                        stack.dependencies[i] = stack_map[sceptreise_path(dep)]
                    except KeyError:
                        raise DependencyDoesNotExistError(
                            "{stackname}: Dependency {dep} not found. "
                            "Valid dependency names are: "
                            "{stackkeys}. "
                            "Please make sure that your dependencies stack_outputs "
                            "have their full path from `config` defined.".
                            format(stackname=stack.name,
                                   dep=dep,
                                   stackkeys=", ".join(stack_map.keys())))

            else:
                stack.dependencies = []
            stacks.add(stack)
        return stacks
Example #2
0
    def construct_stacks(self) -> Set[Stack]:
        """
        Traverses the files under the command path.
        For each file encountered, a Stack is constructed
        using the correct config. Dependencies are traversed
        and a final set of Stacks is returned.

        :returns: A set of Stacks.
        """
        stack_map = {}
        command_stacks = set()

        root = self.context.full_command_path()

        if self.context.full_scan:
            root = self.context.full_config_path()

        if path.isfile(root):
            todo = {root}
        else:
            todo = set()
            for directory_name, sub_directories, files in walk(
                    root, followlinks=True):
                for filename in fnmatch.filter(files, '*.yaml'):
                    if filename.startswith('config.'):
                        continue

                    todo.add(path.join(directory_name, filename))

        stack_group_configs = {}
        full_todo = todo.copy()
        deps_todo = set()

        while todo:
            abs_path = todo.pop()
            rel_path = path.relpath(abs_path,
                                    start=self.context.full_config_path())
            directory, filename = path.split(rel_path)

            if directory in stack_group_configs:
                stack_group_config = stack_group_configs[directory]
            else:
                stack_group_config = stack_group_configs[directory] = \
                    self.read(path.join(directory, self.context.config_file))

            stack = self._construct_stack(rel_path, stack_group_config)
            for dep in stack.dependencies:
                full_dep = str(Path(self.context.full_config_path(), dep))
                if not path.exists(full_dep):
                    raise DependencyDoesNotExistError(
                        "{stackname}: Dependency {dep} not found. "
                        "Please make sure that your dependencies stack_outputs "
                        "have their full path from `config` defined.".format(
                            stackname=stack.name, dep=dep))

                if full_dep not in full_todo and full_dep not in deps_todo:
                    todo.add(full_dep)
                    deps_todo.add(full_dep)

            stack_map[sceptreise_path(rel_path)] = stack

            full_command_path = self.context.full_command_path()
            if abs_path == full_command_path\
                    or abs_path.startswith(full_command_path.rstrip(path.sep) + path.sep):
                command_stacks.add(stack)

        stacks = self.resolve_stacks(stack_map)

        return stacks, command_stacks