
2024年8月にリリースされた Cloudflare Terraform Provider v4.40.0 で Cloudflare Zero Trust 関連のリソースに変更があって,多くのリソースが deprecated になっている.よって,現在最新の v5 にアップデートするためにはリソースの変更に対応する必要がある.最近 Cloudflare Terraform Provider v4 → v5 にアップデートをする機会があって,個人的に検証したことをまとめておこうと思う📝
今回は以下のバージョンを使う.
- Cloudflare Terraform Provider
v4.52.5 - Cloudflare Terraform Provider
v5.11.0
リソース例
今回は大きく2種類のリソースをサンプルとして使う.
- cloudflare_access_tag → cloudflare_zero_trust_access_tag
- cloudflare_access_group → cloudflare_zero_trust_access_group


1. cloudflare_access_tag
👾 main.tf
resource "cloudflare_access_tag" "sandbox" { account_id = "xxx" name = "sandbox-tag" }
Warning
cloudflare_access_tag に対して警告が出ている🚨
╷
│ Warning: Deprecated Resource
│
│ with cloudflare_access_tag.sandbox,
│ on main.tf line 10, in resource "cloudflare_access_tag" "sandbox":
│ 10: resource "cloudflare_access_tag" "sandbox" {
│
│ `cloudflare_access_tag` is now deprecated and will be removed in the next major version. Use `cloudflare_zero_trust_access_tag` instead.
╵
GritQL を使って更新する
Terraform Cloudflare Provider Version 5 Upgrade Guide と Migrating renamed resources では GritQL を使って Terraform コードと tfstate を更新するアプローチが紹介されていた.grit apply コマンドは今まで使ったことがなかった❗️
まずは GritQL で main.tf のリソース名を更新する.
$ grit apply cloudflare_terraform_v5_resource_renames_configuration
./main.tf
-resource "cloudflare_access_tag" "sandbox" {
+resource "cloudflare_zero_trust_access_tag" "sandbox" {
account_id = "xxx"
name = "sandbox-tag"
}
Processed 5 files and found 1 matches
cloudflare_access_tag リソースの属性はシンプルで更新対象はなかった.
$ grit apply cloudflare_terraform_v5 Processed 5 files and found 0 matches
最後は GritQL で terraform.tfstate を更新する.
$ grit apply cloudflare_terraform_v5_resource_renames_state terraform.tfstate
terraform.tfstate
"resources": [
{
"mode": "managed",
- "type": "cloudflare_access_tag",
+ "type": "cloudflare_zero_trust_access_tag",
"name": "sandbox",
"provider": "provider[\"registry.terraform.io/cloudflare/cloudflare\"]",
"instances": [
Processed 1 files and found 1 matches
Cloudflare Terraform Provider v5 にアップデートする
$ terraform init -upgrade Initializing the backend... Initializing provider plugins... - Finding cloudflare/cloudflare versions matching "~> 5.0"... - Installing cloudflare/cloudflare v5.11.0...
差分を確認する
差分なしで問題なくリソース名を変更できた👌
$ terraform plan No changes. Your infrastructure matches the configuration.
2. cloudflare_access_group(失敗)
👾 main.tf
resource "cloudflare_access_group" "sandbox" { account_id = "xxx" name = "sandbox-group" include { email = ["y.yoshida22@gmail.com"] } }
Warning
cloudflare_access_group に対して警告が出ている🚨
╷
│ Warning: Deprecated Resource
│
│ with cloudflare_access_group.sandbox,
│ on main.tf line 1, in resource "cloudflare_access_group" "sandbox":
│ 1: resource "cloudflare_access_group" "sandbox" {
│
│ `cloudflare_access_group` is now deprecated and will be removed in the next major version. Use `cloudflare_zero_trust_access_group` instead.
╵
GritQL を使って更新する
まずは GritQL で main.tf のリソース名を更新する.
$ grit apply cloudflare_terraform_v5_resource_renames_configuration
./main.tf
-resource "cloudflare_access_group" "sandbox" {
+resource "cloudflare_zero_trust_access_group" "sandbox" {
account_id = "xxx"
name = "sandbox-group"
Processed 5 files and found 1 matches
次に GritQL で main.tf の属性を更新する.
⚠️ちなみに以下の変更は間違っていて別途直すことになる.
$ grit apply cloudflare_terraform_v5
./main.tf
account_id = "xxx"
name = "sandbox-group"
- include {
+ include =[ {
email = ["y.yoshida22@gmail.com"]
- }
+ }]
}
Processed 5 files and found 1 matches
最後は GritQL で terraform.tfstate を更新する.
$ grit apply cloudflare_terraform_v5_resource_renames_state terraform.tfstate
terraform.tfstate
"resources": [
{
"mode": "managed",
- "type": "cloudflare_access_group",
+ "type": "cloudflare_zero_trust_access_group",
"name": "sandbox",
"provider": "provider[\"registry.terraform.io/cloudflare/cloudflare\"]",
"instances": [
Processed 1 files and found 1 matches
Cloudflare Terraform Provider v5 にアップデートする
$ terraform init -upgrade Initializing the backend... Initializing provider plugins... - Finding cloudflare/cloudflare versions matching "~> 5.0"... - Installing cloudflare/cloudflare v5.11.0...
差分を確認する
しかし terraform plan コマンドを実行するとエラーになってしまう.原因は include 属性の構文が違うことだった.
$ terraform plan ╷ │ Error: Incorrect attribute value type │ │ on main.tf line 5, in resource "cloudflare_zero_trust_access_group" "sandbox": │ 5: include =[ { │ 6: email = ["y.yoshida22@gmail.com"] │ 7: }] │ │ Inappropriate value for attribute "include": element 0: attribute "email": object required, but have tuple. ╵
👾 main.tf
cloudflare_zero_trust_access_group を参考に修正しつつ適切なコードに修正する.
resource "cloudflare_zero_trust_access_group" "sandbox" { account_id = "xxx" name = "sandbox-group" include = [ { email = { email = "y.yoshida22@gmail.com" } } ] }
差分を確認する
今度はまた別のエラーが出てしまう.cloudflare_access_group と cloudflare_zero_trust_access_group はリソース名以外に構造も変わっていて単純な移行は難しそうだった😇
$ terraform plan Planning failed. Terraform encountered an error while generating this plan. ╷ │ Error: Unable to Read Previously Saved State for UpgradeResourceState │ │ with cloudflare_zero_trust_access_group.sandbox, │ on main.tf line 1, in resource "cloudflare_zero_trust_access_group" "sandbox": │ 1: resource "cloudflare_zero_trust_access_group" "sandbox" { │ │ There was an error reading the saved resource state using the current resource schema. │ │ If this resource state was last refreshed with Terraform CLI 0.11 and earlier, it must be refreshed or applied with an older provider version first. If you manually modified the resource │ state, you will need to manually modify it to match the current resource schema. Otherwise, please report this to the provider developer: │ │ AttributeName("include").ElementKeyInt(0).AttributeName("any_valid_service_token"): invalid JSON, expected "{", got %!q(bool=false) ╵
3. cloudflare_access_group(成功)
GritQL 以外の選択肢として Terraform ネイティブの仕組みを使って removed ブロックと import ブロックを組み合わせるアプローチを試す.個人的には tfstate を直接書き換えることに抵抗があって,可能であればこちらを選択したいとは思う😇
Terraform 管理の対象外にする
まずは Cloudflare Terraform Provider v4 のまま removed ブロックを使ってリソースを Terraform 管理の対象外にする.今回はコードベースで操作しているけど terraform state rm コマンドを使う選択肢もある.
removed { from = cloudflare_access_group.sandbox lifecycle { destroy = false } }
そして terraform apply コマンドを実行しておく.
$ terraform apply 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: # cloudflare_access_group.sandbox will no longer be managed by Terraform, but will not be destroyed # (destroy = false is set in the configuration) . resource "cloudflare_access_group" "sandbox" { id = "bddd74d0-f73c-4e74-9e22-ef6640b86e66" name = "sandbox-group" # (1 unchanged attribute hidden) # (1 unchanged block hidden) } 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: │ - cloudflare_access_group.sandbox │ │ After applying this plan, Terraform will no longer manage these objects. You will need to import them into Terraform to manage them again.
Cloudflare Terraform Provider v5 にアップデートする
$ terraform init -upgrade Initializing the backend... Initializing provider plugins... - Finding cloudflare/cloudflare versions matching "~> 5.0"... - Installing cloudflare/cloudflare v5.11.0...
Terraform 管理の対象にする
最後は import ブロックを使ってリソースを Terraform 管理の対象にする.今回はコードベースで操作しているけど terraform import コマンドを使う選択肢もある.なお cloudflare_zero_trust_access_group の場合は <{accounts|zones}/{account_id|zone_id}>/<group_id> という id でインポートする.
import { id = "accounts/xxx/xxx" to = cloudflare_zero_trust_access_group.sandbox } resource "cloudflare_zero_trust_access_group" "sandbox" { account_id = "xxx" name = "sandbox-group" include = [ { email = { email = "y.yoshida22@gmail.com" } } ] }
そして terraform apply コマンドを実行してインポートする.
$ terraform apply Apply complete! Resources: 1 imported, 0 added, 0 changed, 0 destroyed.
差分を確認する
インポート後に差分がなくうまく Terraform 管理の対象にできた👌
terraform state list コマンドでもリソースを確認できた.
$ terraform plan No changes. Your infrastructure matches the configuration. $ terraform state list cloudflare_zero_trust_access_group.sandbox