Ejemplo n.º 1
0
def describe_stack_events(stack_name, session=None):
    """Performs describe_stack_events on the provided stack name

    http://boto3.readthedocs.io/en/latest/reference/services/cloudformation.html#CloudFormation.Client.describe_stack_events

    Args:
        stack_name (str): Name of the stack to describe
        session (object, optional): boto3 session object

    Returns:
        dict: Standard AWS dictionary with stack event details
    """
    client = boto3_client(service='cloudformation', session=session)
    try:
        response = client.describe_stack_events(StackName=stack_name)
        return response

    except ex.ClientError as e:
        if str(e).endswith(" does not exist"):
            raise ex.NotFoundException(
                f"Could not find stack with name {stack_name}")

        else:
            raise ex.ClientError(
                f"Failed to lookup stack events for {stack_name}: {str(e)}")
Ejemplo n.º 2
0
def disable_termination_protection(stack_name, session=None):
    """Disables Termination Protection on CloudFormation Stacks

    Args:
        stack_name (str): Passing key word arguments that will be used to create the
        session (object, optional): boto3 session object

    Returns:
        none
    """
    try:
        client = boto3_client(service='cloudformation', session=session)
        stack_exists = describe_stack(stack_name=stack_name, session=session)
        if stack_exists:
            logger.info(
                "Checking time difference between Stack Creation and now. (disable if < 20 min)"
            )
            diff = datetime.now(
                timezone.utc) - stack_exists['Stacks'][0]['CreationTime']
            if stack_exists and (divmod(diff.days * 86400 + diff.seconds,
                                        60)[0] < 20):
                logger.info(
                    f"Disabling Termination Protection on {stack_name}")
                response = client.update_termination_protection(
                    EnableTerminationProtection=False, StackName=stack_name)
                logger.debug(response)

            else:
                logger.warning('Time difference is greater than 20 min')

    except Exception as e:
        logger.error(str(e))
        raise Exception
Ejemplo n.º 3
0
def list_stacks(session=None):
    """Gets a list of all CloudFormation stacks in the account

    http://boto3.readthedocs.io/en/latest/reference/services/cloudformation.html#CloudFormation.Client.list_stacks

    Args:
        session (object, optional): boto3 session object

    Returns:
        list of str: List of stack names in the account
    """
    stacks = []
    client = boto3_client(service='cloudformation', session=session)
    try:
        paginator = client.get_paginator("list_stacks")
        for page in paginator.paginate(StackStatusFilter=[
                'CREATE_IN_PROGRESS', 'CREATE_FAILED', 'CREATE_COMPLETE',
                'ROLLBACK_IN_PROGRESS', 'ROLLBACK_FAILED', 'ROLLBACK_COMPLETE',
                'DELETE_IN_PROGRESS', 'DELETE_FAILED', 'UPDATE_IN_PROGRESS',
                'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS', 'UPDATE_COMPLETE',
                'UPDATE_ROLLBACK_IN_PROGRESS', 'UPDATE_ROLLBACK_FAILED',
                'UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS',
                'UPDATE_ROLLBACK_COMPLETE', 'REVIEW_IN_PROGRESS'
        ]):
            for x in page['StackSummaries']:
                stacks.append(x['StackName'])

    except Exception as e:
        raise ex.CloudFormationException(
            f"Failed to get list of cloudformation templates: {str(e)}")

    return stacks
Ejemplo n.º 4
0
def update_stack(**kwargs):
    """Updates an existing stack with new template

    http://boto3.readthedocs.io/en/latest/reference/services/cloudformation.html#CloudFormation.Client.update_stack

    Args:
        stack_name (str): Name of the stack to update
        template (str): Body of a CFN template file, should already have been read in using general_helper.load_file(file)
        capability (str): The capability string noting if the stack contains IAM or custom named IAM resources
                            Options: 'CAPABILITY_IAM'|'CAPABILITY_NAMED_IAM'
        params (list of dict, optional): List of parameter structures that specify input parameters for the stack
        tags (list): tags set on cloudformation stack
        session (object, optional): boto3 session object

    Returns:
        dict: Standard AWS dictionary with stack update results
    """
    logger.info(f"Arguments:{kwargs}")
    logger.info(f"Updating Stack:{kwargs['StackName']}")
    client = boto3_client(service='cloudformation', session=kwargs['session'])
    del kwargs['session']
    try:
        response = client.update_stack(**kwargs)

    except Exception as e:
        logger.warning(e)
        if re.search(r'(No updates are to be performed)', str(e)):
            logger.warning("No updates need to be performed...")
            response = False
        else:
            raise e

    return response
