Skip to main content

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

CI PyPI Coverage Python License: MIT


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 as OK, MISSING, or ERROR; exits 1 when drift is detected so CI pipelines can alert
  • infrakit plan --json — machine-readable plan output for CI systems; returns creates, deletes, has_changes as structured JSON
  • Engine.plan_data() — single source of truth for plan logic; shared by human-readable table output and --json flag
  • 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 drift reports MISSING, exit 1 → infrakit deploy recovers → infrakit drift reports 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_arn for ECS wiring
  • GitHub Action (action.yml) — composite action for infrakit plan/deploy/destroy in 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 starter infrakit.yaml for serverless-api or data-store project types
  • Published to PyPI as sokech-infrakitpip install sokech-infrakit works
  • Multi-arch Docker image (linux/amd64 + linux/arm64) published to GHCR on every tag
  • Deploy idempotency — running infrakit deploy twice 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
  • !ref syntax 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

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
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

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

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

sokech_infrakit-0.5.1.tar.gz (62.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sokech_infrakit-0.5.1-py3-none-any.whl (52.6 kB view details)

Uploaded Python 3

File details

Details for the file sokech_infrakit-0.5.1.tar.gz.

File metadata

  • Download URL: sokech_infrakit-0.5.1.tar.gz
  • Upload date:
  • Size: 62.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sokech_infrakit-0.5.1.tar.gz
Algorithm Hash digest
SHA256 a8bb0323eea117f46c9c7d74a7060b75062f11dec35053df0e5887b094189aae
MD5 3e28ee37b45ef14e76e20b03fabbb2de
BLAKE2b-256 37219e801975965694035e950a79a4f7b8241c69b49e6319198d8d87a0856fc4

See more details on using hashes here.

Provenance

The following attestation bundles were made for sokech_infrakit-0.5.1.tar.gz:

Publisher: publish.yml on SamioneX/InfraKit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sokech_infrakit-0.5.1-py3-none-any.whl.

File metadata

File hashes

Hashes for sokech_infrakit-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 12c831a226723734ac0687e18f98d5e4ec97ef08dda7d685a19520c65a394d81
MD5 8d915343aec288834744d18503a642a4
BLAKE2b-256 4a5de000d1277b8dbc153ad2b5bbbfda170ba1f2c4c706dd8f2dd300b5fa5c57

See more details on using hashes here.

Provenance

The following attestation bundles were made for sokech_infrakit-0.5.1-py3-none-any.whl:

Publisher: publish.yml on SamioneX/InfraKit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page