{"id":51439712,"url":"https://github.com/redscaresu/fakeaws","last_synced_at":"2026-07-05T10:01:53.471Z","repository":{"id":359835428,"uuid":"1247692056","full_name":"redscaresu/fakeaws","owner":"redscaresu","description":"SQLite-backed mock server simulating AWS APIs across 5 wire formats (Query-RPC, JSON 1.0/1.1, REST/XML, REST/JSON). Deterministic terraform-provider-aws compatibility for offline IaC validation. Companion to infrafactory.","archived":false,"fork":false,"pushed_at":"2026-06-11T09:48:46.000Z","size":524,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-11T11:21:33.374Z","etag":null,"topics":["aws","golang","infrastructure-as-code","mock-server","opentofu","sqlite","terraform"],"latest_commit_sha":null,"homepage":"https://github.com/redscaresu/infrafactory","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/redscaresu.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-23T16:45:48.000Z","updated_at":"2026-06-11T09:48:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/redscaresu/fakeaws","commit_stats":null,"previous_names":["redscaresu/fakeaws"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/redscaresu/fakeaws","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redscaresu%2Ffakeaws","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redscaresu%2Ffakeaws/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redscaresu%2Ffakeaws/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redscaresu%2Ffakeaws/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/redscaresu","download_url":"https://codeload.github.com/redscaresu/fakeaws/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redscaresu%2Ffakeaws/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35150063,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","golang","infrastructure-as-code","mock-server","opentofu","sqlite","terraform"],"created_at":"2026-07-05T10:01:52.686Z","updated_at":"2026-07-05T10:01:53.461Z","avatar_url":"https://github.com/redscaresu.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fakeaws\n\n[![CI](https://github.com/redscaresu/fakeaws/actions/workflows/ci.yml/badge.svg)](https://github.com/redscaresu/fakeaws/actions/workflows/ci.yml)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n[![Go 1.25+](https://img.shields.io/badge/Go-1.25%2B-00ADD8?logo=go)](go.mod)\n\nA local Go-based mock of the AWS HTTP API surface, sibling to\n[mockway](https://github.com/redscaresu/mockway) (Scaleway),\n[fakegcp](https://github.com/redscaresu/fakegcp) (GCP), and\n[fakegenesys](https://github.com/redscaresu/fakegenesys) (Genesys Cloud CCaaS).\n\nThe goal: give `terraform-provider-aws` an HTTP server it can hit during\n`tofu apply`, so [infrafactory](https://github.com/redscaresu/infrafactory)\ncan drive AWS-flavoured scenarios end-to-end without ever calling the\nreal cloud.\n\nLocalStack used to fill this niche but has consolidated into a paid\nproduct (April 2026). fakeaws keeps the freedom-to-modify, freedom-to-\nfork story alive — narrow in coverage, deep in the few services we ship.\n\n## Status\n\nTen services across five wire formats. The S43–S48 codex review loop\nclosed at pass 17 with zero allowlist entries; post-S48 polish landed\nthe M51 Query-RPC envelope rewrite, M57 per-resource field parity, M61\nfull RDS lifecycle, M62 full Secrets Manager lifecycle, and the\n2026-05-30/31 self-learning-sweep coverage burst — ~17 missing\nendpoints + envelope/error-code mismatches resolved (EC2 wire shape\ncorrection, DescribeInstanceTypes / DescribeTags / DescribeInstanceAttribute\n/ DescribeRouteTables routeSet+associationSet / ModifySubnetAttribute,\nDynamoDB DescribeContinuousBackups + DescribeTimeToLive, eight Route53\nfixes, IAM destroy preflight + managed-ARN auto-seed, full KMS handler).\nThe 17 review passes are archived under `docs/review-passes/passN.md`.\n\n| Service | Wire format | Endpoint | TF lifecycle |\n| ------- | ----------- | -------- | ------------ |\n| IAM | Query-RPC + XML | `POST /iam` | apply / plan-no-op / destroy ✓ — managed-ARN auto-seed, user/role inline policies, attached-policy preflight |\n| S3 | XML REST | `/s3/\u003cbucket\u003e/\u003ckey\u003e?\u003csub-resource\u003e` | apply / plan-no-op / destroy ✓ (S3 bucket sub-resource reads are limited — for `terraform-provider-aws`'s full Read flow infrafactory pairs fakeaws with SeaweedFS, see M59) |\n| EC2 | Query-RPC + XML (`ShapeEC2Query` envelope) | `POST /ec2/region/\u003cregion\u003e` | VPC + Subnet + IGW + RouteTable + Route + EIP + SG + Instance + KeyPair + AMI fixture; full lifecycle ✓ — InvalidGroup.NotFound / InvalidInstanceID.NotFound / InvalidRouteTableID.NotFound destroy-wait codes, AMI auto-seed, terminated-instance GC on subnet delete |\n| RDS | Query-RPC + XML | `POST /rds/region/\u003cregion\u003e` | DB Instance + Subnet/Parameter/Cluster Groups + Clusters; full lifecycle ✓ (M61: DbiResourceId stability, service-specific 404 codes, DeleteDBInstance envelope, user-field persistence) |\n| DynamoDB | JSON 1.1 + X-Amz-Target | `POST /dynamodb/region/\u003cregion\u003e` | apply / plan-no-op / destroy ✓ — refresh-path DescribeContinuousBackups + DescribeTimeToLive |\n| EKS | JSON-REST | `/eks/region/\u003cregion\u003e/clusters/...` | cluster + node group; full lifecycle ✓ |\n| SQS | JSON 1.0 + X-Amz-Target | `POST /sqs/region/\u003cregion\u003e` | apply / plan-no-op / destroy ✓ |\n| Route53 | XML REST | `/route53/2013-04-01/...` | hosted zone + record set; full lifecycle ✓ — DelegationSet/NameServers, ListTagsForResource, GetDNSSEC, rrset filter + trailing-dot normalisation |\n| Secrets Manager | JSON 1.1 + X-Amz-Target | `POST /secretsmanager/region/\u003cregion\u003e` | apply / plan-no-op / destroy ✓ (M62: ARN-or-name SecretId, epoch timestamps, VersionIdsToStages, GetResourcePolicy + ListSecretVersionIds) |\n| KMS | JSON 1.1 + X-Amz-Target | `POST /kms/region/\u003cregion\u003e` | apply / plan-no-op / destroy ✓ — CreateKey / DescribeKey / GetKeyPolicy / ListAliases / ListResourceTags / EnableKeyRotation / GetKeyRotationStatus / TagResource / ScheduleKeyDeletion / CancelKeyDeletion / EnableKey / DisableKey; in-memory keyed state, **soft-delete** on schedule (KeyState transitions to `PendingDeletion`; DescribeKey returns 200 with that state — matches real AWS lifecycle so `terraform-provider-aws`'s destroy wait-loop completes cleanly) |\n\nPer-resource details + load-bearing FK contracts live in `PLAN.md`;\nthe M61/M62 wire-shape lessons are documented in `AGENTS.md` under\n\"Provider-wait-state-machine debugging\".\n\n## Quickstart\n\n```bash\ngo mod download\nmake install-hooks   # second step after clone — wires .githooks/pre-commit\ngo test ./...\n```\n\n`make install-hooks` is idempotent — re-running is a no-op. The hook\nruns `gitleaks protect --staged --no-banner` *before* `go test ./...`,\nso secret detection short-circuits the commit before tests have a\nchance to print env vars to terminal logs.\n\n### One-shot demo (with sibling repos)\n\nIf you've cloned the four-repo layout, the easiest way to see fakeaws\nin action is via [`infrafactory`](https://github.com/redscaresu/infrafactory)'s\n`make up`:\n\n```bash\ncd ~/dev \u0026\u0026 for r in infrafactory fakeaws fakegcp fakegenesys mockway; do git clone https://github.com/redscaresu/$r.git; done\ncd infrafactory \u0026\u0026 make up\n./bin/infrafactory run scenarios/training/aws-s3.yaml --config infrafactory.yaml   # drives fakeaws end-to-end\nmake down\n```\n\nThat brings up fakeaws on `:8082`, exercises an AWS scenario through\n`tofu apply → test → destroy`, and tears everything down.\n\n## Run\n\n```bash\nmake build \u0026\u0026 ./fakeaws --port 8082 --db :memory:\n# or with logging of every method+path (useful when discovering\n# unimplemented endpoints during provider integration testing):\n./fakeaws --port 8082 --echo\n```\n\n### Docker\n\nPre-built multi-arch images are published to GitHub Container Registry on every push to `main`:\n\n```bash\ndocker run --rm -p 8082:8082 ghcr.io/redscaresu/fakeaws:latest --port 8082\n```\n\nThe Dockerfile in the repo root produces a `~15MB` static image (multi-stage build from `golang:1.25-alpine`).\n\n### Driving real terraform/tofu against the mock\n\nThe repo ships `make demo-*` targets that wire up the env + drive a real\n`hashicorp/aws` provider through a full lifecycle against fakeaws.\nUseful for blog demos and manual exploration.\n\n```bash\nmake build              # one-time\nmake demo-apply         # boots fakeaws + init + apply + plan-no-op (sqs_queue)\nmake demo-apply EXAMPLE=iam_role\nmake demo-shell         # bash subshell with env set + cd'd to example\nmake demo-help          # full target list + available examples\nmake demo-down          # kill fakeaws + clean temp files\n```\n\nThe `plan -detailed-exitcode == 0` check at the end of `demo-apply` is the\ncorrectness oracle — drift in any wire-shape detail (case-sensitive JSON\nkeys, exact status codes, default fields) surfaces here.\n\n## Provider version pin\n\nThis mock targets `hashicorp/aws ~\u003e 5.70`. Bumps require an explicit PR\nthat updates this README, every `examples/*/required_providers` block,\nevery `prompts/aws/*.md` template, and the e2e harness's provider\nconfig — together. Single source of truth for the constraint string is\n`coverage_matrix.yaml`'s header comment.\n\n## Testing examples\n\nThe canonical entry point for end-to-end example coverage is `go test ./examples/...`:\n\n```bash\n# Run every example end-to-end (apply → plan-no-op → destroy)\nINFRAFACTORY_ENABLE_E2E=1 go test ./examples/...\n\n# Run one specific example, with verbose output\nINFRAFACTORY_ENABLE_E2E=1 go test ./examples/... -v -run TestProviderSmokeWorking/\u003cdir\u003e\n\n# Filter to a single sub-tree\nINFRAFACTORY_ENABLE_E2E=1 go test ./examples/... -run TestProviderSmokeMisconfigured\n```\n\nThe harness assumes a fakeaws server is reachable at `FAKEAWS_URL`\n(default `http://127.0.0.1:8082`); CI runs it after `make fakeaws-up`\nfrom the infrafactory Makefile. fakeaws is the canonical\nimplementation of the in-test apply-matrix pattern across the family\n— `mockway`, `fakegcp`, and `fakegenesys` all mirror this shape.\n\nThe same in-test pattern is canonical across all four sibling fakes\n([mockway](https://github.com/redscaresu/mockway),\n[fakegcp](https://github.com/redscaresu/fakegcp),\n[fakegenesys](https://github.com/redscaresu/fakegenesys)) — `go test`\nagainst the smoke harness works identically in each.\n\n## API compatibility\n\nThe point of fakeaws is to be wire-shape compatible with the real `hashicorp/aws` provider — every byte the provider sends or expects to receive must match what real AWS would do, or the provider detects \"drift\" and the apply loop fails. Three guardrails enforce this; they're identical across [`mockway`](https://github.com/redscaresu/mockway) (Scaleway), [`fakegcp`](https://github.com/redscaresu/fakegcp) (GCP), and [`fakeaws`](https://github.com/redscaresu/fakeaws) (AWS).\n\n### 1. Three example trees, auto-discovered\n\nEvery directory under `examples/` is an executable contract against a real Terraform/OpenTofu provider:\n\n| Tree | Contract |\n|---|---|\n| `examples/working/\u003csvc\u003e/` | `apply → plan -detailed-exitcode 0 → destroy` — second plan MUST be a no-op |\n| `examples/misconfigured/\u003csvc\u003e/` | `apply` MUST fail with the documented AWS error code; if `expected.txt` is present, the error output MUST contain that fragment |\n| `examples/updates/\u003csvc\u003e/` | `apply -var-file=v1.tfvars → plan no-op → apply -var-file=v2.tfvars → plan no-op → destroy` |\n\n`examples/provider_smoke_test.go` walks the three trees with `runtime.Caller` and registers each subdirectory as its own `t.Run` sub-test. Adding a directory adds a test — no per-example test wiring. The harness assumes a fakeaws server is reachable at `FAKEAWS_URL` (default `http://127.0.0.1:8082`); CI runs it after `make fakeaws-up` from the infrafactory Makefile.\n\nThe **idempotency gate** (`plan -detailed-exitcode 0`) is the strongest compatibility signal: if fakeaws returns a single field with the wrong case, type, or default, the provider sees drift on the second plan and the test fails. Wire-shape parity across the nine S43–S48 services (S3, IAM, EC2, VPC, RDS, DynamoDB, SQS, Route53, Secrets Manager) was closed by the 17-pass codex review loop driving this gate.\n\n### 2. No allowlist — every example must pass\n\nmockway and fakegcp use an `examples/known_broken.yaml` ratchet for examples whose idempotency gate is currently expected to fail. fakeaws does not: the S43–S48 codex review loop closed at pass 17 with zero allowlist entries, so the smoke harness enforces the working-tree contract strictly. Any new example that drifts must be fixed before merge, not allowlisted. If a regression batch ever needs an allowlist, copy the pattern from `fakegcp/examples/provider_smoke_test.go` (ratchet-only-tighten: entries can only be REMOVED).\n\n### 3. Cross-repo e2e from infrafactory\n\n[`infrafactory`](https://github.com/redscaresu/infrafactory) builds fakeaws from this source tree on a free port for every gated AWS e2e test (`TestE2E_AWS*` in `internal/e2e/`, gated by `INFRAFACTORY_ENABLE_E2E=1`). Those tests drive scenarios end-to-end through infrafactory's harness (plan → mock-apply → topology derivation → destroy), so a compatibility regression surfaces in two places: the local `INFRAFACTORY_ENABLE_E2E=1 go test ./examples/...` and the upstream infrafactory CI.\n\n### Adding coverage for a new resource\n\n1. Add an `examples/working/\u003csvc\u003e/` directory with `providers.tf` + `main.tf`.\n2. Run `INFRAFACTORY_ENABLE_E2E=1 go test ./examples/...` — auto-discovery picks it up.\n3. If it drifts: either fix the handler, or (if the fix is non-trivial) add a `known_broken.yaml` entry pointing at a new BACKLOG ticket.\n4. Mirror with `examples/misconfigured/\u003csvc\u003e/` (FK / validation paths) and `examples/updates/\u003csvc\u003e/` (update paths) as the service warrants.\n5. Add a `TestE2E_AWS\u003cSvc\u003e` in infrafactory's `internal/e2e/aws_services_test.go` so the cross-repo gate covers the scenario flow too.\n6. Append the service id to `LandedServices` in `handlers/regression_manifest.go`. This trips infrafactory's `TestCrossRepoParity_EveryLandedServiceHasScenario` (in its `internal/e2e/cross_repo_parity_test.go`) until either (a) a `scenarios/training/aws-\u003csvc\u003e.yaml` is added on the infrafactory side AND a `cloudParityMap[\"aws\"][\"\u003csvc\u003e\"]` entry pointing at it lands in the same PR, or (b) the service is added to that test's `exempt` map with a written reason (only appropriate for read-only / meta APIs with no standalone resource type). The parity test runs in infrafactory CI on every push, so landing here without the upstream change will break the badge — coordinate the two PRs.\n\n## Documentation\n\n- [`concepts.md`](concepts.md) — load-bearing design doc (pre-flight\n  checklist, service surface, wire-format strategy, anti-patterns,\n  resolved decisions).\n- [`AGENTS.md`](AGENTS.md) — fresh-agent entry point: layout,\n  conventions, anti-patterns, where to look for AWS resource shapes,\n  and the M61/M62 \"Provider-wait-state-machine debugging\" recipe.\n- [`PLAN.md`](PLAN.md) — phase-by-phase delivery history with the\n  FK-chain analyses that gated handler ordering.\n- [`CONTRIBUTING.md`](CONTRIBUTING.md) — PR contract, quality gates,\n  pre-commit hook setup.\n- [`docs/review-passes/passN.md`](docs/review-passes/) — codex review\n  prompts and findings archived per pass; 17 passes preserved\n  alongside the implementation history.\n- [`examples/README.md`](examples/README.md) — quickstart for running\n  the auto-discovered example tree against a live fakeaws.\n- [`infrafactory's auto-learning loop`](https://github.com/redscaresu/infrafactory/blob/main/docs/auto-learning-loop.md)\n  — deep-dive on how infrafactory turns fakeaws failures (and its\n  own LLM-generated HCL mistakes) into durable pitfalls that improve\n  future runs. Worked example: the `aws_subnet\n  map_public_ip_on_launch` pitfall was auto-learned from an\n  iter-pair diff against fakeaws's EC2 surface.\n\n## Non-goals\n\n- No SigV4 *validation* — we accept any `Authorization` header.\n- No real S3 object payload store — buckets and bucket-level config\n  are modelled; PutObject body is discarded.\n- No CloudFormation, Lambda, KMS-as-a-service, EventBridge.\n- No Smithy → Go codegen pipeline. Hand-written handlers, like the\n  other two mocks.\n\n## License\n\nApache 2.0 — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredscaresu%2Ffakeaws","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredscaresu%2Ffakeaws","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredscaresu%2Ffakeaws/lists"}