OpenTofu v1.8.0で実装されたbackend設定の変数化をやってみる

## これは何？
OpenTofu v1.8.0で新しく実装されたbackend設定の変数化をサンプルコードを用いて解説する記事です。
本記事の随筆時点(2025/01/10)ではTerraformには実装されていないのでOpenTofuの独自機能になります。

## OpenTofuとは？
詳細は割愛しますが、利用時のライセンス変更を受けてTerraformをフォークして新しく生まれたものがOpenTofuです。
大まかな使い勝手は同じですが、コマンドが terraform → tofu へ変更になっていたり
アップデートによって本記事で紹介するような大元のTerraformにはない独自機能が実装されていたりします。

https://opentofu.org/

## backend設定の変数化
以下のような書き方が出来るようになったということです。

```HCL
terraform {
  backend "s3" {
    bucket = "tfstate-bucket"
    key    = "${var.project}/${var.environment}.tfstate"
    region = var.region
  }
}
```

tfstate自体をbackendの記述を行いS3に保管するというやり方はよくされると思います。
Terraformでは bucket / key / region等の値は変数化出来ずベタ書きするしかないのですが
OpenTofuの1.8.0の機能追加で値の指定に変数を利用できるようになりました。
インフラの環境ごとにtfstateを分けていたりする場合にbackendの記述をコード上で統一できるので便利ですね。

参考情報はこちら↓

https://github.com/opentofu/opentofu/blob/v1.8/CHANGELOG.md#:~:text=Variables%20and%20Locals%20allowed%20in%20module%20sources%20and%20backend%20configurations%20(with%20limitations)

https://github.com/opentofu/opentofu/pull/1718

## サンプルコード

### provider.tf
AWSを使い、リージョンの指定とスイッチロール + デフォルトタグの設定をしています。

```HCL
provider "aws" {
  region = var.region

  assume_role {
    role_arn = var.role_arn
  }

  default_tags {
    tags = {
      environment = var.environment
    }
  }
}
```

### backend.tf
ここが今回の本題、keyとregionを変数化しています。

```HCL
terraform {
  backend "s3" {
    bucket = "tfstate-bucket"
    key    = "${var.project}/${var.environment}.tfstate"
    region = var.region
  }
}
```

### variables.tf
必要な変数を定義しています。


```HCL
variable "region" {
  type = string
}

variable "role_arn" {
  type = string
}

variable "project" {
  type = string
}

variable "environment" {
  type = string
}
```

### terraform.tfvars
変数に代入したい値を指定しています。

```HCL
region      = "ap-northeast-1"
project     = "opentofu-test"
environment = "dev"
```

### main.tf
適当にVPCリソースを定義、作成できるか確認していきます。

```HCL
resource "aws_vpc" "this" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "${var.project}-vpc"
  }
}
```

## 実行してみる
まずはバージョン確認。
それぞれ現時点での最新バージョンを利用します。

```
$ terraform version
Terraform v1.10.4
on darwin_arm64

$ tofu version
OpenTofu v1.9.0
on darwin_arm64
```

まずはTerraformですが、initの時点でエラーになってしまいます。
Variablesは許可されてへんで〜と言われてますね。

```
$ terraform init
Initializing the backend...
╷
│ Error: Variables not allowed
│ 
│   on backend.tf line 4, in terraform:
│    4:     key    = "${var.project}/${var.environment}.tfstate"
│ 
│ Variables may not be used here.
╵
╷
│ Error: Variables not allowed
│ 
│   on backend.tf line 4, in terraform:
│    4:     key    = "${var.project}/${var.environment}.tfstate"
│ 
│ Variables may not be used here.
╵
╷
│ Error: Variables not allowed
│ 
│   on backend.tf line 5, in terraform:
│    5:     region = var.region
│ 
│ Variables may not be used here.
╵
```

次にOpenTofuです。initは難なく成功しますね。

```
$ tofu init

Initializing the backend...

Successfully configured the backend "s3"! OpenTofu will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v5.83.0...
- Installed hashicorp/aws v5.83.0 (signed, key ID 0C0AF313E5FD9F80)

Providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://opentofu.org/docs/cli/plugins/signing/

OpenTofu has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that OpenTofu can guarantee to make the same selections by default when
you run "tofu init" in the future.

OpenTofu has been successfully initialized!

You may now begin working with OpenTofu. Try running "tofu plan" to see
any changes that are required for your infrastructure. All OpenTofu commands
should now work.

If you ever set or change modules or backend configuration for OpenTofu,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
```

planも問題なく実行できますね。

```
$ tofu plan 

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

OpenTofu will perform the following actions:

  # aws_vpc.this will be created
  + resource "aws_vpc" "this" {
      + arn                                  = (known after apply)
      + cidr_block                           = "10.0.0.0/16"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_dns_hostnames                 = (known after apply)
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags                                 = {
          + "Name" = "opentofu-test-vpc"
        }
      + tags_all                             = {
          + "Name"        = "opentofu-test-vpc"
          + "environment" = "dev"
        }
    }

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

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

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

applyしてみるとVPCが作成されていることが確認できます。

![スクリーンショット 2025-01-10 13.05.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895851/e24c91bc-6176-b13e-6aab-008516d5a30c.png)


S3にも正常にtfstateが保管されてますね。

![スクリーンショット 2025-01-10 13.04.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895851/7b416a50-c57b-3594-9047-4f77fe79ea35.png)


## 終わりに
便利な機能なので有効活用していきたいですね。
とはいえ、今後もTerraformとOpenTofuの機能差分が大きくなっていくことを考えると
両方の動向に注目する必要があるのでキャッチアップが大変になりそうですが頑張りましょう。