def signal_status(status, resource_name=None): if not resource_name: resource_name = info().logical_id() print("Signalling " + status + " for " + info().stack_name() + "." + resource_name) cloudformation().signal_resource( StackName=info().stack_name(), LogicalResourceId=resource_name, UniqueId=info().instance_id(), Status=status, )
def select_stacks(selector): ret = [] paginator = cloudformation().get_paginator('describe_stacks') for page in paginator.paginate(): for stack in page.get('Stacks'): selected = selector(stack) if selected: ret.append(selected) return ret
def find_role_arn(trusted_account): cf_stacks = cloudformation().get_paginator('describe_stacks') for page in cf_stacks.paginate(): for stack in page["Stacks"]: if stack["StackName"].endswith(trusted_account) or \ "-" + trusted_account + "-" in stack["StackName"]: for output in stack["Outputs"]: if output["OutputKey"] == "ManageRole": return output["OutputValue"] return None
def get_stack_operation(stack_name, session=None): stack_oper = "create_stack" try: stack_data = cloudformation(session=session).describe_stacks( StackName=stack_name) # Dump original status, for the record status = stack_data['Stacks'][0]['StackStatus'] log("Status: \033[32;1m" + status + "\033[m") stack_oper = "update_stack" except ClientError as err: if err.response['Error']['Code'] == 'ValidationError' and \ err.response['Error']['Message'].endswith('does not exist'): log("Status: \033[32;1mNEW_STACK\033[m") else: raise return globals()[stack_oper]
def update_stack(stack_name, template, params, dry_run=False, session=None, tags=None): clf = cloudformation(session=session) chset_name = stack_name + "-" + time.strftime("%Y%m%d%H%M%S", time.gmtime()) params = get_template_arguments(stack_name, template, params) params['ChangeSetName'] = chset_name if tags: params["Tags"] = tags chset_id = clf.create_change_set(**params)['Id'] chset_data = clf.describe_change_set(ChangeSetName=chset_id) status = chset_data['Status'] while "_COMPLETE" not in status and status != "FAILED": time.sleep(5) chset_data = clf.describe_change_set(ChangeSetName=chset_id) status = chset_data['Status'] if status == "FAILED": clf.delete_change_set(ChangeSetName=chset_id) if 'StatusReason' in chset_data \ and "The submitted information didn't contain changes" in chset_data['StatusReason']: failed_for_real = False else: failed_for_real = True if 'StatusReason' in chset_data: if failed_for_real: log_str = "\033[31;1mFAILED: " + chset_data[ 'StatusReason'] + "\033[m" else: log_str = chset_data['StatusReason'] log(log_str) if failed_for_real: raise Exception("Creating changeset failed") else: chset_data['CreationTime'] = time.strftime( "%a, %d %b %Y %H:%M:%S +0000", chset_data['CreationTime'].timetuple()) log("\033[32;1m*** Changeset ***:\033[m") log_data(chset_data) if not dry_run: clf.execute_change_set(ChangeSetName=chset_id) else: clf.delete_change_set(ChangeSetName=chset_id) return
def get_end_status(stack_name, session=None): logs = CloudWatchLogsThread(log_group_name=stack_name) logs.start() cf_events = CloudFormationEvents(log_group_name=stack_name) cf_events.start() log("Waiting for stack operation to complete:") status = "_IN_PROGRESS" while True: stack_info = cloudformation(session=session).describe_stacks( StackName=stack_name) status = stack_info['Stacks'][0]['StackStatus'] if "ROLLBACK" in status: color = "\033[31;1m" else: color = "\033[32;1m" log(color + "Status: " + status + "\033[m") if not status.endswith("_IN_PROGRESS"): logs.stop() cf_events.stop() break time.sleep(5) return status
def delete(stack_name, regn, session=None): os.environ['AWS_DEFAULT_REGION'] = regn log("**** Deleting stack '" + stack_name + "'") clf = cloudformation(session=session) cf_events = CloudFormationEvents(log_group_name=stack_name) cf_events.start() clf.delete_stack(StackName=stack_name) while True: try: stack_info = clf.describe_stacks(StackName=stack_name) status = stack_info['Stacks'][0]['StackStatus'] if not status.endswith("_IN_PROGRESS") and not status.endswith( "_COMPLETE"): raise Exception("Delete stack failed: end state " + status) log("Status: \033[32;1m" + status + "\033[m") time.sleep(5) except ClientError as err: cf_events.stop() if err.response['Error']['Code'] == 'ValidationError' and \ err.response['Error']['Message'].endswith('does not exist'): log("Status: \033[32;1mDELETE_COMPLETE\033[m") break else: raise
def list_created_accounts(): cf_stacks = cloudformation().get_paginator('describe_stacks') for page in cf_stacks.paginate(): for stack in page["Stacks"]: if stack["StackName"].startswith("managed-account-"): yield "-".join(stack["StackName"].split("-")[2:-1])
def _get_stack_resources(stack_name, stack_region=None): return cloudformation(region=stack_region).describe_stack_resources( StackName=stack_name)
def _get_stack(stack_name, stack_region=None): ret = cloudformation(region=stack_region).describe_stacks( StackName=stack_name) if "Stacks" in ret and ret["Stacks"]: return ret["Stacks"][0]
def create_stack(stack_name, template, params, session=None, tags=None): params = get_template_arguments(stack_name, template, params) if tags: params["Tags"] = tags cloudformation(session=session).create_stack(**params) return