Skip to main content

Generate Terraform Files

The generate section creates auxiliary configuration files for Terraform components based on your stack configuration. Define file templates once in your stacks and Atmos generates the appropriate files in each component directory.

How It Works

When you run atmos terraform generate files (or any terraform command with auto_generate_files enabled), Atmos:

  1. Reads the generate section from the component's stack configuration
  2. Processes each file definition using extension-aware serialization or Go templates
  3. Writes the generated files to the component directory
  4. Makes template context variables available for dynamic content

This separation means you can generate environment-specific configuration files without hardcoding values in your Terraform modules.

Generated Files

Add generated files to your .gitignore since they are created automatically by Atmos:

# Atmos generated files
locals.tf
*.generated.tf

Use Cases

  • Dynamic Locals: Generate locals.tf files with environment-specific values.
  • Provider Configuration: Create additional provider files dynamically.
  • Documentation: Generate README files with component metadata.
  • Custom Configuration: Create any auxiliary files your Terraform modules need.

Configuration

The generate section is defined at the component level in stack configuration:

stacks/orgs/acme/plat/prod/us-east-1.yaml
components:
terraform:
vpc:
vars:
environment: prod
vpc_cidr: "10.0.0.0/16"
generate:
# Map values are serialized based on file extension
locals.tf:
locals:
environment: "{{ .vars.environment }}"
vpc_cidr: "{{ .vars.vpc_cidr }}"

# String values are treated as Go templates
README.md: |
# VPC Component
Environment: {{ .vars.environment }}
Stack: {{ .atmos_stack }}

Extension-Aware Serialization

When the value is a map, Atmos serializes it based on the file extension:

ExtensionFormatDescription
.tf, .hclHCLValid Terraform/HCL syntax
.jsonJSON2-space indented JSON
.yaml, .ymlYAML2-space indented YAML
OtherJSONDefaults to JSON format

HCL Generation Example

components:
terraform:
vpc:
generate:
locals.tf:
locals:
environment: "{{ .vars.environment }}"
tags:
ManagedBy: Atmos
Component: "{{ .component }}"

JSON Generation Example

components:
terraform:
vpc:
generate:
config.json:
settings:
environment: "{{ .vars.environment }}"
region: "{{ .vars.region }}"

Template Context

String values and map string values are processed as Go templates with access to the full component context:

Available Variables

{{ .vars }}
Component variables from the vars section.
{{ .settings }}
Component settings from the settings section.
{{ .env }}
Component environment variables from the env section.
{{ .backend }}
Backend configuration.
{{ .backend_type }}
Backend type (e.g., s3, azurerm).
{{ .providers }}
Provider configurations.
{{ .metadata }}
Component metadata.
{{ .namespace }}
Namespace context variable.
{{ .tenant }}
Tenant context variable.
{{ .environment }}
Environment context variable.
{{ .stage }}
Stage context variable.
{{ .region }}
Region context variable (if defined in vars).
{{ .atmos_component }}
Atmos component name.
{{ .atmos_stack }}
Atmos stack name.
{{ .component }}
Final component name (after inheritance resolution).
{{ .workspace }}
Terraform workspace name.

Template Example

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

components:
terraform:
vpc:
vars:
environment: prod
vpc_cidr: "10.0.0.0/16"
availability_zones:
- us-east-1a
- us-east-1b
generate:
context.tf: |
# Generated by Atmos - DO NOT EDIT
locals {
atmos_stack = "{{ .atmos_stack }}"
atmos_component = "{{ .atmos_component }}"
environment = "{{ .vars.environment }}"
}

Auto-Generation

Enable automatic file generation during terraform commands by setting auto_generate_files in your atmos.yaml:

atmos.yaml

components:
terraform:
auto_generate_files: true

When enabled, Atmos generates files from the generate section before executing any terraform command (plan, apply, etc.).

Examples

Generate Locals from Variables

Create a locals.tf that mirrors select variables:

components:
terraform:
eks:
vars:
cluster_name: acme-prod
cluster_version: "1.28"
node_groups:
default:
instance_type: m5.large
desired_size: 3
generate:
locals.tf:
locals:
cluster_name: "{{ .vars.cluster_name }}"
cluster_version: "{{ .vars.cluster_version }}"
environment: "{{ .vars.environment }}"

Generate Multiple Files

stacks/catalog/vpc/defaults.yaml

components:
terraform:
vpc:
generate:
# HCL locals file
locals.tf:
locals:
environment: "{{ .vars.environment }}"
stage: "{{ .stage }}"

# JSON configuration
atmos-metadata.json:
stack: "{{ .atmos_stack }}"
component: "{{ .atmos_component }}"
workspace: "{{ .workspace }}"

# Markdown documentation
README.md: |
# {{ .atmos_component }}

This component is deployed to the `{{ .atmos_stack }}` stack.

## Variables

- Environment: {{ .vars.environment }}
- Stage: {{ .stage }}

Conditional Content with Templates

Use Go template conditionals for dynamic content:

components:
terraform:
vpc:
vars:
enable_nat_gateway: true
single_nat_gateway: false
generate:
nat-config.tf: |
locals {
{{ if .vars.enable_nat_gateway }}
nat_gateway_enabled = true
{{ if .vars.single_nat_gateway }}
nat_gateway_count = 1
{{ else }}
nat_gateway_count = length(var.availability_zones)
{{ end }}
{{ else }}
nat_gateway_enabled = false
nat_gateway_count = 0
{{ end }}
}

Component Inheritance with Generate

The generate section is inherited and merged like other component sections:

stacks/catalog/vpc/_defaults.yaml
components:
terraform:
vpc/defaults:
metadata:
type: abstract
generate:
locals.tf:
locals:
managed_by: Atmos

Cleaning Generated Files

Remove generated files with the --clean flag:

# Clean generated files for a single component
atmos terraform generate files vpc -s prod-ue2 --clean

# Clean generated files for all components
atmos terraform generate files --all --clean

Best Practices

  1. Use for Environment-Specific Values: Generate files for values that vary by environment rather than hardcoding in modules.

  2. Add to .gitignore: Generated files should not be committed to version control.

  3. Document Generated Files: Add comments indicating the file is generated and should not be edited manually.

  4. Use Consistent Naming: Establish naming conventions for generated files (e.g., *.generated.tf).

  5. Leverage Inheritance: Define common generate patterns in catalog defaults and inherit them.

  6. Preview Before Applying: Use --dry-run to preview what will be generated.