Open4

CloudFormationで作った環境をTerraformに移すためにやったこと

quo1987quo1987

まずはS3バケット上でtfstateを管理するようにTerraformを構成する。

aws s3api create-bucket --bucket throwtrash-tfstate-us-west-2 --region us-east-1 --acl private --create-bucket-configuration '{"LocationConstraint": "us-west-2"}'
terraform init -backend-config="region=us-west-2" -backend-config="bucket=throwtrash-tfstate-us-west-2"
quo1987quo1987

リソースの定義

ローカルにtfファイルを作成し、プロパティは埋めなくても良いのでリソース定義だけ行う。

hogehoge.tf
resource "aws_iam_role" "LambdaExecRole"{}
...

インポート

CloudFormationで作成済みリソースをterraform importでtfstateに反映する。

# IAMロールのインポート
terraform import aws_iam_role.LambdaExecRole <Role Name>

# S3バケットのインポート
# PreferenceBucket
terraform import aws_s3_bucket.PreferenceBucket <Bucket Name>

# RequestLogBucket
terraform import aws_s3_bucket.RequestLogBucket <Bucket Name>

# Lambda関数のインポート
terraform import aws_lambda_function.ThrowTrashSkill <Lambda ID>

# Lambdaレイヤーバージョンのインポート
terraform import aws_lambda_layer_version.libs <Layer ID>

# Lambdaパーミッションのインポート
terraform import aws_lambda_permission.LambdaEvent <LambdaEvent ID>

backendで指定したs3バケットにtfstateファイルが作成される。

このtfstateをもとにtfファイル内のリソースにプロパティを指定する。

インポートの確認

terraform state pullでtfstateをダウンロード(標準出力)できる

quo1987quo1987

terraform planで差分を確認。

terraform plan -var-file=variables.tfvars -no-color > plan.txt

Lambdaが置き換えられてしまう。function_nameがarn形式になっているからか?

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  ~ update in-place
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # aws_iam_policy.LambdaExecPolicy will be created
  + resource "aws_iam_policy" "LambdaExecPolicy" {
      + arn       = (known after apply)
      + id        = (known after apply)
      + name      = "throwtrash-lambda-policy-us-west-2"
      + path      = "/"
      + policy    = (known after apply)
      + policy_id = (known after apply)
      + tags_all  = (known after apply)
    }

  # aws_lambda_function.ThrowTrashSkill must be replaced
-/+ resource "aws_lambda_function" "ThrowTrashSkill" {
      ~ architectures                  = [
          - "x86_64",
        ] -> (known after apply)
      ~ arn                            = "arn:aws:lambda:us-west-2:xxxxxxxxxxxxx:function:ThrowTrashSkill" -> (known after apply)
      ~ function_name                  = "arn:aws:lambda:us-west-2:xxxxxxxxxxxxx:function:ThrowTrashSkill" -> "ThrowTrashSkill" # forces replacement
      ~ id                             = "arn:aws:lambda:us-west-2:xxxxxxxxxxxxx:function:ThrowTrashSkill" -> (known after apply)
      ~ invoke_arn                     = "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:xxxxxxxxxxxxx:function:ThrowTrashSkill/invocations" -> (known after apply)
      ~ last_modified                  = "2023-12-17T13:33:47.000+0000" -> (known after apply)
      - layers                         = [
          - "arn:aws:lambda:us-west-2:xxxxxxxxxxxxx:layer:throwtrash-skill-libs:50",
        ] -> null
      + publish                        = false
      ~ qualified_arn                  = "arn:aws:lambda:us-west-2:xxxxxxxxxxxxx:function:ThrowTrashSkill:$LATEST" -> (known after apply)
      + signing_job_arn                = (known after apply)
      + signing_profile_version_arn    = (known after apply)
      ~ source_code_hash               = "BjwEgD3eJra8niPxQq0zNP/wx1KkmKSpjoeAP+Ec9wY=" -> (known after apply)
      ~ source_code_size               = 13769 -> (known after apply)
      ~ tags                           = {
            "Group"            = "throwtrash"
            "Purpose"          = "Skill"
          - "lambda:createdBy" = "SAM" -> null
        }
      ~ tags_all                       = {
          - "lambda:createdBy" = "SAM" -> null
            # (2 unchanged elements hidden)
        }
      ~ timeout                        = 30 -> 3
      ~ version                        = "$LATEST" -> (known after apply)
        # (6 unchanged attributes hidden)

      - timeouts {}

      - tracing_config {
          - mode = "PassThrough" -> null
        }

        # (1 unchanged block hidden)
    }

  # aws_lambda_permission.LambdaEvent must be replaced
