Conditional s3 bucket creation

Hi there!

Quick question.
Is there any non documented functionality to make bucket creation optional depending on binary flag?

Something like:

resource "aws_s3_bucket" "this" {
  count  = var.create_bucket ? 1 : 0
  bucket = "name"

Closest I found - amazon web services - How do I conditionally create an S3 bucket - Stack Overflow.

Alternatively it can be declared in separate in tf file but how to make it added into execution optionally in native way and without mangling with shell?

Regards,
Serhii

Exactly what you already wrote in your post.

Thanks @maxb,

Just tested …
But let’s say we have existing module with plenty of resources to be dependent on bucket.
I need to make creation optional but adding count brings index into the picture and change interface.
Is it possible to avoid adding index and use true boolean - not count?

Update:

Also using count with constant name resulting rather a bit confusing result with 3 resources in state that points to the same actual bucket.

terraform state list                                                                                                                                                               
aws_s3_bucket.this[0]
aws_s3_bucket.this[1]
aws_s3_bucket.this[2]

Regards,
Serhii

Hi @chell0veck,

Both count and for_each cause Terraform to track the resource as a collection of instances and create the possibility of there being zero instances of the resource. Without either of those arguments, there is always exactly one instance of the resource, whose address matches the address of the resource itself.

It’s intentional that this changes how you must refer to the instances of the resource elsewhere in your module, because you will need to now write expressions that can support there being zero instances, whereas with a singleton resource (one without count or for_each) you can always assume that a reference to the resource will yield exactly one resource object.

1 Like

Thanks a lot @apparentlymart ,

May I ask if it possible to make resource execution optional, just like commenting the block but within hcl?

Off-top - I assume that’s expected but in case of below example:

resource "aws_s3_bucket" "this" {
  count  = 3
  bucket = "test-bucket-1-887788"
}

output "buckets" {
  value = aws_s3_bucket.this[*].arn
}

that gives an collection of 3 but with 1 actual resource.

buckets = [
  "arn:aws:s3:::test-bucket-1-887788",
  "arn:aws:s3:::test-bucket-1-887788",
  "arn:aws:s3:::test-bucket-1-887788",
]

Hi @chell0veck,

In Terraform there is a distinction between a resource, which is more or less the resource block you write in the configuration, and instances of a resource, which are Terraform’s representation of the remote objects you’re managing with Terraform.

Resource instances can be declared dynamically, using count and for_each, but resources themselves are static: if they are written in the configuration they exist, and if they aren’t written in the configuration they aren’t.

It might help to consider an analogy to a variable declaration vs. a variables value in a general-purpose programming language. Ignoring some very dynamic languages that blur this distinction by allowing you to modify the scope dynamically at runtime, you generally don’t get to conditionally decide whether a variable is declared or not, but you do get to dynamically decide what to associate with it. For example, in the Go programming language:

var example []string
if someCondition {
  example = []string{"hello"}
} else {
  example = []string{}
}
// (this is not really idiomatic Go, but I'm
// writing things out more explicitly for the
// sake of the analogy)

This example variable exists regardless of whether someCondition is true or false, but in some cases it’s a zero-length list and in other cases it’s a one-element list. There is no way to dynamically decide not to declare example at all, but you can comment it out in the source code if you want the compiler to ignore it.

A resource block with count set is analogous to the var example []string declaration in the above, and the count expression itself is roughly analogous to the if statement that follows it.

I’m not sure what you were intending to ask about this example with three S3 buckets, but as with my analogy above you can dynamically decide between having three elements or zero elements (by putting a conditional expression in the count argument), but you can’t dynamically decide that resource "aws_s3_bucket" "this" isn’t declared at all.

1 Like