hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io
Other
42.78k stars 9.56k forks source link

Make TF_IN_AUTOMATION Environment Variable Available in Terraform Configurations #32214

Open p0fi opened 2 years ago

p0fi commented 2 years ago

Terraform Version

Terraform v1.3.4 on darwin_arm64

Use Cases

It would be helpful to have access to the information weather terraform is running in automation or not. When running terraform on a local machine and in CI some resources could have different characteristics e.g. name of a given resource. One could think of an example like this:

locals {
 user-prefix = <am I running in automation> ? "ci" : "user"
}

resource "aws_s3_bucket" "bucket" {
  bucket = "${local.user-prefix}-my-tf-test-bucket"
}

Attempted Solutions

An additional variable could be defined and used in the same way the TF_IN_AUTOMATION flag is used.

Proposal

Make the TF_IN_AUTOMATION flag available the same way terraform workspaces are available under the terraform namespace.

It could be used like this:

locals {
 user-prefix = ${terraform.in_automation} ? "ci" : "user"
}

This should be globally available to avoid having to hand down this flag to child modules.

References

No response

apparentlymart commented 2 years ago

Hi @p0fi! Thanks for sharing this feature request.

The use-case you shared here, of varying configuration based on environment, is intended to be met using existing mechanisms such as input variables, workspaces, or data sources.

The environment variable you are referring to is focused only on avoiding Terraform prompting a user to run specific Terraform commands in situations where that would be impossible.

I don't expect we would overload that mechanism with this entirely unrelated use-case. We could consider other ways to address your need that don't overload an existing feature, although we'd need to discuss why the existing three features intended to support this are inefficient.

Thanks!

PeterBurner commented 2 years ago

I think the main advantage of @p0fi s approach is that the information is accessible from anywhere in the project. Variables have to be passed explicitly, workspaces might not ba available in all scenarios or to all users (company policy) and having the same data source in every module would mean that the request/lookup/call would have to be done multiple times and could, depending on its nature, slow down the deployment significantly.

apparentlymart commented 2 years ago

Hi @PeterBurner! Thanks for that additional context.

Unfortunately what you've framed as an advantage would be perceived by some (including me, currently) as a disadvantage: it would encourage Terraform modules to vary their behavior based only on whether or not they are running in automation, which would not be clear to anyone using that module.

Although it is indeed more work to explicitly pass data from one module to another, that work pays off when a future maintainer reads the resulting code and can understand what behavior customization the module supports. When making language design decisions for the Terraform language, we typically prioritize the reader of the code over the writer, and so will often make design choices that require more work for the original author of a system. Code is typically read far more than it is written.

Given that, my sense is that we will probably decline to add any new "side-channel" ways to vary a module's behavior without declaring an input variable, but we can still discuss other potential ways to address the problem that meet the requirement that any behavior customization be expressed via input variables or something equivalent to input variables.

p0fi commented 2 years ago

While I understand your point, I think that there are already ways to alternate a module's behavior without declaring an input variable. You mentioned yourself: workspaces.

It's perfectly fine to write module code like this

locals {
  user-prefix = ${terraform.workspace} == "dev" ? "A" : "B"
}

Making the TF_IN_AUTOMATION environment variable available to configurations would just mean treating this variable the same way you treat the workspace environment variable (TF_WORKSPACE). I think having a any given configuration to behave different when run in CI is a perfectly reasonable need for many.

apparentlymart commented 2 years ago

Indeed, terraform.workspace was a historical design error that we are now preserving for backward compatibility. We don't intend to add any more features like that.