Terraformで超サクッとループでリソースを用意する方法

ネットワークを構築する際、Variableにいい感じに必要情報を代入してループで一気にresourceをつくってみたので、Terraformを公開します。
2019.08.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、朝7時に起きるのがしんどくなってきた、もこ@札幌オフィスです。

ネットワークを構築する際、Variableにいい感じに必要情報を代入してループで一気にresourceをつくってみたので、Terraformを公開します。

尚、Terraformのバージョンはv0.12.6、aws providerはv2.24.0を利用しています

やってみた

このようなVPC情報とサブネット情報が含まれた変数があったとします。

variable "production-vpc" {
  default = {
    name = "production-vpc"
    cidr = "10.0.0.0/16"
    subnets = {
      subnet1 = {
        availability_zone = "ap-northeast-1a"
        cidr = "10.0.0.0/28"
      }
      subnet2 = {
        availability_zone = "ap-northeast-1c"
        cidr = "10.0.0.16/28"
      }
      subnet3 = {
        availability_zone = "ap-northeast-1a"
        cidr = "10.0.0.32/28"
      }
      subnet4 = {
        availability_zone = "ap-northeast-1c"
        cidr = "10.0.0.48/28"
      }
    }
  }
}

一つの変数(map)にVPCの名前、CIDR、Subnet名、SubnetのCIDR、AZをまとめれれば可読性も高く、なにがどこと紐付いているのかもTerraformのresourceを追わずに見つけれるため、とても便利です。

さて、この変数を使って実際にVPCとSubnetを作ってみましょう。

resource "aws_vpc" "main-vpc" {
  cidr_block = var.production-vpc.cidr
  tags = {
    Name = var.production-vpc.name
  }
}

resource "aws_subnet" "main-subnets" {
  count = length(var.production-vpc.subnets)
  cidr_block = values(var.production-vpc.subnets)[count.index].cidr
  availability_zone = values(var.production-vpc.subnets)[count.index].availability_zone
  tags = {
    Name = keys(var.production-vpc.subnets)[count.index]
  }
  vpc_id = aws_vpc.main-vpc.id

}

とてもシンプルにVPC 1個、Subnet 4個を用意することが出来ました。

ループで作成したリソースは*.idですべて取得することが出来ますが、「特定のSubnetだけを参照してリソースを追加する」ことが多い場合、辛い気がします。

※新しく追加されたfor_eachではListしか利用できないため、シンプルにcountとしています

噛み砕いて解説

length()ではその名の通りvar.production-vpc.subnetsの長さ、今回で言うと4を取得することが出来ます。つまりcountと組み合わせて4個のリソースを作るようにします。

count.indexで現在の配列の位置を取得します。

values()var.production-vpc.subnetsの中の

      subnet1 = {
        availability_zone = "ap-northeast-1a"
        cidr = "10.0.0.0/28"
      }

を呼び出し、availability_zoneやcidrを取得できるようにします。

keys()では上記コードでいうsubnet1を取得することが出来ます。

Nameタグなどを付ける時に便利です。

今回はvalues(var.production-vpc.subnets)[count.index].xxxと書きましたが、

element(values(var.production-vpc.subnets), count.index).xxxのようにelement()を利用して書くことも出来ますが、長くて見づらいです。

IntelliJ IDEAのTerraform Pluginを使えば、このようなコードを書いてしまっても自動で指摘してくれて、自動でいい感じにしてくれます。すごいですね。

TerraformをIntelliJ IDEAで書く方法などは先日書いた記事をご参照ください。

新記法対応! IntelliJ IDEAを使ってTerraformを書いてみた

誰かのお役に立てれば幸いです。