Skip to main content

Posts for year 2019

copy boot drive

make partition

parted /dev/sdc print
parted /dev/sdc rm 1
parted /dev/sdc mkpart primary ext4 1MiB 1GiB 
parted /dev/sdc mkpart primary ext4 1GiB 100% 
parted /dev/sdc set 1 boot on

make filesystem

mkfs -t ext4 -O ^has_journal /dev/sdc1
mkfs -t ext4 -O ^has_journal /dev/sdc2
dumpe2fs /dev/sdc1
dumpe2fs /dev/sdc2

copy files

apt-get install --no-install-recommends dump

mount -o noatime /dev/sdc2 /media/chroot
cd /media/chroot
dump -0 -f - /dev/vgsaturn/lvrootura | sudo restore -rf -

mount -o noatime /dev/sdc1 /media/chroot/boot
cd /media/chroot/boot
dump -0 -f - /dev/sdb1 | sudo restore -rf -

install grub

grub-install --boot-directory=/media/chroot/boot /dev/sdc
grub-mkconfig -o /media/chroot/boot/grub/grub.cfg

lvm

for test, create some image files

dd if=/dev/zero of=file1.img bs=1M count=0 seek=5120
dd if=/dev/zero of=file2.img bs=1M count=0 seek=5120
losetup /dev/loop1 file1.img
losetup /dev/loop2 file2.img

create and remove pv

pvcreate /dev/loop1
pvs
pvdisplay
pvdisplay -m
pvremove /dev/loop1

pvmove can move extents from one pv to another

pvmove /dev/loop1

create and vemove vg

vgcreate vgname /dev/loop1
vgs
vgdisplay
vgchange -an vgname
(if you remove the disk and insert it to another system,
you can find the volume group unless you remove the volume group)
vgremove vgname

you can add/remove pv to vg

vgextend vgname /dev/loop2
vgreduce vgname /dev/loop1

create logical volume

lvcreate -L 1G -n lvname vgname
lvs
lvdisplay
mkfs -t ext4 /dev/vgname/lvname
mount /dev/vgname/lvname /mountpoint

mirror or stripe

lvcreate -L 128M -m 1 -n lvname vgname
lvcreate -L 128M -i 2 -n lvname vgname

snapshot and merge. if you don't want to merge, you can simply remove the snapshot lv

lvcreate -L 64M --snapshot /dev/vgname/lvname -n lvsnap
lvconvert --merge vgname/lvsnap

extend logical volume and filesystem

lvextend -L +512MB /dev/vgname/lvname
e2fsck -f /dev/vgname/lvname
resize2fs /dev/vgname/lvname

shrink filesystem and logical volume

e2fsck -f /dev/vgname/lvname
resize2fs /dev/vgname/lvname 500M
lvchange -an /dev/vgname/lvname
lvreduce -L -512MB /dev/vgname/lvname
lvchange -ay /dev/vgname/lvname
resize2fs /dev/vgname/lvname

remove logical volume

lvchange -an /dev/vgname/lvname
lvremove /dev/vgname/lvname

umount

fuser -vm /mountpoint
umount /mountpoint

extend pv

parted /dev/sda
parted /dev/sda print
parted /dev/sda rm 2
parted /dev/sda resizepart 1 100%

pvdisplay /dev/sda1
vgdisplay vgname
pvresize /dev/sda1

extend partition

parted /dev/sdx print
parted /dev/sdx resizepart [num] 100%
e2fsck -f /dev/sdx[num]
resize2fs /dev/sdx[num]

apigateway

create rest-api

$ aws apigateway get-rest-apis
$ aws apigateway create-rest-api --name <API Name>
$ aws apigateway get-rest-api --rest-api-id <API ID>

create resource

$ aws apigateway get-resources --rest-api-id <API ID>
$ aws apigateway create-resource --rest-api-id <API ID> --parent-id <Parent Resource ID> --path-part subpath
$ aws apigateway get-resource --rest-api-id <API ID> --resource-id <Resource ID>

put method

$ aws apigateway put-method --rest-api-id <API ID> --resource-id <Resource ID> --authorization-type none --http-method get 
$ aws apigateway get-method --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET

put integration response

