importブロック

Terraformのimportブロックは既存のリソースをTerraformの管理下に取り込むための機能。
terraform importコマンドでも同様にリソースを取り込めるが、importブロックを使うとコードで記述できる。
そのためバージョン管理化でインポートした事実を残せたり、コードレビューしたりできる。

手順

importブロックを使って既存リソースを取り込む手順を記載する。

importブロックを追加する

まず既存リソースをインポートするためのimportブロックを追加する。

ここではS3バケットを取り込む例を示す。

import {
  id = "suer-test-bucket"
  to = aws_s3_bucket.sample
}

import {
  id = "suer-test-bucket"
  to = aws_s3_bucket_server_side_encryption_configuration.sample
}

import {
  id = "suer-test-bucket"
  to = aws_s3_bucket_public_access_block.sample
}

importブロックはリソースごとに記述する。

上記の例ではS3バケット(aws_s3_bucket)とそのバケットのサーバーサイド暗号化設定(aws_s3_bucket_server_side_encryption_configuration)、バケットのパブリックアクセスブロック設定(aws_s3_bucket_public_access_block)を取り込んでいる。

idの指定方法

idは取り込むリソースのIDを指定する。
idはリソースの種類ごとに何を書くかが異なる。
AWSプロバイダーのリソースであればTerraformのリソースのドキュメントを参照すると最後にimportという節があり、IDの説明が書いてある。
例えばaws_s3_bucketであれば aws_s3_bucket | Terraform Registry のページの最後を参照する。
すると以下のように説明が書いてある。

In Terraform v1.5.0 and later, use an import block to import S3 bucket using the bucket. For example:

つまりaws_s3_bucketリソースのbucketを指定する、と書いてあるので、idにはbucket(バケット名)を指定する。

toの指定方法

toは取り込むリソースのTerraformのリソースを指定する。

resource "xxx" "yyy" { ... }のようなリソースとして取り込みたいのであれば、to = xxx.yyyのように指定する。
上記の例の1つ目のimportブロックではaws_s3_bucket.sampleを指定しているので、resource "aws_s3_bcuket" "sample" { ... }というリソースとして取り込まれる。

「terraform plan -generate-config-out=出力ファイル」コマンドでHCLコードを生成する

terraform planコマンドで-generate-config-outオプションを指定するとimportブロックに従って必要なコードを生成してくれる。

$ terraform plan -generate-config-out=generated.tf

上記のコマンドを実行するとgenerated.tfというファイルが生成される。

# __generated__ by Terraform
# Please review these resources and move them into your main configuration files.

# __generated__ by Terraform from "suer-test-bucket"
resource "aws_s3_bucket_public_access_block" "sample" {
  block_public_acls       = true
  block_public_policy     = true
  bucket                  = "suer-test-bucket"
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# __generated__ by Terraform from "suer-test-bucket"
resource "aws_s3_bucket_server_side_encryption_configuration" "sample" {
  bucket                = "suer-test-bucket"
  expected_bucket_owner = null
  rule {
    bucket_key_enabled = true
    apply_server_side_encryption_by_default {
      kms_master_key_id = null
      sse_algorithm     = "AES256"
    }
  }
}

# __generated__ by Terraform from "suer-test-bucket"
resource "aws_s3_bucket" "sample" {
  bucket              = "suer-test-bucket"
  bucket_prefix       = null
  force_destroy       = null
  object_lock_enabled = false
  tags                = {}
  tags_all            = {}
}

上記コードは既存リソースの設定を元に生成されている。

生成されたコードを必要なファイルに移動する

上記で生成されたコードを適切なファイルに移動しておく。

terraform {
  required_version = ">= 0.12"

  backend "s3" {
    bucket = "suer-terraform-example"
    key    = "terraform/example.tfstate"
    region = "ap-northeast-1"
  }
}

resource "aws_s3_bucket_public_access_block" "sample" {
  block_public_acls       = true
  block_public_policy     = true
  bucket                  = "suer-test-bucket"
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_server_side_encryption_configuration" "sample" {
  bucket                = "suer-test-bucket"
  expected_bucket_owner = null
  rule {
    bucket_key_enabled = true
    apply_server_side_encryption_by_default {
      kms_master_key_id = null
      sse_algorithm     = "AES256"
    }
  }
}

resource "aws_s3_bucket" "sample" {
  bucket              = "suer-test-bucket"
  bucket_prefix       = null
  force_destroy       = null
  object_lock_enabled = false
  tags                = {}
  tags_all            = {}
}

すべて移動したら生成されたファイルは削除する。

$ rm generated.tf

デフォルト値が設定されている引数を削除する

生成されたコードはデフォルト値が設定されている引数を含めてすべて記述されているので、 記述が不要であれば削除する。

上記例の場合、例えばaws_s3_bucketbucket以外の引数はデフォルト値が設定されているので、削除しても問題ない。

resource "aws_s3_bucket" "sample" {
  bucket              = "suer-test-bucket"
}

「terraform plan」コマンドで変更を確認する

terraform planコマンドで変更を生成オプション無しで確認する。

$ terraform plan
Plan: 3 to import, 0 to add, 0 to change, 0 to destroy.

Plan: 3 to import,のようにすべてのリソースがimportになっていれば成功。

「terraform apply」コマンドでリソースを取り込む

planで確認して問題がなければterraform applyでリソースを取り込む。

$ terraform apply