Skip to content
Draft
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
6 changes: 6 additions & 0 deletions .agent/rules/python.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
trigger: always_on
---

Use `uv` to run Python scripts.
Use `ruff` to format and lint the code.
21 changes: 21 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# EasySAM Architecture

EasySAM is a YAML-to-SAM generator that simplifies the development and deployment of serverless applications on AWS.

## High-Level Architecture

![EasySAM Architecture](./architecture.svg)

## Core Components

- **CLI (`cli.py`, `init.py`)**: The entry point for user interactions. It handles project initialization, resource management commands, and coordinates the overall workflow.
- **YAML Loader (`load.py`)**: Responsible for parsing EasySAM YAML files, resolving imports, and expanding environment variables. It creates an internal representation of the desired infrastructure.
- **SAM Generator (`generate.py`)**: The heart of the tool. It translates the EasySAM internal representation into a valid AWS SAM (Serverless Application Model) template. It also performs schema validation and infers necessary configurations.
- **Prismarine Integration**: EasySAM seamlessly integrates with the Prismarine runtime for advanced DynamoDB modeling and type-safe data access.
- **Deployment Pipeline**: EasySAM leverages the AWS SAM CLI for packaging and deploying the generated templates to the AWS Cloud.

## Key Design Principles

1. **Convention over Configuration**: EasySAM promotes a standard project hierarchy (e.g., `backend/`, `common/`) to reduce boilerplate and improve maintainability.
2. **Surgical Updates**: The generator produces precise SAM templates, allowing for targeted infrastructure changes.
3. **Local-First Development**: Features like environment variable expansion and schema validation enable robust local testing before deployment.
2 changes: 2 additions & 0 deletions docs/CLI_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ easysam --environment dev generate . --path ../shared-lib
Options:

- `--path PATH` (repeatable): additional Python import path(s)
- `--no-docker-build-on-win`: Skip adding Docker build metadata to the template on Windows.

Outputs:

Expand All @@ -78,6 +79,7 @@ Options:
- `--sam-tool TEXT`: custom SAM invocation command (default: `uv run sam`)
- `--no-cleanup`: keep copied `common` dependencies after deploy
- `--override-main-template PATH`: use custom Jinja main template
- `--no-docker-build-on-win`: Skip adding Docker build metadata to the template on Windows.

### `delete`

Expand Down
44 changes: 44 additions & 0 deletions docs/RESOURCE_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import:
| `streams` | map | no | Kinesis streams + Firehose destinations |
| `tables` | map | no | DynamoDB table definitions |
| `functions` | map | no | Lambda function definitions |
| `services` | map | no | ECS Fargate service definitions |
| `paths` | map | no | API Gateway integrations |
| `authorizers` | map | no | API authorizer Lambda configuration |
| `import` | list<string> | no | Import directories scanned for `easysam.yaml` |
Expand Down Expand Up @@ -230,6 +231,49 @@ Fields:
- `allow_credentials` (boolean)
- `max_age` (integer)

## Services (ECS Fargate)

EasySAM supports long-running components using AWS ECS Fargate. These are ideal for background workers, polling loops, or containerized web services.

```yaml
services:
poller:
# Source (exactly one required)
image: 1234567890.dkr.ecr.us-east-1.amazonaws.com/my-repo:latest
build: ./poller # path to Dockerfile directory

# Compute
cpu: 256 # Default: 256 (0.25 vCPU)
memory: 512 # Default: 512 MB
count: 1 # Default: 1 (Number of instances)

# Networking
ports:
- 8080

# Permissions & Environment (Consistent with 'functions')
envvars:
POLL_INTERVAL: "19"
tables:
- MyTable
buckets:
- raw-data
queues:
- jobs
streams:
- my-stream
```

Fields:

- `image`: The ECR or public Docker image URI.
- `build`: Path to a directory containing a `Dockerfile`. Relative to the YAML file.
- `cpu`: CPU units (256, 512, 1024, etc.).
- `memory`: Memory in MiB.
- `count`: The desired number of running tasks.
- `ports`: List of container ports to open (no Load Balancer is created automatically; tasks use public IPs by default).
- `envvars`, `tables`, `buckets`, `queues`, `streams`: Standard permission and environment configuration (same as `functions`).

## Paths (API Gateway)

### Lambda integration
Expand Down
29 changes: 29 additions & 0 deletions docs/architecture.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions docs/reports/containers-initial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Gaps & Deficiencies Findings

- VPC/Subnet Customization: Only default VPC public subnets are mentioned. No support
for custom VPCs, private subnets, or security groups—critical for production.
- Service Discovery/Networking: No mention of service discovery, internal-only services, or load balancer integration.
- Scaling: Only static count is supported; no autoscaling or scheduled scaling.
- Health Checks: No configuration for container health checks.
- Secrets Management: No support for injecting secrets (e.g., from SSM or Secrets Manager).
- Logging: Only basic CloudWatch Logs; no log retention or advanced logging options.
- Lifecycle/Update Strategy: No mention of deployment strategies (rolling, blue/green, etc.).
- Resource Limits: No validation or documentation of allowed CPU/memory combinations.
- Error Handling: No details on error handling for failed deployments or misconfigurations.
- Testing/Local Dev: No guidance for local development or testing of services.
192 changes: 192 additions & 0 deletions docs/superpowers/plans/2026-04-23-ecs-fargate-services.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# ECS Fargate Services Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Implement a new `services` section in EasySAM to deploy long-running background workers or web services on AWS ECS Fargate.

