Home > Back-end >  How do I conditionally create an S3 bucket
How do I conditionally create an S3 bucket

Time:12-15

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.

CodePudding user response:

Sadly you can't do this. data sources must exist, otherwise they error out. There is no build in way in TF to check if a resource exists or not. There is nothing in between, in a sense that a resource may, or may not exist.

If you require such functionality, you have to program it yourself using External Data Source. Or maybe simpler, provide an input variable bucket_exist, so that you explicitly set it during apply.

CodePudding user response:

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.

CodePudding user response:

Data sources are designed to fail this way.

However, if you use a state file from external configuration, it's possible to declare an output in the external state, based on whether the s3 bucket is managed by that state and use it in s3_bucket resource as condition.

For example, the output in external state will be empty string (not managed) or value for whatever property is useful for you. Boolean is another choice. Delete data source from this configuration and add condition to the resource based on the output.

It's your call if any such workarounds complicate or simplify your configuration.

  • Related