-/+ resource "aws_lambda_permission" "LambdaEvent" {
      ~ function_name      = "arn:aws:lambda:us-west-2:xxxxxxxxxxxxx:function:ThrowTrashSkill" -> "ThrowTrashSkill" # forces replacement
      ~ id                 = "ThrowTrashSkill-LambdaEvent-Y6DHPQ70O0UX" -> (known after apply)
      ~ statement_id       = "ThrowTrashSkill-LambdaEvent-Y6DHPQ70O0UX" -> "AllowExecutionFromAlexa" # forces replacement
        # (3 unchanged attributes hidden)
    }

  # aws_s3_bucket.PreferenceBucket will be updated in-place
  ~ resource "aws_s3_bucket" "PreferenceBucket" {
      + acl                         = "private"
      + force_destroy               = false
        id                          = "<Bucket Name>"
        tags                        = {
            "Group"   = "throwtrash"
            "Purpose" = "Skill"
        }
        # (9 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # aws_s3_bucket.RequestLogBucket will be updated in-place
  ~ resource "aws_s3_bucket" "RequestLogBucket" {
      + acl                         = "private"
      + force_destroy               = false
        id                          = "throwtrash-skill-request-logs-us-west-2"
        tags                        = {
            "Group"   = "throwtrash"
            "Purpose" = "Skill"
        }
        # (9 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # aws_s3_bucket_acl.PreferenceBucketAcl will be created
  + resource "aws_s3_bucket_acl" "PreferenceBucketAcl" {
      + acl    = "private"
      + bucket = "<Bucket Name>"
      + id     = (known after apply)
    }

  # aws_s3_bucket_acl.RequestLogBucketAcl will be created
  + resource "aws_s3_bucket_acl" "RequestLogBucketAcl" {
      + acl    = "private"
      + bucket = "throwtrash-skill-request-logs-us-west-2"
      + id     = (known after apply)
    }

Plan: 5 to add, 2 to change, 2 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.
quo1987quo1987

function_nameをarn形式に変えたらupdateに変わった

  # aws_iam_policy.LambdaExecPolicy will be created
  + resource "aws_iam_policy" "LambdaExecPolicy" {
      + arn       = (known after apply)
      + id        = (known after apply)
      + name      = "throwtrash-lambda-policy-us-west-2"
      + path      = "/"
      + policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = "dynamodb:*"
                      + Effect   = "Allow"
                      + Resource = [
                          + "arn:aws:dynamodb:us-west-2: xxxxxxxxxxxxx:table/throwtrash-db-schedule",
                          + "arn:aws:dynamodb:us-west-2: xxxxxxxxxxxxx:table/throwtrash-db-accesstoken",
                        ]
                    },
                  + {
                      + Action   = "lambda:*"
                      + Effect   = "Allow"
                      + Resource = "arn:aws:lambda:us-west-2: xxxxxxxxxxxxx:function:ThrowTrashSkill"
                    },
                  + {
                      + Action   = [
                          + "s3:ListBucket",
                          + "s3:GetObject",
                          + "s3:PutObject",
                        ]
                      + Effect   = "Allow"
                      + Resource = [
                          + "arn:aws:s3:::throwtrash-skill-preference-us-west-2",
                          + "arn:aws:s3:::throwtrash-skill-preference-us-west-2/*",
                          + "arn:aws:s3:::throwtrash-skill-request-logs-us-west-2",
                          + "arn:aws:s3:::throwtrash-skill-request-logs-us-west-2/*",
                        ]
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id = (known after apply)
      + tags      = {
          + "App"   = "throwtrash"
          + "Group" = "skill"
        }
      + tags_all  = {
          + "App"   = "throwtrash"
          + "Group" = "skill"
        }
    }

  # aws_iam_role.LambdaExecRole will be updated in-place
  ~ resource "aws_iam_role" "LambdaExecRole" {
        id                    = "throwtrash-lambda-role-us-west-2"
        name                  = "throwtrash-lambda-role-us-west-2"
      ~ tags                  = {
          + "App"   = "throwtrash"
          + "Group" = "skill"
        }
      ~ tags_all              = {
          + "App"   = "throwtrash"
          + "Group" = "skill"
        }
        # (8 unchanged attributes hidden)

        # (1 unchanged block hidden)
    }

  # aws_lambda_function.ThrowTrashSkill will be updated in-place
  ~ resource "aws_lambda_function" "ThrowTrashSkill" {
        id                             = "arn:aws:lambda:us-west-2: xxxxxxxxxxxxx:function:ThrowTrashSkill"
      + publish                        = false
      ~ tags                           = {
          + "App"              = "throwtrash"
          ~ "Group"            = "throwtrash" -> "skill"
          - "Purpose"          = "Skill" -> null
          - "lambda:createdBy" = "SAM" -> null
        }
      ~ tags_all                       = {
          + "App"              = "throwtrash"
          ~ "Group"            = "throwtrash" -> "skill"
          - "Purpose"          = "Skill" -> null
          - "lambda:createdBy" = "SAM" -> null
        }
        # (17 unchanged attributes hidden)

      - timeouts {}

        # (2 unchanged blocks hidden)
    }

  # aws_lambda_permission.LambdaEvent must be replaced
-/+ resource "aws_lambda_permission" "LambdaEvent" {
      ~ id                 = "ThrowTrashSkill-LambdaEvent-Y6DHPQ70O0UX" -> (known after apply)
      ~ statement_id       = "ThrowTrashSkill-LambdaEvent-Y6DHPQ70O0UX" -> "AllowExecutionFromAlexa" # forces replacement
        # (4 unchanged attributes hidden)
    }

  # aws_s3_bucket.PreferenceBucket will be updated in-place
  ~ resource "aws_s3_bucket" "PreferenceBucket" {
      + acl                         = "private"
      + force_destroy               = false
        id                          = "throwtrash-skill-preference-us-west-2"
      ~ tags                        = {
          + "App"     = "throwtrash"
          ~ "Group"   = "throwtrash" -> "skill"
          - "Purpose" = "Skill" -> null
        }
      ~ tags_all                    = {
          + "App"     = "throwtrash"
          ~ "Group"   = "throwtrash" -> "skill"
          - "Purpose" = "Skill" -> null
        }
        # (8 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # aws_s3_bucket.RequestLogBucket will be updated in-place
  ~ resource "aws_s3_bucket" "RequestLogBucket" {
      + acl                         = "private"
      + force_destroy               = false
        id                          = "throwtrash-skill-request-logs-us-west-2"
      ~ tags                        = {
          + "App"     = "throwtrash"
          ~ "Group"   = "throwtrash" -> "skill"
          - "Purpose" = "Skill" -> null
        }
      ~ tags_all                    = {
          + "App"     = "throwtrash"
          ~ "Group"   = "throwtrash" -> "skill"
          - "Purpose" = "Skill" -> null
        }
        # (8 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

  # aws_s3_bucket_acl.PreferenceBucketAcl will be created
  + resource "aws_s3_bucket_acl" "PreferenceBucketAcl" {
      + acl    = "private"
      + bucket = "throwtrash-skill-preference-us-west-2"
      + id     = (known after apply)
    }

  # aws_s3_bucket_acl.RequestLogBucketAcl will be created
  + resource "aws_s3_bucket_acl" "RequestLogBucketAcl" {
      + acl    = "private"
      + bucket = "throwtrash-skill-request-logs-us-west-2"
      + id     = (known after apply)
    }

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