Terraformで循環参照のエラーが出た時

これは、リソースを変数で参照して整合性?を保とうとしたときに良くなる。

variable "env" {
  type = "string"
  default = "dev"
}
variable "service" {
  type = "string"
  default = "foo"
}

resource "aws_cloudfront_origin_access_identity" "origin_access" {
  comment = "access-identity-${var.env}-${var.service}.s3.amazonaws.com"
}

data "template_file" "s3_policy" {
  template = "${file("s3-bucket-policy.json")}"

  vars {
    bucket_name            = "${var.env}-${var.service}"
    origin_access_identity = "${aws_cloudfront_origin_access_identity.origin_access.id}"
  }
}

resource "aws_s3_bucket" "foo" {
  bucket = "${var.env}-${var.service}"
  acl    = "private"
  policy = "${data.template_file.s3_policy.rendered}"

  tags {
    Name        = "${var.env}-${var.service}"
    Environment = "${var.env}"
    ServiceName = "${var.service}"
  }
}

となっている場合、循環参照が発生する。

❯ terraform plan
Error configuring: 1 error(s) occurred:

* Cycle: data.template_file.s3_policy, aws_s3_bucket.foo, aws_cloudfront_origin_access_identity.origin_access

もう、わけわかんないし辛い気持ちになるけど、Terraformには便利な機能がある。

依存グラフの出力である。

terraform graph -draw-cycles | dot -Tpng > graph.png

f:id:ringo6119:20170322163153p:plain

-draw-cyclesをつけると赤くなるので、分かりやすい。 後は、その依存関係を解決していけば良いだけ。

今回のケースは、aws_cloudfront_origin_access_identityでバケット名を参照しているが、バケット名は"${var.env}-${var.service}"で置き換え可能なため、

resource "aws_cloudfront_origin_access_identity" "origin_access" {
  comment = "access-identity-${var.env}-${var.service}.s3.amazonaws.com"
}

とすると直る。

f:id:ringo6119:20170322163152p:plain

References