def create_stack(context, stack_name, body, **kwargs): retry_boto_call(context.client.create_stack, StackName=stack_name, TemplateBody=body, **kwargs) wait_for_final_state(context, stack_name)
def step_impl(context, stack_name, change_set_name, filename): full_name = get_cloudformation_stack_name(context, stack_name) retry_boto_call(context.client.create_change_set, StackName=full_name, ChangeSetName=change_set_name, TemplateBody=read_template_file(context, filename)) wait_for_final_state(context, stack_name, change_set_name)
def create_stack(context, stack_name, body, **kwargs): retry_boto_call( context.client.create_stack, StackName=stack_name, TemplateBody=body, **kwargs ) wait_for_final_state(context, stack_name)
def step_impl(context, stack_name, state): full_name = get_cloudformation_stack_name(context, stack_name) retry_boto_call( context.client.set_stack_policy, StackName=full_name, StackPolicyBody=generate_stack_policy(state) )
def step_impl(context, stack_name, change_set_name): full_name = get_cloudformation_stack_name(context, stack_name) retry_boto_call( context.client.delete_change_set, ChangeSetName=change_set_name, StackName=full_name )
def delete_stack(context, stack_name): stack = retry_boto_call(context.cloudformation.Stack, stack_name) retry_boto_call(stack.delete) waiter = context.client.get_waiter('stack_delete_complete') waiter.config.delay = 4 waiter.config.max_attempts = 240 waiter.wait(StackName=stack_name)
def step_impl(context, stack_name): full_name = get_cloudformation_stack_name(context, stack_name) response = retry_boto_call(context.client.list_change_sets, StackName=full_name) for change_set in response["Summaries"]: time.sleep(1) retry_boto_call(context.client.delete_change_set, ChangeSetName=change_set['ChangeSetName'], StackName=full_name)
def get_stack_status(context, stack_name): try: stack = retry_boto_call(context.cloudformation.Stack, stack_name) retry_boto_call(stack.load) return stack.stack_status except ClientError as e: if e.response['Error']['Code'] == 'ValidationError' \ and e.response['Error']['Message'].endswith("does not exist"): return None else: raise e
def step_impl(context, stack_name, change_set_name, filename): full_name = get_cloudformation_stack_name(context, stack_name) retry_boto_call(context.client.create_change_set, StackName=full_name, Capabilities=[ 'CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND' ], ChangeSetName=change_set_name, TemplateBody=read_template_file(context, filename)) wait_for_final_state(context, stack_name, change_set_name)
def delete_stacks(context, stack_names): waiter = context.client.get_waiter('stack_delete_complete') waiter.config.delay = 5 waiter.config.max_attempts = 240 for stack_name in reversed(list(stack_names)): time.sleep(1) stack = retry_boto_call(context.cloudformation.Stack, stack_name) retry_boto_call(stack.delete) waiter.wait(StackName=stack_name) time.sleep(1)
def create_stack(context, stack_name, body, **kwargs): retry_boto_call(context.client.create_stack, StackName=stack_name, TemplateBody=body, **kwargs, Capabilities=[ 'CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND' ]) wait_for_final_state(context, stack_name)
def wait_for_final_state(context, stack_name): stack = retry_boto_call(context.cloudformation.Stack, stack_name) delay = 2 max_retries = 150 attempts = 0 while attempts < max_retries: retry_boto_call(stack.load) if not stack.stack_status.endswith("IN_PROGRESS"): return attempts += 1 time.sleep(delay) raise Exception("Timeout waiting for stack to reach final state.")
def delete_stacks(context, stack_names): for stack_name in stack_names: time.sleep(1) stack = retry_boto_call(context.cloudformation.Stack, stack_name) retry_boto_call(stack.delete) waiter = context.client.get_waiter('stack_delete_complete') waiter.config.delay = 5 waiter.config.max_attempts = 240 for stack_name in stack_names: time.sleep(1) waiter.wait(StackName=stack_name)
def get_stack_creation_times(context, stacks): creation_times = {} response = retry_boto_call(context.client.describe_stacks) for stack in response["Stacks"]: if stack["StackName"] in stacks: creation_times[stack["StackName"]] = stack["CreationTime"] return creation_times
def check_stack_status(context, stack_names, desired_status): response = retry_boto_call(context.client.describe_stacks) for stack_name in stack_names: for stack in response["Stacks"]: if stack["StackName"] == stack_name: assert stack["StackStatus"] == desired_status
def create_stacks(context, stack_names): body = read_template_file(context, "valid_template.json") for stack_name in stack_names: time.sleep(1) try: retry_boto_call(context.client.create_stack, StackName=stack_name, TemplateBody=body) except ClientError as e: if e.response['Error']['Code'] == 'AlreadyExistsException' \ and e.response['Error']['Message'].endswith("already exists"): pass else: raise e for stack_name in stack_names: wait_for_final_state(context, stack_name)
def get_stack_status(context, stack_name, region_name=None): if region_name is not None: Stack = boto3.resource('cloudformation', region_name=region_name).Stack else: Stack = context.cloudformation.Stack try: stack = retry_boto_call(Stack, stack_name) retry_boto_call(stack.load) return stack.stack_status except ClientError as e: if e.response['Error']['Code'] == 'ValidationError' \ and e.response['Error']['Message'].endswith("does not exist"): return None else: raise e
def step_impl(context, stack_name): full_name = get_cloudformation_stack_name(context, stack_name) response = retry_boto_call(context.client.list_change_sets, StackName=full_name) del response["ResponseMetadata"] for output in context.output: del output["ResponseMetadata"] assert response == output
def create_stacks(context, stack_names): body = read_template_file(context, "valid_template.json") for stack_name in stack_names: time.sleep(1) try: retry_boto_call( context.client.create_stack, StackName=stack_name, TemplateBody=body ) except ClientError as e: if e.response['Error']['Code'] == 'AlreadyExistsException' \ and e.response['Error']['Message'].endswith("already exists"): pass else: raise e for stack_name in stack_names: wait_for_final_state(context, stack_name)
def step_impl(context, change_set_name, stack_name): full_name = get_cloudformation_stack_name(context, stack_name) response = retry_boto_call(context.client.describe_change_set, StackName=full_name, ChangeSetName=change_set_name) del response["ResponseMetadata"] del context.output["ResponseMetadata"] assert response == context.output
def step_impl(context, stack_name, change_set_name): full_name = get_cloudformation_stack_name(context, stack_name) response = retry_boto_call(context.client.describe_stacks, StackName=full_name) change_set_id = response["Stacks"][0]["ChangeSetId"] stack_status = response["Stacks"][0]["StackStatus"] assert stack_status == "UPDATE_COMPLETE" assert change_set_name == change_set_id.split("/")[1]
def step_impl(context, stack_name): full_name = get_cloudformation_stack_name(context, stack_name) response = retry_boto_call(context.client.describe_stack_resources, StackName=full_name) properties = {"LogicalResourceId", "PhysicalResourceId"} formatted_response = [{k: v for k, v in item.items() if k in properties} for item in response["StackResources"]] assert [{stack_name: formatted_response}] == context.output
def get_change_set_status(context, stack_name, change_set_name): try: response = retry_boto_call(context.client.describe_change_set, ChangeSetName=change_set_name, StackName=stack_name) except ClientError as e: if e.response['Error']['Code'] == 'ChangeSetNotFound': return None else: raise e return response["Status"]
def get_stack_policy(context, stack_name): try: response = retry_boto_call(context.client.get_stack_policy, StackName=stack_name) except ClientError as e: if e.response['Error']['Code'] == 'ValidationError' \ and e.response['Error']['Message'].endswith("does not exist"): return None else: raise e return response.get("StackPolicyBody")
def get_stack_policy(context, stack_name): try: response = retry_boto_call( context.client.get_stack_policy, StackName=stack_name ) except ClientError as e: if e.response['Error']['Code'] == 'ValidationError' \ and e.response['Error']['Message'].endswith("does not exist"): return None else: raise e return response.get("StackPolicyBody")
def step_impl(context, stack_name): full_name = get_cloudformation_stack_name(context, stack_name) response = retry_boto_call( context.client.describe_stack_resources, StackName=full_name ) properties = {"LogicalResourceId", "PhysicalResourceId"} formatted_response = [ {k: v for k, v in item.items() if k in properties} for item in response["StackResources"] ] assert formatted_response == context.output
def step_impl(context, stack_name): expected_resources = {} sceptre_response = [] for stack_resources in context.response.values(): for resource in stack_resources: sceptre_response.append(resource["PhysicalResourceId"]) response = retry_boto_call(context.client.describe_stack_resources, StackName=get_cloudformation_stack_name( context, stack_name)) expected_resources[stack_name] = response["StackResources"] for short_name, resources in expected_resources.items(): for resource in resources: sceptre_response.remove(resource["PhysicalResourceId"]) assert sceptre_response == []
def step_impl(context, stack_name): expected_resources = {} sceptre_response = [] for stack_resources in context.response.values(): for resource in stack_resources: sceptre_response.append(resource["PhysicalResourceId"]) response = retry_boto_call( context.client.describe_stack_resources, StackName=get_cloudformation_stack_name(context, stack_name) ) expected_resources[stack_name] = response["StackResources"] for short_name, resources in expected_resources.items(): for resource in resources: sceptre_response.remove(resource["PhysicalResourceId"]) assert sceptre_response == []
def step_impl(context, stack_group_name, status): full_stack_names = get_full_stack_names(context, stack_group_name).values() response = retry_boto_call(context.client.describe_stacks) stacks_to_delete = [] for stack_name in full_stack_names: for stack in response["Stacks"]: if stack["StackName"] == stack_name: if stack["StackStatus"] != status: stacks_to_delete.append(stack_name) delete_stacks(context, stacks_to_delete) for stack in get_stack_names(context, stack_group_name): set_template_path(context, stack, "valid_template.json") create_stacks(context, full_stack_names) check_stack_status(context, full_stack_names, status)
def step_impl(context, stack_group_name): stacks_names = get_full_stack_names(context, stack_group_name) expected_resources = {} sceptre_response = [] for stack_resources in context.response: for resource in stack_resources.values(): sceptre_response.append(resource[0]["PhysicalResourceId"]) for short_name, full_name in stacks_names.items(): time.sleep(1) response = retry_boto_call(context.client.describe_stack_resources, StackName=full_name) expected_resources[short_name] = response["StackResources"] for short_name, resources in expected_resources.items(): for resource in resources: sceptre_response.remove(resource["PhysicalResourceId"]) assert sceptre_response == []
def step_impl(context, environment_name, status): full_stack_names = get_full_stack_names(context, environment_name).values() response = retry_boto_call(context.client.describe_stacks) stacks_to_delete = [] for stack_name in full_stack_names: for stack in response["Stacks"]: if stack["StackName"] == stack_name: if stack["StackStatus"] != status: stacks_to_delete.append(stack_name) delete_stacks(context, stacks_to_delete) for stack in get_stack_names(context, environment_name): set_template_path(context, stack, "valid_template.json") create_stacks(context, full_stack_names) check_stack_status(context, full_stack_names, status)
def step_impl(context, environment_name): stacks_names = get_full_stack_names(context, environment_name) expected_resources = {} sceptre_response = [] for stack_resources in context.response.values(): for resource in stack_resources: sceptre_response.append(resource["PhysicalResourceId"]) for short_name, full_name in stacks_names.items(): time.sleep(1) response = retry_boto_call( context.client.describe_stack_resources, StackName=full_name ) expected_resources[short_name] = response["StackResources"] for short_name, resources in expected_resources.items(): for resource in resources: sceptre_response.remove(resource["PhysicalResourceId"]) assert sceptre_response == []
def update_stack(context, stack_name, body, **kwargs): stack = retry_boto_call(context.cloudformation.Stack, stack_name) retry_boto_call(stack.update, TemplateBody=body, **kwargs) wait_for_final_state(context, stack_name)
def get_stack_resources(context, stack_name): cf_stack_name = get_cloudformation_stack_name(context, stack_name) resources = retry_boto_call(context.client.describe_stack_resources, StackName=cf_stack_name) return resources['StackResources']
def describe_stack(context, stack_name) -> dict: cf_stack_name = get_cloudformation_stack_name(context, stack_name) response = retry_boto_call(context.client.describe_stacks, StackName=cf_stack_name) return response['Stacks'][0]
def step_impl(context, stack_name): full_name = get_cloudformation_stack_name(context, stack_name) response = retry_boto_call(context.client.list_change_sets, StackName=full_name) for output in context.output: assert output == {stack_name: response.get("Summaries", {})}