読者です 読者をやめる 読者になる 読者になる

terraformのmoduleで定義したresouseにアクセスするにはoutputしないとダメ

moduleの誤解

何もわかってなかった。 module使うと変数とかをscope化できるからいいなーって思ってたけど、resourceもscope化されるってことだった。 まぁ逆に言えば、module内にresource名は被らないように気をつける必要がないとも言えるけど。 terraform how to get another module resource みたいな感じでググってもそんなにでてこないから多分当たり前の概念過ぎるんだろうな。

他のmoduleのresource名を取得するには

resource名から取ろうとしてもダメ

例えばこんなディレクトリ構成で、bastionの方でbase_networkで定義したvpcのidが欲しいみたいな場合。

├── base_network
│   ├── route_table.tf
│   ├── subnet.tf
│   └── vpc.tf
├── bastion
│   ├── ec2.tf
│   ├── eip.tf
│   └── security_group.tf
├── main.tf

vpc.tfで、resource "aws_vpc" "default"なんてやった場合に、bastionの中でaws_vpc.default.idってやっても、そんなresourceありませんよみたいな感じに言われてしまう。

外部から使いたい値をoutputする

なので、どうするかっていうと、各module内でoutputを定義する。

output "vpc_id" { value = "${aws_vpc.default.id}" }

で、これでbastionの方で、"${module.base_network.vpc_id}"ってやれば使えるんかなと思ったけど、使えない。 bastionの中で、moduleとして、base_networkをimportしないといけないんだと思う。 でも、そうすると依存関係がスパゲッティみたいになってしまうのが想像できる。 そこで、moduleを定義するときに、変数を受け取れるのでそこで受け取る。

module側はvariableで受け取る

main.tfが各moduleをimportするところなんだけど、そこで、変数の橋渡しをしてあげるイメージ。

provider "aws" {}

module "base_network" {
  source = "./base_network"
}

module "bastion" {
  source = "./bastion"
  vpc_id = "${module.base_network.vpc_id}"
}

で、bastion内で使うときは、"${var.vpc_id}"でいける。

最終的にはこんな感じになる。

├── base_network
│   ├── outputs.tf
│   ├── route_table.tf
│   ├── subnet.tf
│   ├── variables.tf
│   └── vpc.tf
├── bastion
│   ├── ec2.tf
│   ├── eip.tf
│   ├── outputs.tf
│   ├── security_group.tf
│   └── variables.tf
├── main.tf

これは、 terraform-community-modules · GitHubで使われてる基本的なやり方だった。やっとスタートラインにたどり着いた感じだw