Skip to main content

Generate Terraform Providers

The providers section generates Terraform provider configuration files (providers_override.tf.json) for your components. This allows you to manage provider settings declaratively in your stack configuration, with Atmos automatically generating the provider files when you run Terraform commands. This section is Terraform-specific.

How It Works

When you run any atmos terraform command, Atmos:

  1. Reads your providers configuration from the stack
  2. Generates a providers_override.tf.json file in the component directory
  3. Terraform uses this file to configure providers without modifying your source code

This approach lets you define provider configuration once in your stacks and have Atmos generate the appropriate files for each environment.

Generated Files

Add providers_override.tf.json to your .gitignore since these files are generated automatically by Atmos and should not be committed to version control:

# Atmos generated files
providers_override.tf.json

Use Cases

  • Provider Configuration: Set region, credentials, and other provider-specific settings.
  • Provider Aliases: Configure multiple instances of the same provider for multi-region or multi-account deployments.
  • Dynamic Configuration: Use templates to configure providers based on stack context.
  • Assume Role: Configure cross-account access via role assumption.

Configuration Scopes

Component-Type Level

Provider settings defined under terraform apply to all Terraform components:

stacks/orgs/acme/plat/prod/_defaults.yaml
terraform:
providers:
aws:
region: us-east-1
assume_role:
role_arn: "arn:aws:iam::123456789012:role/TerraformRole"

Component Level

Provider settings within a component override the defaults:

stacks/orgs/acme/plat/prod/us-east-1.yaml
components:
terraform:
vpc:
providers:
aws:
region: us-west-2

Merge Behavior

Providers are deep-merged from the most general to the most specific level:

  1. Component-type terraform.providers: (applies to all Terraform components)
  2. Component components.terraform.<name>.providers (applies to a specific component)

Provider configurations are merged at the provider level. If both levels define the same provider, the configurations are deep-merged with component-level values taking precedence.

Examples

Basic Provider Configuration

stacks/orgs/acme/plat/prod/_defaults.yaml

terraform:
providers:
aws:
region: us-east-1

Multi-Region with Provider Aliases

Configure multiple AWS regions using provider aliases:

stacks/orgs/acme/plat/prod/global.yaml
components:
terraform:
dns:
providers:
aws:
region: us-east-1
aws.uswest2:
region: us-west-2
alias: uswest2
aws.euwest1:
region: eu-west-1
alias: euwest1

Cross-Account Access with Assume Role

stacks/orgs/acme/plat/prod/_defaults.yaml
terraform:
providers:
aws:
region: us-east-1
assume_role:
role_arn: "arn:aws:iam::{{ .vars.account_id }}:role/TerraformRole"
session_name: "atmos-{{ .component }}"
external_id: "{{ .vars.external_id }}"

Multiple Providers

Configure multiple provider types:

stacks/orgs/acme/plat/prod/_defaults.yaml
terraform:
providers:
aws:
region: us-east-1

kubernetes:
config_path: "~/.kube/config"
config_context: "prod-cluster"

helm:
kubernetes:
config_path: "~/.kube/config"
config_context: "prod-cluster"

Dynamic Provider Configuration

Use templates for dynamic configuration:

stacks/orgs/acme/_defaults.yaml
terraform:
providers:
aws:
region: "{{ .vars.region }}"
assume_role:
role_arn: "arn:aws:iam::{{ .vars.account_id }}:role/{{ .vars.terraform_role_name }}"
default_tags:
tags:
Environment: "{{ .stage }}"
ManagedBy: "Atmos"
Component: "{{ .component }}"

Component-Specific Provider Override

stacks/orgs/acme/plat/prod/us-east-1.yaml
import:
- orgs/acme/plat/prod/_defaults

components:
terraform:
# Uses default provider configuration
vpc:
vars:
vpc_cidr: "10.0.0.0/16"

# Overrides provider for cross-account access
shared-services:
providers:
aws:
assume_role:
role_arn: "arn:aws:iam::999999999999:role/SharedServicesRole"
vars:
# ...

Provider with Kubernetes from EKS

stacks/orgs/acme/plat/prod/us-east-1.yaml
components:
terraform:
eks-addons:
providers:
aws:
region: us-east-1

kubernetes:
host: "{{ .vars.eks_cluster_endpoint }}"
cluster_ca_certificate: "{{ .vars.eks_cluster_ca_certificate }}"
exec:
api_version: "client.authentication.k8s.io/v1beta1"
command: "aws"
args:
- "eks"
- "get-token"
- "--cluster-name"
- "{{ .vars.eks_cluster_name }}"

helm:
kubernetes:
host: "{{ .vars.eks_cluster_endpoint }}"
cluster_ca_certificate: "{{ .vars.eks_cluster_ca_certificate }}"
exec:
api_version: "client.authentication.k8s.io/v1beta1"
command: "aws"
args:
- "eks"
- "get-token"
- "--cluster-name"
- "{{ .vars.eks_cluster_name }}"

Provider Configuration Reference

AWS Provider

Common configuration options:

providers:
aws:
region: us-east-1
profile: my-profile
assume_role:
role_arn: "arn:aws:iam::123456789012:role/Role"
session_name: "session-name"
external_id: "external-id"
duration_seconds: 3600
default_tags:
tags:
Environment: prod
allowed_account_ids:
- "123456789012"
forbidden_account_ids:
- "000000000000"

Kubernetes Provider

providers:
kubernetes:
host: "https://kubernetes.example.com"
cluster_ca_certificate: "base64-encoded-ca-cert"
token: "auth-token"
config_path: "~/.kube/config"
config_context: "context-name"
exec:
api_version: "client.authentication.k8s.io/v1beta1"
command: "aws"
args:
- "eks"
- "get-token"
- "--cluster-name"
- "my-cluster"

Helm Provider

providers:
helm:
kubernetes:
host: "https://kubernetes.example.com"
cluster_ca_certificate: "base64-encoded-ca-cert"
token: "auth-token"
repository_config_path: "~/.helm/repositories.yaml"
repository_cache: "~/.helm/cache"

Best Practices

  1. Use Assume Role: Configure providers to assume roles rather than using long-lived credentials.

  2. Centralize Common Configuration: Define shared provider settings in catalog defaults and import them.

  3. Use Default Tags: Configure default_tags to ensure all resources are properly tagged.

  4. Template Dynamic Values: Use Go templates for values that vary by environment or component.

  5. Restrict Account Access: Use allowed_account_ids to prevent accidental deployments to wrong accounts.

  6. Version Pin Providers: While provider versions are managed in Terraform code, ensure your stack configuration is compatible with your provider versions.