🎉

Terraform v1.7.0でリリースされそうな新機能まとめ

2023/12/13に公開

はじめに

こんにちは!
Social Databank Tech Blog Advent Calendar 2023の13日目は、SDBのどいが担当します。よろしくお願いします。
(あっという間に後半戦に突入ですね。)


先日、2023年12月6日に、terraform v1.7のベータ版がリリースされました。🎉

https://github.com/hashicorp/terraform/releases/tag/v1.7.0-beta1

いくつか新機能がリリースされるようなので、先取りして試してみようと思います。(AWS)

🎉 新機能 🎉

1: terraform testでproviderをmock化

terraform v1.6でterraform のテスト機能 terraform test がリリースされました。
v1.7ではterraform test実行時にproviderをmock化できるようです。

https://developer.hashicorp.com/terraform/language/v1.7.x/tests/mocking#mock-providers

例えば、作成するAWS VPCのCIDRブロックが10.0.0.0/16であることをテストしたいとします。この状態でそのままterraform testを実施する場合、AWSの認証情報(アクセスキーとシークレットアクセスキー)がないというエラーが発生します。

cidr_block.tftest.hcl
provider "aws" {}

run "sets_correct_name" {
  assert {
    condition     = aws_vpc.vpc.cidr_block == "10.0.0.0/16"
    error_message = "incorrect cidr block."
  }
}
% terraform test
vpc_cidr_block.tftest.hcl... in progress
  run "sets_correct_name"... fail
╷
│ Error: No valid credential sources found
│ 
│   with provider["registry.terraform.io/hashicorp/aws"],
│   on vpc_cidr_block.tftest.hcl line 3, in provider "aws":3: provider "aws" {}
│ 
│ Please see https://registry.terraform.io/providers/hashicorp/aws
│ for more information about providing credentials.
│ 
│ Error: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, request canceled, context deadline exceeded
│ 
╵
vpc_cidr_block.tftest.hcl... tearing down
vpc_cidr_block.tftest.hcl... fail

Failure! 0 passed, 1 failed.

代わりにmock_providerを利用すれば認証情報を必要としなくてもterraform testが実行可能になります。

cidr_block.tftest.hcl
- provider "aws" {}

+ mock_provider "aws" {
+   alias = "fake"
+ }

run "sets_correct_name" {
+   providers = {
+     aws = aws.fake
+   }

  assert {
    condition     = aws_vpc.vpc.cidr_block == "10.0.0.0/16"
    error_message = "incorrect cidr block."
  }
}
$ terraform test
vpc_cidr_block.tftest.hcl... in progress
  run "sets_correct_name"... pass
vpc_cidr_block.tftest.hcl... tearing down
vpc_cidr_block.tftest.hcl... pass

Success! 1 passed, 0 failed.

認証情報がいらないということで、本当の意味で単体テストが可能になったのではないでしょうか。

2: removedブロックのサポート

以前はterraformで管理しているリソースをterraform管理下から外す際に、terraform state rm というコマンドを実行する必要がありました。
今回のリリースで、removedブロックがサポートされ、terraformで管理しているリソースを管理下から外す操作をplan/apply時に実行できるようになるようです。

https://developer.hashicorp.com/terraform/language/v1.7.x/resources/syntax#removing-resources

以下のようにVPCとサブネットをterraformで管理していて、サブネットをterraform管理下から外したいけどリソースの削除はしたくない場合は、removedブロックを記述します。

  resource "aws_vpc" "vpc" {
    cidr_block = "10.0.0.0/16"
  }

- resource "aws_subnet" "subnet" {
-   vpc_id     = aws_vpc.vpc.id
-   cidr_block = "10.0.0.0/24"
- }

+ removed {
+   from = aws_subnet.subnet
+
+   lifecycle {
+     destroy = false
+   }
+ }

terraform planを実行してみると、以下のような結果になります。

aws_subnet.subnet: Refreshing state... [id=subnet-xxxxxxxxxxxxxx]
aws_vpc.vpc: Refreshing state... [id=vpc-xxxxxxxxxxxxxx]

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

Terraform will perform the following actions:

 # aws_subnet.subnet will no longer be managed by Terraform, but will not be destroyed
 # (destroy = false is set in the configuration)
 . resource "aws_subnet" "subnet" {
      - arn                                            = "arn:aws:ec2:ap-northeast-1:123456789012:subnet/subnet-xxxxxxxxxxxxxx" -> null
      - assign_ipv6_address_on_creation                = false -> null
      - availability_zone                              = "ap-northeast-1a" -> null
      - availability_zone_id                           = "apne1-az4" -> null
      - cidr_block                                     = "10.0.0.0/24" -> null
      - enable_dns64                                   = false -> null
      - enable_lni_at_device_index                     = 0 -> null
      - enable_resource_name_dns_a_record_on_launch    = false -> null
      - enable_resource_name_dns_aaaa_record_on_launch = false -> null
      - id                                             = "subnet-xxxxxxxxxxxxxx" -> null
      - ipv6_native                                    = false -> null
      - map_customer_owned_ip_on_launch                = false -> null
      - map_public_ip_on_launch                        = false -> null
      - owner_id                                       = "123456789012" -> null
      - private_dns_hostname_type_on_launch            = "ip-name" -> null
      - tags                                           = {} -> null
      - tags_all                                       = {} -> null
      - vpc_id                                         = "vpc-xxxxxxxxxxxxxx" -> null
    }

Plan: 0 to add, 0 to change, 0 to destroy.
╷
│ Warning: Some objects will no longer be managed by Terraform
│ 
│ If you apply this plan, Terraform will discard its tracking information for the following objects, but it will not delete them:
│  - aws_subnet.subnet
│ 
│ After applying this plan, Terraform will no longer manage these objects. You will need to import them into Terraform to manage them again.
╵

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

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.

aws_subnet.subnet will no longer be managed by Terraform, but will not be destroyedという出力がありますね。
リソースは削除されずに、terraformの管理下から外れるのみという挙動になりそうです。

特に今はインフラをコードで管理して、CICDでデプロイするケースは多いかと思いますが、applyしたタイミングでremoveも実行できるので、チーム内でレビューができて便利ですね!

まとめ

本記事では、terraform v1.7でリリース(されそうな)新機能を紹介しました。
これからのv1.7の正式リリースに期待したいと思います。


ということで、13日目の記事はどいが担当しました。
14日目の記事は、@saimyonさんが担当します。お楽しみに!

ソーシャルデータバンク テックブログ

Discussion