feat(kafka): multi-cluster support (named clusters + --cluster + v3 migrate)#45
Merged
Conversation
Brainstormed design (named kafka.clusters mirroring database.connections, --cluster flag, per-pattern/reactor cluster binding, v2->v3 + config migrate) and the 4-task implementation plan. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…de review) Batched application of 8 fixes from the 4-reviewer fan-out for the Multi-Cluster Kafka feature (PR #45). 1. discover no longer hard-fails on an unresolvable cluster: the kafka-patterns item-detail resolve_cluster_name call is wrapped so a ConfigError yields cluster=null (the item still renders topic/match/ params/example). A cluster-agnostic pattern with >1 cluster and no default_cluster passes validation, so an inspection command must not exit 2 on it. 2. resolve_cluster_name is now keyword-only (*, explicit=None, binding_cluster=None), mirroring the DB analog resolve_connection_name; all call sites updated to keyword form. 3. --cluster help shortened to "Cluster name override" across produce/consume/assert (the old text over-promised a single default source). 4. mock_run re-raises resolve_cluster_name failures with reactor context, so a dangling reactor.cluster / unresolvable cluster names the reactor. 5. migrate: comment at the v1 gate now states the missing/legacy-version assumption explicitly (do not broaden the gate). 6. migrate: _migrate_* helper rewrites param widened to list[dict[str, Any]] (structural rewrites carry non-str before/after). 7. Renamed test_mock_kafka_requires_resolvable_default_cluster_error to test_mock_kafka_reactor_no_clusters_error (accurate: builds no clusters). 8. Added test_kafka_consume_explicit_cluster (mirrors the produce test). Tests: covering (discover/kafka/mock/migrate/validator) 160 passed; full unit suite 964 passed (+2). Co-Authored-By: Claude <noreply@anthropic.com>
Following the discover cluster-resilience fix (f6901d0), the kafka-patterns discover.item now yields cluster: null (instead of exit 2) for a cluster-agnostic pattern with >1 cluster and no default_cluster. The discover.item shape contract now reflects this nullable case. Co-Authored-By: Claude <noreply@anthropic.com>
The v2->v3 version bump (Task 1) migrated unit fixtures but missed the inline integration configs in test_logs_commands.py, test_mock_daemon.py, and test_mock_commands.py (_build_config + reactor e2e). They still had version: "2" / flat kafka, so the v3 guard rejected them at load -> "Config dialect v2 is no longer supported". CI (full suite) caught what unit-only review runs missed. Bump to v3 + convert flat kafka to clusters. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds support for multiple named Kafka clusters in one
agctl.yaml, mirroring the existingdatabase.connectionsmodel. PreviouslyConfig.kafkawas a single object (one broker set, one TLS block) — asymmetric withdatabase.connections/services/logs.sources, which are all named maps.What changed
kafka:restructured from a single object tokafka.clusters.<name>(named map, each withbrokers/ssl/timeout_seconds/default_consumer_group/schema_registry_url) +kafka.default_cluster.KafkaClustermodel;KafkaSSLreused unchanged.resolve_cluster_namemirrorsresolve_connection_name(db_commands.py): precedence--cluster> pattern/reactor.cluster>kafka.default_cluster> single-cluster auto-default.new_kafka_client(cluster, …)now takes a resolvedKafkaCluster.--cluster <name>onkafka produce/consume/assert;kafka assert --patternresolves both topic and cluster from the pattern.MockEnginetakes a per-reactor client map (kafka_clients: dict[reactor_name→client]); eachmocks.kafka.reactors.<name>can target its own cluster via an optionalclusterfield.config migrate— lifts a flatkafka:block intokafka.clusters.default, handles v1→v3 (jq + structural, one pass) and v2→v3 (structural only — v2 exprs are already envelope-rooted, so no double-prefix). Bumpsversionto"3". Envelope keyalready_v2→already_current.kafka-patternsitem detail surfaces the resolved cluster.skills/synced to v3.2 → 3)A
version: "2"(or"1") config is now rejected at load with a pointer to migrate. Run:agctl config migrate # backs up to <path>.bak, lifts kafka → clusters, bumps to v3The migration is non-mutating on input, idempotent on v3, and safe for v1 and v2 sources.
Testing
migrate_config(v1/v2→v3 one-pass, idempotency, non-mutation), validator per-cluster cross-refs, per-cluster mock-reactor wiring + shared-cluster client reuse, discover cluster surfacing, and the v1/v2cli_flags_notegate.require_kafkasuite runs against the default cluster unchanged; a new self-skippingrequire_kafka_second_brokerround-trip is gated onAGCTL_TEST_KAFKA_BROKER_2.confluent_kafkainstalled (fakes), per convention.Review
Per-task reviews (sonnet) all Approved; final whole-branch review (opus) verdict Ready to merge — with fixes. The single Important finding (
config migrate'scli_flags_noteunconditionally told v2→v3 migrators to prefix.body |/.value |on CLI flags, which would double-prefix working scripts) was fixed by gating that advice on v1 sources only (commit55e606c). No Critical issues.Spec / Plan
docs/superpowers/specs/active/2026-07-09-agctl-kafka-multi-cluster-design.mddocs/superpowers/plans/active/2026-07-09-agctl-kafka-multi-cluster.md(These stay in
active/until the PR merges, then move toarchive/as ADRs.)🤖 Generated with Claude Code