Terraformの最新と旧式のimportコマンドの使用方法

# 概要
 現在、業務で`terraform`を使う機会があり、AWSで構築した内容を`terraform`化する事を行なっています。今回、`import`を使用して`terraform`化を行なったので、その実施方法について、備忘録も含めて記載します。

# Terraformの概要
- [HashiCorp](https://www.hashicorp.co.jp/)によって開発されたオープンソースのインフラストラクチャコード（IaC）ツール
- インフラストラクチャの構築、変更、およびバージョニングを効率的に修正、更新が出来る
- サーバー、ネットワーク、データベースなどのリソースを含むインフラストラクチャを、宣言的な設定言語でコードとして記述する

下記は`terraformの`公式ドキュメント

https://registry.terraform.io/namespaces/hashicorp

# 前提条件
- `Terraform`が動作する環境がある
(以前、私が`Terraform`の導入方法について記事を書いた事があるので、導入されてない方は参考にして下さい)

https://qiita.com/kengo-sk8/items/1d6ca8347da1b5419c58

# version1.5以上で使えるimport
:::note warn
`VPC`を使ってimportを行なっています。
:::

## 手順
- `Terraform`の初期化を行う
```sh
terraform init
```

- `main.tf`に下記の記述をする
```main.tf
# 構成文
import {
  to = Resource Type.Resource Name
  id = "ARN (Amazon Resource Name) または Resource Name"
}

# 入力例
import {
  to = aws_vpc.test_vpc 
  id = "vpc-a01106c2"
}

/*
aws_vpc        : Resource Type(リソース タイプ)
test_vpc       : Resource Name(リソース ネーム)
"vpc-a01106c2" : ARN or Resource Name
id に関しては、terraformの公式ドキュメントとAWSのコンソール画面を良く確認して、値を貼り付ける
*/

# 構成文
resource "Resource Type" "Resource Name" {
  # 何も記載しない。但し、必須入力項目がある場合は、記載する必要がある
}

# 入力例
resource "aws_vpc" "test_vpc" {
  # ...
}

```
:::note warn
`import`の記述に関しては、各リソースタイプの一番下に記載されている
[[公式]VPCのimport方法](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc#import)
:::

- 下記のコマンドを使用して、ファイルを出力する
```sh
terraform plan -generate-config-out=generated.tf
# ファイル名は重複してなければ任意の名前で問題ない。test.tf等の名前でもファイルの出力は可能
```
- 出力されたファイルを修正して、`plan`が通る様にする


# 旧式のimport
:::note info
このやり方は、手動で作成したAWSリソースをTerraformで管理する際にも使用します。
その場合は、こちらのやり方でimportをやる事が基本となります。
:::

## 手順
:::note warn
旧式の`import`では、`module`を使用して構築しています。
:::
- `Terraform`の初期化を行う
```sh
terraform init
```

- `main.tf`と`vpc.tf`に下記の記述をする
(`vpc.tf`は、`network`ディレクトリーの階層に設置する)
```main.tf
module "network" {
  source = "./network"
}
```

```vpc.tf
resource "aws_vpc" "test_vpc" {

}
```

- ディレクトリー構成
```sh
.
├── .terraform
├── network/
│   └── vpc.tf
├── main.tf
# 以下省略
```

- `import`の記述に関しては、各リソースタイプの一番下に記載されている為、その部分を参考にして、`import`コマンドを作成する
```sh
# 構文1
terraform import module.[module Name].[Resource Type].[Resource Name] [ARN or Resource Name]

# 入力例1
terraform import module.network.aws_vpc.vpc vpc-a01106c2
```
```sh
# 構文2(main.tfにresourceの記述がある場合のコマンド)
terraform import [Resource Type].[Resource Name] [ARN (Amazon Resource Name)]

# 入力例2(main.tfにresourceの記述がある場合のコマンド)
terraform import aws_vpc.test_vpc vpc-a01106c2
```

- 上記のコマンドが正常に動作すると下記の出力結果が表示される
```sh
# 出力結果
module.network.aws_vpc.vpc: Importing from ID "vpc-*****************"...
module.network.aws_vpc.vpc: Import prepared!
  Prepared aws_vpc for import
module.network.aws_vpc.vpc: Refreshing state... [id=vpc-*****************]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
```

- 下記のコマンドで`Terraform`が管理しているすべてのリソースが表示される為、`import`したリストが表示されているか確認する
```sh
# Terraformの管理下にあるインフラストラクチャの状態（state）を一覧で表示するコマンド
terraform state list

# 出力結果
module.network.aws_vpc.vpc
```

- `terraform state show`を使用して、`import`した内容を表示する
(`terraform.tfstate`にも出力した結果が記載されている為、そこを確認しても良い)
```sh
# 構文
terraform state show RESOURCE_TYPE.NAME

# 入力例
terraform state show module.network.aws_vpc.test_vpc

# 出力結果
# module.network.aws_vpc.vpc:
resource "aws_vpc" "test_vpc" {
    arn                                  = "arn:aws:ec2:**************:************:vpc/vpc-*****************"
    assign_generated_ipv6_cidr_block     = false
    cidr_block                           = "0.0.0.0/0"
    default_network_acl_id               = "acl-*****************"
    default_route_table_id               = "rtb-*****************"
    default_security_group_id            = "sg-*****************"
    dhcp_options_id                      = "dopt-*****************"
    enable_dns_hostnames                 = false
    enable_dns_support                   = true
    enable_network_address_usage_metrics = false
    id                                   = "vpc-*****************"
    instance_tenancy                     = "default"
    ipv6_netmask_length                  = 0
    main_route_table_id                  = "rtb-*****************"
    owner_id                             = "************"
    tags                                 = {
        "Name" = "test-vpc-1"
    }
    tags_all                             = {
        "Name" = "test-vpc-1"
    }
}
# 一部の値にマスキングを行なっています。
```
- 出力された内容を修正して、`plan`が通る様にする



## 補足
`tfstate`ファイルの内容を消去するコマンド
```shell
terraform state rm [消去するmodule or resource]
```

`tfstate`ファイルを更新する方法
```sh
terraform state mv [消去するmodule or resource]
```

# 著者の作成したコード
テストで使用したコードを`git hub`に上げましたので、ご確認頂ければと思います。

https://github.com/kengo-sk8/terraform_import

# 参考資料
- [[公式]terraformでAWSの設定を行う為の記述方法](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)
- [[公式]Import](https://developer.hashicorp.com/terraform/language/import)
- [AWSリソースをTerraform管理対象に「追加」「削除」する方法](https://blog.mmmcorp.co.jp/2020/08/30/aws-terraform-sate/)