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
61 changes: 57 additions & 4 deletions examples/snippets/.claude/skills/developing-components/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,20 @@ description:

# Developing Components

> **Scope:** This skill is generic and applies to any Cloud Posse reference architecture project. It covers patterns for
> vendoring and creating Terraform components that are consistent across all customers.

Components are opinionated Terraform root modules that implement a specific AWS resource with predefined conventions.

## Before Creating a New Component

**Always check for existing components first.** Creating new components adds maintenance burden.

### 1. Check Local Generic Components
### 1. Check Local Components

```bash
ls components/terraform/
```

Many use cases can be solved by configuring existing generic components via catalog:

Expand All @@ -29,12 +36,58 @@ Browse https://docs.cloudposse.com/components/library/ for pre-built components.
- `aurora-postgres`, `rds` - Databases
- `elasticache-redis` - Caching
- `ecs`, `ecs-service` - Container workloads
- `cloudwatch-logs`, `sns-topic`, `sqs-queue` - AWS services
- `s3-bucket`, `dynamodb`, `sqs-queue` - Storage and messaging
- `cloudwatch-logs`, `sns-topic` - Monitoring and notifications

#### Cloud Posse Component Sources

| Resource | Location |
| ---------------------- | ---------------------------------------------------------- |
| Component Library Docs | https://docs.cloudposse.com/components/library/ |
| Component Repositories | `github.com/cloudposse-terraform-components/aws-<service>` |
| Mixins Repository | `github.com/cloudposse-terraform-components/mixins` |

**Find latest version:**

```bash
gh release view --repo cloudposse-terraform-components/aws-<component> --json tagName
```

#### Vendoring a Cloud Posse Component

1. Create the component directory and `component.yaml`:

```bash
mkdir -p components/terraform/<component-name>
```

2. Create `components/terraform/<component-name>/component.yaml`:

<!-- prettier-ignore-start -->

```yaml
apiVersion: atmos/v1
kind: ComponentVendorConfig
spec:
source:
uri: github.com/cloudposse-terraform-components/aws-<component>.git//src?ref={{ .Version }}
version: <latest-version> # Use gh release view to find this
included_paths:
- "**/**"
excluded_paths:
- "providers.tf"
mixins:
# Use provider mixin without account-map dependency (for single-account deployments)
- uri: https://raw.githubusercontent.com/cloudposse-terraform-components/mixins/{{ .Version }}/src/mixins/provider-without-account-map.tf
version: v0.3.2
filename: providers.tf
```

<!-- prettier-ignore-end -->

To vendor a Cloud Posse component:
3. Pull the component:

```bash
# Add to component.yaml in the component directory, then:
atmos vendor pull -c <component-name>
```

Expand Down
141 changes: 114 additions & 27 deletions examples/snippets/.claude/skills/developing-stacks/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,62 @@ description: >-

# Developing Stacks

> **Scope:** This skill is specific to the **acme** infrastructure repository. It documents the
> stack structure, naming conventions, and deployment patterns used here. For generic component development, see
> `developing-components`.

Guide for configuring Atmos stacks to deploy Terraform components across environments.

## Stack Architecture Overview

Stacks follow a hierarchical structure with inheritance at multiple levels:
This repository uses a multi-tenant, multi-stage stack structure:

```
stacks/
├── orgs/acme/ # Organization root
│ ├── _defaults.yaml # Org-wide defaults (namespace, backend, account_map)
│ ├── plat/ # Platform tenant
│ │ ├── _defaults.yaml # Tenant defaults (tenant: plat)
│ │ ├── dev/ # Dev stage
│ │ │ ├── _defaults.yaml # Stage defaults + auth identity
│ │ │ └── us-east-2/ # Region
│ │ │ ├── foundation.yaml
│ │ │ ├── platform.yaml
│ │ │ └── app.yaml
├── catalog/ # Component defaults library
├── orgs/acme/ # Organization root (namespace: acme)
│ ├── _defaults.yaml # Org-wide defaults (namespace, backend, account_map)
│ ├── core/ # Core tenant (shared infrastructure)
│ │ ├── _defaults.yaml # Tenant defaults (tenant: core)
│ │ ├── root/ # Root account stage
│ │ │ ├── _defaults.yaml # Stage defaults + auth identity
│ │ │ └── global-region/ # Global region (us-east-1)
│ │ │ └── foundation.yaml
│ │ ├── auto/ # Automation account
│ │ ├── artifacts/ # Artifacts account (ECR, S3)
│ │ ├── audit/ # Audit/logging account
│ │ ├── dns/ # DNS account
│ │ ├── network/ # Network account (TGW, VPN)
│ │ └── security/ # Security account
│ └── plat/ # Platform tenant (workloads)
│ ├── _defaults.yaml # Tenant defaults (tenant: plat)
│ ├── dev/ # Dev stage
│ │ ├── _defaults.yaml # Stage defaults + auth identity
│ │ ├── global-region/ # Global resources (IAM)
│ │ │ └── foundation.yaml
│ │ └── us-east-1/ # Primary region
│ │ ├── foundation.yaml # VPC, networking
│ │ ├── platform.yaml # ECS/EKS, databases
│ │ └── app.yaml # Application resources
│ ├── staging/ # Staging stage
│ ├── prod/ # Production stage
│ └── sandbox/ # Sandbox stage
├── catalog/ # Component defaults library
│ ├── vpc/defaults.yaml
│ ├── ecs/defaults.yaml
│ ├── eks/cluster/defaults.yaml
│ └── ...
└── mixins/ # Reusable fragments
├── region/us-east-2.yaml
└── mixins/ # Reusable fragments
├── region/us-east-1.yaml
└── stage/dev.yaml
```

