【朗報】Terraform v0.8.0でREPL機能が限定的にサポートされます
はじめに
こんにちは、中山です。
実質的なメジャーバージョンアップであるv0.8.0に向けてベータリリースが続いています。現在(2016年11月15日)、v0.8.0系とv0.7.X系が同時にリリースされている状況です。今回はv0.8.0に搭載予定の機能である console
サブコマンドについてご紹介します。これは、まだ制限がありますが、TerraformをREPL形式で実行できる機能です。
機能概要
この機能はこちらのPRで取り込まれたものです。 terraform console
を実行するとREPL形式で変数展開が実行可能です。また、stateファイルがある場合はその中から各種属性を確認できます。今までは、Terraformの変数展開の挙動を確認するために、いちいちtfファイルを用意する必要がありました。これは少々面倒です。この機能によりさっと動作を確認できるようになったのは素晴らしいアップデートだと思います。
ただし、上記PRにも書かれていますが、現時点ではTerraformそのものの実行( plan
/ apply
など )はサポートされていません。将来的には搭載予定のようなので期待したいと思います。
使ってみる
では、早速使ってみましょう。現時点ではv0.8.0がリリースされていないため、自分でTerraformをコンパイルする必要があります。詳細はこちらのドキュメントに詳しいですが、簡単に説明すると以下のコマンドで実行可能です(事前にGo環境は整えておく必要はあります)。
$ go get github.com/hashicorp/terraform $ cd $GOPATH/src/github.com/hashicorp/terraform $ git checkout aaf1ad05324153c88113da7cdcc3bf36e5df9adb $ git log -1 commit aaf1ad05324153c88113da7cdcc3bf36e5df9adb Merge: 25d19ef 1a6056b Author: Mitchell Hashimoto <xmitchx@gmail.com> Date: Mon Nov 14 11:53:49 2016 -0800 Merge pull request #10093 from hashicorp/f-console Add `terraform console` for REPL $ make dev $ $GOPATH/bin/terraform version Terraform v0.8.0-dev (aaf1ad05324153c88113da7cdcc3bf36e5df9adb)
この機能からstateファイルも扱ってみたいので以下のようなサンプルとなるコードを用意しました。VPC内に複数のサブネットを作るだけのものです。 main.tf
など適当なファイル名で保存すればそのまま利用可能です。
variable "name" { default = "test-vpc" } variable "vpc_cidr" { default = "192.168.0.0/16" } provider "aws" { region = "ap-northeast-1" } data "aws_availability_zones" "az" {} resource "aws_vpc" "vpc" { cidr_block = "${var.vpc_cidr}" enable_dns_support = true enable_dns_hostnames = true tags { Name = "${var.name}-vpc" } } resource "aws_internet_gateway" "igw" { vpc_id = "${aws_vpc.vpc.id}" tags { Name = "${var.name}-igw" } } resource "aws_subnet" "frontend_subnet" { count = 2 vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${cidrsubnet(var.vpc_cidr, 8, count.index)}" availability_zone = "${data.aws_availability_zones.az.names[count.index]}" map_public_ip_on_launch = true tags { Name = "${var.name}-frontend-subnet-${count.index + 1}" } } resource "aws_route_table" "frontend_subnet" { vpc_id = "${aws_vpc.vpc.id}" route { cidr_block = "0.0.0.0/0" gateway_id = "${aws_internet_gateway.igw.id}" } tags { Name = "${var.name}-frontend-rtb" } } resource "aws_route_table_association" "frontend_subnet" { count = 2 subnet_id = "${element(aws_subnet.frontend_subnet.*.id, count.index)}" route_table_id = "${aws_route_table.frontend_subnet.id}" } resource "aws_subnet" "application_subnet" { count = 2 vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${cidrsubnet(var.vpc_cidr, 8, count.index + 100)}" availability_zone = "${data.aws_availability_zones.az.names[count.index]}" map_public_ip_on_launch = true tags { Name = "${var.name}-application-subnet-${count.index + 1}" } } resource "aws_route_table" "application_subnet" { vpc_id = "${aws_vpc.vpc.id}" route { cidr_block = "0.0.0.0/0" gateway_id = "${aws_internet_gateway.igw.id}" } tags { Name = "${var.name}-application-rtb" } } resource "aws_route_table_association" "application_subnet" { count = 2 subnet_id = "${element(aws_subnet.application_subnet.*.id, count.index)}" route_table_id = "${aws_route_table.application_subnet.id}" } resource "aws_subnet" "datastore_subnet" { count = 2 vpc_id = "${aws_vpc.vpc.id}" cidr_block = "${cidrsubnet(var.vpc_cidr, 8, count.index + 200)}" availability_zone = "${data.aws_availability_zones.az.names[count.index]}" map_public_ip_on_launch = false tags { Name = "${var.name}-datastore-subnet-${count.index + 1}" } } resource "aws_network_acl" "acl" { vpc_id = "${aws_vpc.vpc.id}" subnet_ids = ["${aws_subnet.frontend_subnet.*.id}", "${aws_subnet.application_subnet.*.id}"] ingress { protocol = "-1" rule_no = 100 action = "allow" cidr_block = "0.0.0.0/0" from_port = 0 to_port = 0 } egress { protocol = "-1" rule_no = 100 action = "allow" cidr_block = "0.0.0.0/0" from_port = 0 to_port = 0 } tags { Name = "${var.name}-acl" } }
以下のコマンドで環境を構築してください。
$ $GOPATH/bin/terraform plan $ $GOPATH/bin/terraform apply <snip> Apply complete! Resources: 15 added, 0 changed, 0 destroyed. The state of your infrastructure has been saved to the path below. This state is required to modify and destroy your infrastructure, so keep it safe. To inspect the complete state use the `terraform show` command. State path: terraform.tfstate
では早速 console
を利用してみます。stateファイルがあるディレクトリ上で以下のコマンドを実行してください。すると、以下のようにREPLが開始されます。
$ $GOPATH/bin/terraform console >
ヘルプは help
で確認できます。下の方に記載されているように exit
などでREPLから抜けることが可能です。readline機能があるので基本的なシェルと同じショートカットが利用できます(補完は未実装)。
> help The Terraform console allows you to experiment with Terraform interpolations. You may access resources in the state (if you have one) just as you would from a configuration. For example: "aws_instance.foo.id" would evaluate to the ID of "aws_instance.foo" if it exists in your state. Type in the interpolation to test and hit <enter> to see the result. To exit the console, type "exit" and hit <enter>, or use Control-C or Control-D.
この状態で各種変数展開の挙動が確認できます。例えば、 cidrhost
関数の挙動を確認したい場合は以下のように実行します。
> cidrhost("10.0.0.0/8", 2) 10.0.0.2
stateファイルに記載されている変数の内容を確認したい場合は、一度REPLを抜けて state list
の出力を表示させると便利です。
$ $GOPATH/bin/terraform state list aws_availability_zones.az aws_internet_gateway.igw aws_network_acl.acl aws_route_table.application_subnet aws_route_table.frontend_subnet aws_route_table_association.application_subnet[0] aws_route_table_association.application_subnet[1] aws_route_table_association.frontend_subnet[0] aws_route_table_association.frontend_subnet[1] aws_subnet.application_subnet[0] aws_subnet.application_subnet[1] aws_subnet.datastore_subnet[0] aws_subnet.datastore_subnet[1] aws_subnet.frontend_subnet[0] aws_subnet.frontend_subnet[1] aws_vpc.vpc
VPCの各種属性を確認してみます。
> aws_vpc.vpc.id vpc-98cc00fc > aws_vpc.vpc.cidr_block 192.168.0.0/16 > aws_vpc.vpc.instance_tenancy default
もちろん、 *
でリストの展開もOKです。
> concat(aws_subnet.frontend_subnet.*.id, aws_subnet.application_subnet.*.id) [ subnet-9637bbe0, subnet-c235e39a, subnet-a937bbdf, subnet-c035e398 ]
まとめ
いかがでしょうか。
まだまだ限定的な機能しかサポートされていませんが、結構夢がひろがりんぐな機能だと思います。例えば、障害時などで緊急に対応する必要がある場合、Terraformのコードをいちいち修正するのはちょっとしんどいと思います。ただし、マネジメントコンソールで操作してしまうとstateファイルとの差分が出てしまう。そういった場合、この機能を使うとstateファイルを更新しつつ、アドホックにTerraformが実行できるかもしれません。
あるいは、awscliの代替としての使い道もありそうです。stateファイルにAWSリソースの情報が保存されるので、awscliの用に describe
系コマンドでいちいちパース処理をしなくても良いかもしれません。または、かっちりとTerraformでコードを組む前に、動作検証含めREPL形式で構築するといった使い方もできそうです。
いずれにせよ、今後のアップデートに期待できる機能になりそうです。
本エントリがみなさんの参考になれば幸いです。