Skip to content

feat: Target Pods at CREATE time instead of workload objects#183

Merged
pdettori merged 3 commits into
rossoctl:mainfrom
cwiklik:feat/pod-level-webhook
Mar 10, 2026
Merged

feat: Target Pods at CREATE time instead of workload objects#183
pdettori merged 3 commits into
rossoctl:mainfrom
cwiklik:feat/pod-level-webhook

Conversation

@cwiklik

@cwiklik cwiklik commented Mar 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Change the mutating webhook from intercepting workload objects (Deployments, StatefulSets, DaemonSets, Jobs, CronJobs) to intercepting Pods at CREATE time. This follows the pattern used by Istio, Linkerd, and Vault Agent Injector, and eliminates GitOps drift caused by mutating workload objects stored in etcd.

  • Webhook handler decodes corev1.Pod directly — no workload switch/case
  • deriveWorkloadName() extracts a stable workload name from GenerateName
  • MutatingWebhookConfiguration targets pods in the core API group with CREATE only
  • objectSelector pre-filters on kagenti.io/type in [agent, tool] + kagenti.io/inject NotIn [disabled]
  • namespaceSelector requires kagenti-enabled: "true" label
  • reinvocationPolicy: IfNeeded for multi-webhook compatibility
  • ClusterRole: removed apps/batch permissions, added replicasets get/list/watch
  • Rollout script applies webhook config before image rollout to avoid race conditions
  • 5 Ginkgo webhook handler tests added
  • Documentation updated (ARCHITECTURE.md, README.md, CLAUDE.md)

Closes #176 (Phase 1 of 2 — Phase 2 is AgentRuntime CR integration, tracked in #177)

Test plan

  • make build passes
  • make test passes (5 new webhook handler tests + existing precedence tests)
  • Deployed to Kind cluster via webhook-rollout.sh — clean startup logs
  • End-to-end: agent Pod with kagenti.io/type=agent receives sidecars
  • End-to-end: Pod without label is not intercepted
  • CI passes
  • Reviewer validates Helm chart renders correctly (helm template)

cwiklik added 2 commits March 9, 2026 16:32
Change the mutating webhook from intercepting Deployments, StatefulSets,
DaemonSets, Jobs, and CronJobs to intercepting Pods at CREATE time.
This follows the pattern used by Istio, Linkerd, and Vault Agent Injector,
and eliminates GitOps drift caused by mutating workload objects in etcd.

Key changes:
- Webhook handler decodes corev1.Pod directly (no workload switch/case)
- deriveWorkloadName() extracts stable name from GenerateName
- MutatingWebhookConfiguration targets pods in core API group
- objectSelector pre-filters on kagenti.io/type + kagenti.io/inject
- namespaceSelector requires kagenti-enabled=true label
- reinvocationPolicy set to IfNeeded for multi-webhook compatibility
- ClusterRole updated: removed apps/batch perms, added replicasets
- Rollout script applies webhook config before image rollout (race fix)
- 5 Ginkgo webhook handler tests added

Closes rossoctl#176 (Phase 1)

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: cwiklik <cwiklikj@gmail.com>
- Add comment to deriveWorkloadName clarifying it returns the ReplicaSet
  name (not Deployment); Deployment-level resolution is Phase 2 (rossoctl#177)
- Handle edge case where both GenerateName and Name are empty (fall back
  to UID with warning log)
- Add table-driven tests for deriveWorkloadName (5 edge cases)
- Fix copyright year (2025 -> 2025-2026)
- Add nolint directives for standard Ginkgo/Gomega dot imports

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: cwiklik <cwiklikj@gmail.com>
@cwiklik cwiklik added the enhancement New feature or request label Mar 9, 2026
@cwiklik cwiklik self-assigned this Mar 9, 2026

@cwiklik cwiklik left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Well-structured architectural change moving the mutating webhook from workload-level to Pod-level interception. Removes significant complexity (multi-Kind switch), adds proper safety guards (Kind check, namespace opt-in, object selector), and includes 5 meaningful Ginkgo tests. Follows the proven pattern used by Istio, Linkerd, and Vault Agent Injector.

No blocking issues found. Suggestions below are non-blocking improvements.

Areas reviewed: Go, Helm/K8s, Shell, Docs, Security
Commits: 1 (signed off, Assisted-By correct)
CI status: pending at time of review

Verdict: APPROVE (submitted as COMMENT since author cannot self-approve)

Comment thread kagenti-webhook/internal/webhook/v1alpha1/authbridge_webhook.go
Comment thread kagenti-webhook/config/webhook/manifests.yaml

@pdettori pdettori left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Well-structured PR that follows the Istio/Linkerd pattern of mutating Pods at CREATE instead of workload objects. The code is significantly simpler, RBAC surface is reduced, and the rationale (GitOps drift elimination) is sound.

Areas reviewed: Go, Helm/K8s, Shell, Tests, Docs
Commits: 2 — both signed-off with Assisted-By trailer ✓
CI: Passing (CI Checks ✓, DCO ✓)

The main concern is the kagenti-enabled: "true" namespace selector being a breaking change for existing deployments — operators need a documented migration step. The test suite is a good start but the positive injection assertion may need a Get() re-fetch to be reliable against envtest behavior.

Verdict: COMMENT — one item needs attention (namespace migration path) but the design is solid.

Comment thread charts/kagenti-webhook/templates/authbridge-mutatingwebhook.yaml
Comment thread kagenti-webhook/config/webhook/manifests.yaml
Comment thread kagenti-webhook/internal/webhook/v1alpha1/authbridge_webhook.go Outdated
Comment thread kagenti-webhook/internal/webhook/v1alpha1/authbridge_webhook.go
- Re-fetch Pods after Create in all tests to assert on server-side
  mutations rather than in-memory state (false-pass prevention)
- Add UID fallback test entry for deriveWorkloadName
- Use structured logging (V(0).Info) instead of embedding severity
  in message string
- Document BREAKING CHANGE: namespaces now require kagenti-enabled=true
  label for injection — add migration step to README
- Rollout script labels AuthBridge demo namespace with kagenti-enabled=true

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: cwiklik <cwiklikj@gmail.com>

@pdettori pdettori left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@pdettori
pdettori merged commit 0b61c7e into rossoctl:main Mar 10, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request Ready for Review!

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

feature: Webhook: target Pods at CREATE time instead of workload objects

2 participants