10

I have a terraform file which fails when I run terraform plan and I get the error:

Error: Cycle: module.hosting.data.template_file.bucket_policy, module.hosting.aws_s3_bucket.website

It makes sense since the bucket refers to the policy and vice versa:

data "template_file" "bucket_policy" {
  template = file("${path.module}/policy.json")
  vars = {
    bucket = aws_s3_bucket.website.arn
  }
}

resource "aws_s3_bucket" "website" {
  bucket = "xxx-website"

  website {
    index_document = "index.html"
  }

  policy = data.template_file.bucket_policy.rendered
}

How can I avoid this bidirectional reference?

Alain O'Dea
  • 21,033
  • 1
  • 58
  • 84
saronet
  • 117
  • 1
  • 2
  • 11

2 Answers2

5

You can use the aws_s3_bucket_policy resource. This allows you to create the resources without a circular dependency.

This way, Terraform can:

  1. Create the bucket
  2. Create the template file, using the bucket ARN
  3. Create the policy, referring back to the template file and attaching it to the bucket.

The code would look something like this:

data "template_file" "bucket_policy" {
  template = file("${path.module}/policy.json")
  vars = {
    bucket = aws_s3_bucket.website.arn
  }
}

resource "aws_s3_bucket" "website" {
  bucket = "xxx-website"

  website {
    index_document = "index.html"
  }
}

resource "aws_s3_bucket_policy" "b" {
  bucket = "${aws_s3_bucket.website.id}"

  policy = data.template_file.bucket_policy.rendered
}
Dennis Traub
  • 50,557
  • 7
  • 93
  • 108
3

You could build the ARN of the bucket yourself:

locals {
  bucket_name = "example"
  bucket_arn  = "arn:aws:s3:::${local.bucket_name}"
}

data "template_file" "bucket_policy" {
  template = file("${path.module}/policy.json")
  vars = {
    bucket = local.bucket_arn
  }
}

resource "aws_s3_bucket" "website" {
  bucket = local.bucket_name

  website {
    index_document = "index.html"
  }

  policy = data.template_file.bucket_policy.rendered
}
ydaetskcoR
  • 53,225
  • 8
  • 158
  • 177
  • Nice suggestion, but then I get another error: `Error putting S3 policy: MalformedPolicy: Policy has invalid resource` – saronet May 18 '20 at 18:52
  • *Edit for my comment above:* works perfectly. I had also to make a corresponding change in the policy.json file – saronet May 18 '20 at 19:54
  • 1
    This works, but it’s more complicated than necessary. Also, to manually build an Amazon S3 ARN is simple but there are other resource types that can have circular dependencies with more complicated ARNs. And manually building the ARNs for all of them can be pretty cumbersome and error-prone. For this reason there are specific attachable resources, like in this case the aws_s3_bucket_policy, that help resolve the circular dependency without being hacky. – Dennis Traub May 18 '20 at 20:10