CircleCIでTerraformを自動化してみた！LT用資料

## イベント詳細とスライド

■connpass URL

https://circleci.connpass.com/event/140666/

2019/8/23（金曜日）
CircleCIのユーザーコミュニティ主催のイベントで、LT枠をいただけたので、LTしてきました！
入り切らなかった内容はこちらにざっと書いていきます

■LTスライド

https://www.slideshare.net/hikarumiyazawa1/circle-ci-terraformplanapplyautomation-165781459

## .circleci/config.yml

```

version: 2.1

jobs:

  approval-notification-plan:

    docker:
      - image: alpine:3.10.1

    working_directory: ~/repo

    steps:
      - checkout

      - run:
          name: "Slack Approval Notification Terraform Plan"
          command: |
            chmod 755 plan_slack.sh
            cat plan_slack.sh
            apk update
            apk add curl
            ash ./plan_slack.sh
          working_directory: ~/repo/shellscripts

  plan:
    docker:
      - image: hashicorp/terraform:0.12.6

    working_directory: ~/repo

    steps:
      - checkout

      - run:
          name: "Init terraform"
          command: terraform init
          working_directory: ~/repo/[your_terraform_workspace_path]

      - run:
          name: "Validate terraform"
          command: terraform validate
          working_directory: ~/repo/[your_terraform_workspace_path]

      - run:
          name: "[OREGON-DEV] Workspace Select terraform"
          command: terraform workspace select oregon-dev
          working_directory: ~/repo/[your_terraform_workspace_path]
      - run:
          name: "[OREGON-DEV] Plan terraform"
          command: terraform plan
          working_directory: ~/repo/[your_terraform_workspace_path]

      - run:
          name: "[DEV] Workspace Select terraform"
          command: terraform workspace select dev
          working_directory: ~/repo/[your_terraform_workspace_path]
      - run:
          name: "[DEV] Plan terraform"
          command: terraform plan
          working_directory: ~/repo/[your_terraform_workspace_path]

      - run:
          name: "[STG] Workspace Select terraform"
          command: terraform workspace select stg
          working_directory: ~/repo/[your_terraform_workspace_path]
      - run:
          name: "[STG] Plan terraform"
          command: terraform plan
          working_directory: ~/repo/[your_terraform_workspace_path]

      - run:
          name: "[PRD] Workspace Select terraform"
          command: terraform workspace select prd
          working_directory: ~/repo/[your_terraform_workspace_path]
      - run:
          name: "[PRD] Plan terraform"
          command: terraform plan
          working_directory: ~/repo/[your_terraform_workspace_path]

  approval-notification-apply:

    docker:
      - image: alpine:3.10.1

    working_directory: ~/repo

    steps:
      - checkout

      - run:
          name: "Slack Approval Notification"
          command: |
            apk update
            apk add curl
            chmod 755 apply_slack.sh
            cat apply_slack.sh
            ash ./apply_slack.sh
          working_directory: ~/repo/shellscripts/

  apply-oregon-dev:

    docker:
      - image: hashicorp/terraform:0.12.6

    working_directory: ~/repo

    steps:
      - checkout

      - run:
          name: Init terraform
          command: terraform init
          working_directory: ~/repo/[your_terraform_workspace_path]

      - run:
          name: "[OREGON-DEV] Workspace Select terraform"
          command: terraform workspace select oregon-dev
          working_directory: ~/repo/[your_terraform_workspace_path]
      - run:
          name: "[OREGON-DEV] Apply terraform"
          command: terraform apply -auto-approve
          working_directory: ~/repo/[your_terraform_workspace_path]

  apply-dev:

    docker:
      - image: hashicorp/terraform:0.12.6

    working_directory: ~/repo

    steps:
      - checkout

      - run:
          name: Init terraform
          command: terraform init
          working_directory: ~/repo/[your_terraform_workspace_path]

      - run:
          name: "[DEV] Workspace Select terraform"
          command: terraform workspace select dev
          working_directory: ~/repo/[your_terraform_workspace_path]
      - run:
          name: "[DEV] Apply terraform"
          command: terraform apply -auto-approve
          working_directory: ~/repo/[your_terraform_workspace_path]

  apply-stg:

    docker:
      - image: hashicorp/terraform:0.12.6

    working_directory: ~/repo

    steps:
      - checkout

      - run:
          name: Init terraform
          command: terraform init
          working_directory: ~/repo/[your_terraform_workspace_path]

      - run:
          name: "[STG] Workspace Select terraform"
          command: terraform workspace select stg
          working_directory: ~/repo/[your_terraform_workspace_path]
      - run:
          name: "[STG] Apply terraform"
          command: terraform apply -auto-approve
          working_directory: ~/repo/[your_terraform_workspace_path]

  apply-prd:

    docker:
      - image: hashicorp/terraform:0.12.6

    working_directory: ~/repo

    steps:
      - checkout

      - run:
          name: Init terraform
          command: terraform init
          working_directory: ~/repo/[your_terraform_workspace_path]

      - run:
          name: "[PRD] Workspace Select terraform"
          command: terraform workspace select prd
          working_directory: ~/repo/[your_terraform_workspace_path]
      - run:
          name: "[PRD] Apply terraform"
          command: terraform apply -auto-approve
          working_directory: ~/repo/[your_terraform_workspace_path]

orbs:
  slack: circleci/slack@3.2.0

workflows:
  plan-and-apply:
    jobs:
      - approval-notification-plan

      - hold-plan:
          type: approval
          requires:
            - approval-notification-plan

      - plan:
          requires:
            - hold-plan

      - approval-notification-apply:
          requires:
            - plan
          filters:
            branches:
              only: master

      - hold-oregon-dev:
          type: approval
          requires:
            - approval-notification-apply
          filters:
            branches:
              only: master
      - apply-oregon-dev:
          requires:
            - hold-oregon-dev
          filters:
            branches:
              only: master

      - hold-dev:
          type: approval
          requires:
            - approval-notification-apply
          filters:
            branches:
              only: master
      - apply-dev:
          requires:
            - hold-dev
          filters:
            branches:
              only: master

      - hold-stg:
          type: approval
          requires:
            - approval-notification-apply
          filters:
            branches:
              only: master
      - apply-stg:
          requires:
            - hold-stg
          filters:
            branches:
              only: master

      - hold-prd:
          type: approval
          requires:
            - approval-notification-apply
          filters:
            branches:
              only: master
      - apply-prd:
          requires:
            - hold-prd
          filters:
            branches:
              only: master
```