**Architecture:** Extend the YAML model to support `services`, update the loading logic to handle these new resources, and modify the Jinja2 template to generate the corresponding ECS resources (Cluster, TaskDefinition, Service) and IAM roles.

**Tech Stack:** Python, Jinja2, AWS SAM/CloudFormation, JSON Schema.

---

### Task 1: Update Schema for Services

**Files:**
- Modify: `src/easysam/schemas.json`

- [ ] **Step 1: Add service definitions to the schema**
Update `src/easysam/schemas.json` to include `services_schema` and update the top-level `properties`.

```json
{
"definitions": {
"services_schema": {
"type": "object",
"properties": {
"image": { "type": "string" },
"build": { "type": "string" },
"cpu": { "type": "integer", "enum": [256, 512, 1024, 2048, 4096] },
"memory": { "type": "integer" },
"count": { "type": "integer", "minimum": 0 },
"ports": { "type": "array", "items": { "type": "integer" } },
"envvars": { "type": "object", "patternProperties": { "^[A-Za-z0-9_]+$": { "type": "string" } } },
"tables": { "type": "array", "items": { "type": "string" } },
"buckets": { "type": "array", "items": { "type": "string" } },
"queues": { "type": "array", "items": { "type": "string" } },
"streams": { "type": "array", "items": { "type": "string" } }
},
"oneOf": [
{ "required": ["image"] },
{ "required": ["build"] }
],
"additionalProperties": false
}
},
"properties": {
"services": {
"type": "object",
"patternProperties": {
"^[a-z0-9-]+$": { "$ref": "#/definitions/services_schema" }
},
"additionalProperties": false
}
}
}
```

- [ ] **Step 2: Commit**

```bash
git add src/easysam/schemas.json
git commit -m "feat: add services to JSON schema"
```

---

### Task 2: Update Loading Logic

**Files:**
- Modify: `src/easysam/load.py`

- [ ] **Step 1: Add 'services' to SUPPORTED_SECTIONS and local import logic**
Update `SUPPORTED_SECTIONS` and ensure `preprocess_file` handles `services`.

```python
SUPPORTED_SECTIONS = [
'tables',
'paths',
'functions',
'buckets',
'authorizers',
'prismarine',
'import',
'lambda',
'search',
'mqtt',
'services', # Add this
]

# Update preprocess_file to include:
if services_def := entry_data.get('services'):
if 'services' not in resources_data:
resources_data['services'] = {}
resources_data['services'].update(services_def)
```

- [ ] **Step 2: Add defaults for services**
Create a `process_default_services` function and call it in `preprocess_defaults`.

```python
def process_default_services(resources_data: dict, errors: list[str]):
if 'services' in resources_data:
for name, service in resources_data['services'].items():
service.setdefault('cpu', 256)
service.setdefault('memory', 512)
service.setdefault('count', 1)
```

- [ ] **Step 3: Commit**

```bash
git add src/easysam/load.py
git commit -m "feat: support services in loading logic"
```

---

### Task 3: Add CLI Flag

**Files:**
- Modify: `src/easysam/cli.py`

- [ ] **Step 1: Add --no-docker-build-on-win option**
Update `@click.command()` for `generate` and `deploy`.

```python
@click.option('--no-docker-build-on-win', is_flag=True, help='Skip Docker build metadata on Windows')
```

- [ ] **Step 2: Pass the flag to generate_template**
Ensure the flag is passed from CLI to the template generation logic.

- [ ] **Step 3: Commit**

```bash
git add src/easysam/cli.py
git commit -m "feat: add --no-docker-build-on-win CLI flag"
```

---

### Task 4: Update Template Generation

**Files:**
- Modify: `src/easysam/template.j2`

- [ ] **Step 1: Add ECS Cluster resource**
Render a single ECS Cluster if `services` are defined.

```jinja2
{% if services is defined %}
{{ lprefix }}Cluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Sub "{{ lprefix }}-cluster-${Stage}"
{% endif %}
```

- [ ] **Step 2: Add ECS Task Definition and Service**
Loop through `services` and render TaskDefinition (with IAM roles) and Service.

- [ ] **Step 3: Handle --no-docker-build-on-win**
Use the flag to conditionally render `Metadata: BuildMethod: docker`.

- [ ] **Step 4: Commit**

```bash
git add src/easysam/template.j2
git commit -m "feat: render ECS resources in SAM template"
```

---

### Task 5: Verification and Testing

**Files:**
- Create: `tests/test_services.py`

- [ ] **Step 1: Write a test case for a simple service**
Verify that a `resources.yaml` with a service generates the expected CloudFormation resources.

- [ ] **Step 2: Run tests**

Run: `pytest tests/test_services.py -v`
Expected: PASS

- [ ] **Step 3: Commit**

```bash
git add tests/test_services.py
git commit -m "test: add verification tests for ECS services"
```
Loading