$ aws apigateway put-integration-response --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET --status-code 200 --selection-pattern "" --response-templates '{"application/json":"{\"json\":\"template\"}"}'
$ aws apigateway get-integration-response --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET --status-code 200

put method response

$ aws apigateway put-method-response --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET --status-code 200 --response-models '{"text/plain":"Empty"}'
$ aws apigateway get-method-response --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET --status-code 200

update integration

$ jq '.' test.json
[
  {
    "op": "add",
    "path": "/requestTemplates/application~1json",
    "value": "{\"example\":\"json\"}"
  }
]
$ aws apigateway update-integration --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET --patch-operations file://test.json

create deployment

$ aws apigateway get-deployments --rest-api-id <API ID>
$ aws apigateway create-deployment --rest-api-id <API ID> --stage-name <Stage Name>
$ aws apigateway get-deployment --rest-api-id <API ID> --deployment-id <Deployment ID>

create stage

$ aws apigateway get-stages --rest-api-id <API ID>
$ aws apigateway create-stage --rest-api-id <API ID> --stage-name <Stage Name> --deployment-id <Deployment ID>
$ aws apigateway get-stage --rest-api-id <API ID> --stage-name <Stage Name>

test invoke method

$ aws apigateway test-invoke-method --rest-api-id <API ID> --resource-id <Resource ID>
  --http-method [GET|POST|DELETE|...]
  --path-with-query-string "/"
  --body "bodystring"

create api key

$ aws apigateway get-api-keys
$ aws apigateway create-api-key --name testkey
$ aws apigateway get-api-key --api-key <Key ID>
$ aws apigateway get-api-key --api-key <Key ID> --include-value

update api key

$ aws apigateway update-api-key --api-key <Key ID> --patch-operations '{ "op":"replace", "path":"/enabled", "value":"true" }'

create usage plan

$ aws apigateway get-usage-plans
$ aws apigateway create-usage-plan --name myusageplan --api-stages '{"apiId":"<API ID>","stage":"<Stage Name>"}' --throttle '{ "burstLimit": 2, "rateLimit": 1.0 }' --quota '{ "limit": 320, "offset": 0, "period": "DAY" }'
$ aws apigateway get-usage-plan --usage-plan-id <Usage Plan ID>

associate usage-plan and key

$ aws apigateway get-usage-plan-keys --usage-plan-id <Usage Plan ID>
$ aws apigateway create-usage-plan-key --usage-plan-id <Usage Plan ID> --key-id <Key ID> --key-type API_KEY
$ aws apigateway get-usage-plan-key --usage-plan-id <Usage Plan ID> --key-id <Key ID>

update method

$ aws apigateway update-method --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET --patch-operations op='replace',path='/apiKeyRequired',value='true'
$ aws apigateway get-method --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET

test run with api-key

$ curl https://<API ID>.execute-api.<Region Name>.amazonaws.com/<Stage Name> --header "x-api-key:<API Key Value>"

diassociate usage-plan and key

$ aws apigateway get-usage-plan-key --usage-plan-id <Usage Plan ID> --key-id <Key ID>
$ aws apigateway delete-usage-plan-key --usage-plan-id <Usage Plan ID> --key-id <Key ID>

delete stage

$ aws apigateway get-stage --rest-api-id <API ID> --stage-name <Stage Name>
$ aws apigateway delete-stage --rest-api-id <API ID> --stage-name <Stage Name>

delete deployment

$ aws apigateway get-deployment --rest-api-id <API ID> --deployment-id <Deployment ID>
$ aws apigateway delete-deployment --rest-api-id <API ID> --deployment-id <Deployment ID>

delete usage-plan

$ aws apigateway get-usage-plan --usage-plan-id <Usage Plan ID>
$ aws apigateway delete-usage-plan --usage-plan-id <Usage Plan ID>

delete api key

$ aws apigateway get-api-key --api-key <Key ID>
$ aws apigateway delete-api-key --api-key <Key ID>

delete integration response

$ aws apigateway get-integration-response --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET --status-code 200
$ aws apigateway delete-integration-response --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET --status-code 200

delete method response

$ aws apigateway get-method-response --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET --status-code 200
$ aws apigateway delete-method-response --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET --status-code 200

delete integration

$ aws apigateway get-integration --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET
$ aws apigateway delete-integration --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET

delete method

