How can reuse the same provider block in several files?

I’m trying to follow the guidelines from Terraform: UP & Running 2nd Edition Chapter 4. How to Create Reusable Infrastructure with Terraform Modules

I have the following structure
./live/dev/vpc/main.tf
./live/dev/services/eks/main.tf

The provider "aws" {...} block for all the ‘/live/dev’ is the same, and I wonder how can I avoid repeating myself and have a ./live/dev/aws_config.tf and reference that from the other **/main.tf files. Is there any way to do that or it’s an antipattern?

Assuming that each of those live/dev/foo directories is a separate Terraform configuration, there is no direct way in Terraform to share information between configurations like that: configurations are intentionally separate from one another.

Some options in similar vein include:

  • For the AWS provider in particular it’s typical for the provider "aws" block to have very little in it (often just region) and have all of the information about who is authenticating be derived from the surrounding environment, whether via instance profiles, ~/.aws/credentials, or environment variables.

    In that case, the “ambient” settings are in a sense shared across all of the configurations you apply with them active, and so setting up those standard AWS configuration mechanisms is the most common answer, with the bonus that it will also then work for other AWS-integrated software such as the AWS CLI.

  • Use a symlink to make the same .tf file appear to be in all of the directories. Terraform reads all files named .tf, including symlinks, so it will then behave the same as if you’d copied the same file into all of the directories.

  • Write a shared module that exports (as output values) the meaningful information from the provider block and then call that module from all of the configurations, assigning the resulting information into a local provider block:

    module "env" {
      source = "../env"
    }
    
    provider "aws" {
      region = module.env.region
    
      assume_role {
        role_arn = module.env.assume_role_arn
      }
    }
    

    This avoids repeating the meaningful information in multiple files, but still leaves the presence of an aws provider configuration explicit rather than implied.

    This is an example of a data-only module, which can consist either entirely of output blocks with hard-coded shared values or of one or more data blocks to look up the values more dynamically somehow.

1 Like