## Environment Variables

![スクリーンショット_2019-08-23_16_44_17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148264/d62a04b8-11ba-4f22-566f-134510dc6c90.jpeg)



## slack通知用 shellscript

※Slack通知には便利なorbsが用意されています。今回はwebhookを使いまわして、別のチャンネルに通知したかったため、CircleCIのorbsの中からいい感じに取り出して、加工しました。

何か特別やりたいことが無い限りは、こちらがめちゃめちゃおすすめです！
https://circleci.com/orbs/registry/orb/circleci/slack


■plan_slack.sh

```
POSTDATA=`cat << EOF
{"channel":"#infra-sre","attachments":[{"fallback":"CircleCI tf plan Approval","text":"tf plan approval br=[${CIRCLE_BRANCH}]","fields":[{"title":"Project","value":"${CIRCLE_PROJECT_REPONAME}","short":true},{"title":"Job Number","value":"${CIRCLE_BUILD_NUM}","short":true}],"actions":[{"type":"button","text":"Visit Workflow","url":"https://circleci.com/workflow-run/${CIRCLE_WORKFLOW_ID}"},{"type":"button","text":"Visit Github","url":"https://github.com/your-organization/${CIRCLE_PROJECT_REPONAME}/tree/${CIRCLE_BRANCH}"}],"color":"good"}]}
EOF`
echo $POSTDATA
curl -X POST -H "Content-type: application/json" -d "$POSTDATA" ${SLACK_WEBHOOK}

```

■apply_slack.sh


```
POSTDATA=`cat << EOF
{"channel":"#infra-sre","attachments":[{"fallback":"CircleCI tf apply Approval","text":"tf apply approval br=[${CIRCLE_BRANCH}]","fields":[{"title":"Project","value":"${CIRCLE_PROJECT_REPONAME}","short":true},{"title":"Job Number","value":"${CIRCLE_BUILD_NUM}","short":true}],"actions":[{"type":"button","text":"Visit Workflow","url":"https://circleci.com/workflow-run/${CIRCLE_WORKFLOW_ID}"}],"color":"good"}]}
EOF`
echo $POSTDATA
curl -X POST -H "Content-type: application/json" -d "$POSTDATA" ${SLACK_WEBHOOK}

```