【小ネタ】Terraformがv0.7.7でマップとリストの算術演算をサポートしました
はじめに
こんにちは、中山です。
2016年10月18日、Terraformのv0.7.7がリリースされました。CHANGELOGはこちらです。さまざまなアップデートがあるのですが、個人的にはリストとマップの算術演算サポートに注目しています。このアップデートによってより表現力の高い簡潔な記述が可能になりました。
早速使ってみたのでレポートします。
使ってみた
サンプルとなるコードは以下のとおりです。分かりやすいように1つのファイルにまとめています。
variable "region" { default = "ap-northeast-1" } variable "env" { default = [ "dev", "prd", ] } variable "vpc_cidrs" { default = { dev_1 = "172.16.0.0/16" dev_2 = "172.17.0.0/16" prd_1 = "172.18.0.0/16" prd_2 = "172.19.0.0/16" } } provider "aws" { region = "${var.region}" } resource "aws_vpc" "vpc" { count = "${length(var.vpc_cidrs)}" cidr_block = "${var.vpc_cidrs["${var.env[count.index / 2]}_${count.index % 2 + 1}"]}" enable_dns_support = true enable_dns_hostnames = true }
内容的にはVPCを4つ作成しているだけです。ハイライトしている箇所に注目していただきたいのですが、以下の内容を記述しています。
- 5-10行: マップのキーをリストとして定義
- 12-19行:
dev_<num>
とprd_<num>
というキーでVPC用CIDRをマップとして定義 - 27行: 今回サポートした算術演算を利用してマップのバリューに変数を展開
今までは27行目のような算術演算が使えなかったので、(今回の例で言うと) aws_vpc
リソースを複数定義したりする冗長な記述をする必要がありました。今回のアップデートによりマップとリストを組み合わせてより簡潔なコードの記述が可能になっています。
27行目の内容を解説すると以下の処理を行っています。
${var.env[count.index / 2]}
ではcount.index
(0から3が入る)を2で割って商を求めています。0/0/1/1と算出されるので結果としてdev
とprd
毎に連続して展開されます。${count.index % 2 + 1}
ではcount.index
を2で割って余りを求めています。余りは0と1が交互に算出されるのでそれに1を足すと1/2/1/2となります。- 最終的に(例えば
count.index
に0が入っていると)"${var.vpc_cidrs["dev_1"]}"
になるのでマップの一番初めのバリューである172.16.0.0/16
へ展開されます。
実行してみる
まず最初に以前のバージョン(v0.7.6)で上記コードを実行してみます。恐らく以下のようにクラッシュしてしまうと思います。
$ terraform version Terraform v0.7.6 Your version of Terraform is out of date! The latest version is 0.7.7. You can update by downloading from www.terraform.io $ terraform plan panic: runtime error: index out of range <snip> !!!!!!!!!!!!!!!!!!!!!!!!!!! TERRAFORM CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!! Terraform crashed! This is always indicative of a bug within Terraform. A crash log has been placed at "crash.log" relative to your current working directory. It would be immensely helpful if you could please report the crash with Terraform[1] so that we can fix this. When reporting bugs, please include your terraform version. That information is available on the first line of crash.log. You can also get it by running 'terraform --version' on the command line. [1]: https://github.com/hashicorp/terraform/issues !!!!!!!!!!!!!!!!!!!!!!!!!!! TERRAFORM CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
それでは続いてv0.7.7のTerraformで実行してみます。
$ terraform version Terraform v0.7.7 $ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. The Terraform execution plan has been generated and is shown below. Resources are shown in alphabetical order for quick scanning. Green resources will be created (or destroyed and then created if an existing resource exists), yellow resources are being changed in-place, and red resources will be destroyed. Cyan entries are data sources to be read. Note: You didn't specify an "-out" parameter to save this plan, so when "apply" is called, Terraform can't guarantee this is what will execute. + aws_vpc.vpc.0 cidr_block: "172.16.0.0/16" default_network_acl_id: "<computed>" default_route_table_id: "<computed>" default_security_group_id: "<computed>" dhcp_options_id: "<computed>" enable_classiclink: "<computed>" enable_dns_hostnames: "true" enable_dns_support: "true" instance_tenancy: "<computed>" main_route_table_id: "<computed>" + aws_vpc.vpc.1 cidr_block: "172.17.0.0/16" default_network_acl_id: "<computed>" default_route_table_id: "<computed>" default_security_group_id: "<computed>" dhcp_options_id: "<computed>" enable_classiclink: "<computed>" enable_dns_hostnames: "true" enable_dns_support: "true" instance_tenancy: "<computed>" main_route_table_id: "<computed>" + aws_vpc.vpc.2 cidr_block: "172.18.0.0/16" default_network_acl_id: "<computed>" default_route_table_id: "<computed>" default_security_group_id: "<computed>" dhcp_options_id: "<computed>" enable_classiclink: "<computed>" enable_dns_hostnames: "true" enable_dns_support: "true" instance_tenancy: "<computed>" main_route_table_id: "<computed>" + aws_vpc.vpc.3 cidr_block: "172.19.0.0/16" default_network_acl_id: "<computed>" default_route_table_id: "<computed>" default_security_group_id: "<computed>" dhcp_options_id: "<computed>" enable_classiclink: "<computed>" enable_dns_hostnames: "true" enable_dns_support: "true" instance_tenancy: "<computed>" main_route_table_id: "<computed>" Plan: 4 to add, 0 to change, 0 to destroy.
正常に実行できました。やりましたね。
まとめ
いかがだったでしょうか。
Terraformの表現力が増えていくのはユーザにとってとてもうれしいアップデートだと思います。このままどんどん進化してほしいと思います。個人的には変数内での変数展開をサポートして欲しいなと思っています。
本エントリがみなさんの参考になれば幸いです。