Terraform備忘録

# お題
Terraform(`v0.12`)での備忘録。
Terraform CLIのインストールやAWSプロジェクトの作成及びローカルからコマンド叩ける状態になっている前提。

# 環境
### # OS - Linux(Ubuntu)
```
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
```

### # IDE - Visual Studio Code
```
Version: 1.35.1
Commit: c7d83e57cd18f18026a8162d042843bda1bcf21f
Date: 2019-06-12T14:27:31.086Z
```

##### vscode-terraform Plugin
```
Name: Terraform
Id: mauve.terraform
Description: Syntax highlighting, linting, formatting, and validation for Hashicorp's Terraform
Version: 1.3.12
Publisher: Mikael Olenfalk
VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=mauve.terraform
```

### # Terraform
```
$ terraform version
Terraform v0.12.2
```

### # tfenv
```
$ tfenv
tfenv 0.6.0
```

# Terraform Commands (CLI)

すべての仕様はもちろん公式に書いている。
https://www.terraform.io/docs/commands/index.html

## CLI使用に使うテンプレートファイル

```main.tf
resource "aws_instance" "sample" {
  ami = "ami-0f9ae750e8274075b"
  instance_type = "t2.micro"
}
```

## テンプレートファイル書いたら、何はともあれ `init`

### terraform init
```
$ terraform init

Initializing the backend...

　〜〜　省略　〜〜

* provider.aws: version = "~> 2.16"

Terraform has been successfully initialized!
```

すると、同一ディレクトリに「`.terraform`」ディレクトリが作られる。
中身はこんな感じ。

```
$ ls -l .terraform/plugins/linux_amd64/
total 143096
-rwxr-xr-x 1 sky0621 sky0621        79 Jun 23 07:40 lock.json
-rwxr-xr-x 1 sky0621 sky0621 146519904 Jun 23 07:40 terraform-provider-aws_v2.16.0_x4
```

## 公式のフォーマッタにかける。

### terraform fmt
例えばこんなファイルフォーマットで書いてたりすると、

```main.tf
resource   "aws_instance" "sample" {
      ami = "ami-0f9ae750e8274075b" 
        instance_type = "t2.micro"
}
```

フォーマッタにかけることで、

```
$ terraform fmt
main.tf
```

このように直してくれる。

```main.tf
resource "aws_instance" "sample" {
  ami           = "ami-0f9ae750e8274075b"
  instance_type = "t2.micro"
}
```

## 今度はバリデーション

### terraform validate
例えば「`abc = 123`」のような存在しない定義をすると、

```main.tf
resource "aws_instance" "sample" {
  ami           = "ami-0f9ae750e8274075b"
  instance_type = "t2.micro"
  abc = 123
}
```

バリデーション実行で、

```
$ terraform validate

Error: Unsupported argument

  on main.tf line 4, in resource "aws_instance" "sample":
   4:   abc = 123

An argument named "abc" is not expected here. Did you mean "arn"?
```

と怒ってくれる。（`terraform plan`実行前のお作法にしたい。）
正しい場合は以下のように表示される。

```
$ terraform validate
Success! The configuration is valid.
```

## 実行プランの確認

### terraform plan

```
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.sample will be created
  + resource "aws_instance" "sample" {
      + ami                          = "ami-0a5244998f15ade9d"
      + arn                          = (known after apply)
      + associate_public_ip_address  = (known after apply)
      + availability_zone            = (known after apply)
      + cpu_core_count               = (known after apply)
      + cpu_threads_per_core         = (known after apply)
      + get_password_data            = false
      + host_id                      = (known after apply)
      + id                           = (known after apply)
      + instance_state               = (known after apply)
      + instance_type                = "t2.micro"
      + ipv6_address_count           = (known after apply)
      + ipv6_addresses               = (known after apply)
      + key_name                     = (known after apply)
      + network_interface_id         = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      + primary_network_interface_id = (known after apply)
      + private_dns                  = (known after apply)
      + private_ip                   = (known after apply)
      + public_dns                   = (known after apply)
      + public_ip                    = (known after apply)
      + security_groups              = (known after apply)
      + source_dest_check            = true
      + subnet_id                    = (known after apply)
      + tenancy                      = (known after apply)
      + volume_tags                  = (known after apply)
      + vpc_security_group_ids       = (known after apply)

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + iops                  = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
```

## 問題なければ、AWS実環境に反映

### terraform apply

```
$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.sample will be created
  + resource "aws_instance" "sample" {

　　〜〜　省略　〜〜

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_instance.sample: Creating...
aws_instance.sample: Still creating... [10s elapsed]
aws_instance.sample: Still creating... [20s elapsed]
aws_instance.sample: Still creating... [30s elapsed]
aws_instance.sample: Creation complete after 32s [id=i-0a5244998f15ade9d]

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

### AWS環境反映の確認

EC2インスタンス１つ出来てる。

![screenshot-ap-northeast-1.console.aws.amazon.com-2019-06-23-08-09-03-042.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180599/2fbfb974-1a7b-d4b9-8cc7-aef4acd76ec4.png)

## 不要になったら消す

### terraform destroy

```
$ terraform destroy
aws_instance.sample: Refreshing state... [id=i-0a5244998f15ade9d]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # aws_instance.sample will be destroyed
  - resource "aws_instance" "sample" {

　　〜〜　省略　〜〜

Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_instance.sample: Destroying... [id=i-0a5244998f15ade9d]
aws_instance.sample: Still destroying... [id=i-0a5244998f15ade9d, 10s elapsed]
aws_instance.sample: Still destroying... [id=i-0a5244998f15ade9d, 20s elapsed]
aws_instance.sample: Destruction complete after 29s

Destroy complete! Resources: 1 destroyed.
```