$ aws apigateway get-method --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET
$ aws apigateway delete-method --rest-api-id <API ID> --resource-id <Resource ID> --http-method GET

delete resource

$ aws apigateway get-resource --rest-api-id <API ID> --resource-id <Resource ID>
$ aws apigateway delete-resource --rest-api-id <API ID> --resource-id <Resource ID>

delete rest-api

$ aws apigateway get-rest-api --rest-api-id <API ID>
$ aws apigateway delete-rest-api --rest-api-id <API ID>

cloudformation sample template

    ApiGatewayRestApi:
      Type: AWS::ApiGateway::RestApi
      Properties:
        Name: "ApiGatewayRestApi"
        Tags:
          - "Key": "Name"
            "Value": "test"
    ApiGatewayResourceSubject:
      Type: AWS::ApiGateway::Resource
      Properties:
        ParentId: !GetAtt ApiGatewayRestApi.RootResourceId
        PathPart: "{subject}"
        RestApiId: !Ref ApiGatewayRestApi
    TestLambdaPermission:
      Type: AWS::Lambda::Permission
      Properties:
        FunctionName: !GetAtt TestLambda.Arn
        Action: lambda:InvokeFunction
        Principal: apigateway.amazonaws.com
    ApiGatewayGET:
      Type: AWS::ApiGateway::Method
      Properties:
        HttpMethod: "GET"
        RestApiId: !Ref ApiGatewayRestApi
        ResourceId: !Ref ApiGatewayResourceSubject
        RequestParameters:
          "method.request.path.string": true
          "method.request.path.year": true
        AuthorizationType: "NONE"
        MethodResponses:
            - StatusCode: 200
              ResponseModels:
                application/json;charset=UTF-8: Empty
        Integration:
          Type: "AWS_PROXY"
          IntegrationHttpMethod: "POST"
          RequestParameters:
            "integration.request.path.string": "method.request.path.string"
            "integration.request.path.year": "method.request.path.year"
          Uri: !Sub >-
            arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${TestLambda.Arn}/invocations
          RequestTemplates:
            application/json: "{ \"statusCode\" : 200 }"
    DeployDevel:
      DependsOn: ApiGatewayGET
      Type: 'AWS::ApiGateway::Deployment'
      Properties:
        RestApiId: !Ref ApiGatewayRestApi
        StageName: "devel"

sns

create topic

$ aws sns create-topic --name <Topic Name>
$ aws sns list-topics
$ aws sns get-topic-attributes --topic-arn <Topic ARN>

create subscription

$ aws lambda list-functions | jq '.Functions[].FunctionArn'

$ aws sns subscribe --topic-arn <Topic ARN> --protocol lambda --notification-endpoint <Lambda ARN>
$ aws sns list-subscriptions
$ aws sns get-subscription-attributes --subscription-arn <Subscription ARN>

publish

$ aws sns publish --topic-arn <Topic ARN> --subject "test subject" --message "this is test message"

unsubscribe

$ aws sns unsubscribe --subscription-arn <Subscription ARN>

delete topic

$ aws sns delete-topic --topic-arn <Topic ARN>

create SNS with CloudFormation

prepare yaml file

$ cat sns.yml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  MySNSTopic:
    Type: 'AWS::SNS::Topic'
  MySubscription:
    Type: 'AWS::SNS::Subscription'
    Properties: 
      Endpoint: !Ref lambdaARN
      Protocol: lambda
      TopicArn: !Ref MySNSTopic
Parameters:
  lambdaARN:
    Type: String
$ aws cloudformation validate-template --template-body file://sns.yml

prepare paremeter file

$ jq '.' sns.parameter
[
  {
    "ParameterKey": "lambdaARN",
    "ParameterValue": "<lambda ARN>"
  }
]

create stack

$ aws cloudformation create-stack --template-body file://sns.yml --stack-name <Stack Name> --parameters file://sns.parameter

confirm CloudFormation

$ aws cloudformation list-stacks
$ aws cloudformation describe-stacks --stack-name <Stack Name>
$ aws cloudformation get-template --stack-name <Stack Name> --query 'TemplateBody' | xargs -0 printf

confirm SNS

$ aws sns list-topics
$ aws sns list-subscriptions

delete stack

