インフラ維新 ハシモトプロダクト Terraform の Command Line Interface( CLI )

## <i class="fa fa-moon-o" style="font-size:1em;"></i>　概要
インフラ維新 ハシモトプロダクト Terraform の Command Line Interface( CLI ) について

## <i class="fa fa-question-circle" style="font-size:1em;"></i> Terraform について
Terraform については下記記事を参照

* <i class="fa fa-external-link-square" style="font-size:1em;"></i> [ハシモトさんの頭に広がる宇宙 Terraform とは？](http://qiita.com/tbpgr/items/a0a31c433f65e58368c6)

## <i class="fa fa-code" style="font-size:1em;"></i> Terraform の CLI
Terraform はシンプルな一つの Command Line Interface のツールです。
各機能は、サブコマンドとして実現されています。

一般的な CLI アプリケーションと同様、エラーが発生すれば 0 以外のステータスを返却し、
`-h` or `--help` オプションによって、ヘルプを表示します。

## <i class="fa fa-check-circle" style="font-size:1em;"></i> 前提
Terraform で Ruboty-Gacha アプリケーション を Heroku に構築する、
という利用例を元にCLI を説明します。

Ruboty-Gacha については、下記記事を参照

* <i class="fa fa-external-link-square" style="font-size:1em;"></i> [Sinatra + Heroku で Ruboty の Plugin の中からランダムで1つ選んでツイートする Web アプリケーションを作成 - tbpgr - Qiita](http://qiita.com/tbpgr/items/048d876d2198c779142f)

設定内容は以下を使用します。

* heroku.tf

~~~
variable "heroku_email" {}
variable "heroku_api_key" {}

provider "heroku" {
  email = "${var.heroku_email}"
  api_key = "${var.heroku_api_key}"
}

resource "heroku_app" "web" {
  name = "ruboty-gacha"
  region = "us"
  stack = "cedar-14"
  config_vars {
    BUILDPACK_URL="https://github.com/tbpgr/ruboty-gacha.git"
  }
}

output "heroku-name" {
  value = "${heroku_app.web.name}"
}

output "heroku-region" {
  value = "${heroku_app.web.region}"
}

output "heroku-stack" {
  value = "${heroku_app.web.stack}"
}
~~~

## <i class="fa fa-tint" style="font-size:1em;"></i> apply

`apply` は、要求された設定や事前に決めた `terraform plan` による実行プランを
適用するコマンドです。

詳細は、下記の公式ドキュメント参照。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [apply - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/apply.html)

### <i class="fa fa-flask" style="font-size:1em;"></i> 試行
以下の内容で、 heroku に新規アプリケーション用の環境が作成されます。

~~~bash
% terraform apply \
    -var heroku_email=$HEROKU_EMAIL \
    -var heroku_api_key=$HEROKU_API_KEY
heroku_app.web: Creating...
  all_config_vars.#:           "" => "<computed>"
  config_vars.#:               "" => "1"
  config_vars.0.#:             "" => "1"
  config_vars.0.BUILDPACK_URL: "" => "https://github.com/tbpgr/ruboty-gacha.git"
  git_url:                     "" => "<computed>"
  heroku_hostname:             "" => "<computed>"
  name:                        "" => "ruboty-gacha"
  region:                      "" => "us"
  stack:                       "" => "cedar-14"
  web_url:                     "" => "<computed>"
heroku_app.web: Creation complete


Outputs:

  heroku-name   = ruboty-gacha
  heroku-region = us
  heroku-stack  = cedar-14
~~~

## <i class="fa fa-tint" style="font-size:1em;"></i> destroy
`destroy` は、Terraform で管理されたインフラを削除します。

詳細は、下記の公式ドキュメント参照。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [destroy - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/destroy.html)

### <i class="fa fa-flask" style="font-size:1em;"></i> 試行
実行時に対話形式で

* 実行有無
* heroku api key
* heroku に登録している email address

を確認されます。

~~~bash
% terraform destroy
Do you really want to destroy?
  Terraform will delete all your managed infrastructure.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: <input yes>

var.heroku_api_key
  Enter a value: <input your api key>

var.heroku_email
  Enter a value: <input your email>

heroku_app.web: Refreshing state... (ID: ruboty-gacha)
heroku_app.web: Destroying...
heroku_app.web: Destruction complete

Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
~~~

## <i class="fa fa-tint" style="font-size:1em;"></i> get
`get` は、最新のモジュールを取得します。
取得したモジュールは `./.terraform` に保存されます。

詳細は、下記の公式ドキュメント参照。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [get - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/get.html)

### <i class="fa fa-flask" style="font-size:1em;"></i> 試行

* Terraform 設定ファイルに 以下の設定を追記

~~~
module "consul" {
    source = "github.com/hashicorp/consul/terraform/aws"
    servers = 3
}
~~~

* get を実行

~~~bash
% terraform get
Get: git::https://github.com/hashicorp/consul.git
~~~

## <i class="fa fa-tint" style="font-size:1em;"></i> graph
実行プランをグラフで可視化します。
出力は Graphviz の DOT ファイルフォーマットです。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [graph - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/graph.html)

### <i class="fa fa-flask" style="font-size:1em;"></i> 試行

~~~bash
% terraform graph > graph.dot
% cat graph.dot
digraph {
        compound = "true"
        newrank = "true"
        subgraph "root" {
                "[root] heroku_app.web" [label = "heroku_app.web", shape = "box"]
                "[root] provider.heroku" [label = "provider.heroku", shape = "diamond"]
                "[root] heroku_app.web" -> "[root] provider.heroku"
        }
}
~~~

#### `dot` コマンドで png ファイルを生成
graphviz の dot コマンドで dot ファイルから画像を生成します。

~~~bash
% dot -Tpng -o ruboty-gacha_graph.png graph.dot
~~~

![ruboty-gacha_graph.png](https://qiita-image-store.s3.amazonaws.com/0/43480/8121f999-7e57-aa00-d12b-3cae80bc6394.png)

## <i class="fa fa-tint" style="font-size:1em;"></i> init
skeleton として他の module を利用して、 Terraform の設定を初期化します。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [init - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/init.html)

### <i class="fa fa-flask" style="font-size:1em;"></i> 試行

~~~bash
% terraform init github.com/hashicorp/terraform/examples/aws-two-tier
% tree
.
├── main.tf
├── outputs.tf
├── README.md
└── variables.tf

0 directories, 4 files
~~~

## <i class="fa fa-tint" style="font-size:1em;"></i> output
state ファイルの output から値を取得します。
state ファイルの output は、 Terraform ファイル内で
output 記法によって出力されます。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [output - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/output.html)

### <i class="fa fa-flask" style="font-size:1em;"></i> 試行

~~~bash
% terraform output heroku-name
ruboty-gacha
% terraform output heroku-region
us
% terraform output heroku-stack
cedar-14
~~~

## <i class="fa fa-tint" style="font-size:1em;"></i> plan
実行プランを作成します。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [plan - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/plan.html)

### <i class="fa fa-flask" style="font-size:1em;"></i> 試行

~~~bash
% terraform plan \
    -var heroku_email=$HEROKU_EMAIL \
    -var heroku_api_key=$HEROKU_API_KEY
Refreshing Terraform state prior to plan...


The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

+ heroku_app.web
    all_config_vars.#:           "" => "<computed>"
    config_vars.#:               "" => "1"
    config_vars.0.#:             "" => "1"
    config_vars.0.BUILDPACK_URL: "" => "https://github.com/tbpgr/ruboty-gacha.git"
    git_url:                     "" => "<computed>"
    heroku_hostname:             "" => "<computed>"
    name:                        "" => "ruboty-gacha"
    region:                      "" => "us"
    stack:                       "" => "cedar-14"
    web_url:                     "" => "<computed>"
~~~

## <i class="fa fa-tint" style="font-size:1em;"></i> push
 Terraform 設定ファイルを <i class="fa fa-external-link" style="font-size:1em;"></i> [Atras](https://atlas.hashicorp.com/) にアップロードします。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [push - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/push.html)

## <i class="fa fa-tint" style="font-size:1em;"></i> refresh
state ファイルを更新します。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [refresh - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/refresh.html)

state ファイルについては下記参照

* <i class="fa fa-external-link" style="font-size:1em;"></i> [State - Docs - Terraform](https://www.terraform.io/docs/state/index.html)

### <i class="fa fa-flask" style="font-size:1em;"></i> 試行

~~~bash
% terraform refresh \
    -var heroku_email=$HEROKU_EMAIL \
    -var heroku_api_key=$HEROKU_API_KEY
heroku_app.web: Refreshing state... (ID: ruboty-gacha)
~~~

## <i class="fa fa-tint" style="font-size:1em;"></i> remote
リモートの関連の操作。
`config`, `pull`, `push` のサブコマンドがある。

詳しくは以下のリンク先を参照

* <i class="fa fa-external-link" style="font-size:1em;"></i> [remote - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/remote.html)

## <i class="fa fa-tint" style="font-size:1em;"></i> show
state や plan ファイルから人間が読みやすい形式で内容を表示します。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [show - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/show.html)

### <i class="fa fa-flask" style="font-size:1em;"></i> 試行

~~~bash
% terraform show
heroku_app.web:
  id = ruboty-gacha
  all_config_vars.# = 1
  all_config_vars.BUILDPACK_URL = https://github.com/tbpgr/ruboty-gacha.git
  config_vars.# = 1
  config_vars.0.# = 1
  config_vars.0.BUILDPACK_URL = https://github.com/tbpgr/ruboty-gacha.git
  git_url = git@heroku.com:ruboty-gacha.git
  heroku_hostname = ruboty-gacha.herokuapp.com
  name = ruboty-gacha
  region = us
  stack = cedar-14
  web_url = https://ruboty-gacha.herokuapp.com/


Outputs:

heroku-name = ruboty-gacha
heroku-region = us
heroku-stack = cedar-14
~~~

## <i class="fa fa-tint" style="font-size:1em;"></i> taint
詳しくは以下のリンク先を参照

* <i class="fa fa-external-link" style="font-size:1em;"></i> [taint - COMMANDS(CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/taint.html)

## <i class="fa fa-tint" style="font-size:1em;"></i> version
version を表示します

### <i class="fa fa-flask" style="font-size:1em;"></i> 試行

~~~bash
% terraform version
Terraform v0.5.2
~~~

## <i class="fa fa-warning" style="font-size:1em;"></i> その他
その他、より詳しい情報については公式サイトのドキュメントをご確認ください。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [TERRAFORM COMMANDS (CLI) - Docs - Terraform](https://www.terraform.io/docs/commands/index.html)