🤖

tfrefactorを使ってTerraform AWS Provider v4へアップグレード

2022/10/06に公開

このページについて

TerraformのAWS Provider v4の破壊的変更が含まれており、特にS3については aws_s3_bucket のパラメータを分割する必要があるなど影響範囲が大きいです。
v4へアップグレードする際に活用できる tfrefactor を使ってみました。

参考記事

https://qiita.com/Shoyu_N/items/871ebf0c1d41493c22ac

tfrefactor

https://github.com/anGie44/ohmyhcl/tree/main/tfrefactor

インストール

こちらでインストールできました。

$ git clone https://github.com/anGie44/ohmyhcl
$ cd ohmyhcl/tfrefactor
$ go build -o path/to/bin/tfrefactor

試してみた

アップグレードの流れ

  1. AWS Providerバージョンを書き換えて、 terraform init -upgrade で初期化
    • 今回は、3.70.0 → 4.33.0
  2. tfrefactoraws_s3_bucket のパラメータを分割
  3. 新規作成したリソースを terraform import する
  4. terraform plan で差分確認

元となるs3.tf

s3.tf
# Bucket
resource "aws_s3_bucket" "sample" {
  bucket = "sample-bucket"
  acl    = "private"

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }

  tags = {
    "Name" = "sample-bucket"
  }
}

# Bucket Public Access Block
resource "aws_s3_bucket_public_access_block" "sample" {
  bucket = aws_s3_bucket.sample.bucket
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

tfrefactor実行

-c オプションで新規作成したリソース一覧をcsv出力できます。

$ tfrefactor resource aws_s3_bucket s3.tf -c

実行してできたファイル

  • s3_migrated.tf
  • s3_new_resources.csv
s3_migrated.tf
# Bucket
resource "aws_s3_bucket" "sample" {
  bucket = "sample-bucket"
  tags = {
    "Name" = "sample-bucket"
  }
}

# Bucket Public Access Block
resource "aws_s3_bucket_public_access_block" "sample" {
  bucket = aws_s3_bucket.sample.bucket
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_acl" "sample_acl" {
  bucket = aws_s3_bucket.sample.id
  acl    = "private"
}

resource "aws_s3_bucket_server_side_encryption_configuration" "sample_server_side_encryption_configuration" {
  bucket = aws_s3_bucket.sample.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}
s3_new_resources.csv
aws_s3_bucket_acl.sample_acl,aws_s3_bucket.sample
aws_s3_bucket_server_side_encryption_configuration.sample_server_side_encryption_configuration,aws_s3_bucket.sample

aws_s3_bucket の中に含まれていたパラメータ、 aclとserver_side_encryption_configurationが、 aws_s3_bucket_aclaws_s3_bucket_server_side_encryption_configuration という別リソースに分割されました。

元のファイル名を変更する

$ mv s3.tf s3.tf.tmp

この状態でterraform planすると

分割された新規作成されたリソース( aws_s3_bucket_acl , aws_s3_bucket_server_side_encryption_configuration )が、そのまま新規作成されるようなプランとなってしまうため、terraform importが必要となります。

$ terraform plan

~

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # aws_s3_bucket_acl.sample_acl will be created
  + resource "aws_s3_bucket_acl" "sample_acl" {
      + acl    = "private"
      + bucket = "sample-bucket"
      + id     = (known after apply)

      + access_control_policy {
          + grant {
              + permission = (known after apply)

              + grantee {
                  + display_name  = (known after apply)
                  + email_address = (known after apply)
                  + id            = (known after apply)
                  + type          = (known after apply)
                  + uri           = (known after apply)
                }
            }

          + owner {
              + display_name = (known after apply)
              + id           = (known after apply)
            }
        }
    }

  # aws_s3_bucket_server_side_encryption_configuration.sample_server_side_encryption_configuration will be created
  + resource "aws_s3_bucket_server_side_encryption_configuration" "sample_server_side_encryption_configuration" {
      + bucket = "sample-bucket"
      + id     = (known after apply)

      + rule {
          + apply_server_side_encryption_by_default {
              + sse_algorithm = "AES256"
            }
        }
    }

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

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you
run "terraform apply" now.

terraform import

tfrefactorで作成したcsvファイルを元にして、terraform importコマンドを作成します。
リソース数が多い場合は別途スクリプト化した方が良いと思います。

また、バケットACLについてはterraform importする際に、設定によって指定するパラメータが異なります。
今回は元々 private にしていたため、以下のようにコマンドを作成しました。

$ terraform import aws_s3_bucket_acl.example bucket-name,private

https://registry.terraform.io/providers/hashicorp /aws/latest/docs/resources/s3_bucket_acl#import

$ terraform import aws_s3_bucket_acl.sample_acl sample-bucket,private
$ terraform import aws_s3_bucket_server_side_encryption_configuration.sample_server_side_encryption_configuration sample-bucket

差分確認

無事インポートできたら、terraform planして差分がないことを確認します。

$ terraform plan
~
No changes. Your infrastructure matches the configuration.

後始末

S3のtfファイル名を修正します。

$ mv s3_migrated.tf s3.tf

不要であれば以下のファイルを削除します。

  • s3.tf.tmp
  • s3_new_resources.csv

参考記事

https://qiita.com/kjm/items/ad03eb832e250f2051bd

GitHubで編集を提案
アイレット株式会社

Discussion