Spaces:
Running
Running
Contributing to MiniStack
Thanks for wanting to contribute. The codebase is intentionally simple β each AWS service is a single self-contained Python file inside ministack/services/. Adding a new service or fixing a bug should take minutes, not hours.
Project Structure
ministack/
βββ ministack/
β βββ app.py # ASGI entry point, service routing, reset endpoint
β βββ core/
β β βββ responses.py # json_response, error_response_json, new_uuid
β β βββ router.py # detect_service(), SERVICE_PATTERNS
β β βββ lambda_runtime.py
β β βββ persistence.py
β βββ services/
β βββ s3.py, sqs.py, sns.py, dynamodb.py, ...
β βββ cognito.py # example of a two-client service file
βββ tests/
β βββ conftest.py # pytest fixtures (boto3 clients)
β βββ test_services.py # all integration tests
βββ Dockerfile
βββ pyproject.toml
βββ CHANGELOG.md
Adding a New Service
Every service follows the same 4-step pattern:
1. Create ministack/services/myservice.py
"""
MyService Emulator.
JSON-based API via X-Amz-Target.
Supports: OperationOne, OperationTwo, ...
"""
import json
import logging
from ministack.core.responses import json_response, error_response_json, new_uuid
logger = logging.getLogger("myservice")
ACCOUNT_ID = "000000000000"
REGION = "us-east-1"
_state: dict = {} # in-memory storage
async def handle_request(method, path, headers, body, query_params):
target = headers.get("x-amz-target", "")
action = target.split(".")[-1] if "." in target else ""
try:
data = json.loads(body) if body else {}
except json.JSONDecodeError:
return error_response_json("SerializationException", "Invalid JSON", 400)
handlers = {
"OperationOne": _operation_one,
"OperationTwo": _operation_two,
}
handler = handlers.get(action)
if not handler:
return error_response_json("InvalidAction", f"Unknown action: {action}", 400)
return handler(data)
def _operation_one(data):
return json_response({"result": "ok"})
def _operation_two(data):
return json_response({})
def reset():
_state.clear()
Protocol guide:
- JSON services (DynamoDB, SecretsManager, Glue, Athena, Cognito, etc.) β use
json_response/error_response_json, route viaX-Amz-Target - XML/Query services (S3, SQS, SNS, IAM, STS, RDS, ElastiCache, EC2) β build XML responses, route via
Actionquery param; use_xml(status, root_tag, inner)pattern; verify field names against botocore shapes viaLoader().load_service_model() - REST services (Lambda, ECS, Route53) β route via URL path
2. Register in ministack/app.py
from ministack.services import myservice
SERVICE_REGISTRY = {
# ... existing ...
"myservice": {"module": "myservice"},
}
If the service needs aliases, add them in the registry entry.
3. Add detection to ministack/core/router.py
SERVICE_PATTERNS = {
# ... existing ...
"myservice": {
"target_prefixes": ["AWSMyService"], # for X-Amz-Target routing
"host_patterns": [r"myservice\."], # for host-based routing
},
}
Add any credential scope or Action-based routing as needed.
4. Add a fixture to tests/conftest.py
@pytest.fixture(scope="session")
def mysvc():
return make_client("myservice")
5. Add tests to tests/test_services.py
def test_myservice_operation_one(mysvc):
resp = mysvc.operation_one(Param="value")
assert resp["result"] == "ok"
Running Tests Locally
# Start the stack
docker compose up -d
# Install test dependencies
pip install boto3 pytest pytest-xdist duckdb docker cbor2
# Parallel-safe phase: run tests that are safe to run concurrently
pytest tests/ -v -n 4 --dist=loadfile -m "not serial"
# Serial/global-state phase: run tests that mutate runtime state or require isolation
pytest tests/ -v -m serial
# Run a specific service
pytest tests/ -v -k "cognito"
Code Conventions
- One file per service β keep everything for a service in
ministack/services/myservice.py - Imports β always
from ministack.core.responses import ..., neverfrom core.responses import ... - In-memory state β use module-level dicts (
_things: dict = {}) - reset() β every service must expose a
reset()that clears all module-level state; it's called by/_ministack/reset - No external AWS deps β no
boto3,botocore, oraws-sdkin service code - Minimal dependencies β
duckdbanddockerare optional; guard withtry/except ImportError - Error responses β match real AWS error codes and HTTP status codes as closely as possible
- Logging β
logger = logging.getLogger("servicename"); DEBUG for request details, INFO for significant events
Pull Request Checklist
- New service file in
ministack/services/ - Registered in
ministack/app.pySERVICE_REGISTRY - Detection patterns added to
ministack/core/router.py - Fixture added to
tests/conftest.py - Tests added and passing (
pytest tests/ -v) - Linting passes (
ruff check ministack/) - Service added to the table in
README.md - Entry added to
CHANGELOG.md
What We're Looking For
High-value contributions right now:
- CloudFront β distribution CRUD, invalidations, origin configuration
- CodeBuild / CodePipeline β CI/CD pipeline stubs
- AppSync β GraphQL API CRUD
- SQS FIFO β message group / deduplication support
- More Cognito flows β hosted UI, federated identity providers, custom auth triggers
Questions?
Open a GitHub Discussion or file an issue with the question label.