def diff_command(ctx: Context, differ: str, show_no_echo: bool, path: str): """Indicates the difference between the currently DEPLOYED stacks in the command path and the stacks configured in Sceptre right now. This command will compare both the templates as well as the subset of stack configurations that can be compared. Some settings (such as sceptre_user_data) are not available in a CloudFormation stack description, so the diff will not be indicated. Currently compared stack configurations are: \b * parameters * notifications * role_arn * stack_tags Important: There are resolvers (notably !stack_output, among others) that rely on other stacks to be already deployed when they are resolved. When producing a diff on Stack Configs that have such resolvers that point to non-deployed stacks, this presents a challenge, since this means those resolvers cannot be resolved. This particularly applies to stack parameters and when a stack's template uses sceptre_user_data with resolvers in it. In order to continue to be useful when producing a diff in these conditions, this command will do the following: 1. If the resolver CAN be resolved, it will be resolved and the resolved value will be in the diff results. 2. If the resolver CANNOT be resolved, it will be replaced with a string that represents the resolver and its arguments. For example: !stack_output my_stack.yaml::MyOutput will resolve in the parameters to "{ !StackOutput(my_stack.yaml::MyOutput) }". Particularly in cases where the replaced value doesn't work in the template as the template logic requires and causes an error, there is nothing further Sceptre can do and diffing will fail. """ 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"), output_format=ctx.obj.get('output_format'), no_colour=ctx.obj.get('no_colour') ) output_format = context.output_format plan = SceptrePlan(context) if differ == "deepdiff": stack_differ = DeepDiffStackDiffer(show_no_echo) writer_class = DeepDiffWriter elif differ == 'difflib': stack_differ = DifflibStackDiffer(show_no_echo) writer_class = DiffLibWriter else: raise ValueError(f"Unexpected differ type: {differ}") diffs: Dict[Stack, StackDiff] = plan.diff(stack_differ) num_stacks_with_diff = output_diffs(diffs.values(), writer_class, sys.stdout, output_format) if num_stacks_with_diff: logger.warning( f"{num_stacks_with_diff} stacks with differences detected." )
def diff_command(ctx, path): 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")) plan = SceptrePlan(context) response = plan.diff() exit(stack_status_exit_code(response.values()))
def step_impl(context, stack_name, diff_type): sceptre_context = SceptreContext(command_path=stack_name + '.yaml', project_path=context.sceptre_dir) sceptre_plan = SceptrePlan(sceptre_context) differ_classes = { 'deepdiff': DeepDiffStackDiffer, 'difflib': DifflibStackDiffer } writer_class = {'deepdiff': DeepDiffWriter, 'difflib': DeepDiffWriter} differ = differ_classes[diff_type]() context.writer_class = writer_class[diff_type] context.output = list(sceptre_plan.diff(differ).values())