controller: add A2AAgentRegistration CRD and reconciler - #3
Conversation
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
…nctions Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Signed-off-by: Aman-Cool <aman017102007@gmail.com>
…writers Signed-off-by: Aman-Cool <aman017102007@gmail.com>
…-gateway into a2a-crd-controller
|
Live verification done on Kind (Istio 1.27) against the tip... the fixed |
… receivers Signed-off-by: Aman-Cool <aman017102007@gmail.com>
Part of the A2A workshop (design: Kuadrant#1114, upstream issue: Kuadrant#766) ; this is Tasks 3-5 plus the minimal slice of Task 6 from the implementation plan — the CRD, the reconciler, and the config-writer plumbing it needs. Data-plane consumption of the a2aAgents config (MCPServersConfig field, loadConfig, broker observer) is deliberately NOT here.., that's Tasks 7/8, so the broker ignores the new config section until then.
The A2AAgentRegistration CRD mirrors MCPServerRegistration's machinery without cargo-culting its field set: agentPrefix (required, the /a2a/{prefix} routing key), targetRef, optional agentCardURL override, broker-only credentialRef, and state. Both agentPrefix and targetRef are immutable via CEL — retargeting a registration would leave the previous agent's config behind, so replacing an agent means replacing the registration (this also retires the TODO MCPServerRegistration carries about unhandled targetRef changes).
The reconciler follows the sibling controller's flow — finalizer-guarded config-first deletion, gateway/extension discovery with listener-attachment filtering, per-namespace config fan-out, the status no-op guard — with one deliberate strengthening: cross-namespace targetRef requires a ReferenceGrant in the route's namespace (from: A2AAgentRegistration, to: HTTPRoute), the same consent model MCPGatewayExtension uses and the boundary maleck13 called for on Kuadrant#1139. The controller watches ReferenceGrants (backed by a target-namespace index), and revoking a grant withdraws the previously written config rather than just flipping status.., consent withdrawn means exposure withdrawn. Everywhere else config stays last-known-good on failure, mirroring MCP, so transient errors never rip a live agent out of the data plane — the semantics are documented on the failure path.
Also here: the shared HTTPRoute gateway/endpoint helpers extracted to free functions so both registration controllers use them, config UpsertA2AAgent/RemoveA2AAgent with the same retry-on-conflict + skip-unchanged-write discipline, reference doc, sample, and the controller CLAUDE.md section.
Verification so far: 56/56 controller integration specs (envtest, --race) covering finalizer, happy path, deletion, disabled state, missing route, credentialRef paths incl. the required-label rejection, cross-namespace with and without a grant, grant revocation withdrawing config, and the CEL immutability rules ; kube-api-linter 0 issues ; generate-all idempotent. The earlier commits were verified end-to-end on a live Kind cluster (Ready=True, a2aAgents in the config Secret, deletion scrubbing) — the ReferenceGrant gate and immutability commits still need that live pass, which is the remaining item before this leaves draft. Findings from that run land here.