def lambda_handler()

in scripts/lambda_codebuild.py [0:0]


def lambda_handler(event, context):
    """Main Lambda Handling function"""

    def log_config(loglevel=None, botolevel=None):
        if 'ResourceProperties' in event.keys():
            if 'loglevel' in event['ResourceProperties'] and not loglevel:
                loglevel = event['ResourceProperties']['loglevel']
            if 'botolevel' in event['ResourceProperties'] and not botolevel:
                botolevel = event['ResourceProperties']['botolevel']
        if not loglevel:
            loglevel = 'warning'
        if not botolevel:
            botolevel = 'error'

        # Set log verbosity levels
        loglevel = getattr(logging, loglevel.upper(), 20)
        botolevel = getattr(logging, botolevel.upper(), 40)
        mainlogger = logging.getLogger()
        mainlogger.setLevel(loglevel)
        logging.getLogger('boto3').setLevel(botolevel)
        logging.getLogger('botocore').setLevel(botolevel)

        mylogger = logging.getLogger("lambda_handler")
        mylogger.setLevel(loglevel)

        return logging.LoggerAdapter(
            mylogger,
            {'requestid': event.get('RequestId','__None__')}
        )

    def cleanup_images():
        """loop over and delete images in each repo"""

        properties = event['ResourceProperties']
        for repository in [
            'AWXTaskRegistry',
            'AWXWebRegistry',
            'MemcachedRegistry',
            'RabbitMQRegistry',
            'SidecarRegistry'
        ]:
            logger.debug("Cleaning Up: " + repository)
            logger.debug("Trying to cleanup: " + properties[repository])
            cleanup_images_repo(properties[repository])

    def cleanup_images_repo(repository):
        """Delete Container images"""
        logger.debug(account_id)
        ecr_client = boto3.client('ecr')
        response = ecr_client.describe_images(
            registryId=account_id,
            repositoryName=repository
        )

        imageIds = []
        for imageDetail in response['imageDetails']:
            imageIds.append(
                {
                    'imageDigest': imageDetail['imageDigest'],
                }
            )

        if len(imageIds):
            logger.debug("Deleting images")
            response = ecr_client.batch_delete_image(
                registryId=account_id,
                repositoryName=repository,
                imageIds=imageIds
            )

    def execute_build():
        """Kickoff CodeBuild Project"""
        build = boto3.client('codebuild')

        project_name = event["ResourceProperties"]["BuildProjectName"]
        signal_url = event["ResponseURL"]
        stack_id = event["StackId"]
        request_id = event["RequestId"]
        logical_resource_id = event["LogicalResourceId"]
        url = urlparse(event['ResponseURL'])

        logger.info("Kicking off build: {}".format(project_name))

        environment = [
            {'name': 'url_path',                'value': url.path},
            {'name': 'url_query',               'value': url.query},
            {'name': 'cfn_signal_url',          'value': signal_url},
            {'name': 'cfn_stack_id',            'value': stack_id},
            {'name': 'cfn_request_id',          'value': request_id},
            {'name': 'cfn_logical_resource_id', 'value': logical_resource_id}
        ]

        response = build.start_build(
            projectName=project_name,
            environmentVariablesOverride=environment
        )
        return response

    def get_response_dict():
        """Setup Response object for CFN Signal"""

        response_dict = {
            'StackId': event['StackId'],
            'RequestId': event['RequestId'],
            'LogicalResourceId': event['LogicalResourceId'],
            'Status': 'SUCCESS'
        }

        return response_dict

    def send_response(status=None, reason=None):
        if status is not None:
            response['Status'] = status

        if reason is not None:
            response['Reason'] = reason

        if 'ResponseURL' in event and event['ResponseURL']:
            url = urlparse(event['ResponseURL'])
            logger.debug(url.hostname)
            body = json.dumps(response)
            https = http.client.HTTPSConnection(url.hostname)
            https.request('PUT', url.path + '?' + url.query, body)
            logger.info("Sent CFN Response")

        return response

    """Main Lambda Logic"""
    logger = log_config()
    logger.info(event)

    # Setup base response
    response = get_response_dict()
    account_id = context.invoked_function_arn.split(":")[4]
    response['PhysicalResourceId'] = "1233244324"

    # CREATE UPDATE (want to avoid rebuilds unless something changed)
    if event['RequestType'] in ("Create", "Update"):
        try:
            execute_build()
        except Exception as exce:
            logger.error("Build threw exception: " + str(exce))
            logger.error(exce, exc_info=True)
            # Signal back that we failed
            return send_response(
                status="FAILED",
                reason=str(exce)
            )
        else:  # We want codebuild to send the signal
            logger.info("Codebuild project running, Codebuild will signal back")
            return
    elif event['RequestType'] == "Delete":
        try:
            logger.info("Cleaning up repositories and images")

            # Cleanup the images in the repository
            cleanup_images()
        except Exception as exce:
            logger.error("Exception: " + str(exce))
            logger.error(exce, exc_info=True)

            # Signal back that we failed
            return send_response(
                status="FAILED",
                reason=str(exce)
            )

        # signal success to CFN
        logger.info("Cleanup complete signal back")
        return send_response()
    else:  # Invalid RequestType
        message = "Invalid request type send error signal to cfn: {} " \
                  "(expecting: Create, Update, Delete)" \
                  "".format(event['RequestType'])

        logger.error(message)
        return send_response(
            status="FAILED",
            reason=message
        )