Ejemplo n.º 5
0
def describe_stack(stack_name, session=None):
    """Performs describe_stack on the provided stack name

    http://boto3.readthedocs.io/en/latest/reference/services/cloudformation.html#CloudFormation.Client.describe_stacks

    Args:
        stack_name (str): Name of the stack to describe
        session (object, optional): boto3 session object

    Returns:
        dict: Standard AWS dictionary with stack details
    """
    client = boto3_client(service='cloudformation', session=session)
    try:
        logger.info(f"Getting details about CloudFormation Stack:{stack_name}")
        response = client.describe_stacks(StackName=stack_name)
        return response

    except ex.ClientError as e:
        if str(e).endswith(" does not exist"):
            logger.warning(f"Stack, {stack_name} does not exist...")
            # return False

        else:
            raise ex.ClientError(
                f"Failed to lookup stack {stack_name}: {str(e)}")

    except Exception as e:
        logger.warning(f"describe_stack error:{str(e)}")
Ejemplo n.º 6
0
def delete_stack(stack_name: str, session=None):
    """Deletes the provided stack name

    http://boto3.readthedocs.io/en/latest/reference/services/cloudformation.html#CloudFormation.Client.delete_stack

    Args:
        stack_name (str): Name of the stack to delete
        session (object, optional): boto3 session object

    Returns:
        dict: Standard AWS dictionary with stack deletion results
    """
    client = boto3_client(service='cloudformation', session=session)
    response = client.delete_stack(StackName=stack_name)
    return response
Ejemplo n.º 7
0
def enable_termination_protection(stack_name, session=None):
    """Enables Termination Protection on CloudFormation Stacks

    Args:
        stack_name (str): Passing key word arguments that will be used to create the
        session (object, optional): boto3 session object

    Returns:
        none
    """
    logger.info(f"Setting Termination Protection on {stack_name}")
    try:
        client = boto3_client(service='cloudformation', session=session)
        response = client.update_termination_protection(
            EnableTerminationProtection=True, StackName=stack_name)
        logger.debug(response)

    except Exception as e:
        logger.error(str(e))
        raise Exception
Ejemplo n.º 8
0
def validate_template(template, session=None):
    """Performs template validation on the provided template body.

    http://boto3.readthedocs.io/en/latest/reference/services/cloudformation.html#CloudFormation.Client.validate_template

    Args:
        template (str): Body of a CFN template file, should already have been read in using helper.load_file(file)
        session (object, optional): boto3 session object

    Returns:
        dict: Standard AWS dictionary with validation results, raises exception if template is invalid
    """
    logger.info("Validating CloudFormation Template")
    client = boto3_client(service='cloudformation', session=session)
    try:
        response = client.validate_template(TemplateBody=template)
        return response

    except ex.ClientError as e:
        raise ex.ClientError(
            f"CloudFormation template validation failed: {str(e)}")
Ejemplo n.º 9
0
def get_stack_waiter(event, session=None):
    """Gets an object that can wait for some stack condition to be true

    http://boto3.readthedocs.io/en/latest/reference/services/cloudformation.html#CloudFormation.Client.get_waiter

    Args:
        event (str): Name of the event to wait for IE: 'stack_create_complete'
        session (object, optional): boto3 session object

    Returns:
        :obj:`boto3.waiter.Waiter`: Waiter object
    """

    client = boto3_client(service='cloudformation', session=session)
    try:
        waiter = client.get_waiter(event)

    except BaseException as e:
        raise ex.StackWaiterException(
            f"Failed to retrieve stack waiter for event {event}: {str(e)}")

    return waiter
def assume_role_arn(role_arn, role_session_name=function_name, profile=None):
    """Assumes the provided role name in the provided account number

    http://boto3.readthedocs.io/en/latest/reference/services/sts.html#STS.Client.assume_role

    Args:
        role_arn (str): Arn of the IAM Role to assume
        role_session_name (str, optional): The name you'd like to use for the session
            (suggested to use the lambda function name)
        profile (str, optional): Local AWS Profile name

    Returns:
        dict: Returns standard AWS dictionary with credential details
    """
    logger.info(f"Assuming Role:{role_arn}")
    sts_client = boto3_client(service='sts', profile=profile)

    assumed_role_object = sts_client.assume_role(
        RoleArn=role_arn, RoleSessionName=role_session_name)

    assumed_credentials = assumed_role_object['Credentials']
    return assumed_credentials
Ejemplo n.º 11
0
def create_stack(**kwargs):
    """Creates a cloudformation stack using the provided parameters

    http://boto3.readthedocs.io/en/latest/reference/services/cloudformation.html#CloudFormation.Client.create_stack

    Args:
        stack_name (str): Name of the stack to create
        template (str): Body of a CFN template file, should already have been read in using general_helper.load_file(file)
        capability (str): The capability string noting if the stack contains IAM or custom named IAM resources
                            Options: 'CAPABILITY_IAM'|'CAPABILITY_NAMED_IAM'
        params (list of dict, optional): List of parameter structures that specify input parameters for the stack
        tags (list): tags set on cloudformation stack
        session (object, optional): boto3 session object

    Returns:
        dict: Standard AWS dictionary with create_stack results
    """
    logger.info(f"Arguments:{kwargs}")
    logger.info(f"Creating Stack:{kwargs['StackName']}")
    client = boto3_client(service='cloudformation', session=kwargs['session'])
    del kwargs['session']
    response = client.create_stack(**kwargs)

    return response