Skip to main content

advanced cloudformation

create an initial cloudformation stack

aws cloudformation validate-template --template-body file://template-000.yml
aws cloudformation create-stack --stack-name mystack  --template-body file://mystack-000.yml

confirm the result

aws cloudformation describe-stacks --stack-name mystack 
aws cloudformation describe-stack-resources --stack-name mystack 
aws cloudformation describe-stack-events --stack-name mystack

change set

create change set after editing template file

aws cloudformation create-change-set --stack-name mystack --template-body file://mystack-001.yml --change-set-name mystack-001 --description 'create new Internet Gateway'
aws cloudformation list-change-sets --stack-name mystack 
aws cloudformation describe-change-set --stack-name mystack --change-set-name mystack-001

execute the change set

aws cloudformation execute-change-set --stack-name mystack --change-set-name mystack-001
aws cloudformation list-change-sets --stack-name mystack

drift

detect stack drift after manual operation

aws cloudformation detect-stack-drift --stack-name mystack 
aws cloudformation describe-stack-resource-drifts --stack-name mystack

create change set after editing template file to fit to current resource

aws cloudformation create-change-set --stack-name mystack --template-body file://mystack-002.yml --change-set-name mystack-002 --description 'reflect manual operation'
aws cloudformation list-change-sets --stack-name mystack 
aws cloudformation describe-change-set --stack-name mystack --change-set-name mystack-002

execute the change set

aws cloudformation execute-change-set --stack-name mystack --change-set-name mystack-002

remove change set when the status is false

aws cloudformation delete-change-set --stack-name mystack --change-set-name mystack-002

import

create template file

$ diff -u template.yml.orig template.yml
+Parameters:
+  ImageId:
+    Type: AWS::EC2::Image::Id
+  InstanceType:
+    Type: String
+  KeyName:
+    Type: AWS::EC2::KeyPair::KeyName
+  SecurityGroupId:
+    Type: AWS::EC2::SecurityGroup::Id
+  SubnetId:
+    Type: AWS::EC2::Subnet::Id
+

+  ## EC2 instance
+  EC2Instance1:
+    Type: AWS::EC2::Instance
+    DeletionPolicy: Retain
+    Properties: 
+      InstanceType: !Ref InstanceType
+      ImageId: !Ref ImageId
+      KeyName: !Ref KeyName
+      NetworkInterfaces: 
+        - DeviceIndex: "0"
+          GroupSet:
+            - !Ref SecurityGroupId
+          SubnetId: !Ref SubnetId
+      BlockDeviceMappings: 
+        - DeviceName: "/dev/xvda"
+          Ebs: 
+            VolumeType: "gp3"
+            VolumeSize: "8"
+      CreditSpecification:
+        CPUCredits: "standard"

create parameter file

$ jq . parameters.json
[
  {
    "ParameterKey": "ImageId",
    "ParameterValue": "ami-007daaef51c7530e7"
  },
  {
    "ParameterKey": "InstanceType",
    "ParameterValue": "t4g.nano"
  },
  {
    "ParameterKey": "KeyName",
    "ParameterValue": "testkey"
  },
  {
    "ParameterKey": "SecurityGroupId",
    "ParameterValue": "sg-xxxxxxxxxxxxxxxxx"
  },
  {
    "ParameterKey": "SubnetId",
    "ParameterValue": "subnet-xxxxxxxxxxxxxxxxx"
  }
]

create a resources-to-import file

$ jq . import.json 
[
  {
    "ResourceType": "AWS::EC2::Instance",
    "LogicalResourceId": "EC2Instance1",
    "ResourceIdentifier": {
      "InstanceId": "i-xxxxxxxxxxxxxxxxx"
    }
  }
]

create change set for import and execute it

$ aws cloudformation validate-template --template-body file://template.yml
$ aws cloudformation create-change-set --stack-name mystack --change-set-name import-ec2instance --change-set-type IMPORT --resources-to-import file://import.json --template-body file://template.yml --parameters file://parameters.json
$ aws cloudformation describe-change-set --change-set-name import-ec2instance --stack-name mystack
$ aws cloudformation execute-change-set  --change-set-name import-ec2instance --stack-name mystack

confirm the result

$ aws cloudformation describe-stacks --stack-name mystack
$ aws cloudformation describe-stack-events --stack-name mystack

detect stack drift

$ aws cloudformation detect-stack-drift --stack-name mystack
$ aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id xxxxxxxxxxxxx-xxxx-xxxx-xxxxxxxxxxx
$ aws cloudformation describe-stack-resource-drifts --stack-name mystack

If any drift exist, edit stack template to fit to current resource and create and execute change set.

after that, change deletion policy to Delete and update stack if needed

$ aws cloudformation update-stack --stack-name mystack --template-body file://template.yml --parameters file://parameters.json