Ansibleを更新したら、CircleCIでAMIを作成する


cloudpack大阪の佐々木です。

以前、CFn → Ansible → ServerspecをCircleCIでCIする
http://qiita.com/taishin/items/89b42106582a2aa5495b
というのを書きました。
このときはCFnとAnsibleを同時にテストするという方法をとっていたのですが、
これらは分けて管理した方がいいような気がしてきました。

なので、Ansibleのgitリポジトリをプッシュした時に、AMIを作成するようにしてみました。

https://github.com/taishin/ami-ci

EC2の起動はaws-cliでもいいのですが、前のCFnをそのまま使いました。

circle.ymlでやっていることは下記です。

- pre部分
	1. CFnでEC2を起動
	2. ansibleでデプロイ

- override部分
	1. ansibleでデプロイしたインスタンスのAMIを作成
	2. 作成したAMIを使って、CFnでEC2を起動
	3. serverspecでテスト

- post部分
	1. CFnを削除
	2. AMIにタグ付け

```yaml:circle.yml
machine:
  timezone: Asia/Tokyo
  ruby:
    version:
      2.1.2
  environment:
    AWS_AMI_ID: ami-6154bb00
    AWS_INSTANCE_TYPE: t2.micro
    AWS_CF_STACK_NAME: ci-test
    SSH_USER: ec2-user
    AMI_NAME: ami-ci

dependencies:
  pre:
    - sudo pip install ansible

test:
  pre:
    - aws cloudformation create-stack --stack-name $AWS_CF_STACK_NAME --template-body file://ami-ci.cform --parameters ParameterKey=KeyName,ParameterValue=$AWS_KEY_NAME ParameterKey=ImageId,ParameterValue=$AWS_AMI_ID ParameterKey=InstanceType,ParameterValue=$AWS_INSTANCE_TYPE
    - aws cloudformation wait stack-create-complete --stack-name $AWS_CF_STACK_NAME
    - aws cloudformation describe-stacks --stack-name $AWS_CF_STACK_NAME | jq -r '.Stacks[].Outputs[] | select(.OutputKey == "PublicIP") | .OutputValue' > /tmp/publicip.txt
    - aws cloudformation describe-stacks --stack-name $AWS_CF_STACK_NAME | jq -r '.Stacks[].Outputs[] | select(.OutputKey == "InstanceId") | .OutputValue' > /tmp/instanceid.txt
    - echo "`cat /tmp/publicip.txt` testserver" >> /tmp/hosts.txt
    - cp /etc/hosts .
    - sudo bash -c "cat hosts /tmp/hosts.txt | tee /etc/hosts"
    - echo "Host testserver" >> ~/.ssh/config
    - echo "User $SSH_USER" >> ~/.ssh/config
    - ssh -t $SSH_USER@testserver sudo yum update -y
    - ssh -t $SSH_USER@testserver sudo yum install epel-release -y
    - ansible-playbook -i ansible/hosts ansible/nginx.yml
    
  override:
    - aws ec2 create-image --name $AMI_NAME-`git log -n 1 --format=%H` --instance-id `cat /tmp/instanceid.txt` | jq -r '.ImageId' > /tmp/imageid.txt
    - sleep 300
    - aws cloudformation create-stack --stack-name ${AWS_CF_STACK_NAME}-2 --template-body file://ami-ci.cform --parameters ParameterKey=KeyName,ParameterValue=$AWS_KEY_NAME ParameterKey=ImageId,ParameterValue=`cat /tmp/imageid.txt` ParameterKey=InstanceType,ParameterValue=$AWS_INSTANCE_TYPE
    - aws cloudformation wait stack-create-complete --stack-name ${AWS_CF_STACK_NAME}-2
    - aws cloudformation describe-stacks --stack-name ${AWS_CF_STACK_NAME}-2 | jq -r '.Stacks[].Outputs[] | select(.OutputKey == "PublicIP") | .OutputValue' > /tmp/publicip.txt
    - echo "`cat /tmp/publicip.txt` amitestserver" >> /tmp/hosts2.txt
    - cp /etc/hosts .
    - sudo bash -c "cat hosts /tmp/hosts2.txt | tee /etc/hosts"
    - echo "Host amitestserver" >> ~/.ssh/config
    - echo "User $SSH_USER" >> ~/.ssh/config
    - bundle exec rake spec:amitestserver
  post:
    - aws cloudformation delete-stack --stack-name $AWS_CF_STACK_NAME
    - aws cloudformation delete-stack --stack-name ${AWS_CF_STACK_NAME}-2
    - aws ec2 create-tags --resources `cat /tmp/imageid.txt` --tags Key=commitId,Value=`git log -n 1 --format=%H` Key=Name,Value=ami-ci-`git log -n 1 --format=%H` Key=Name,Value=$AMI_NAME
Contact GitHub API Training Shop Blog About
```


起動時に都度Ansibleを実行することもなくなり、起動も早くなるので、AutoScaleとかでも使いやすくなるかなーと思います。