$ aws cloudformation delete-stack --stack-name <Stack Name>
$ aws cloudformation list-stacks --query 'StackSummaries[?StackName==`<Stack Name>`]'
$ aws cloudformation describe-stacks --stack-name <Stack Name>

glacier

create vault

$ aws glacier create-vault --account-id - --vault-name <Vault Name>
$ aws glacier list-vaults --account-id -

set vault notification

$ jq '.' vault-notifications.json
{
  "SNSTopic": "<ARN of SNS Topic>",
  "Events": [
    "ArchiveRetrievalCompleted",
    "InventoryRetrievalCompleted"
  ]
}
$ aws glacier set-vault-notifications --account-id - --vault-name <Vault Name> --vault-notification-config file://vault-notifications.json
$ aws glacier get-vault-notifications --account-id - --vault-name <Vault Name>

set strategy of retrieval policy to free tier

$ jq '.' retrieval-policy.json 
{
  "Rules": [
    {
      "Strategy": "FreeTier"
    }
  ]
}
$ aws glacier set-data-retrieval-policy --account-id - --policy file://retrieval-policy.json
$ aws glacier get-data-retrieval-policy --account-id -

upload archive

$ aws glacier upload-archive --account-id - --vault-name <Vault Name> --body testdata.tar.enc
$ aws glacier describe-vault --account-id - --vault-name <Vault Name>

retrieve inventory

$ jq '.' inventory-retrieval.json
{
  "Type": "inventory-retrieval"
}
$ aws glacier initiate-job --account-id - --vault-name <Vault Name> --job-parameters file://inventory-retrieval.json
$ aws glacier list-jobs --account-id - --vault-name <Vault Name>

$ aws glacier describe-job --account-id - --vault-name <Vault Name> --job-id <Job ID>
$ aws glacier get-job-output --account-id - --vault-name <Vault Name> --job-id <Job ID> output.json

retrieve archive

$ jq '.' archive-retrieval.json
{
  "Type": "archive-retrieval",
  "ArchiveId": "<Archive ID>"
}
$ aws glacier initiate-job --account-id - --vault-name <Vault Name> --job-parameters file://archive-retrieval.json
$ aws glacier list-jobs --account-id - --vault-name <Vault Name>

$ aws glacier describe-job --account-id - --vault-name <Vault Name> --job-id <Job ID>
$ aws glacier get-job-output --account-id - --vault-name <Vault Name> --job-id <Job ID> output.dat

delete archive

$ aws glacier delete-archive --account-id - --vault-name <Vault Name> --archive-id <Archive ID>

delete vault notification

$ aws glacier delete-vault-notifications --account-id - --vault-name <Vault Name>
$ aws glacier get-vault-notifications --account-id - --vault-name <Vault Name>

delete vault

$ aws glacier describe-vault --account-id - --vault-name <Vault Name>
$ aws glacier delete-vault --account-id - --vault-name <Vault Name>

s3

objects

$ aws s3 ls s3://mybucketname/
$ aws s3 cp testfile.txt s3://mybucketname/
$ aws s3 cp s3://mybucketname/testfile.txt testfile2.txt
$ aws s3 rm s3://mybucketname/testfile.txt

bucket

$ aws s3api list-buckets
$ aws s3api list-buckets --query 'Buckets[?Name == `mybucketname`]'
$ aws s3api create-bucket --bucket mybucketname --region ap-northeast-1 --create-bucket-configuration LocationConstraint=ap-northeast-1
$ aws s3api delete-bucket --bucket mybucketname

default encryption for a bucket

$ aws s3api get-bucket-encryption --bucket mybucketname
$ aws s3api put-bucket-encryption --bucket mybucketname \
--server-side-encryption-configuration '{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}'

$ aws s3api head-object --bucket mybucketname --key testfile.txt

public access block

$ aws s3api get-public-access-block --bucket mybucketname
$ aws s3api put-public-access-block --bucket mybucketname \
--public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"

versioning

enable and disable versioning for a bucket

$ aws s3api get-bucket-versioning --bucket mybucketname
$ aws s3api put-bucket-versioning --bucket mybucketname --versioning-configuration '{"Status":"Enabled"}'
$ aws s3api put-bucket-versioning --bucket mybucketname --versioning-configuration '{"Status":"Suspended"}'

list object versions

