OSS 版 drone 0.4 + terraform で インフラCIする

#概要
drone0.4 の terraform plugin で インフラCI する

 - レポジトリは Github のプライベートレポジトリを作成
 - デプロイ先は AWS


drone 0.4 の環境構築に関しては[以前の記事](http://qiita.com/quickguard/items/06747c1762a0373b8204)参照

terraform plugin の詳細は[こちら](http://readme.drone.io/plugins/terraform/)

#前提
- drone の OAuth applications 登録済み
- terraform の tfstate は S3 で管理する

#準備
**レポジトリの作成**
Github 上で CI 用の新規レポジトリを作成する
![01.png](https://qiita-image-store.s3.amazonaws.com/0/105824/4d73b322-594b-fc1d-9560-7debd64c34e3.png)

**レポジトリを Activate する**
Drone にアクセスして、作成したレポジトリを選択して Activate する
![02.png](https://qiita-image-store.s3.amazonaws.com/0/105824/189882c0-471a-65cf-2493-1ede8421a930.png)

Deploy Key は自動で登録されるため、Github, Drone の設定についてはこれで完了

#S3 Bucket 作成
tfstate 管理用の S3 Bucket を作成する

```
$ aws s3 mb s3://quickguard-terraform-config
```

#secret variable 作成
Drone 画面の SECRETS より環境変数を入力して secret variable を作成する

![03.png](https://qiita-image-store.s3.amazonaws.com/0/105824/10dc05ee-cd5f-6d4a-0906-c87f76a066e9.png)

**環境変数の内容**

- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY 
- AWS_DEFAULT_REGION
- SSH_KEY_NAME ： EC2インスタンスに設定する SSH Key Name
- TFSTATE_BUCKET ： tfstate 管理用の S3 Bucket Name
- TFSTATE_KEY ： tfstate Name

作成された secret variable を .drone.sec ファイルとして保存してコミットしておく

```
$ git add .drone.sec
$ git commit -m "[CI SKIP]added .drone.sec file"
```

#.drone.yml を作成

```bash:.drone.yml
build:
  image: docker-registry:5000/terraform
  environment:
    - AWS_ACCESS_KEY_ID=$$AWS_ACCESS_KEY_ID
    - AWS_SECRET_ACCESS_KEY=$$AWS_SECRET_ACCESS_KEY
    - AWS_DEFAULT_REGION=$$AWS_DEFAULT_REGION
    - SSH_KEY_NAME=$$SSH_KEY_NAME
    - TFSTATE_BUCKET=$$TFSTATE_BUCKET
    - TFSTATE_KEY=$$TFSTATE_KEY
  commands:
    - cd $DRONE_DIR
    - rm -rf .terraform
    - terraform remote config -backend=s3 -backend-config=region=${AWS_DEFAULT_REGION} -backend-config=bucket=${TFSTATE_BUCKET} -backend-config=key=${TFSTATE_KEY}
    - terraform remote pull
    - terraform plan -var access_key=${AWS_ACCESS_KEY_ID} -var secret_key=${AWS_SECRET_ACCESS_KEY} -var region=${AWS_DEFAULT_REGION} -var key_name=${SSH_KEY_NAME}
  when:
    branch: "!master"

deploy:
  terraform:
    plan: false
    sensitive: true
    remote:
      backend: S3
      config:
        access_key: $$AWS_ACCESS_KEY_ID
        secret_key: $$AWS_SECRET_ACCESS_KEY
        region: $$AWS_DEFAULT_REGION
        bucket: $$TFSTATE_BUCKET
        key: $$TFSTATE_KEY
    vars:
      access_key: $$AWS_ACCESS_KEY_ID
      secret_key: $$AWS_SECRET_ACCESS_KEY
      region: $$AWS_DEFAULT_REGION
      key_name: $$SSH_KEY_NAME
    when:
      branch: master
```
※image は alpine をベースに terraterm 0.6.11 をインストールしたコンテナを使用
※`terraform plan` は master branch 以外に commit された際に実行
※`terraform apply` は master branch に commit 時のみ実行

テスト時の terraform コンテナの Dockerfile は以下

```bash:Dockerfile
FROM alpine:3.2

ENV TERRAFORM_VERSION 0.6.11

RUN apk add --update wget bash git perl libxml2-utils openssh ca-certificates unzip && \
    wget -q "https://circle-artifacts.com/gh/andyshinn/alpine-pkg-glibc/6/artifacts/0/home/ubuntu/alpine-pkg-glibc/packages/x86_64/glibc-2.21-r2.apk" && \
    apk add --allow-untrusted glibc-2.21-r2.apk && \
    wget -q -O /terraform.zip "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" && \
    unzip /terraform.zip -d /bin && \
    apk del --purge wget ca-certificates unzip && \
    rm -rf /var/cache/apk/* glibc-2.21-r2.apk /terraform.zip

VOLUME ["/data"]

WORKDIR /data

ENTRYPOINT ["/bin/terraform"]

CMD ["--help"]
```

`.drone.sec` ファイルと `.drone.yml` ファイルをレポジトリに commit しておく
(terraform のコードがまだないため、commit メッセージに `[CI SKIP]` を入力してスキップしておく)

#インフラCIしてみる

terraform のコードはとりあえず [example](https://github.com/hashicorp/terraform/tree/master/examples/aws-eip) を適当に修正して作成

```bash:main.tf
provider "aws" {
    access_key = "${var.access_key}"
    secret_key = "${var.secret_key}"
    region = "${var.region}"
}

resource "aws_eip" "default" {
  instance = "${aws_instance.web.id}"
  vpc = true
}

resource "aws_security_group" "default" {
  name = "eip_example"
  description = "Used in the terraform"

  ingress {
    from_port = 22
    to_port = 22
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port = 80
    to_port = 80
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "web" {
  instance_type = "t2.micro"
  ami = "${lookup(var.aws_amis, var.region)}"
  key_name = "${var.key_name}"
  security_groups = ["${aws_security_group.default.name}"]

  user_data = "${file("userdata.sh")}"
  tags {
    Name = "eip-example"
  }
}
```

```bash:outputs.tf
output "address" {
  value = "${aws_instance.web.private_ip}"
}
output "elastic ip" {
  value = "${aws_eip.default.public_ip}"
}
```

```bash:variables.tf
variable "access_key" {
  description = "AWS access key"
}

variable "secret_key" {
  description = "AWS secret key"
}

variable "region" {
  description = "The AWS region to create things in."
}

# ubuntu-trusty-14.04 (x64)
variable "aws_amis" {
  default = {
    "ap-northeast-1" = "ami-a21529cc"
  }
}

variable "key_name" {
  description = "Name of the SSH keypair to use in AWS."
}
```

```bash:userdata.sh
#!/bin/bash -v
apt-get update -y
apt-get install -y nginx > /tmp/nginx.log
```

適当な branch 作成して terraform のコードを push ,　Pull Request を作成する

![06.png](https://qiita-image-store.s3.amazonaws.com/0/105824/c7657246-e84b-e495-8952-d75b2c8ba2b0.png)

**テスト(terraform plan)結果**
![07.png](https://qiita-image-store.s3.amazonaws.com/0/105824/0c66f29c-6377-70c2-1d37-ddf7eba2b651.png)

問題なければ Merge する

**terraform apply 結果**
![08.png](https://qiita-image-store.s3.amazonaws.com/0/105824/eb4f5f78-664e-a0ce-c526-edbdf40fe49a.png)

terraform の output も確認できる