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'
							 | 
						||
| 
								 | 
							
								  BUILDID:
							 | 
						||
| 
								 | 
							
								    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 BUILDID ] ]
							 | 
						||
| 
								 | 
							
								      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 BUILDID ] ]
							 | 
						||
| 
								 | 
							
								       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 BUILDID ] ]
							 | 
						||
| 
								 | 
							
								      Action: "lambda:InvokeFunction"
							 | 
						||
| 
								 | 
							
								      Principal: "events.amazonaws.com"
							 | 
						||
| 
								 | 
							
								      SourceArn: !GetAtt DeleteStackEventRule.Arn
							 | 
						||
| 
								 | 
							
								  GenerateCronExpLambda:
							 | 
						||
| 
								 | 
							
								    Type: "AWS::Lambda::Function"
							 | 
						||
| 
								 | 
							
								    Properties:
							 | 
						||
| 
								 | 
							
								      FunctionName: !Join [ "", [ 'GenerateCronExpressionLambda', !Ref BUILDID ] ]
							 | 
						||
| 
								 | 
							
								      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 BUILDID ] ]
							 | 
						||
| 
								 | 
							
								      ServiceToken: !GetAtt GenerateCronExpLambda.Arn
							 | 
						||
| 
								 | 
							
								      ttl: !Ref 'TTL'
							 |