Create resource only if it doesn't exist

Hi
I want to create s3 bucket only if its not available on the aws account.

I tried the below code

data "aws_s3_bucket" "my_objects" {
  bucket = "${var.squad}-tf1-state-${var.environment}-${data.aws_region.current.name}-${data.aws_caller_identity.current.account_id}"
}

resource "aws_s3_bucket" "tfstate_bucket" {
  count = data.aws_s3_bucket.my_objects.bucket ? 1 : 0
  bucket = "${var.squad}-tf1-state-${var.environment}-${data.aws_region.current.name}-${data.aws_caller_identity.current.account_id}"
}

but it looks like data gives an error as object not found. It will be helpful if someone can guide/suggest way to solve this.

 Error: Failed getting S3 bucket (jino-tf1-state-nonprod-us-east-2-xxxxxx): NotFound: Not Found

Thanks

I think this will be either difficult or impossible with Terraform.

The issue is that the entire design of Terraform is based around the declarative specification of what resources exist, and full ownership of the lifecycle of what it creates.

The tool just isn’t built for what you want to do with it, I’m afraid.

Okay, so to solve this I have to use a aws client then, which will check for resource and then apply the change. Thanks for the quick reply. Much appreciated @maxb

One way to think about this with Terraform is that it’s the caller of the module that determines whether this bucket should be managed by this Terraform configuration or not, rather than the module attempting to decide that for itself.

For example, you can declare an input variable which the caller can use to specify an existing S3 bucket name to use, and then use conditional logic to declare an inline S3 bucket only if that input variable is null.

You can then decide externally whether a particular use of the module should be managing the bucket or not, either manually (just have the human operator decide) or with some custom scripting you implement outside of Terraform.

The reason why Terraform requires you to make this decision is that Terraform needs to know which objects it is managing and which it is not. If you have multiple configurations all thinking they “own” a single remote object then they will argue with one another about what the settings are, and if you remove the object from one configuration that configuration could cause it to be destroyed from under the other users of it.

The conditional approach above then is a compromise that allows sharing modules while still keeping it explicit which one user of the module is taking ownership of the lifecycle of that object.

1 Like