{"id":51508565,"url":"https://github.com/blackwell-systems/gcp-eventarc-emulator","last_synced_at":"2026-07-08T03:30:43.305Z","repository":{"id":348799322,"uuid":"1199957334","full_name":"blackwell-systems/gcp-eventarc-emulator","owner":"blackwell-systems","description":"Production-grade GCP Eventarc emulator with full API coverage (47 RPCs), CloudEvent routing, CEL conditions, and gRPC/REST support. Run Eventarc locally with no GCP credentials.","archived":false,"fork":false,"pushed_at":"2026-04-03T07:22:14.000Z","size":392,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-03T08:55:28.027Z","etag":null,"topics":["cloudevents","emulator","eventarc","gcp","golang","google-cloud","grpc","grpc-gateway","local-development","testing"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blackwell-systems.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-02T22:13:49.000Z","updated_at":"2026-04-03T07:22:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/blackwell-systems/gcp-eventarc-emulator","commit_stats":null,"previous_names":["blackwell-systems/gcp-eventarc-emulator"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/blackwell-systems/gcp-eventarc-emulator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blackwell-systems%2Fgcp-eventarc-emulator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blackwell-systems%2Fgcp-eventarc-emulator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blackwell-systems%2Fgcp-eventarc-emulator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blackwell-systems%2Fgcp-eventarc-emulator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blackwell-systems","download_url":"https://codeload.github.com/blackwell-systems/gcp-eventarc-emulator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blackwell-systems%2Fgcp-eventarc-emulator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35251015,"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-08T02:00:06.796Z","response_time":61,"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":["cloudevents","emulator","eventarc","gcp","golang","google-cloud","grpc","grpc-gateway","local-development","testing"],"created_at":"2026-07-08T03:30:42.665Z","updated_at":"2026-07-08T03:30:43.292Z","avatar_url":"https://github.com/blackwell-systems.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GCP Eventarc Emulator\n\n[![Blackwell Systems](https://raw.githubusercontent.com/blackwell-systems/blackwell-docs-theme/main/badge-trademark.svg)](https://github.com/blackwell-systems)\n[![Go Reference](https://pkg.go.dev/badge/github.com/blackwell-systems/gcp-eventarc-emulator.svg)](https://pkg.go.dev/github.com/blackwell-systems/gcp-eventarc-emulator)\n[![Go Version](https://img.shields.io/badge/go-1.24+-blue.svg)](https://go.dev/)\n[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)\n\n\u003e **Production-grade GCP Eventarc emulator** — full API surface (47 RPCs), CloudEvent routing with CEL conditions, and multi-protocol support (gRPC + REST + CloudEvents). Run Eventarc locally with no GCP credentials.\n\nImplements the full Eventarc v1 API surface (47 RPCs) plus the Publishing service, including CloudEvent routing, CEL-based trigger matching, and HTTP delivery in binary content mode. Optional IAM enforcement integrates with the local [GCP IAM control plane](https://github.com/blackwell-systems/gcp-iam-control-plane).\n\nEnables local development, integration testing, and CI pipelines for event-driven systems without requiring access to GCP.\n\n## Key Capabilities\n\n- Full Eventarc API surface (47 RPCs including Publishing + Operations)\n- CloudEvent routing with attribute filters and CEL condition evaluation\n- HTTP delivery in CloudEvents binary content mode (`ce-*` headers)\n- Triple protocol support: gRPC, REST (grpc-gateway), and CloudEvents\n- Optional IAM enforcement via local GCP IAM emulator\n- Drop-in compatibility with GCP SDKs (no code changes required)\n\n## Quick Start\n\n**Prerequisites:** Go 1.24+\n\n**For Docker-based workflows** (demo, sdk-demo): Docker with Compose plugin v2\n(`docker compose version`). Docker Desktop includes this by default. On Docker\nEngine, install the Compose plugin: https://docs.docker.com/compose/install/\n\n```bash\ngo install github.com/blackwell-systems/gcp-eventarc-emulator/cmd/server-dual@latest\nserver-dual\n```\n\ngRPC on `:9085`, REST on `:8085`.\n\n**Verify it works:**\n```bash\n# Create a trigger\ncurl -X POST \"http://localhost:8085/v1/projects/my-project/locations/us-central1/triggers?triggerId=my-trigger\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"eventFilters\": [\n      {\"attribute\": \"type\", \"value\": \"google.cloud.pubsub.topic.v1.messagePublished\"}\n    ],\n    \"destination\": {\n      \"httpEndpoint\": {\"uri\": \"http://localhost:3000/webhook\"}\n    }\n  }'\n\n# List triggers\ncurl \"http://localhost:8085/v1/projects/my-project/locations/us-central1/triggers\"\n\n# List providers\ncurl \"http://localhost:8085/v1/projects/my-project/locations/us-central1/providers\"\n```\n\n\u003e **Tip:** Pipe curl output through `| jq .` for formatted JSON.\n\n### Verify gRPC connectivity\n\n```bash\ngrpcurl -plaintext localhost:9085 list\n# -\u003e google.cloud.eventarc.v1.Eventarc\n# -\u003e google.cloud.eventarc.publishing.v1.Publisher\n# -\u003e google.longrunning.Operations\n```\n\nInstall grpcurl: https://github.com/fullstorydev/grpcurl\n\n### Health endpoints (REST and dual only)\n\n```bash\ncurl http://localhost:8085/healthz   # {\"status\":\"ok\"}\ncurl http://localhost:8085/readyz    # {\"status\":\"ok\"}\n```\n\nBoth return HTTP 200. Use these in Docker health checks, Kubernetes probes, or CI readiness scripts. The gRPC-only server (`server`) does not expose HTTP — probe it with `grpcurl list localhost:9085`.\n\n---\n\n## Architecture\n\n```\n                   ┌─────────────────────────────┐\n                   │     GCP SDK / gRPC Client    │\n                   └──────────────┬──────────────┘\n                                  │\n              ┌───────────────────┼───────────────────┐\n              │                   │                    │\n   ┌──────────▼──────────┐  ┌────▼─────┐  ┌──────────▼──────────┐\n   │  Eventarc Service   │  │   LRO    │  │  Publisher Service  │\n   │  (40 RPCs: CRUD     │  │  Store   │  │  (PublishEvents,    │\n   │   for 8 resources)  │  │          │  │   PublishChannel-   │\n   │                     │  │          │  │   ConnectionEvents) │\n   └──────────┬──────────┘  └──────────┘  └──────────┬──────────┘\n              │                                       │\n              │              ┌───────────┐            │\n              │              │   Router  │◄───────────┘\n              │              │ (match by │\n              │              │  filters  │\n              │              │  + CEL)   │\n              │              └─────┬─────┘\n              │                    │\n              │           ┌────────▼────────┐\n              │           │   Dispatcher    │\n              │           │  (HTTP POST,    │\n              │           │   binary mode,  │\n              │           │   ce-* headers) │\n              │           └────────┬────────┘\n              │                    │\n              │           ┌────────▼────────┐\n              │           │  HTTP Endpoint  │\n              │           │  (your service) │\n              └───────────┘  └───────────────┘\n```\n\n1. **Configure** — Create triggers with event filters and HTTP destinations via the Eventarc gRPC/REST API\n2. **Publish** — Send CloudEvents via the Publisher gRPC service\n3. **Route** — The router matches events against trigger filters and optional CEL conditions\n4. **Deliver** — The dispatcher HTTP POSTs to destinations using CloudEvents binary content mode (`ce-*` headers)\n\n---\n\n## API Coverage\n\nImplements the full Eventarc v1 API surface across triggers, channels, message buses, pipelines, and providers, along with the Publishing and Operations services (47 RPCs total).\n\nThe API surface is compatible with the official GCP Eventarc clients and follows the same request/response structure. See [docs/api.md](docs/api.md) for the full list of supported operations.\n\n---\n\n## Server Variants\n\n\u003e **Not sure which to pick?** Use `server-dual`. It does everything the others do.\n\n| Variant | Protocols | Best For |\n|---------|-----------|----------|\n| `server-dual` | gRPC + REST | Most users — works with SDKs and curl |\n| `server` | gRPC only | Go/Python/Java SDK users who want minimal overhead |\n| `server-rest` | REST/HTTP only | Shell scripts, curl, non-Go languages without gRPC |\n\n### Install\n\n**Docker (recommended):**\n```bash\ndocker build -t gcp-eventarc-emulator .\ndocker run -p 9085:9085 -p 8085:8085 gcp-eventarc-emulator\n```\n\n\u003e Note: The `docker compose` examples require Docker Compose plugin v2 (not the\n\u003e standalone `docker-compose` v1). Verify with `docker compose version`.\n\n**Go install:**\n```bash\n# gRPC only\ngo install github.com/blackwell-systems/gcp-eventarc-emulator/cmd/server@latest\n\n# REST API only\ngo install github.com/blackwell-systems/gcp-eventarc-emulator/cmd/server-rest@latest\n\n# Both protocols (recommended)\ngo install github.com/blackwell-systems/gcp-eventarc-emulator/cmd/server-dual@latest\n```\n\n### Run Server\n\n\u003e **Note:** Go accepts both `-flag` and `--flag`. Examples use `--` for clarity.\n\n**gRPC server:**\n```bash\nserver --port 9085\n```\n\n**REST server:**\n```bash\nserver-rest\n# gRPC (internal) on :9086, HTTP on :8085\n```\n\n**Dual protocol server:**\n```bash\nserver-dual\n# gRPC on :9085, HTTP on :8085\n```\n\n---\n\n## Use with GCP SDKs\n\nPoint your existing GCP SDK code at the emulator. No code changes needed beyond the connection setup.\n\n**Go:**\n```go\nimport (\n    eventarc \"cloud.google.com/go/eventarc/apiv1\"\n    \"google.golang.org/api/option\"\n    \"google.golang.org/grpc\"\n    \"google.golang.org/grpc/credentials/insecure\"\n)\n\nconn, _ := grpc.NewClient(\"localhost:9085\",\n    grpc.WithTransportCredentials(insecure.NewCredentials()),\n)\nclient, _ := eventarc.NewClient(ctx, option.WithGRPCConn(conn))\ndefer client.Close()\n\n// Use client normally — API is identical to real GCP\n```\n\n**Python:**\n```python\nfrom google.cloud import eventarc_v1\nimport grpc\n\nchannel = grpc.insecure_channel(\"localhost:9085\")\nclient = eventarc_v1.EventarcClient(\n    transport=eventarc_v1.transports.EventarcGrpcTransport(channel=channel)\n)\n```\n\n## Use with REST API\n\n```bash\n# Create a trigger that routes Pub/Sub events to your local service\ncurl -X POST \"http://localhost:8085/v1/projects/test/locations/us-central1/triggers?triggerId=pubsub-trigger\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"eventFilters\": [\n      {\"attribute\": \"type\", \"value\": \"google.cloud.pubsub.topic.v1.messagePublished\"}\n    ],\n    \"destination\": {\n      \"httpEndpoint\": {\"uri\": \"http://localhost:3000/events\"}\n    }\n  }'\n\n# Create a channel\ncurl -X POST \"http://localhost:8085/v1/projects/test/locations/us-central1/channels?channelId=my-channel\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'\n\n# List all triggers\ncurl \"http://localhost:8085/v1/projects/test/locations/us-central1/triggers\"\n```\n\n---\n\n## Event Routing \u0026 Delivery\n\n### How Events Are Matched\n\nWhen a CloudEvent is published via the Publisher service:\n\n1. **Attribute filters** — Each trigger's `eventFilters` are matched against the event's `type`, `source`, and extension attributes (exact match, all must pass)\n2. **CEL conditions** — If the trigger has a `condition` field, it's evaluated as a [CEL expression](https://github.com/google/cel-spec) against the event attributes\n3. **Delivery** — Matching triggers' destinations receive the event via HTTP POST\n\n### Binary Content Mode\n\nEvents are delivered using **CloudEvents binary content mode** (matching real GCP Eventarc behavior):\n\n```\nPOST /webhook HTTP/1.1\nContent-Type: application/json\nCe-Specversion: 1.0\nCe-Type: google.cloud.pubsub.topic.v1.messagePublished\nCe-Source: //pubsub.googleapis.com/projects/my-project/topics/my-topic\nCe-Id: abc-123\nCe-Subject: my-subject\n\n{\"subscription\":\"...\",\"message\":{\"data\":\"base64...\"}}\n```\n\nEvent attributes go in `Ce-*` HTTP headers; the payload goes in the body. This matches how real Eventarc delivers to Cloud Run and HTTP endpoints.\n\n### Authorization Token for Cloud Run\n\nSet the `EVENTARC_EMULATOR_TOKEN` environment variable to include an `Authorization: Bearer` header on all dispatched requests:\n\n```bash\nEVENTARC_EMULATOR_TOKEN=my-test-token server-dual\n```\n\nIf unset, no authorization header is added (fine for local HTTP test servers).\n\n---\n\n## Usage Modes\n\n**Standalone** — Run independently for Eventarc-only testing:\n```bash\nserver-dual\n```\n\n**With IAM Enforcement** — Run with IAM checks:\n```bash\nIAM_MODE=strict IAM_EMULATOR_HOST=localhost:8080 server-dual\n# Now requires valid permissions for all operations\n```\n\n**Orchestrated Ecosystem** — Use with [GCP IAM Control Plane](https://github.com/blackwell-systems/gcp-iam-control-plane):\n```bash\ngcp-emulator start\n# Eventarc + Secret Manager + KMS + IAM emulator\n# Single policy file, unified authorization\n```\n\n---\n\n## IAM Integration\n\nOptional permission checks using the [GCP IAM Emulator](https://github.com/blackwell-systems/gcp-iam-emulator). All 39 Eventarc operations have IAM permission mappings — see [docs/api.md](docs/api.md) for the full list.\n\n### Enforcement Modes\n\n| Scenario | `off` | `permissive` | `strict` |\n|----------|-------|--------------|----------|\n| No IAM emulator | Allow | Allow | Deny |\n| IAM unavailable | Allow | Allow | Deny |\n| No principal | Allow | Deny | Deny |\n| Permission denied | Allow | Deny | Deny |\n\n---\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `EVENTARC_EMULATOR_HOST` | `localhost:9085` | gRPC host:port |\n| `EVENTARC_HTTP_PORT` | `8085` | HTTP/REST port (server-rest, server-dual) |\n| `EVENTARC_EMULATOR_TOKEN` | *(unset)* | Bearer token for dispatched HTTP requests |\n| `GCP_MOCK_LOG_LEVEL` | `info` | Log level: debug, info, warn, error |\n| `IAM_MODE` | `off` | IAM enforcement: off, permissive, strict |\n| `IAM_EMULATOR_HOST` | `localhost:8080` | IAM emulator address |\n\n\u003e **Note:** `IAM_MODE` and `GCP_MOCK_LOG_LEVEL` use legacy prefixes for\n\u003e backward compatibility. A future release will standardize on `EVENTARC_` prefix.\n\n---\n\n## REST Gateway\n\nThe REST API is powered by [grpc-gateway v2](https://github.com/grpc-ecosystem/grpc-gateway), which transcodes HTTP/JSON requests to gRPC using the official Eventarc proto HTTP annotations. This means:\n\n- REST paths match the real GCP Eventarc REST API exactly\n- Request/response JSON matches GCP's format\n- Both the Eventarc service and Publisher service are exposed\n\n---\n\n## Demo\n\nRun the full loop — trigger creation, event publishing, and binary content mode delivery — using Docker:\n\n```bash\n# Start the emulator and a webhook receiver\ndocker compose up -d\n\n# Run the demo script\n./examples/demo.sh\n\n# See the delivered CloudEvent (binary content mode, Ce-* headers)\ndocker compose logs webhook\n\n# Tear down\ndocker compose down\n```\n\nThe demo creates triggers, channels, message buses, pipelines, and enrollments, then publishes a CloudEvent and shows it arriving at the webhook receiver with `Ce-*` headers.\n\n---\n\n## SDK Demo\n\nRun the full SDK workflow — list providers, create a trigger, publish a CloudEvent, and delete the trigger — using the official `cloud.google.com/go/eventarc` SDK:\n\n```bash\n# Terminal 1: start emulator\ngo run ./cmd/server-dual\n\n# Terminal 2: start webhook receiver (separate module)\ncd examples/webhook-receiver \u0026\u0026 go run main.go\n\n# Terminal 3: run the SDK demo\ncd examples/sdk-demo \u0026\u0026 EVENTARC_EMULATOR_HOST=localhost:9085 go run main.go\n```\n\nThe sdk-demo automatically creates `my-channel` before publishing. If you prefer to pre-create it manually:\n\n```bash\ncurl -X POST \"http://localhost:8085/v1/projects/my-project/locations/us-central1/channels?channelId=my-channel\" \\\n  -H \"Content-Type: application/json\" -d '{}'\n```\n\n---\n\n## Testing\n\n```bash\n# Run all tests\ngo test ./...\n\n# With race detector\ngo test -race ./...\n\n# Integration tests only\ngo test -v -run TestIntegration ./...\n```\n\n## Differences from GCP\n\n- In-memory storage (no persistence)\n- Immediate LRO resolution (no async operations)\n- Optional IAM enforcement (off by default)\n- No regional replication or constraints\n- Static provider list (seeded at startup)\n\nDesigned for local development and testing — not production use.\n\n---\n\n## Disclaimer\n\nThis project is not affiliated with, endorsed by, or sponsored by Google LLC or Google Cloud Platform. \"Google Cloud\", \"Eventarc\", and related trademarks are property of Google LLC. This is an independent open-source implementation for testing and development purposes.\n\n## Maintained By\n\nMaintained by **Dayna Blackwell** — founder of Blackwell Systems, building reference infrastructure for cloud and AI systems.\n\n[GitHub](https://github.com/blackwell-systems) · [LinkedIn](https://linkedin.com/in/dayna-blackwell) · [Blog](https://blog.blackwell-systems.com)\n\n## Related Projects\n\n- [**GCP IAM Control Plane**](https://github.com/blackwell-systems/gcp-iam-control-plane) — CLI to orchestrate the Local IAM Control Plane\n- [GCP Secret Manager Emulator](https://github.com/blackwell-systems/gcp-secret-manager-emulator) — IAM-enforced Secret Manager emulator\n- [GCP KMS Emulator](https://github.com/blackwell-systems/gcp-kms-emulator) — IAM-enforced KMS emulator\n- [GCP IAM Emulator](https://github.com/blackwell-systems/gcp-iam-emulator) — Policy engine for IAM enforcement\n- [gcp-emulator-auth](https://github.com/blackwell-systems/gcp-emulator-auth) — Enforcement proxy library\n\n---\n\n## License\n\nApache License 2.0 — See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblackwell-systems%2Fgcp-eventarc-emulator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblackwell-systems%2Fgcp-eventarc-emulator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblackwell-systems%2Fgcp-eventarc-emulator/lists"}