$ aws s3api list-object-versions  --bucket mybucketname --prefix testfile.txt
$ aws s3api list-object-versions  --bucket mybucketname --prefix testfile.txt --query 'Versions[?IsLatest==`true`].VersionId'

remove all versions for a file (When a file remains in a bucket, you can not delete the bucket)

$ delete_objects=$(aws s3api list-object-versions --bucket mybucketname --prefix testfile.txt \
> --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}')

$ aws s3api delete-objects --bucket mybucketname --delete "${delete_objects}"

bucket notification configuration

$ aws s3api get-bucket-notification-configuration --bucket bucketname
$ jq . notification.json 
{
  "QueueConfigurations": [
    {
      "Events": [
        "s3:ObjectCreated:*"
      ],
      "QueueArn": "arn:aws:sqs:<region>:<id>:<queuename>",
      "Filter": {
        "Key": {
          "FilterRules": [
            {
              "Name": "prefix",
              "Value": "input/"
            }
          ]
        }
      }
    }
  ]
}
$ aws s3api put-bucket-notification-configuration --bucket bucketname --notification-configuration file://notification.json

Before configure bucket notification, add policy to SQS queue like below

{
  "Version": "2012-10-17",
  "Id": "arn:aws:sqs:<region>:<id>:<queuename>/<policyname>",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:<region>:<id>:<queuename>",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:s3:::<bucketname>"
        }
      }
    }
  ]
}

sample cloudformation template

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  BucketName:
    Type: String
Resources:
  MyPrivBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      BucketName: !Ref BucketName
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: AES256
      VersioningConfiguration:
        Status: "Enabled"
      Tags:
        - "Key": "Name"
          "Value": "test"

boto3 client

file operation

import boto3
import sys
bucket = "mybucketname"
try:
    s3_client = boto3.client('s3')
    s3_client.upload_file('testfile.txt', bucket, 'dirname/uploaded.txt')
    s3_client.download_file(bucket, 'dirname/uploaded.txt', 'downloaded.txt')
    s3_client.delete_object(Bucket = bucket, Key='dirname/uploaded.txt')
except:
    print ("error")
    sys.exit()

bucket operation

import boto3
import sys
bucket = "mybucketname"

try:
    s3_client = boto3.client('s3')
    # list buckets
    response = s3_client.list_buckets()
    for i in response.get('Buckets'):
        print(i.get('Name'))

    # delete a bucket
    response = s3_client.delete_bucket(
        Bucket=bucket
    )
    print(response)

except Exception as e:
    print (e)
    sys.exit()

Lambda

list functions

aws lambda list-functions
aws lambda get-function --function-name hello-world-python

You can download the zipfile of the source code with "jq -r '.Code.Location' result.json"

confirm CloudWatch Logs

aws logs describe-log-groups | jq .'logGroups[].logGroupName'
aws logs describe-log-streams --log-group-name /aws/lambda/hello-world-python
aws logs get-log-events --log-group-name /aws/lambda/hello-world-python --log-stream-name '2019/10/05/xxxxxxxx'

create function

aws lambda create-function --function-name hello-world-python \
--runtime python2.7 \
--handler lambda_function.lambda_handler \
--role arn:aws:iam::xxxxxxxx \
--zip-file fileb://../lambda_function.zip

modify function

aws lambda update-function-configuration --function-name hello-world-python --environment '{"Variables":{"key":"value"}}'
aws lambda update-function-code --function-name hello-world-python --zip-file fileb://../lambda_function.zip

invocation

aws lambda invoke --function-name hello-world-python --invocation-type DryRun --payload '{"message":"a b c 1 2 3"}' outfile.tmp
aws lambda invoke --function-name hello-world-python --payload '{"message":"a b c 1 2 3"}' outfile.tmp

delete function

aws lambda list-functions
aws lambda get-function --function-name hello-world-python
aws lambda delete-function --function-name hello-world-python

cloudformation sample template

    TestLambda:
      Type: AWS::Lambda::Function
      Properties:
        Code:
          S3Bucket: !Ref BucketName
          S3Key: "lambda_function.zip"
          S3ObjectVersion: !Ref S3ObjectVersion
        FunctionName: "TestFunction"
        Handler: "lambda_function.lambda_handler"
        MemorySize: 128
        Role: !GetAtt TestLambdaRole.Arn
        Runtime: "python2.7"
        Timeout: 3
        Tags:
          - "Key": "Name"
            "Value": "test"

