Import Basics
Imports are how you keep your stack configurations DRY (Don't Repeat Yourself). Instead of copying the same settings into every stack file, you define them once and import them where needed.
Think of imports like #include in C or import in Python—you're bringing configuration from other files into the current one.
Your First Import
Let's say you have common tags that should apply to all resources in all environments:
stacks/globals.yaml
Now any stack can import these tags:
stacks/dev.yaml
The vpc component in the dev stack now has access to all the tags from globals.yaml, plus its own variables.
The .yaml extension is optional in imports. - globals and - globals.yaml both work.
How Imports Work
When Atmos processes a stack file, it:
- Reads the imports list (top to bottom)
- Loads each imported file (recursively processing their imports too)
- Deep merges all configurations into one unified structure
- Applies the current file's configuration on top
The result is a single, merged configuration that behaves like one big YAML file.
Import Order Matters
Files are processed sequentially. Later imports override earlier ones.
stacks/aws-defaults.yaml
stacks/gcp-defaults.yaml
stacks/my-stack.yaml
Order changed:
stacks/my-stack.yaml
Multiple Imports
You can import as many files as you need:
stacks/prod.yaml
All four files merge together, with later imports overriding earlier ones, and the current file overriding all imports.
Organizing Imports
A common pattern is to create a _defaults directory for shared configuration:
stacks/
├── _defaults/
│ ├── globals.yaml
│ ├── aws.yaml
│ └── tags.yaml
├── dev.yaml
├── staging.yaml
└── prod.yaml
stacks/_defaults/globals.yaml
stacks/dev.yaml
The _defaults/ directory is just a convention. You can organize imports however makes sense for your project.
What Gets Merged?
Imports merge everything in the YAML structure:
- Top-level
vars - Component configurations
- Backend settings
- Metadata
- Any custom keys you add
stacks/base.yaml
stacks/dev.yaml
After merge:
vars:
namespace: myapp # From base
environment: dev # From dev
components:
terraform:
vpc:
vars:
enable_dns: true # From base
cidr_block: "10.0.0.0/16" # From dev
Common Import Patterns
1. Global + Regional + Environment
stacks/prod-us-east-1.yaml
2. Shared Component Defaults
stacks/_defaults/vpc-defaults.yaml
stacks/dev.yaml
3. Layered Configuration
import:
- _defaults/globals # Layer 1: Global
- _defaults/aws # Layer 2: Provider
- _defaults/networking # Layer 3: Domain
- _defaults/prod # Layer 4: Environment
Each layer adds or overrides settings from the previous layers.
Imports vs Inheritance
Confused about the difference?
- Imports
- Bring entire files into the current stack. All settings merge together. Use for sharing common configuration across stacks.
- Inheritance
- Make one component extend another component's configuration. Use for component variations (e.g., "vpc" extends "vpc-base").
We'll cover inheritance in the next section. For now, focus on imports for file-level reuse.
Key Takeaways
- Imports bring configuration from other files into the current stack
- Order matters - later imports override earlier ones
- Deep merge combines all settings into one unified structure
- Use for DRY configuration - define once, import everywhere
- Organize in
_defaults/for clarity (optional convention)
What's Next
Imports get you far, but sometimes you need component-level reuse. That's where inheritance comes in:
- Learn about Inheritance - Create component variations
- Organize your Stacks - Patterns for large projects
- Advanced Imports - Templates, filters, and more