docs(P13): plan-as-execute + verify (v1.2.3)
---ci--- project: acdl phase: 13 milestone: v1.2 status: verify verdict: VERIFIED requirements: covered: [REQ-31] ---/ci--- Phase 13 plan-as-execute + verify. scripts/verify_phase13.sh green. 6 ECS L1s authored + registered (l1-vpc, l1-ecs-cluster, l1-ecs-service, l1-iam-role, l1-alb, l1-ecr). Adapter generalized to table-driven TYPE_MAP (12 IR types) + INPUT_MAP + OUTPUT_MAP. S3 regression: the v1.1 spike l1-s3 produces byte-identical main.tf. Ready to ship v1.2.3.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# l1-alb — Application Load Balancer primitive (multi-resource L1)
|
||||
|
||||
An L1 module for an Application Load Balancer (load balancer + target
|
||||
group + listener). Substrate-agnostic (the IR types are
|
||||
`aws:elbv2:loadbalancer`, `aws:elbv2:listener`, `aws:elbv2:targetgroup`,
|
||||
not Terraform resource types). This is a multi-resource L1: the
|
||||
interface declares the group's inputs/outputs plus a `resources` array
|
||||
listing the IR types it emits. The IR instance (Phase 14/15) will have
|
||||
multiple `resources` entries all with `module: "l1-alb@1.0.0"`.
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
|
||||
See `interface.json`: inputs `name` (string), `subnets` (string,
|
||||
comma-separated, ref to l1-vpc), `security_group` (string), `port`
|
||||
(number, default 80), `protocol` (string, default "HTTP"), `region`
|
||||
(string); outputs `lb_arn` (arn) + `listener_arn` (arn) +
|
||||
`target_group_arn` (arn); no NFRs.
|
||||
|
||||
The `resources` array lists the emitted IR types:
|
||||
|
||||
- `aws:elbv2:loadbalancer` — application load balancer in the VPC
|
||||
subnets.
|
||||
- `aws:elbv2:targetgroup` — target group for the ECS service tasks.
|
||||
- `aws:elbv2:listener` — listener forwarding the LB port to the target
|
||||
group.
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates each
|
||||
emitted IR resource to Terraform:
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:elbv2:loadbalancer` | `resource "aws_lb" "<id>" { ... }` |
|
||||
| `resource.inputs.name` | `name = <value>` arg |
|
||||
| `resource.inputs.subnets` | `subnets = [<value>]` arg (comma-split) |
|
||||
| `resource.inputs.security_group` | `security_groups = [<value>]` arg (comma-split) |
|
||||
| `resource.outputs.lb_arn` | `output "lb_arn" { value = aws_lb.<id>.id }` |
|
||||
| `resource.type = aws:elbv2:targetgroup` | `resource "aws_lb_target_group" "<id>" { ... }` |
|
||||
| `resource.inputs.port` | `port = <value>` arg |
|
||||
| `resource.inputs.protocol` | `protocol = <value>` arg |
|
||||
| `resource.outputs.target_group_arn` | `output "target_group_arn" { value = aws_lb_target_group.<id>.arn }` |
|
||||
| `resource.type = aws:elbv2:listener` | `resource "aws_lb_listener" "<id>" { ... }` |
|
||||
| `resource.inputs.lb_arn` | `load_balancer_arn = <value>` arg (identity) |
|
||||
| `resource.inputs.port` | `port = <value>` arg |
|
||||
| `resource.inputs.protocol` | `protocol = <value>` arg |
|
||||
| `resource.outputs.listener_arn` | `output "listener_arn" { value = aws_lb_listener.<id>.id }` |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates.
|
||||
|
||||
## Versioning (W3.D)
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
a 12-month deprecation window.
|
||||
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"name": "l1-alb",
|
||||
"version": "1.0.0",
|
||||
"kind": "l1",
|
||||
"type": "aws:elbv2:loadbalancer",
|
||||
"description": "Application Load Balancer primitive (substrate-agnostic IR types aws:elbv2:loadbalancer + aws:elbv2:listener + aws:elbv2:targetgroup; the Terraform adapter translates to aws_lb/aws_lb_listener/aws_lb_target_group).",
|
||||
"inputs": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name tag for the load balancer and child resources.",
|
||||
"required": true
|
||||
},
|
||||
"subnets": {
|
||||
"type": "string",
|
||||
"description": "Comma-separated subnet ids (ref to l1-vpc).",
|
||||
"required": true
|
||||
},
|
||||
"security_group": {
|
||||
"type": "string",
|
||||
"description": "Security group id for the load balancer.",
|
||||
"required": true
|
||||
},
|
||||
"port": {
|
||||
"type": "number",
|
||||
"description": "Listener port (default 80).",
|
||||
"required": false,
|
||||
"default": 80
|
||||
},
|
||||
"protocol": {
|
||||
"type": "string",
|
||||
"description": "Listener protocol (default HTTP).",
|
||||
"required": false,
|
||||
"default": "HTTP"
|
||||
},
|
||||
"region": {
|
||||
"type": "string",
|
||||
"description": "AWS region the load balancer is created in.",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"lb_arn": {
|
||||
"type": "arn",
|
||||
"description": "The load balancer ARN."
|
||||
},
|
||||
"listener_arn": {
|
||||
"type": "arn",
|
||||
"description": "The listener ARN."
|
||||
},
|
||||
"target_group_arn": {
|
||||
"type": "arn",
|
||||
"description": "The target group ARN."
|
||||
}
|
||||
},
|
||||
"nfrs": {},
|
||||
"resources": [
|
||||
{
|
||||
"type": "aws:elbv2:loadbalancer",
|
||||
"description": "Application load balancer in the VPC subnets.",
|
||||
"inputs": ["name", "subnets", "security_group"],
|
||||
"outputs": ["lb_arn"]
|
||||
},
|
||||
{
|
||||
"type": "aws:elbv2:targetgroup",
|
||||
"description": "Target group for the ECS service tasks.",
|
||||
"inputs": ["name", "port", "protocol", "vpc_id"],
|
||||
"outputs": ["target_group_arn"]
|
||||
},
|
||||
{
|
||||
"type": "aws:elbv2:listener",
|
||||
"description": "Listener forwarding the LB port to the target group.",
|
||||
"inputs": ["lb_arn", "port", "protocol", "target_group_arn"],
|
||||
"outputs": ["listener_arn"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
# l1-ecr — ECR repository primitive
|
||||
|
||||
An L1 module for an ECR repository that hosts the ECS task image.
|
||||
Single-purpose, substrate-agnostic (the IR type is
|
||||
`aws:ecr:repository`, not a Terraform resource type).
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
|
||||
See `interface.json`: inputs `name` + `region` (strings), outputs
|
||||
`repository_url` (string) + `repository_arn` (arn), no NFRs.
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates this
|
||||
L1's IR shape to Terraform:
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:ecr:repository` | `resource "aws_ecr_repository" "<id>" { ... }` |
|
||||
| `resource.inputs.name` | `name = <value>` arg |
|
||||
| `resource.inputs.region` | `provider "aws" { region = <value> }` |
|
||||
| `resource.outputs.repository_url` | `output "repository_url" { value = aws_ecr_repository.<id>.repository_url }` |
|
||||
| `resource.outputs.repository_arn` | `output "repository_arn" { value = aws_ecr_repository.<id>.arn }` |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates.
|
||||
|
||||
## Versioning (W3.D)
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
a 12-month deprecation window.
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "l1-ecr",
|
||||
"version": "1.0.0",
|
||||
"kind": "l1",
|
||||
"type": "aws:ecr:repository",
|
||||
"description": "ECR repository primitive (substrate-agnostic IR type aws:ecr:repository; the Terraform adapter translates to aws_ecr_repository).",
|
||||
"inputs": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The ECR repository name.",
|
||||
"required": true
|
||||
},
|
||||
"region": {
|
||||
"type": "string",
|
||||
"description": "AWS region the repository is created in.",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"repository_url": {
|
||||
"type": "string",
|
||||
"description": "The ECR repository URL."
|
||||
},
|
||||
"repository_arn": {
|
||||
"type": "arn",
|
||||
"description": "The ECR repository ARN."
|
||||
}
|
||||
},
|
||||
"nfrs": {}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
# l1-ecs-cluster — ECS Fargate cluster primitive
|
||||
|
||||
An L1 module for an ECS Fargate cluster. Single-purpose,
|
||||
substrate-agnostic (the IR type is `aws:ecs:cluster`, not a Terraform
|
||||
resource type).
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
|
||||
See `interface.json`: inputs `name` + `region` (strings), outputs
|
||||
`cluster_arn` (arn) + `cluster_id` (string), no NFRs.
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates this
|
||||
L1's IR shape to Terraform:
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:ecs:cluster` | `resource "aws_ecs_cluster" "<id>" { ... }` |
|
||||
| `resource.inputs.name` | `name = <value>` arg |
|
||||
| `resource.inputs.region` | `provider "aws" { region = <value> }` |
|
||||
| `resource.outputs.cluster_arn` | `output "cluster_arn" { value = aws_ecs_cluster.<id>.arn }` |
|
||||
| `resource.outputs.cluster_id` | `output "cluster_id" { value = aws_ecs_cluster.<id>.id }` |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates.
|
||||
|
||||
## Versioning (W3.D)
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
a 12-month deprecation window.
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "l1-ecs-cluster",
|
||||
"version": "1.0.0",
|
||||
"kind": "l1",
|
||||
"type": "aws:ecs:cluster",
|
||||
"description": "ECS Fargate cluster primitive (substrate-agnostic IR type aws:ecs:cluster; the Terraform adapter translates to aws_ecs_cluster).",
|
||||
"inputs": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The ECS cluster name.",
|
||||
"required": true
|
||||
},
|
||||
"region": {
|
||||
"type": "string",
|
||||
"description": "AWS region the cluster is created in.",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"cluster_arn": {
|
||||
"type": "arn",
|
||||
"description": "The ECS cluster ARN."
|
||||
},
|
||||
"cluster_id": {
|
||||
"type": "string",
|
||||
"description": "The ECS cluster id (name)."
|
||||
}
|
||||
},
|
||||
"nfrs": {}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
# l1-ecs-service — ECS Fargate service primitive (multi-resource L1)
|
||||
|
||||
An L1 module for an ECS Fargate service (task definition + service).
|
||||
Substrate-agnostic (the IR types are `aws:ecs:task_definition` and
|
||||
`aws:ecs:service`, not Terraform resource types). This is a
|
||||
multi-resource L1: the interface declares the group's inputs/outputs
|
||||
plus a `resources` array listing the IR types it emits. The IR instance
|
||||
(Phase 14/15) will have multiple `resources` entries all with
|
||||
`module: "l1-ecs-service@1.0.0"`.
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
|
||||
See `interface.json`: inputs `image` (string, ECR image URL), `port`
|
||||
(number), `cpu` (number, default 256), `memory` (number, default 512),
|
||||
`env` (optional JSON map string), `cluster_arn` (arn, ref to
|
||||
l1-ecs-cluster), `subnets` (string, ref to l1-vpc), `security_group`
|
||||
(string), `lb_target_group_arn` (arn, optional, ref to l1-alb), `region`
|
||||
(string); outputs `service_arn` (arn) + `task_def_arn` (arn); no NFRs.
|
||||
|
||||
The `resources` array lists the emitted IR types:
|
||||
|
||||
- `aws:ecs:task_definition` — Fargate task definition. The adapter
|
||||
jsonencodes `image`/`port`/`env` into `container_definitions`.
|
||||
- `aws:ecs:service` — Fargate service running the task definition in the
|
||||
cluster + subnets (+ optional ALB target group wiring).
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates each
|
||||
emitted IR resource to Terraform:
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:ecs:task_definition` | `resource "aws_ecs_task_definition" "<id>" { ... }` |
|
||||
| `resource.inputs.image` + `port` + `env` | `container_definitions = jsonencode(...)` (adapter-built) |
|
||||
| `resource.inputs.cpu` | `cpu = <value>` arg |
|
||||
| `resource.inputs.memory` | `memory = <value>` arg |
|
||||
| `resource.outputs.task_def_arn` | `output "task_def_arn" { value = aws_ecs_task_definition.<id>.arn }` |
|
||||
| `resource.type = aws:ecs:service` | `resource "aws_ecs_service" "<id>" { ... }` |
|
||||
| `resource.inputs.cluster_arn` | `cluster = <value>` arg (identity) |
|
||||
| `resource.inputs.subnets` | `network_configuration { subnets = [...] }` (emit as-is) |
|
||||
| `resource.inputs.security_group` | `network_configuration { security_groups = [...] }` (emit as-is) |
|
||||
| `resource.inputs.lb_target_group_arn` | `load_balancer { target_group_arn = <value> }` (emit as-is) |
|
||||
| `resource.outputs.service_arn` | `output "service_arn" { value = aws_ecs_service.<id>.id }` |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates. The `container_definitions` JSON is built
|
||||
by the adapter from the IR `image`/`port`/`env` inputs (the one
|
||||
transformation the adapter owns for ECS task definitions).
|
||||
|
||||
## Versioning (W3.D)
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
a 12-month deprecation window.
|
||||
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"name": "l1-ecs-service",
|
||||
"version": "1.0.0",
|
||||
"kind": "l1",
|
||||
"type": "aws:ecs:task_definition",
|
||||
"description": "ECS Fargate service primitive (substrate-agnostic IR types aws:ecs:task_definition + aws:ecs:service; the Terraform adapter translates to aws_ecs_task_definition/aws_ecs_service).",
|
||||
"inputs": {
|
||||
"image": {
|
||||
"type": "string",
|
||||
"description": "ECR image URL for the task container.",
|
||||
"required": true
|
||||
},
|
||||
"port": {
|
||||
"type": "number",
|
||||
"description": "Container port the service listens on.",
|
||||
"required": true
|
||||
},
|
||||
"cpu": {
|
||||
"type": "number",
|
||||
"description": "Task CPU units (Fargate).",
|
||||
"required": false,
|
||||
"default": 256
|
||||
},
|
||||
"memory": {
|
||||
"type": "number",
|
||||
"description": "Task memory (MiB, Fargate).",
|
||||
"required": false,
|
||||
"default": 512
|
||||
},
|
||||
"env": {
|
||||
"type": "string",
|
||||
"description": "Environment variables as a JSON map string (optional).",
|
||||
"required": false
|
||||
},
|
||||
"cluster_arn": {
|
||||
"type": "arn",
|
||||
"description": "ECS cluster ARN (ref to l1-ecs-cluster).",
|
||||
"required": true
|
||||
},
|
||||
"subnets": {
|
||||
"type": "string",
|
||||
"description": "Comma-separated subnet ids (ref to l1-vpc).",
|
||||
"required": true
|
||||
},
|
||||
"security_group": {
|
||||
"type": "string",
|
||||
"description": "Security group id for the service ENIs.",
|
||||
"required": true
|
||||
},
|
||||
"lb_target_group_arn": {
|
||||
"type": "arn",
|
||||
"description": "Optional ALB target group ARN (ref to l1-alb).",
|
||||
"required": false
|
||||
},
|
||||
"region": {
|
||||
"type": "string",
|
||||
"description": "AWS region the service is created in.",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"service_arn": {
|
||||
"type": "arn",
|
||||
"description": "The ECS service ARN."
|
||||
},
|
||||
"task_def_arn": {
|
||||
"type": "arn",
|
||||
"description": "The ECS task definition ARN."
|
||||
}
|
||||
},
|
||||
"nfrs": {},
|
||||
"resources": [
|
||||
{
|
||||
"type": "aws:ecs:task_definition",
|
||||
"description": "Fargate task definition; the adapter jsonencodes image/port/env into container_definitions.",
|
||||
"inputs": ["image", "port", "cpu", "memory", "env"],
|
||||
"outputs": ["task_def_arn"]
|
||||
},
|
||||
{
|
||||
"type": "aws:ecs:service",
|
||||
"description": "Fargate service running the task definition in the cluster + subnets.",
|
||||
"inputs": ["cluster_arn", "subnets", "security_group", "lb_target_group_arn", "port"],
|
||||
"outputs": ["service_arn"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# l1-iam-role — IAM role primitive
|
||||
|
||||
An L1 module for an IAM role (used as the ECS task execution role).
|
||||
Single-purpose, substrate-agnostic (the IR type is `aws:iam:role`, not a
|
||||
Terraform resource type).
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
|
||||
See `interface.json`: inputs `role_name` (string), `assume_role_policy`
|
||||
(JSON string), `managed_policies` (optional comma-separated ARNs),
|
||||
`region` (string); outputs `role_arn` (arn) + `role_id` (string), no
|
||||
NFRs.
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates this
|
||||
L1's IR shape to Terraform:
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:iam:role` | `resource "aws_iam_role" "<id>" { ... }` |
|
||||
| `resource.inputs.role_name` | `name = <value>` arg |
|
||||
| `resource.inputs.assume_role_policy` | `assume_role_policy = <value>` arg (JSON string) |
|
||||
| `resource.inputs.managed_policies` | `managed_policy_arns = [<arns>]` arg (comma-split) |
|
||||
| `resource.inputs.region` | `provider "aws" { region = <value> }` |
|
||||
| `resource.outputs.role_arn` | `output "role_arn" { value = aws_iam_role.<id>.arn }` |
|
||||
| `resource.outputs.role_id` | `output "role_id" { value = aws_iam_role.<id>.id }` |
|
||||
|
||||
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||
content — it only translates.
|
||||
|
||||
## Versioning (W3.D)
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
a 12-month deprecation window.
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "l1-iam-role",
|
||||
"version": "1.0.0",
|
||||
"kind": "l1",
|
||||
"type": "aws:iam:role",
|
||||
"description": "IAM role primitive (substrate-agnostic IR type aws:iam:role; the Terraform adapter translates to aws_iam_role).",
|
||||
"inputs": {
|
||||
"role_name": {
|
||||
"type": "string",
|
||||
"description": "The IAM role name.",
|
||||
"required": true
|
||||
},
|
||||
"assume_role_policy": {
|
||||
"type": "string",
|
||||
"description": "Assume-role policy document (JSON string).",
|
||||
"required": true
|
||||
},
|
||||
"managed_policies": {
|
||||
"type": "string",
|
||||
"description": "Comma-separated list of managed policy ARNs to attach.",
|
||||
"required": false
|
||||
},
|
||||
"region": {
|
||||
"type": "string",
|
||||
"description": "AWS region the role is created in.",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"role_arn": {
|
||||
"type": "arn",
|
||||
"description": "The IAM role ARN."
|
||||
},
|
||||
"role_id": {
|
||||
"type": "string",
|
||||
"description": "The IAM role id."
|
||||
}
|
||||
},
|
||||
"nfrs": {}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
# l1-vpc — VPC primitive (multi-resource L1)
|
||||
|
||||
An L1 module for a VPC with subnets and a route table. Substrate-agnostic
|
||||
(the IR types are `aws:ec2:vpc`, `aws:ec2:subnet`, `aws:ec2:routetable`,
|
||||
not Terraform resource types). This is a multi-resource L1: the
|
||||
interface declares the group's inputs/outputs plus a `resources` array
|
||||
listing the IR types it emits. The IR instance (Phase 14/15) will have
|
||||
multiple `resources` entries all with `module: "l1-vpc@1.0.0"`.
|
||||
|
||||
## Interface (the IR-typed contract)
|
||||
|
||||
See `interface.json`: inputs `cidr` (string, e.g. "10.0.0.0/16"), `azs`
|
||||
(string, comma-separated, e.g. "us-east-1a,us-east-1b"), `name` (string,
|
||||
used for tagging), `region` (string); outputs `vpc_id` (string),
|
||||
`subnet_ids` (string, comma-separated), `igw_id` (string); no NFRs.
|
||||
|
||||
The `resources` array lists the emitted IR types:
|
||||
|
||||
- `aws:ec2:vpc` — the VPC itself (cidr → cidr_block, name → tag).
|
||||
- `aws:ec2:subnet` — one subnet per availability zone (`azs` split on
|
||||
comma); inputs include the parent VPC id.
|
||||
- `aws:ec2:routetable` — route table bound to the VPC with an internet
|
||||
gateway + default route (0.0.0.0/0 → igw).
|
||||
|
||||
## IR → Terraform mapping (performed by the adapter)
|
||||
|
||||
The Terraform adapter (`adapters/terraform/adapter.py`) translates each
|
||||
emitted IR resource to Terraform:
|
||||
|
||||
| IR | Terraform |
|
||||
|----|-----------|
|
||||
| `resource.type = aws:ec2:vpc` | `resource "aws_vpc" "<id>" { ... }` |
|
||||
| `resource.inputs.cidr` | `cidr_block = <value>` arg |
|
||||
| `resource.inputs.name` | `tags = { Name = <value> }` (emit as-is) |
|
||||
| `resource.outputs.vpc_id` | `output "vpc_id" { value = aws_vpc.<id>.id }` |
|
||||
| `resource.type = aws:ec2:subnet` | `resource "aws_subnet" "<id>" { ... }` |
|
||||
| `resource.inputs.cidr` | `cidr_block = <value>` arg |
|
||||
| `resource.inputs.az` | `availability_zone = <value>` arg |
|
||||
| `resource.outputs.subnet_id` | `output "subnet_id" { value = aws_subnet.<id>.id }` |
|
||||
| `resource.type = aws:ec2:routetable` | `resource "aws_route_table" "<id>" { ... }` |
|
||||
| `resource.inputs.vpc_id` | `vpc_id = <value>` arg |
|
||||
|
||||
The internet gateway + default route are emitted as part of the route
|
||||
table resource's IR (the `igw_id` output is wired via the route table's
|
||||
inputs). The adapter is a thin layer (ARCHITECTURE.md §12.2); it does
|
||||
not own L1 content — it only translates.
|
||||
|
||||
## Versioning (W3.D)
|
||||
|
||||
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||
require a new registry entry (immutable publication); old entries enter
|
||||
a 12-month deprecation window.
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "l1-vpc",
|
||||
"version": "1.0.0",
|
||||
"kind": "l1",
|
||||
"type": "aws:ec2:vpc",
|
||||
"description": "VPC primitive (substrate-agnostic IR types aws:ec2:vpc + aws:ec2:subnet + aws:ec2:routetable; the Terraform adapter translates to aws_vpc/aws_subnet/aws_route_table).",
|
||||
"inputs": {
|
||||
"cidr": {
|
||||
"type": "string",
|
||||
"description": "VPC CIDR block, e.g. 10.0.0.0/16.",
|
||||
"required": true
|
||||
},
|
||||
"azs": {
|
||||
"type": "string",
|
||||
"description": "Comma-separated availability zones, e.g. us-east-1a,us-east-1b.",
|
||||
"required": true
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name tag for the VPC and child resources.",
|
||||
"required": true
|
||||
},
|
||||
"region": {
|
||||
"type": "string",
|
||||
"description": "AWS region the VPC is created in.",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"vpc_id": {
|
||||
"type": "string",
|
||||
"description": "The VPC id."
|
||||
},
|
||||
"subnet_ids": {
|
||||
"type": "string",
|
||||
"description": "Comma-separated subnet ids."
|
||||
},
|
||||
"igw_id": {
|
||||
"type": "string",
|
||||
"description": "The internet gateway id."
|
||||
}
|
||||
},
|
||||
"nfrs": {},
|
||||
"resources": [
|
||||
{
|
||||
"type": "aws:ec2:vpc",
|
||||
"description": "The VPC itself.",
|
||||
"inputs": ["cidr", "name"],
|
||||
"outputs": ["vpc_id"]
|
||||
},
|
||||
{
|
||||
"type": "aws:ec2:subnet",
|
||||
"description": "One subnet per availability zone (azs split on comma).",
|
||||
"inputs": ["cidr", "az", "vpc_id", "name"],
|
||||
"outputs": ["subnet_id"]
|
||||
},
|
||||
{
|
||||
"type": "aws:ec2:routetable",
|
||||
"description": "Route table bound to the VPC with an internet gateway + default route.",
|
||||
"inputs": ["vpc_id", "igw_id", "name"],
|
||||
"outputs": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -6,6 +6,48 @@
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"l1-vpc": {
|
||||
"1.0.0": {
|
||||
"interface": "modules-ir/l1/l1-vpc/interface.json",
|
||||
"published_at": "2026-07-21T21:30:00Z",
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"l1-ecs-cluster": {
|
||||
"1.0.0": {
|
||||
"interface": "modules-ir/l1/l1-ecs-cluster/interface.json",
|
||||
"published_at": "2026-07-21T21:30:00Z",
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"l1-ecs-service": {
|
||||
"1.0.0": {
|
||||
"interface": "modules-ir/l1/l1-ecs-service/interface.json",
|
||||
"published_at": "2026-07-21T21:30:00Z",
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"l1-iam-role": {
|
||||
"1.0.0": {
|
||||
"interface": "modules-ir/l1/l1-iam-role/interface.json",
|
||||
"published_at": "2026-07-21T21:30:00Z",
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"l1-alb": {
|
||||
"1.0.0": {
|
||||
"interface": "modules-ir/l1/l1-alb/interface.json",
|
||||
"published_at": "2026-07-21T21:30:00Z",
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"l1-ecr": {
|
||||
"1.0.0": {
|
||||
"interface": "modules-ir/l1/l1-ecr/interface.json",
|
||||
"published_at": "2026-07-21T21:30:00Z",
|
||||
"deprecated": false
|
||||
}
|
||||
},
|
||||
"l2-static-asset": {
|
||||
"1.0.0": {
|
||||
"composition": "modules-ir/l2/l2-static-asset/composition.json",
|
||||
|
||||
Reference in New Issue
Block a user