CloudFormation

sample template of CloudFormation in yaml format

$ cat mystack.yml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  FirstVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      Tags:
      - Key: Name
        Value: myfirststack

validate template file

$ aws cloudformation validate-template --template-body file://mystack.yml

create stack

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

confrim information of created stack

$ aws cloudformation list-stacks
$ aws cloudformation describe-stacks --stack-name mystack
$ aws cloudformation describe-stack-events --stack-name mystack --query 'StackEvents[?ResourceType==`AWS::CloudFormation::Stack`]'

$ aws cloudformation describe-stack-resources --stack-name mystack
$ aws cloudformation list-stack-resources --stack-name mystack

$ aws cloudformation get-template --stack-name mystack
$ aws cloudformation get-template --stack-name mystack | jq -r '.TemplateBody'
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  FirstVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      Tags:
      - Key: Name
        Value: first-VPC

update template file and validate it

$ diff -u mystack.yml{,.bak}
--- mystack.yml 2019-09-16 11:23:04.368417527 +0900
+++ mystack.yml.bak     2019-09-16 10:51:35.053928361 +0900
@@ -1,12 +1,9 @@
 AWSTemplateFormatVersion: '2010-09-09'
-Parameters:
-  CidrBlock:
-    Type: String
 Resources:
   FirstVPC:
     Type: AWS::EC2::VPC
     Properties:
-      CidrBlock: !Ref CidrBlock
+      CidrBlock: 10.0.0.0/16
       Tags:
       - Key: Name
-        Value: mystack-VPC
+        Value: first-VPC

$ aws cloudformation validate-template --template-body file://mystack.yml

update the stack

$ aws cloudformation update-stack --stack-name mystack --template-body file://mystack.yml --parameters ParameterKey=CidrBlock,ParameterValue=10.0.0.0/17

confirm

delete the stack

$ aws cloudformation delete-stack --stack-name mystack

create stack with ansible

$ cat mystack.yml 
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  FirstVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.10.0.0/16
      Tags:
      - Key: Name
        Value: mystack

$ cat playbook.yml 
- hosts: 127.0.0.1
  connection: local
  gather_facts: False
  tasks:
    - name: create a cloudformation stack
      cloudformation:
        stack_name: "mystack"
        state: "present"
        region: "ap-northeast-1"
        disable_rollback: true
        template: "mystack.yml"

$ ansible-playbook --syntax-check playbook.yml 
$ ansible-playbook --list-tasks playbook.yml 
$ ansible-playbook --check playbook.yml
$ ansible-playbook playbook.yml

update stack with ansible

$ cat mystack.yml
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  CidrBlock:
    Type: String
Resources:
  FirstVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref CidrBlock
      Tags:
      - Key: Name
        Value: mystack

$ cat playbook.yml 
- hosts: 127.0.0.1
  connection: local
  gather_facts: False
  tasks:
    - name: create a cloudformation stack
      cloudformation:
        stack_name: "mystack"
        state: "present"
        region: "ap-northeast-1"
        disable_rollback: true
        template: "mystack.yml"
        template_parameters:
          CidrBlock: "10.20.0.0/16"

$ ansible-playbook playbook.yml

variable from command line

$ cat mystack.yml
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  CidrBlock:
    Type: String
Resources:
  FirstVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref CidrBlock
      Tags:
      - Key: Name
        Value: mystack

$ cat playbook.yml
- hosts: 127.0.0.1
  connection: local
  gather_facts: False
  tasks:
    - name: create a cloudformation stack
      cloudformation:
        stack_name: "mystack"
        state: "present"
        region: "ap-northeast-1"
        disable_rollback: true
        template: "mystack.yml"
        template_parameters:
          CidrBlock: "{{ CidrBlock }}"

$ ansible-playbook -e "CidrBlock=10.30.0.0/16" playbook.yml

delete stack with ansible

$ cat playbook.yml
- hosts: 127.0.0.1
  connection: local
  gather_facts: False
  tasks:
    - name: delete a cloudformation stack
      cloudformation:
        stack_name: "mystack"
        state: "absent"
        region: "ap-northeast-1"

$ ansible-playbook playbook.yml