**Stack name format:** `{namespace}-{tenant}-{region_short}-{stage}`

Examples for this repository:
- `acme-core-use1-root` - Core root account in us-east-1
- `acme-plat-use1-dev` - Platform dev in us-east-1
- `acme-plat-use1-prod` - Platform prod in us-east-1

## Core Patterns

### 1. Catalog Defaults (Recommended Starting Point)
Expand Down Expand Up @@ -66,10 +95,10 @@ components:
Import the catalog and inherit from the abstract component in your target stack:

```yaml
# stacks/orgs/acme/plat/dev/us-east-2/foundation.yaml
# stacks/orgs/acme/plat/dev/us-east-1/foundation.yaml
import:
- orgs/acme/plat/dev/_defaults
- mixins/region/us-east-2
- mixins/region/us-east-1
- catalog/vpc/defaults

components:
Expand All @@ -80,7 +109,7 @@ components:
inherits:
- vpc/defaults # Inherits from the abstract component
vars:
ipv4_primary_cidr_block: 10.0.0.0/16 # Override for this environment
ipv4_primary_cidr_block: 10.2.0.0/16 # Dev environment CIDR
```

**Inheritance merging:**
Expand Down Expand Up @@ -146,7 +175,7 @@ terraform:
backend_type: s3
backend:
s3:
bucket: acme-core-use2-root-tfstate
bucket: acme-core-use1-root-tfstate
# ...

# stacks/orgs/acme/plat/_defaults.yaml (tenant level)
Expand Down Expand Up @@ -215,11 +244,11 @@ components:
# Validate the stack configuration
atmos validate stacks

# See the resolved configuration
atmos describe component <component> -s <stack>
# See the resolved configuration (example for dev)
atmos describe component <component> -s acme-plat-use1-dev

# Plan the deployment
atmos terraform plan <component> -s <stack>
atmos terraform plan <component> -s acme-plat-use1-dev
```

## Stack File Organization
Expand All @@ -236,6 +265,64 @@ Stack files are organized by layer:

## Common Patterns

### Catalog Organization for Multiple Purposes

When deploying multiple instances of the same component for different purposes, organize the catalog with abstract
defaults and purpose-specific files that inherit from them:

```
stacks/catalog/
└── <component>/
├── defaults.yaml # Abstract base component (not deployed directly)
└── <purpose>.yaml # Purpose-specific configuration
```

**Abstract defaults file** (`stacks/catalog/<component>/defaults.yaml`):

```yaml
components:
terraform:
<component>/defaults:
metadata:
type: abstract # Not deployed directly
component: <component> # Points to Terraform component
vars:
enabled: true
# Organization-wide defaults for this component
```

**Purpose-specific catalog file** (`stacks/catalog/<component>/<purpose>.yaml`):

```yaml
import:
- catalog/<component>/defaults

components:
terraform:
<component>/<purpose>:
metadata:
component: <component> # Points to Terraform component
inherits:
- <component>/defaults # Inherits from abstract component
vars:
# Only include values that differ from defaults (keep it DRY)
name: <purpose>-specific-name
some_setting: override-value # Overrides default
```

**Import in target stack:**

```yaml
import:
- catalog/<component>/<purpose>
```

**Deploy:**

```bash
atmos terraform plan <component>/<purpose> -s acme-plat-use1-dev
```

### Environment-Specific CIDR Blocks

```yaml
Expand All @@ -248,23 +335,23 @@ components:
vars:
# No CIDR here - must be specified per environment

# stacks/orgs/acme/plat/dev/us-east-2/foundation.yaml
# stacks/orgs/acme/plat/dev/us-east-1/foundation.yaml
components:
terraform:
vpc:
metadata:
inherits: [vpc/defaults]
vars:
ipv4_primary_cidr_block: 10.0.0.0/16
ipv4_primary_cidr_block: 10.2.0.0/16

# stacks/orgs/acme/plat/prod/us-east-2/foundation.yaml
# stacks/orgs/acme/plat/prod/us-east-1/foundation.yaml
components:
terraform:
vpc:
metadata:
inherits: [vpc/defaults]
vars:
ipv4_primary_cidr_block: 10.1.0.0/16
ipv4_primary_cidr_block: 10.0.0.0/16
```

### Cross-Component Dependencies
Expand Down Expand Up @@ -314,10 +401,10 @@ components:

```bash
# See fully resolved configuration
atmos describe component <component> -s <stack>
atmos describe component <component> -s acme-plat-use1-dev

# See all components in a stack
atmos describe stacks -s <stack>
atmos describe stacks -s acme-plat-use1-dev

# Validate all stacks
atmos validate stacks
Expand Down
1 change: 1 addition & 0 deletions examples/snippets/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ atmos terraform clean <component> -s <stack> # Destroys local .terraform and
## Important Notes

- Uses **OpenTofu** (not Terraform) - `command: "tofu"` in atmos.yaml
- **Never run `tofu init` or `terraform init` directly** in component directories. Atmos handles initialization automatically when running `atmos terraform plan/apply`.
- Prefer `!terraform.state` in stack YAML over `remote-state.tf` files
- Prefer existing generic components (`iam-role`, `s3-bucket`, `lambda`) over creating new ones
- Set `account_map_enabled: false` - uses static `account_map` variable, not account-map component
Expand Down
Loading