Component Catalog Patterns
The Component Catalog Patterns are a collection of strategies for organizing and managing reusable component configurations across multiple stacks. These patterns enable you to maintain DRY (Don't Repeat Yourself) configuration while providing flexibility for customization across different environments, regions, and organizational units.
The Component Catalog is one of Atmos's most powerful features, allowing you to create a library of pre-configured components that can be easily imported and customized for different deployment contexts. Whether you're managing a simple multi-environment setup or a complex multi-organization architecture, these patterns help you maintain consistency while avoiding configuration duplication.
You will learn
- Creating a centralized library of reusable component configurations
- Using catalogs to maintain consistency across environments while allowing customization
- Combining catalogs with mixins for powerful configuration inheritance
- Leveraging templates for dynamic component generation
- Understanding when to use catalogs vs inline configuration
Available Patterns
The Component Catalog patterns provide different approaches for organizing and managing component configurations:
Core Pattern: Basic Component Catalog
The foundation pattern that establishes a centralized library of component configurations. This pattern creates a mirror structure of your Terraform components in the stacks/catalog directory, making it easy to find and manage default configurations.
Advanced Patterns
1. Component Catalog with Mixins
Combines the Component Catalog pattern with mixins to create powerful, multi-layered configuration inheritance. This pattern is ideal for complex organizational structures where you need to share configuration across multiple dimensions (regions, environments, teams).
2. Component Catalog Template
Uses Go templates within catalog configurations to dynamically generate component settings. This pattern enables sophisticated configuration logic and reduces repetition when dealing with patterns in your infrastructure.
Use-cases
Use the Component Catalog pattern when:
-
You have many components that are provisioned in multiple stacks (many OUs, accounts, regions) with different configurations for each stack
-
You need to make the components' default configurations reusable across different stacks
-
You want the component catalog folders structures to mirror the Terraform components folder structure to make it easy to find and manage
-
You want to keep the configurations DRY
Benefits
The Component Catalog pattern provides the following benefits:
-
The defaults for the components are defined in just one place (in the catalog) making the entire configuration DRY
-
The defaults for the components are reusable across many environments by using hierarchical imports
-
It's easy to add a new manifest in the component's catalog to enable a new component's feature, then import the manifest into the corresponding stacks where the feature is required
Design Pattern
The Component Catalog pattern prescribes the following:
-
For each Terraform component, create a folder with the same name in
stacks/catalogto make it symmetrical and easy to find. For example, thestacks/catalog/vpcfolder should mirror thecomponents/terraform/vpcfolder. -
In the component's catalog folder, create
defaults.yamlmanifest with all the default values for the component (the defaults that can be reused across multiple environments). Define all the required Atmos sections, e.g.metadata,settings,vars,env. -
In the component's catalog folder, add other manifests for different combinations of component configurations. We refer to them as archetype manifests. Each archetype can import the
defaults.yamlfile to reuse the default values and make the entire config DRY. For example:stacks/catalog/vpc/disabled.yaml- component manifest with the component disabled (vars.enabled: false)stacks/catalog/vpc/dev.yaml- component manifest with the settings related to thedevaccountstacks/catalog/vpc/staging.yaml- component manifest with the settings related to thestagingaccountstacks/catalog/vpc/prod.yaml- component manifest with the settings related to theprodaccountstacks/catalog/vpc/ue2.yaml- component manifest with the settings forus-east-2regionstacks/catalog/vpc/uw2.yaml- component manifest with the settings forus-west-2regionstacks/catalog/vpc/feature-1.yaml- component manifest withfeature-1setting enabled
Having the dev, staging, prod, ue2 and uw2 manifests in the component's catalog makes the most sense for multi-org, multi-OU and/or
multi-region architectures, such that there will be multiple dev/staging/prod or region configurations, which get imported into multiple Org/OU
top-level stack manifests.
-
After we have defined the manifests for different use-cases, we import them into different top-level stacks depending on a particular use-case. For example:
- import the
catalog/vpc/ue2.yamlmanifest into thestacks/mixins/region/us-east-2.yamlmixin since we need thevpccomponent with theus-east-2region-related config provisioned in the region - import the
catalog/vpc/uw2.yamlmanifest into thestacks/mixins/region/us-west-2.yamlmixin since we need thevpccomponent with theus-west-2region-related config provisioned in the region - import the
catalog/vpc/dev.yamlmanifest into thestacks/orgs/acme/plat/dev/us-east-2.yamltop-level stack since we need thevpccomponent with the dev-related config provisioned in the stack - import the
catalog/vpc/prod.yamlmanifest into thestacks/orgs/acme/plat/prod/us-east-2.yamltop-level stack since we need thevpccomponent with the prod-related config provisioned in the stack - import the
catalog/vpc/staging.yamlmanifest into thestacks/orgs/acme/plat/staging/us-east-2.yamltop-level stack since we need thevpccomponent with the dev-related config provisioned in the stack - import the
catalog/vpc/disabled.yamlmanifest into a stack where we want thevpccomponent to be disabled (e.g. temporarily until it's needed) - etc.
- import the
Example
The following example shows the Atmos stack and component configurations to provision the vpc and vpc-flow-logs-bucket components into
a multi-account, multi-region environment. The components' configurations for each account and region are defined in the components' catalog.
│ # Centralized stacks configuration (stack manifests)
├── stacks
│ └── catalog # component-specific defaults
│ ├── vpc
│ │ ├── defaults.yaml
│ │ ├── disabled.yaml
│ │ ├── dev.yaml
│ │ ├── prod.yaml
│ │ ├── staging.yaml
│ │ ├── ue2.yaml
│ │ └── uw2.yaml
│ └── vpc-flow-logs-bucket
│ ├── defaults.yaml
│ └── disabled.yaml
│ # Centralized components configuration
└── components
└── terraform # Terraform components (a.k.a Terraform "root" modules)
├── vpc
└── vpc-flow-logs-bucket
Add the following minimal configuration to atmos.yaml CLI config file :
components:
terraform:
base_path: "components/terraform"
stacks:
base_path: "stacks"
name_pattern: "{tenant}-{environment}-{stage}"
included_paths:
# Tell Atmos to search for the top-level stack manifests in the `orgs` folder and its sub-folders
- "orgs/**/*"
excluded_paths:
# Tell Atmos that the `defaults` folder and all sub-folders don't contain top-level stack manifests
- "defaults/**/*"
schemas:
jsonschema:
base_path: "stacks/schemas/jsonschema"
opa:
base_path: "stacks/schemas/opa"
atmos:
manifest: "stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json"
Add the following configuration to the stacks/catalog/vpc-flow-logs-bucket/defaults.yaml manifest:
components:
terraform:
vpc-flow-logs-bucket:
metadata:
# Point to the Terraform component
component: vpc-flow-logs-bucket
vars:
enabled: true
name: "vpc-flow-logs"
traffic_type: "ALL"
force_destroy: true
lifecycle_rule_enabled: false
Add the following default configuration to the stacks/catalog/vpc/defaults.yaml manifest:
components:
terraform:
vpc:
metadata:
# Point to the Terraform component
component: vpc
settings:
# All validation steps must succeed to allow the component to be provisioned
validation:
validate-vpc-component-with-jsonschema:
schema_type: jsonschema
schema_path: "vpc/validate-vpc-component.json"
description: Validate 'vpc' component variables using JSON Schema
check-vpc-component-config-with-opa-policy:
schema_type: opa
schema_path: "vpc/validate-vpc-component.rego"
module_paths:
- "catalog/constants"
description: Check 'vpc' component configuration using OPA policy
vars:
enabled: true
name: "common"
max_subnet_count: 3
map_public_ip_on_launch: true
assign_generated_ipv6_cidr_block: false
nat_gateway_enabled: true
nat_instance_enabled: false
vpc_flow_logs_enabled: true
vpc_flow_logs_traffic_type: "ALL"
vpc_flow_logs_log_destination_type: "s3"
nat_eip_aws_shield_protection_enabled: false
subnet_type_tag_key: "acme/subnet/type"
ipv4_primary_cidr_block: 10.9.0.0/18
Add the following default configuration to the stacks/catalog/vpc/ue2.yaml manifest:
import:
- catalog/vpc/defaults
components:
terraform:
vpc:
vars:
availability_zones:
- us-east-2a
- us-east-2b
- us-east-2c
Add the following default configuration to the stacks/catalog/vpc/uw2.yaml manifest:
import:
- catalog/vpc/defaults
components:
terraform:
vpc:
vars:
availability_zones:
- us-west-2a
- us-west-2b
- us-west-2c
Add the following default configuration to the stacks/catalog/vpc/dev.yaml manifest:
components:
terraform:
vpc:
vars:
ipv4_primary_cidr_block: 10.7.0.0/18
Add the following default configuration to the stacks/catalog/vpc/staging.yaml manifest:
components:
terraform:
vpc:
vars:
ipv4_primary_cidr_block: 10.9.0.0/18
Add the following default configuration to the stacks/catalog/vpc/prod.yaml manifest:
components:
terraform:
vpc:
vars:
ipv4_primary_cidr_block: 10.8.0.0/18
# In `prod`, don't map public IPs on launch
# Override `map_public_ip_on_launch` from the defaults
map_public_ip_on_launch: false
Import stacks/catalog/vpc/ue2.yaml into the stacks/mixins/region/us-east-2.yaml manifest:
import:
# Import the `ue2` manifest with `vpc` configuration for `us-east-2` region
- catalog/vpc/ue2
# All accounts (stages) in `us-east-2` region will have the `vpc-flow-logs-bucket` component
- catalog/vpc-flow-logs-bucket/defaults
vars:
region: us-east-2
environment: ue2
# Other defaults for the `us-east-2` region
Import stacks/catalog/vpc/uw2.yaml into the stacks/mixins/region/us-west-2.yaml manifest:
import:
# Import the `uw2` manifest with `vpc` configuration for `us-west-2` region
- catalog/vpc/uw2
# All accounts (stages) in `us-west-2` region will have the `vpc-flow-logs-bucket` component
- catalog/vpc-flow-logs-bucket/defaults
vars:
region: us-west-2
environment: uw2
# Other defaults for the `us-west-2` region
Import mixins/region/us-east-2 and stacks/catalog/vpc/dev.yaml into the stacks/orgs/acme/plat/dev/us-east-2.yaml top-level stack:
import:
- orgs/acme/plat/dev/_defaults
- mixins/region/us-east-2
# Override the `vpc` component configuration for `dev` by importing the `catalog/vpc/dev` manifest
- catalog/vpc/dev
Import mixins/region/us-west-2 and stacks/catalog/vpc/dev.yaml into the stacks/orgs/acme/plat/dev/us-west-2.yaml top-level stack:
import:
- orgs/acme/plat/dev/_defaults
- mixins/region/us-west-2
# Override the `vpc` component configuration for `dev` by importing the `catalog/vpc/dev` manifest
- catalog/vpc/dev
Import mixins/region/us-east-2 and stacks/catalog/vpc/staging.yaml into the stacks/orgs/acme/plat/staging/us-east-2.yaml top-level stack:
import:
- orgs/acme/plat/staging/_defaults
- mixins/region/us-east-2
# Override the `vpc` component configuration for `staging` by importing the `catalog/vpc/staging` manifest
- catalog/vpc/staging
Import mixins/region/us-west-2 and stacks/catalog/vpc/staging.yaml into the stacks/orgs/acme/plat/staging/us-west-2.yaml top-level stack:
import:
- orgs/acme/plat/staging/_defaults
- mixins/region/us-west-2
# Override the `vpc` component configuration for `staging` by importing the `catalog/vpc/staging` manifest
- catalog/vpc/staging
Import mixins/region/us-east-2 and stacks/catalog/vpc/prod.yaml into the stacks/orgs/acme/plat/prod/us-east-2.yaml top-level stack:
import:
- orgs/acme/plat/prod/_defaults
- mixins/region/us-east-2
# Override the `vpc` component configuration for `prod` by importing the `catalog/vpc/prod` manifest
- catalog/vpc/prod
Import mixins/region/us-west-2 and stacks/catalog/vpc/prod.yaml into the stacks/orgs/acme/plat/prod/us-west-2.yaml top-level stack:
import:
- orgs/acme/plat/prod/_defaults
- mixins/region/us-west-2
# Override the `vpc` component configuration for `prod` by importing the `catalog/vpc/prod` manifest
- catalog/vpc/prod
Limitations
The Component Catalog pattern has the following limitations and drawbacks:
- Although it's always recommended to use, the catalog structure described by the pattern can be complex for basic infrastructures, e.g. for a very simple organizational structure (one organization and OU), and just a few components deployed into a few accounts and regions
To address the limitations of the Component Catalog Design Pattern when you are provisioning a very basic infrastructure, use the following patterns:
Related Patterns
Component Catalog Variations
- Component Catalog with Mixins - Combine catalogs with mixins for multi-dimensional inheritance
- Component Catalog Template - Use templates for dynamic configuration generation
Alternative Approaches
- Component Inheritance - Direct component inheritance without catalogs
- Inline Component Configuration - Configure components directly in stack files
- Inline Component Customization - Customize components inline for simple cases
Organizational Patterns
- Organizational Structure Configuration - Structure catalogs for complex organizations