144 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			YAML
		
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			YAML
		
	
	
AWSTemplateFormatVersion: '2010-09-09'
 | 
						|
Description: Schedule automatic deletion of CloudFormation stacks
 | 
						|
Metadata:
 | 
						|
  AWS::CloudFormation::Interface:
 | 
						|
    ParameterGroups:
 | 
						|
      - Label:
 | 
						|
          default: Input configuration
 | 
						|
        Parameters:
 | 
						|
          - StackName
 | 
						|
          - TTL
 | 
						|
    ParameterLabels:
 | 
						|
      StackName:
 | 
						|
        default: Stack name
 | 
						|
      TTL:
 | 
						|
        default: Time-to-live
 | 
						|
Parameters:
 | 
						|
  EnvironmentName:
 | 
						|
    Type: String
 | 
						|
    Default: development
 | 
						|
    Description: 'Your deployment environment: DEV, QA , PROD'
 | 
						|
  BUILDGUID:
 | 
						|
    Type: String
 | 
						|
    Default: ''
 | 
						|
  StackName:
 | 
						|
    Type: String
 | 
						|
    Description: Stack name that will be deleted.
 | 
						|
  DeleteStackName:
 | 
						|
    Type: String
 | 
						|
    Description: Stack name that will be deleted.
 | 
						|
  TTL:
 | 
						|
    Type: Number
 | 
						|
    Description: Time-to-live in minutes for the stack.
 | 
						|
Resources:
 | 
						|
  DeleteCFNLambda:
 | 
						|
    Type: "AWS::Lambda::Function"
 | 
						|
    Properties:
 | 
						|
      FunctionName: !Join [ "", [ 'DeleteCFNLambda', !Ref BUILDGUID ] ]
 | 
						|
      Code:
 | 
						|
        ZipFile: |
 | 
						|
          import boto3
 | 
						|
          import os
 | 
						|
          import json
 | 
						|
 | 
						|
          stack_name = os.environ['stackName']
 | 
						|
          delete_stack_name = os.environ['deleteStackName']
 | 
						|
 | 
						|
          def delete_cfn(stack_name):
 | 
						|
              try:
 | 
						|
                  cfn = boto3.resource('cloudformation')
 | 
						|
                  stack = cfn.Stack(stack_name)
 | 
						|
                  stack.delete()
 | 
						|
                  return "SUCCESS"
 | 
						|
              except:
 | 
						|
                  return "ERROR"
 | 
						|
 | 
						|
          def handler(event, context):
 | 
						|
              print("Received event:")
 | 
						|
              print(json.dumps(event))
 | 
						|
              result = delete_cfn(stack_name)
 | 
						|
              delete_cfn(delete_stack_name)
 | 
						|
              return result          
 | 
						|
      Environment:
 | 
						|
        Variables:
 | 
						|
          stackName: !Ref 'StackName'
 | 
						|
          deleteStackName: !Ref 'DeleteStackName'
 | 
						|
      Handler: "index.handler"
 | 
						|
      Runtime: "python3.6"
 | 
						|
      Timeout: "5"
 | 
						|
      Role:
 | 
						|
       'Fn::ImportValue': !Sub '${EnvironmentName}:DeleteCFNLambdaExecutionRole'
 | 
						|
  DeleteStackEventRule:
 | 
						|
     DependsOn:
 | 
						|
       - DeleteCFNLambda
 | 
						|
       - GenerateCronExpression
 | 
						|
     Type: "AWS::Events::Rule"
 | 
						|
     Properties:
 | 
						|
       Name: !Join [ "", [ 'DeleteStackEventRule', !Ref BUILDGUID ] ]
 | 
						|
       Description: Delete stack event
 | 
						|
       ScheduleExpression: !GetAtt GenerateCronExpression.cron_exp
 | 
						|
       State: "ENABLED"
 | 
						|
       Targets:
 | 
						|
          -
 | 
						|
            Arn: !GetAtt DeleteCFNLambda.Arn
 | 
						|
            Id: 'DeleteCFNLambda'
 | 
						|
  PermissionForDeleteCFNLambda:
 | 
						|
    Type: "AWS::Lambda::Permission"
 | 
						|
    DependsOn:
 | 
						|
      - DeleteStackEventRule
 | 
						|
    Properties:
 | 
						|
      FunctionName: !Join [ "", [ 'DeleteCFNLambda', !Ref BUILDGUID ] ]
 | 
						|
      Action: "lambda:InvokeFunction"
 | 
						|
      Principal: "events.amazonaws.com"
 | 
						|
      SourceArn: !GetAtt DeleteStackEventRule.Arn
 | 
						|
  GenerateCronExpLambda:
 | 
						|
    Type: "AWS::Lambda::Function"
 | 
						|
    Properties:
 | 
						|
      FunctionName: !Join [ "", [ 'GenerateCronExpressionLambda', !Ref BUILDGUID ] ]
 | 
						|
      Code:
 | 
						|
        ZipFile: |
 | 
						|
          from datetime import datetime, timedelta
 | 
						|
          import os
 | 
						|
          import logging
 | 
						|
          import json
 | 
						|
          import cfnresponse
 | 
						|
 | 
						|
          def deletion_time(ttl):
 | 
						|
              delete_at_time = datetime.now() + timedelta(minutes=int(ttl))
 | 
						|
              hh = delete_at_time.hour
 | 
						|
              mm = delete_at_time.minute
 | 
						|
              yyyy = delete_at_time.year
 | 
						|
              month = delete_at_time.month
 | 
						|
              dd = delete_at_time.day
 | 
						|
              # minutes hours day month day-of-week year
 | 
						|
              cron_exp = "cron({} {} {} {} ? {})".format(mm, hh, dd, month, yyyy)
 | 
						|
              return cron_exp
 | 
						|
 | 
						|
          def handler(event, context):
 | 
						|
            print('Received event: %s' % json.dumps(event))
 | 
						|
            status = cfnresponse.SUCCESS
 | 
						|
            try:
 | 
						|
                if event['RequestType'] == 'Delete':
 | 
						|
                    cfnresponse.send(event, context, status, {})
 | 
						|
                else:
 | 
						|
                    ttl = event['ResourceProperties']['ttl']
 | 
						|
                    responseData = {}
 | 
						|
                    responseData['cron_exp'] = deletion_time(ttl)
 | 
						|
                    cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
 | 
						|
            except Exception as e:
 | 
						|
                logging.error('Exception: %s' % e, exc_info=True)
 | 
						|
                status = cfnresponse.FAILED
 | 
						|
                cfnresponse.send(event, context, status, {}, None)          
 | 
						|
      Handler: "index.handler"
 | 
						|
      Runtime: "python3.6"
 | 
						|
      Timeout: "5"
 | 
						|
      Role:
 | 
						|
       'Fn::ImportValue': !Sub '${EnvironmentName}:DeleteCFNLambdaExecutionRole'
 | 
						|
  GenerateCronExpression:
 | 
						|
    Type: "Custom::GenerateCronExpression"
 | 
						|
    Version: "1.0"
 | 
						|
    Properties:
 | 
						|
      Name: !Join [ "", [ 'GenerateCronExpression', !Ref BUILDGUID ] ]
 | 
						|
      ServiceToken: !GetAtt GenerateCronExpLambda.Arn
 | 
						|
      ttl: !Ref 'TTL'
 |