Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 110 additions & 110 deletions NOTICE

Large diffs are not rendered by default.

Large diffs are not rendered by default.

80 changes: 69 additions & 11 deletions examples/locals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ Learn more about [Locals](https://atmos.tools/stacks/locals).

## What You'll See

- **Basic locals**: Define reusable values within a file
- **Dependency resolution**: Locals can reference other locals
- **Context access**: Locals can access `settings`, `vars`, and `env` from the same file
- **File-scoped isolation**: Each stack file has independent locals
- **Basic locals** — define reusable values within a file
- **Dependency resolution** — locals reference other locals, resolved via topological sort
- **Context access** — locals use `{{ .settings.X }}`, `{{ .vars.X }}` from the same file
- **Sprig functions** — pipe syntax like `{{ .locals.namespace | upper }}`
- **Complex values** — maps with templates for resource tags
- **Multiple components** — the same locals shared across components in a file
- **File-scoped isolation** — dev.yaml and prod.yaml have independent locals

## Try It

Expand All @@ -22,14 +25,69 @@ atmos describe locals -s dev
# View resolved locals for a specific component
atmos describe locals myapp -s dev

# Compare dev vs prod
atmos describe locals myapp -s prod
# See how locals flow into component vars
atmos describe component myapp -s dev

# Compare dev vs prod (same patterns, different values)
atmos describe component myapp -s prod

# Worker component appends a suffix to locals
atmos describe component myapp-worker -s dev
```

## Features Demonstrated

### 1. Basic Locals and References

```yaml
locals:
namespace: acme
environment: development
name_prefix: "{{ .locals.namespace }}-{{ .locals.environment }}"
```

Locals are resolved in dependency order — `name_prefix` waits for `namespace` and `environment`.

### 2. Settings and Vars Access

```yaml
settings:
version: v1
vars:
stage: dev
locals:
app_version: "{{ .settings.version }}" # → "v1"
stage_name: "{{ .vars.stage }}" # → "dev"
```

### 3. Sprig Functions

```yaml
locals:
namespace_upper: '{{ .locals.namespace | upper }}' # → "ACME"
```

### 4. Complex Values (Maps)

```yaml
locals:
default_tags:
Namespace: "{{ .locals.namespace }}"
Environment: "{{ .locals.environment }}"
Team: "{{ .settings.team }}"
ManagedBy: Atmos
```

### 5. File-Scoped Isolation

Each stack file has its own locals. Even though both `dev.yaml` and `prod.yaml`
define `namespace: acme`, they are completely separate — changing one never
affects the other. Locals never propagate across file boundaries via imports.

## Key Files

| File | Purpose |
|------|---------|
| `stacks/deploy/dev.yaml` | Development stack with locals |
| `stacks/deploy/prod.yaml` | Production stack with locals |
| `components/terraform/myapp/main.tf` | Terraform component |
| File | Purpose |
|--------------------------------------|-------------------------------------------|
| `stacks/deploy/dev.yaml` | Dev stack: all locals features |
| `stacks/deploy/prod.yaml` | Prod stack: same patterns, different values |
| `components/terraform/myapp/main.tf` | Mock Terraform component |
31 changes: 18 additions & 13 deletions examples/locals/components/terraform/myapp/main.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
# Mock component for locals demo.
#
# This component outputs the variables it receives, allowing you to see
# how locals are resolved and passed to components.

variable "name" {
type = string
Expand All @@ -24,22 +21,30 @@ variable "tags" {
default = {}
}

output "name" {
description = "Application name"
value = var.name
variable "deploy_target" {
type = string
description = "Deployment target (computed from conditional locals)"
default = "stable"
}

output "environment" {
description = "Environment name"
value = var.environment
variable "managed_by" {
type = string
description = "Tool that manages this resource"
default = "atmos"
}

output "name" {
value = var.name
}

output "full_name" {
description = "Full application name"
value = var.full_name
value = var.full_name
}

output "deploy_target" {
value = var.deploy_target
}

output "tags" {
description = "Resource tags"
value = var.tags
value = var.tags
}
34 changes: 23 additions & 11 deletions examples/locals/stacks/deploy/dev.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Development Environment Stack
#
# This stack demonstrates locals for reducing repetition and building
# computed values. Locals are file-scoped (cannot be accessed from other files).
# Demonstrates locals features in one concise file.
# Locals are file-scoped: they never propagate across file boundaries.

settings:
version: v1
Expand All @@ -10,32 +10,33 @@ settings:
vars:
stage: dev

# Locals can reference other locals, settings, and vars.
locals:
# Basic values
# 1. Basic values
namespace: acme
environment: development

# Reference other locals
# 2. Reference other locals (dependency-ordered via topological sort)
name_prefix: "{{ .locals.namespace }}-{{ .locals.environment }}"

# Access settings
# 3. Access settings and vars from the same file
app_version: "{{ .settings.version }}"

# Access vars
stage_name: "{{ .vars.stage }}"

# Build complex computed values
# 4. Build computed values from other locals
full_name: "{{ .locals.name_prefix }}-{{ .locals.stage_name }}"

# Maps work too
# 5. Sprig functions (pipe syntax)
namespace_upper: '{{ .locals.namespace | upper }}'

# 6. Complex values (maps with templates)
default_tags:
Namespace: "{{ .locals.namespace }}"
Environment: "{{ .locals.environment }}"
Team: "{{ .settings.team }}"
ManagedBy: Atmos

# Components use the resolved locals
# Components use resolved locals via Go templates.
# Locals are NOT included in component output — they are strictly internal.
components:
terraform:
myapp:
Expand All @@ -44,3 +45,14 @@ components:
environment: "{{ .locals.environment }}"
full_name: "{{ .locals.full_name }}"
tags: "{{ .locals.default_tags }}"

# Another component reusing global locals.
# Section-level locals can also be defined under `terraform.locals` when needed.
myapp-worker:
metadata:
component: myapp
vars:
name: "{{ .locals.namespace }}"
environment: "{{ .locals.environment }}"
full_name: "{{ .locals.full_name }}-worker"
tags: "{{ .locals.default_tags }}"
12 changes: 8 additions & 4 deletions examples/locals/stacks/deploy/prod.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Production Environment Stack
#
# This stack shows locals with different values for production.
# Each file has its own isolated locals scope.
# Each file has its own independent locals scope.
# Even though both dev.yaml and prod.yaml define `namespace: acme`,
# they are completely separate — changing one never affects the other.

settings:
version: v2
Expand All @@ -14,11 +15,14 @@ locals:
namespace: acme
environment: production

# Same pattern, different values
# Same patterns as dev.yaml, different values.
name_prefix: "{{ .locals.namespace }}-{{ .locals.environment }}"
full_name: "{{ .locals.name_prefix }}-{{ .vars.stage }}"

# Production-specific tags
# Sprig pipe syntax works too.
namespace_upper: '{{ .locals.namespace | upper }}'

# Production-specific tags with extra fields.
default_tags:
Namespace: "{{ .locals.namespace }}"
Environment: "{{ .locals.environment }}"
Expand Down
2 changes: 1 addition & 1 deletion examples/quick-start-advanced/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ARG GEODESIC_OS=debian
# https://atmos.tools/
# https://github.com/cloudposse/atmos
# https://github.com/cloudposse/atmos/releases
ARG ATMOS_VERSION=1.209.0
ARG ATMOS_VERSION=1.210.0

# Terraform: https://github.com/hashicorp/terraform/releases
ARG TF_VERSION=1.5.7
Expand Down
Loading
Loading