Search code examples
amazon-web-servicesterraformterraform-provider

How do I conditionally create an S3 bucket


Is there a way I can use a terraform data call for a bucket (perhaps created and stored in a different state file) and then in the event nothing is in data, create the resource by setting a count?

I've been doing some experiments and continually get the following:

Error: Failed getting S3 bucket (example_random_bucket_name): NotFound: Not Found
        status code: 404, request id: <ID here>, host id: <host ID here>

Sample code to test (this has been modified from the original code which generated this error):

variable "bucket_name" {
  default = "example_random_bucket_name"
}

data "aws_s3_bucket" "new" {
  bucket = var.bucket_name
}

resource "aws_s3_bucket" "s3_bucket" {
  count = try(1, data.aws_s3_bucket.new.id == "" ? 1 : 0 )
  bucket = var.bucket_name
}

I feel like rather than generating an error I should get an empty result, but that's not the case.


Solution

  • Terraform is a desired-state system, so you can only describe what result you want, not the steps/conditions to get there.

    If Terraform did allow you to decide whether to declare a bucket based on whether there is already a bucket of that name, you would create a configuration that could never converge: on the first run, it would not exist and so your configuration would declare it. But on the second run, the bucket would then exist and therefore your configuration would not declare it anymore, and so Terraform would plan to destroy it. On the third run, it would propose to create it again, and so on.

    Instead, you must decide as part of your system design which Terraform configuration (or other system) is responsible for managing each object:

    • If you decide that a particular Terraform configuration is responsible for managing this S3 bucket then you can declare it with an unconditional aws_s3_bucket resource.
    • If you decide that some other system ought to manage the bucket then you'll write your configuration to somehow learn about the bucket name from elsewhere, such as by an input variable or using the aws_s3_bucket data source.