Component Catalog Template
The Component Catalog Template Design Pattern is used when you have an unbounded number of a component's instances provisioned in one environment (the same organization, OU/tenant, account and region). New instances with different settings can be configured and provisioned anytime. The old instances must be kept unchanged and never destroyed.
This is achieved by using Go
Templates in Imports and
Hierarchical Imports with Context.
Use-cases
Use the Component Catalog Template pattern when:
-
You have an unbounded number of a component's instances provisioned in one environment (the same organization, OU/tenant, account and region)
-
New instances of the component with different settings can be configured and provisioned anytime
-
The old instances of the component must be kept unchanged and never destroyed
-
You want to keep the configurations DRY
Benefits
The Component Catalog Template pattern provides the following benefits:
-
All settings for a component are defined in just one place (in the component's template) making the entire configuration DRY
-
Many instances of the component can be provisioned without repeating all the configuration values
-
New Atmos components are generated dynamically
Design Pattern
The Component Catalog Template pattern recommends the following:
-
In the component's catalog folder, create a
Go
template manifest with all the configurations for the component (refer toGo
Templates in Imports for more details) -
Import the
Go
template manifest into a top-level stack many times to configure the component's instances using Hierarchical Imports with Context and providing different template values for each import
Example
Suppose that we have an EKS cluster provisioned in one of the accounts and regions. The cluster is running many different applications, each one requires an IAM role for service accounts (IRSA) with permissions to access various AWS resources.
The Development team can create a new application anytime, and we need to provision a new IRSA in the EKS cluster. We'll use the Component Catalog Template Design Pattern to configure the IAM roles with different settings for each application.
│ # Centralized stacks configuration (stack manifests)
├── stacks
│ └── catalog # component-specific defaults
│ └── eks
│ └── iam-role
│ └── defaults.tmpl
│ # Centralized components configuration
└── components
└── terraform # Terraform components (a.k.a Terraform "root" modules)
└── eks
└── iam-role
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/eks/iam-role/defaults.tmpl
Go
template manifest:
components:
terraform:
eks/iam-role/{{ .app_name }}:
metadata:
# Point to the Terraform component
component: eks/iam-role
vars:
enabled: true
tags:
Service: {{ .app_name }}
service_account_name: {{ .service_account_name }}
service_account_namespace: {{ .service_account_namespace }}
# Example of using the Sprig functions in `Go` templates.
# Refer to https://masterminds.github.io/sprig for more details.
{{ if hasKey . "iam_managed_policy_arns" }}
iam_managed_policy_arns:
{{ range $i, $iam_managed_policy_arn := .iam_managed_policy_arns }}
- '{{ $iam_managed_policy_arn }}'
{{ end }}
{{ - end }}
Import the stacks/catalog/eks/iam-role/defaults.tmpl
manifest template into a top-level stack,
for example stacks/orgs/acme/plat/prod/us-east-2.yaml
, and provide the configuration for each application in the context
object:
import:
- orgs/acme/plat/prod/_defaults
- mixins/region/us-east-2
# This import will dynamically generate a new Atmos component `eks/iam-role/admin-ui`
- path: catalog/eks/iam-role/defaults.tmpl
context:
app_name: "admin-ui"
service_account_name: "admin-ui"
service_account_namespace: "admin"
iam_managed_policy_arns: [ "<arn1>", "<arn2>" ]
# This import will dynamically generate a new Atmos component `eks/iam-role/auth`
- path: catalog/eks/iam-role/defaults.tmpl
context:
app_name: "auth"
service_account_name: "auth"
service_account_namespace: "auth"
iam_managed_policy_arns: [ "<arn3>" ]
# This import will dynamically generate a new Atmos component `eks/iam-role/payment-processing`
- path: catalog/eks/iam-role/defaults.tmpl
context:
app_name: "payment-processing"
service_account_name: "payment-processing"
service_account_namespace: "payments"
iam_managed_policy_arns: [ "<arn4>", "<arn5>" ]
# Add new application configurations here
To provision the Atmos components in the stack, execute the following commands:
atmos terraform apply eks/iam-role/admin-ui --stack plat-ue2-prod
atmos terraform apply eks/iam-role/auth --stack plat-ue2-prod
atmos terraform apply eks/iam-role/payment-processing --stack plat-ue2-prod
Limitations
The Component Catalog Template pattern has the following limitations and drawbacks:
-
Since new Atmos components are generated dynamically, sometimes it's not easy to know the names of the Atmos components that need to be provisioned without looking at the
Go
template and figuring out all the Atmos component names -
With great power comes great responsibility. The Go templating engine leads to infinite possibilities, which makes the stack configs more challenging to maintain and reduces consistency. Try to leverage the inheritance model as much as possible, over templated stack configs.
To address the limitations of the Component Catalog Template Design Pattern, consider using the following patterns:
Related Patterns
- Component Catalog
- Component Catalog with Mixins
- Component Inheritance
- Inline Component Configuration
- Inline Component Customization
- Organizational Structure Configuration