Example #1
0
def create_command(ctx, path, change_set_name, yes):
    """
    Creates a stack or a change set.

    Creates a stack for a given config PATH. Or if CHANGE_SET_NAME is specified
    creates a change set for stack in PATH.

    :param path: Path to a Stack or StackGroup
    :type path: str
    :param change_set_name: A name of the Change Set - optional
    :type change_set_name: str
    :param yes: A flag to assume yes to all questions.
    :type yes: bool
    """
    context = SceptreContext(
        command_path=path,
        project_path=ctx.obj.get("project_path"),
        user_variables=ctx.obj.get("user_variables"),
        options=ctx.obj.get("options"),
        ignore_dependencies=ctx.obj.get("ignore_dependencies"))

    action = "create"
    plan = SceptrePlan(context)

    if change_set_name:
        confirmation(action,
                     yes,
                     change_set=change_set_name,
                     command_path=path)
        plan.create_change_set(change_set_name)
    else:
        confirmation(action, yes, command_path=path)
        responses = plan.create()
        exit(stack_status_exit_code(responses.values()))
Example #2
0
def update_command(ctx, path, change_set, verbose, yes):
    """
    Updates a stack for a given config PATH. Or perform an update via
    change-set when the change-set flag is set.
    \f

    :param path: Path to execute the command on.
    :type path: str
    :param change_set: Whether a change set should be created.
    :type change_set: bool
    :param verbose: A flag to print a verbose output.
    :type verbose: bool
    :param yes: A flag to answer 'yes' to all CLI questions.
    :type yes: bool
    """

    context = SceptreContext(
        command_path=path,
        project_path=ctx.obj.get("project_path"),
        config_directory=ctx.obj.get("config_directory"),
        user_variables=ctx.obj.get("user_variables"),
        options=ctx.obj.get("options"),
        output_format=ctx.obj.get("output_format"),
        ignore_dependencies=ctx.obj.get("ignore_dependencies"))

    plan = SceptrePlan(context)

    if change_set:
        change_set_name = "-".join(["change-set", uuid1().hex])
        plan.create_change_set(change_set_name)
        try:
            # Wait for change set to be created
            statuses = plan.wait_for_cs_completion(change_set_name)
            # Exit if change set fails to create
            for status in list(statuses.values()):
                if status != StackChangeSetStatus.READY:
                    exit(1)

            # Describe changes
            descriptions = plan.describe_change_set(change_set_name)
            for description in list(descriptions.values()):
                if not verbose:
                    description = simplify_change_set_description(description)
                write(description, context.output_format)

            # Execute change set if happy with changes
            if yes or click.confirm("Proceed with stack update?"):
                plan.execute_change_set(change_set_name)
        except Exception as e:
            raise e
        finally:
            # Clean up by deleting change set
            plan.delete_change_set(change_set_name)
    else:
        confirmation("update", yes, command_path=path)
        responses = plan.update()
        exit(stack_status_exit_code(responses.values()))
Example #3
0
def step_impl(context, change_set_name, stack_name):
    sceptre_context = SceptreContext(command_path=stack_name + '.yaml',
                                     project_path=context.sceptre_dir)

    sceptre_plan = SceptrePlan(sceptre_context)
    allowed_errors = {'ValidationError', 'ChangeSetNotFound'}
    try:
        sceptre_plan.create_change_set(change_set_name)
    except ClientError as e:
        if e.response['Error']['Code'] in allowed_errors:
            context.error = e
            return
        else:
            raise e

    wait_for_final_state(context, stack_name, change_set_name)
Example #4
0
class Sceptre(CloudFormation):
    def __init__(self, project, stack, *args, **kwargs):
        self.project = project
        self.stack = stack
        super(Sceptre, self).__init__(project, *args, **kwargs)
        self.stack_name = self.get_stack(stack)['StackName']
        context = SceptreContext(
            self.resolve_sceptre_project_path().as_posix(),
            self.resolve_stack_file().as_posix(),
            ignore_dependencies=True
        )
        self.plan = SceptrePlan(context)
        # import pdb; pdb.set_trace()

    @staticmethod
    def resolve_sceptre_project_path():
        cwd = Path().cwd()
        for content in cwd.iterdir():
            if 'infrastructure' in content.as_posix() and content.is_dir():
                return content
        raise ClickException(
            'We could not find an infrastructure folder. Make sure you are at '
            'the top-level directory of the project you are trying to deploy.'
        )

    def resolve_stack_file(self):
        stack_file_path = self.stack
        if not self.stack.endswith('.yaml'):
            stack_file_path += '.yaml'
        if not self.stack.startswith('prod/'):
            stack_file_path = Path('prod') / stack_file_path
        return Path(stack_file_path)

    def create_change_set(self, change_set_name):
        os.environ['AWS_DEFAULT_PROFILE'] = self.aws_profile
        os.environ['AWS_DEFAULT_REGION'] = self.aws_region
        with click_spinner.spinner():
            self.plan.create_change_set(change_set_name)
            self.plan.wait_for_cs_completion(change_set_name)