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.34k stars 9.49k forks source link

Configure provider from *.tfvars #23340

Open timurb opened 4 years ago

timurb commented 4 years ago

Current Terraform Version

$ terraform -v
Terraform v0.12.13
+ provider.aws v2.35.0

Use-cases

It would be nice if I could specify configuration for provider using *.tfvars file (or env variables could probably also work).

Currently I have to either make that configuration explicit or type configuration manually each time. I'm talking specifically about the case when I have no provider blocks in my configuration and Terraform pulls the provider implicitly.

Attempted Solutions

When I have AWS resources and don't have provider defined every time I run terraform apply I get the following message:

$ terraform apply
provider.aws.region
  The region where AWS operations will take place. Examples
  are us-east-1, us-west-2, etc.

  Enter a value: 

If I try to put provider.aws.region to terraform.tfvars I get the following error:

$ terraform apply

Error: Argument or block definition required

  on terraform.tfvars line 4:
   4: provider.aws.region = "eu-west-1"

An argument or block definition is required here. To set an argument, use the
equals sign "=" to introduce the argument value.

Proposal

As a user I would expect that I'm able to use parameter name specified on input label provider.aws.region as my variable.

It could reduce confusion if that label is displayed differently. I'd really like to be able to configure providers using terraform.tfvars

References

There is a similar issue relating to backends, feel free to close this one if you feel they are the same: https://github.com/hashicorp/terraform/issues/19300

timurb commented 4 years ago

A good option could be to save the provider config params into state file and reuse it on the next run instead of asking a user.

teamterraform commented 4 years ago

Thanks for sharing this use-case, @timurb!

As a way to get something like what you're looking for today, note that the region argument for the AWS provider can also be set via the AWS_DEFAULT_REGION environment variable, for consistency with the AWS CLI.

The way to configure provider arguments with .tfvars today is to declare a variable and pass it in to the configuration:

variable "aws_region" {
  type = string
}

provider "aws" {
  region = var.aws_region
}

At this time we don't have plans to save provider configuration to the state because provider configuration often contains credentials that are specific to a particular user and not re-usable between different users working with the same state. However, it might be an acceptable compromise to store those input values in a local directory (never persisted to remote state storage) so that a particular user only has to enter them once.

For settings like region though, which are more telling Terraform what to manage rather than how to authenticate, our current recommendation is to configure them explicitly in the configuration as you would for any other declaration of something for Terraform to manage. region is, in effect, an implied additional argument to all of the resources declared against that provider configuration.

timurb commented 4 years ago

That's why I've created this ticket. I was looking for a way to keep region configuration implicit in child modules as recommended in https://www.terraform.io/docs/configuration/modules.html#providers and probably only make it explicit in parent modules/environment definitions. At the same time I run terraform directly in child module by using gitignored terraform.tfvars (and could do that without extra typing with this feature available) — that is the way I do dev/test work on individual modules. (I should have actually put this into ticket description)

Using env var AWS_DEFAULT_REGION as you suggest could also be ok when combined with https://github.com/direnv/direnv though, I'll probably stick to it for now.

Thanks!

mshakhmaykin commented 4 years ago

I am voting for the same feature.

 terraform plan -var-file ../../controller.tfvars

Error: Argument or block definition required

  on ../../controller.tfvars line 1:
   1: provider.aviatrix.username="admin"

An argument or block definition is required here. To set an argument, use the
equals sign "=" to introduce the argument value.

There's no explicit provider definition in our code, because it's assumed by resource names. And normally credentials are passed via Gitlab ENV variables. But for the local tests we want to have a way to keep the creds file and use it as a regular tfvfars.