Skip to main content

Using Custom Component Types

Beyond the native component types, Atmos lets you define custom component types so you can manage any tool—AWS CDK, CloudFormation, Pulumi, Bicep, database migrations, and more—with the same stack-based configuration system used for Terraform, Helmfile, and Packer.

Custom component types are defined through custom commands. Unlike the native types, which ship with built-in orchestration, a custom type is one you wire up yourself: you declare the type on a custom command and supply the execution steps, while Atmos handles stack resolution, inheritance, and configuration merging exactly as it does for native components.

How It Works

Define a component.type on a custom command and tell Atmos which argument provides the component name and which provides the stack name. Atmos then looks up components.<type>.<name> from your stack manifests and exposes the fully resolved configuration via {{ .Component.* }}.

# atmos.yaml
commands:
- name: script
description: "Run script components"
arguments:
- name: component
type: component # Provides the component name
required: true
flags:
- name: stack
shorthand: s
semantic_type: stack # Provides the stack name
required: true
component:
type: script # Your custom component type
steps:
- 'echo "App: {{ .Component.vars.app_name }}"'
- 'echo "Version: {{ .Component.vars.version }}"'

Configure the component in stack manifests just like a native type—with full imports and inheritance:

# stacks/deploy/dev.yaml
components:
script: # Matches component.type
deploy-app:
vars:
app_name: "myapp"
version: "1.0.0"

Run it:

atmos script deploy-app -s dev
# App: myapp
# Version: 1.0.0

Global vars, settings, and env are merged automatically, and a component's env section is exported as real environment variables—making it straightforward to pass secrets securely.

Native vs. Custom

AspectNative types (Terraform/Helmfile/Packer/Ansible)Custom types
OrchestrationBuilt into AtmosYou supply the steps
DefinitionAlways availableDefined via a custom command
Stack configurationcomponents.<type>.<name>components.<type>.<name>
Configuration accessNative flags/varfiles{{ .Component.* }} templates

Try It

Explore a complete, working example that defines a custom script component type and configures it through stacks.

Custom Components Example

This example demonstrates how to define custom component types in Atmos using custom commands.

Overview

Custom component types allow you to extend Atmos beyond the built-in component types (Terraform, Helmfile, Packer). You can define any component type (e.g., script, ansible, manifest) and access its configuration from stack files via Go templates.

Structure

examples/custom-components/
├── atmos.yaml                           # Atmos configuration with custom command
├── components/
│   └── script/
│       └── deploy-app/
│           └── deploy.sh                # Example script (not executed)
└── stacks/
    ├── catalog/
    │   └── script/
    │       └── deploy-app.yaml          # Base component configuration
    └── deploy/
        └── dev.yaml                     # Stack with overrides

Usage

  1. Build atmos (from repo root):

    make build
  2. Run the custom command:

    cd examples/custom-components
    ../../build/atmos script deploy-app -s dev
  3. Expected output:

    Component: deploy-app
    Stack: dev
    App: myapp
    Version: 1.0.0
    Replicas: 1
    Env: deploying v1.0.0 to us-east-1
    

How It Works

  1. Custom Command Definition (atmos.yaml):

    • The script command defines a custom component type
    • Arguments and flags with type: component and semantic_type: stack identify which values to use
    • The component: section specifies the component type name
  2. Stack Configuration (stacks/):

    • Components are defined under components.script.<name>
    • Standard Atmos inheritance and overrides work as expected
  3. Template Access:

    • Steps can access component config via {{ .Component.* }}
    • All component sections are available: vars, settings, metadata, etc.
  4. Environment Variables:

    • The component env section is exported as real environment variables to every step, just like the built-in terraform/helmfile/packer/ansible component types.
    • Steps (and scripts they invoke) read them directly as $APP_VERSION, $DEPLOY_REGION, etc.
    • For sensitive values, use !secret NAME in the env section so the value resolves from a secret backend and is masked in output — never inline a secret into the command string. See Passing secrets.