Declarative AWS infrastructure deployment from a single YAML file
Project description
InfraKit
Declarative AWS infrastructure from a single YAML file.
pip install sokech-infrakit && infrakit deploy
What is InfraKit?
InfraKit is a production-grade CLI tool that reads an infrakit.yaml file and provisions AWS infrastructure with the properties that matter in real deployments: idempotency, atomic rollback, drift detection, and remote state with distributed locking.
Define your stack in YAML. Deploy, detect drift, and recover — all from the CLI.
# infrakit.yaml
project: my-api
region: us-east-1
env: prod
services:
users_table:
type: dynamodb
billing: pay-per-request
hash_key: userId
hash_key_type: S
api_role:
type: iam-role
assumed_by: lambda.amazonaws.com
policies:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
api_handler:
type: lambda
runtime: python3.12
handler: app.handler
code: ./src
role: !ref api_role.arn
environment:
TABLE_NAME: !ref users_table.name
api_gateway:
type: api-gateway
integration: !ref api_handler.arn
routes:
- GET /users/{id}
- POST /users
$ infrakit plan
+ users_table (dynamodb) will be created
+ api_role (iam-role) will be created
+ api_handler (lambda) will be created
+ api_gateway (api-gateway) will be created
Plan: 4 to create, 0 to update, 0 to destroy.
$ infrakit deploy --auto-approve
+ users_table (dynamodb) — creating ✓
+ api_role (iam-role) — creating ✓
+ api_handler (lambda) — creating ✓
+ api_gateway (api-gateway) — creating ✓
Deploy complete.
# Later — someone deletes users_table from the AWS console
$ infrakit drift
┌──────────────┬──────────┬─────────┬──────────────────────────────┐
│ Name │ Type │ Status │ Detail │
├──────────────┼──────────┼─────────┼──────────────────────────────┤
│ users_table │ dynamodb │ MISSING │ Resource deleted out-of-band. │
│ api_role │ iam-role │ OK │ │
│ api_handler │ lambda │ OK │ │
│ api_gateway │ api-gtw │ OK │ │
└──────────────┴──────────┴─────────┴──────────────────────────────┘
Drift detected: 1 missing, 0 error(s).
Run `infrakit deploy` to reconcile.
$ infrakit deploy --auto-approve
= api_role (iam-role) — no changes
! users_table (dynamodb) — drift detected, recreating ✓
= api_handler (lambda) — no changes
= api_gateway (api-gateway) — no changes
Deploy complete.
Roadmap
| Phase | Goal | Status |
|---|---|---|
| Phase 1 | Core — schema validation, 5 resource providers, deploy/destroy/plan CLI | ✅ Complete |
| Phase 2 | DX — infrakit init, PyPI publish, Docker image, idempotency improvements |
✅ Complete |
| Phase 3 | DevOps — S3+DynamoDB remote state, ECS/ElastiCache/ALB providers, GitHub Action | ✅ Complete |
| Phase 4 | Reliability — drift detection, atomic rollback observability, machine-readable plan output | ✅ Complete |
Phase 4 deliverables (complete)
infrakit drift— compares state file against live AWS; reports each resource asOK,MISSING, orERROR; exits 1 when drift is detected so CI pipelines can alertinfrakit plan --json— machine-readable plan output for CI systems; returnscreates,deletes,has_changesas structured JSONEngine.plan_data()— single source of truth for plan logic; shared by human-readable table output and--jsonflag- Rollback observability — writes
status="failed"to state before attempting delete so a crash mid-rollback leaves a traceable record; reports any resources that could not be cleaned up - 184 tests, 90.2% coverage, mypy strict + ruff passing
- Live AWS verified — deploy task-manager stack → delete DynamoDB table out-of-band →
infrakit driftreports MISSING, exit 1 →infrakit deployrecovers →infrakit driftreports all OK, exit 0
Phase 3 deliverables (complete)
- S3 + DynamoDB remote state backend — same pattern as Terraform; safe for concurrent CI runners
- ECS Fargate provider — auto-detects default VPC/subnets; registers with ALB target group via
load_balancer: !ref alb.target_group_arn - ElastiCache provider — Redis and Memcached clusters; VPC-aware subnet group and security group management
- ALB provider — Application Load Balancer + target group + listener; outputs
target_group_arnfor ECS wiring - GitHub Action (
action.yml) — composite action forinfrakit plan/deploy/destroyin any workflow examples/task-manager/— deployable ECS Fargate + ALB + DynamoDB example; used in Phase 4 drift detection demo- 166 tests, 90.6% coverage, mypy strict + ruff passing
Phase 2 deliverables (complete)
infrakit init— interactive scaffolding command; generates a starterinfrakit.yamlforserverless-apiordata-storeproject types- Published to PyPI as
sokech-infrakit—pip install sokech-infrakitworks - Multi-arch Docker image (
linux/amd64+linux/arm64) published to GHCR on every tag - Deploy idempotency — running
infrakit deploytwice on an unchanged stack prints "All resources up to date." and exits 0; drift (resource deleted in AWS) triggers a targeted recreate - GitHub Actions CI on every push (Python 3.11 + 3.12), PyPI publish and Docker push on tag
- 129 tests, 91.8% coverage, mypy strict + ruff passing
Phase 1 deliverables (complete)
- Pydantic v2 schema validation — all errors reported before any AWS call
- Resource providers:
dynamodb,lambda,api-gateway,s3,iam-role !refsyntax for cross-resource references (resolved via dependency DAG)- Dependency graph (DAG) — resources provisioned in correct order automatically
- Local JSON state backend with advisory locking
- Atomic rollback on deploy failure
infrakit validate,infrakit plan,infrakit deploy,infrakit destroy,infrakit status- 115 tests, 91% coverage enforced in CI
Installation
Local / development
git clone https://github.com/SamioneX/InfraKit
cd InfraKit
pip install -e ".[dev]"
pip
pip install sokech-infrakit
Docker
docker run --rm \
-v ~/.aws:/root/.aws:ro \
-v $(pwd):/workspace \
-w /workspace \
ghcr.io/samionex/infrakit deploy
Commands
| Command | Description |
|---|---|
infrakit validate |
Validate config schema without calling AWS |
infrakit plan |
Show what would change without applying (--json for CI output) |
infrakit deploy |
Provision all resources in dependency order; recovers drifted resources |
infrakit destroy |
Tear down all managed resources in reverse dependency order |
infrakit status |
Show current state from the state file |
infrakit init |
Scaffold a new infrakit.yaml interactively |
infrakit drift |
Compare state against live AWS; exits 1 if drift is detected |
Supported Resource Types
| Type | AWS Resource |
|---|---|
dynamodb |
Amazon DynamoDB Table |
iam-role |
AWS IAM Role + inline and managed policies |
lambda |
AWS Lambda Function |
api-gateway |
Amazon API Gateway (HTTP API v2) |
s3 |
Amazon S3 Bucket |
ecs-fargate |
ECS Fargate Service + Task Definition |
elasticache |
ElastiCache Cluster (Redis / Memcached) |
alb |
Application Load Balancer + target group + listener |
dns |
DNS record via Route53 or Cloudflare |
sentinelapi |
SentinelAPI edge gateway stack via sentinel-api SDK |
Config Reference
Top-level fields
project: my-api # used for resource naming and state key
region: us-east-1 # AWS region
env: prod # dev | staging | prod
State backend
state:
backend: local # local (default) | s3
path: .infrakit/state.json # local backend path
# Remote backend (S3 + DynamoDB locking — same pattern as Terraform)
state:
backend: s3
bucket: my-infrakit-state # must pre-exist
lock_table: infrakit-locks # DynamoDB table (LockID String primary key); must pre-exist
!ref syntax
Reference an output attribute of another resource — InfraKit resolves the correct provisioning order automatically:
role: !ref api_role.arn
environment:
TABLE_NAME: !ref users_table.name
Supported attributes per resource type:
| Type | Attributes |
|---|---|
dynamodb |
.name, .arn, .stream_arn |
lambda |
.name, .arn, .function_name, .function_url |
iam-role |
.arn, .name |
s3 |
.name, .arn, .bucket_url |
api-gateway |
.endpoint, .id |
ecs-fargate |
.name, .arn, .cluster |
elasticache |
.name, .endpoint, .port, .arn |
alb |
.id, .endpoint, .arn, .hosted_zone_id, .target_group_arn |
dns |
.provider, .zone, .record, .record_type, .target |
sentinelapi |
.alb_dns_name, .service_url, .ecs_cluster_name, .ecs_service_name, .request_logs_table_name |
When a resource references !ref <lambda>.function_url, InfraKit automatically enables
Lambda Function URL creation for that Lambda during deploy.
DNS records (dns)
# Route53 CNAME (minimal)
api_dns:
type: dns
provider: route53
zone: sokech.com
record: api
target: !ref app_alb.endpoint
# Cloudflare CNAME using token in AWS Secrets Manager
api_dns_cf:
type: dns
provider: cloudflare
zone: sokech.com
record: api
target: !ref app_alb.endpoint
proxied: true
# optional override (default: /<project>/cloudflare-token)
cloudflare_token_secret: /sokech/cloudflare-token
# Route53 alias A record (useful for apex)
root_dns:
type: dns
provider: route53
zone: sokech.com
record: "@"
record_type: A
alias: true
target: !ref app_alb.endpoint
target_hosted_zone_id: !ref app_alb.hosted_zone_id
SentinelAPI (sentinelapi)
sentinel:
type: sentinelapi
mode: full
upstream_base_url: https://backend.example.com
jwt:
jwks_url: https://idp.example.com/.well-known/jwks.json
algorithm: RS256
optimize_for: cost
sentinel_dns:
type: dns
provider: route53
zone: example.com
record: api-sentinel
record_type: CNAME
target: !ref sentinel.alb_dns_name
State Management
InfraKit tracks deployed resources in a state file. Resources are saved individually — a failed deploy only rolls back what was created in that run.
$ cat .infrakit/state.json
{
"resources": {
"users_table": {
"type": "dynamodb",
"outputs": { "name": "my-api-prod-users_table", "arn": "arn:aws:..." },
"status": "created"
}
}
}
For team and CI/CD use, switch to the remote S3+DynamoDB backend (same pattern as Terraform) — see the State backend config section above.
Development
git clone https://github.com/SamioneX/InfraKit
cd InfraKit
pip install -e ".[dev]"
make test # pytest + coverage report (must be ≥90%)
make lint # ruff check + mypy
make format # ruff format
Test structure
tests/
├── unit/ # pure Python, no AWS calls
│ ├── providers/ # one file per provider
│ ├── test_schema.py
│ ├── test_dependency.py
│ ├── test_state.py
│ └── test_cli.py
└── integration/ # full deploy/destroy flows via moto
└── test_deploy_flow.py
All AWS calls are mocked with moto — no AWS account or credentials required to run the test suite.
Architecture Decisions
See ARCHITECTURE.md for detailed rationale behind key design choices:
- Typer over Click — type annotations as CLI argument definitions, Rich output built in
- Pydantic v2 for schema validation — schema-as-code, human-readable errors, validated before any AWS call
- AWS session Singleton — single injection point for mocking, minimal connection overhead
- Dependency DAG (networkx) — automatic resource ordering, cycle detection at validation time
- S3 + DynamoDB state — same pattern as Terraform, safe for concurrent CI runners
License
MIT © Samuel Okechukwu
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sokech_infrakit-0.6.1.tar.gz.
File metadata
- Download URL: sokech_infrakit-0.6.1.tar.gz
- Upload date:
- Size: 69.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a2d0c8a0e11b29ccc585fd1e7914649d2709df491bef57c80a68ce107a095248
|
|
| MD5 |
9b26a2c35e35260133374b43d0ab87ae
|
|
| BLAKE2b-256 |
846484165dd44595202fdf626961965505b0c0b39799601f58cbfcf3fc184b0b
|
Provenance
The following attestation bundles were made for sokech_infrakit-0.6.1.tar.gz:
Publisher:
publish.yml on SamioneX/InfraKit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sokech_infrakit-0.6.1.tar.gz -
Subject digest:
a2d0c8a0e11b29ccc585fd1e7914649d2709df491bef57c80a68ce107a095248 - Sigstore transparency entry: 1034482438
- Sigstore integration time:
-
Permalink:
SamioneX/InfraKit@d8f2912fbc8e3a0211e1e784faa5c4fbfc4584c0 -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/SamioneX
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d8f2912fbc8e3a0211e1e784faa5c4fbfc4584c0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sokech_infrakit-0.6.1-py3-none-any.whl.
File metadata
- Download URL: sokech_infrakit-0.6.1-py3-none-any.whl
- Upload date:
- Size: 56.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e83542ec238f8562679929b142b396d935b9eca18858d33f7b7c72730f460e7
|
|
| MD5 |
d799467b062494083f003af96e13bea8
|
|
| BLAKE2b-256 |
4c715cef7726539c5efc7c02754b93eced4a63cdd923d70e8d81f31507e39fd0
|
Provenance
The following attestation bundles were made for sokech_infrakit-0.6.1-py3-none-any.whl:
Publisher:
publish.yml on SamioneX/InfraKit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sokech_infrakit-0.6.1-py3-none-any.whl -
Subject digest:
2e83542ec238f8562679929b142b396d935b9eca18858d33f7b7c72730f460e7 - Sigstore transparency entry: 1034482519
- Sigstore integration time:
-
Permalink:
SamioneX/InfraKit@d8f2912fbc8e3a0211e1e784faa5c4fbfc4584c0 -
Branch / Tag:
refs/tags/v0.6.1 - Owner: https://github.com/SamioneX
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d8f2912fbc8e3a0211e1e784faa5c4fbfc4584c0 -
Trigger Event:
push
-
Statement type: