Rollback EC2 Provisioning if UserData Execution Fails

0

I am creating an EC2 instance (Windows) via Cloud Formation. I am also executing some User Data scripts (PowerShell). Sometimes, some scripts throw errors. If that happens, I want to roll back and terminate the EC2 instance. I am using the WaitCondition resource as mentioned in the link. Even when the instance is successfully provisioned and the User Data is successfully executed, the WaitCondition doesn't receive a success signal and the instance is getting rolled back. Please help.

 DBEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !GetAtt AMIInfo.Id
      KeyName: !Ref sshKeyName
      InstanceType: !Ref dbInstanceType
      IamInstanceProfile: !Ref EC2InstanceProfile
      PropagateTagsToVolumeOnCreation: True
      SecurityGroupIds:
        - !Ref EC2SecurityGroup
      SubnetId: !Select [ 0, !Ref pvtSubnetIdRef ]
      Tags:
        - Key: "Name"
          Value: !Ref dbInstanceName
      UserData:
        Fn::Base64:
          !Sub |
          <powershell>
            # START LOG.
            $LASTEXITCODE=0
            $ErrorActionPreference = "Stop"
            cfn-init.exe -v --stack ${AWS::StackName} --resource DBEC2Instance --region ${AWS::Region}              
            $timestamp = Get-Date -Format yyyyMMdd-hhmm
            Start-Transcript -Path $logpath -Force
            
            #  DOWNLOAD FILES
            write "Downloading files from S3 bucket '${bucketName}'"
            Get-S3Object -BucketName ${bucketName} -KeyPrefix ${S3Path}/ | Read-S3Object -Folder "C:\"

            #  CALL CUSTOM UTILITY
            write "running CustomUtility'.
            write "Last Exit Code: $LASTEXITCODE"
            cfn-signal.exe -e $LASTEXITCODE --stack ${AWS::StackName}  --resource DBEC2Instance --region ${AWS::Region}
            if ( $LASTEXITCODE -ne 0 ) 
            { 
              write-error "CustomUtility exit code '$LASTEXITCODE' does not indicate success. Refer logs for details." 
            }
            
          </powershell>  
  
  WaitHandle:
    Type: AWS::CloudFormation::WaitConditionHandle
  WaitCondition:
    Type: AWS::CloudFormation::WaitCondition
    DependsOn: DBEC2Instance
  # Properties:
    #   Handle: !Ref 'WaitHandle'
    #   Timeout: '900'
    #   Count: 1
    CreationPolicy:
      ResourceSignal:
        Timeout: PT10M
        Count: 1
asked 8 months ago263 views
1 Answer
1

From your post, I have noticed that you are using both wait condition handle and CreationPolicy and the syntax is also used incorrectly.

For Amazon EC2 and Auto Scaling resources, we recommend that you use a CreationPolicy attribute instead of wait conditions. Add a CreationPolicy attribute to those resources, and use the cfn-signal helper script to signal when an instance creation process has completed successfully.

You can use a wait condition for situations like the following:

  • To coordinate stack resource creation with configuration actions that are external to the stack creation.
  • To track the status of a configuration process.

For these situations, we recommend that you associate a CreationPolicy attribute with the wait condition so that you don't have to use a wait condition handle. For more details please refer to our public document

Below is the sample Cloudformation template -

Parameters:
  InstanceKey:
    Type: 'AWS::EC2::KeyPair::KeyName'
Resources:
  DBEC2Instance:
    Type: 'AWS::EC2::Instance'
    Properties:
      ImageId: ami-xxxxxxxxxxxx
      KeyName: !Ref InstanceKey
      InstanceType: m5.large
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
      UserData: !Base64 
        'Fn::Sub': |
          <powershell>
            # START LOG. 
            $lastexitcode = 0       
            $timestamp = Get-Date -Format yyyyMMdd-hhmm
            write " Date: $timestamp."
            #  CALL CUSTOM UTILITY
            write "running CustomUtility."
            cfn-signal.exe -e $lastexitcode --stack ${AWS::StackName}  --resource WaitCondition --region ${AWS::Region}
          </powershell> 
           
  WaitCondition:
    Type: 'AWS::CloudFormation::WaitCondition'
    CreationPolicy:
      ResourceSignal:
        Timeout: PT5M
        Count: 1
  InstanceSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupDescription: Allow ssh on the instance
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3389
          ToPort: 3389
          CidrIp: x.x.x.x/x
AWS
SUPPORT ENGINEER
answered 8 months ago
  • Thank you for your help. However, it is not working. As you can see my code, I tried WaitConditionHandle, but it is not linked to any other resource. So, I am not sure, whether there will be any impact. Also, the documentation is not very clear on how to get this working. I have a couple of more questions, though.

    1. In my code, I have cfn-init also. Is it not required?
    2. In the WaitCondition, don't we need a DependsOn property on the EC2 Instance

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions