Skip to content

Commit fe11524

Browse files
coderabbitai[bot]CodeRabbit
andauthored
fix: apply CodeRabbit auto-fixes
Fixed 15 file(s) based on 20 unresolved review comments. Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
1 parent 6d54444 commit fe11524

15 files changed

Lines changed: 208 additions & 64 deletions

File tree

.agents/skills/agentrax-context/SKILL.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ name: agentrax-context
33
description: Project context and settled architecture decisions for the Agentrax Kubernetes operator (module agentrax.io/v1alpha1, repo agentrax). Always consult this before writing, reviewing, or reasoning about any code in this repository — CRD types, the reconciler, the rollout controller, the autoscaler, the quota webhook, or the MCP registry — so implementation stays consistent with the design doc instead of drifting or re-deriving decisions that are already settled. Trigger on any mention of AgentDeployment, TenantQuota, canary rollout, or this repo's controllers, even if the user doesn't name the skill directly.
44
---
55

6+
# Agentrax Context Skill
7+
68
> When uncertain about any architecture decision, defer to `docs/ARCHITECTURE.md` rather than improvising. Don't guess when the doc has the answer.
79
810
## Non-negotiable terminology
@@ -26,7 +28,7 @@ description: Project context and settled architecture decisions for the Agentrax
2628
| Package | Responsibility |
2729
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
2830
| `api/v1alpha1/` | CRD Go types, validation markers, defaulting. No business logic. |
29-
| `internal/controller/` | Reconcile loops. Only code that calls the Kubernetes API for core owned resources. |
31+
| `internal/controller/` | Reconcile loops. Only code that calls the Kubernetes API for core-owned resources. |
3032
| `internal/rollout/` | Canary state machine and PromQL threshold evaluation. |
3133
| `internal/scaling/` | HPA generation and quota-capped scaling logic. |
3234
| `internal/registry/` | MCP registrar, registry HTTP handler, TTL sweep. |

README.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,14 @@ flowchart TB
9494
cd agentrax
9595
```
9696

97-
2. **Install cluster dependencies** (cert-manager, Prometheus Operator, Gateway API CRDs):
97+
2. **Install cluster dependencies** (cert-manager, Prometheus Operator, Gateway API CRDs, and Prometheus Adapter):
9898

9999
```bash
100100
make deploy-deps
101101
```
102102

103+
Note: Prometheus Adapter installation instructions are printed by `make deploy-deps`. Follow the displayed guidance to complete the metrics pipeline setup.
104+
103105
3. **Install Agentrax CRDs:**
104106

105107
```bash
@@ -113,6 +115,7 @@ flowchart TB
113115
```
114116

115117
5. **Verify the operator is running:**
118+
116119
```bash
117120
kubectl get pods -n agentrax-system
118121
```
@@ -245,14 +248,16 @@ curl -s http://localhost:9090/agents | jq .
245248
]
246249
```
247250

251+
The `ttl` field is expressed in nanoseconds (e.g., `90000000000` = 90 seconds).
252+
248253
### Endpoints
249254

250-
| Method | Path | Description |
251-
| -------- | ---------------------------- | ----------------------------------------------------------------- |
252-
| `GET` | `/agents` | List all active, non-expired registered agents. |
253-
| `GET` | `/agents/{namespace}/{name}` | Get details and discovered tool capabilities of a specific agent. |
254-
| `POST` | `/agents` | Register or update an agent entry directly. |
255-
| `DELETE` | `/agents/{namespace}/{name}` | Deregister an agent from the registry store. |
255+
| Method | Path | Description |
256+
| -------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
257+
| `GET` | `/agents` | List all active, non-expired registered agents. |
258+
| `GET` | `/agents/{namespace}/{name}` | Get details and discovered tool capabilities of a specific agent. |
259+
| `POST` | `/agents` | Directly register or update an agent entry (bypasses MCP handshake; for administrative use or testing, not normal operation). |
260+
| `DELETE` | `/agents/{namespace}/{name}` | Deregister an agent from the registry store. |
256261

257262
---
258263

charts/agentrax/templates/deployment.yaml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,27 +58,31 @@ spec:
5858
valueFrom:
5959
fieldRef:
6060
fieldPath: metadata.namespace
61+
- name: AGENTRAX_REGISTRY_TTL
62+
value: {{ .Values.registry.ttl | default "90s" | quote }}
63+
- name: AGENTRAX_MCP_HEALTH_INTERVAL
64+
value: {{ .Values.mcp.healthInterval | default "30s" | quote }}
6165
{{- range $key, $val := .Values.env }}
6266
- name: {{ $key }}
6367
value: {{ $val | quote }}
6468
{{- end }}
6569
ports:
6670
- name: registry
67-
containerPort: 9090
71+
containerPort: {{ .Values.registry.bindPort | default 9090 }}
6872
protocol: TCP
6973
- name: health
70-
containerPort: 8081
74+
containerPort: {{ .Values.manager.healthProbeBindPort | default 8081 }}
7175
protocol: TCP
7276
livenessProbe:
7377
httpGet:
7478
path: /healthz
75-
port: 8081
79+
port: {{ .Values.manager.healthProbeBindPort | default 8081 }}
7680
initialDelaySeconds: 15
7781
periodSeconds: 20
7882
readinessProbe:
7983
httpGet:
8084
path: /readyz
81-
port: 8081
85+
port: {{ .Values.manager.healthProbeBindPort | default 8081 }}
8286
initialDelaySeconds: 5
8387
periodSeconds: 10
8488
resources:

charts/agentrax/templates/registry-service.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ spec:
1313
ports:
1414
- name: registry
1515
port: {{ .Values.registry.service.port | default 9090 }}
16-
targetPort: 9090
16+
targetPort: {{ .Values.registry.bindPort | default 9090 }}
1717
protocol: TCP

charts/agentrax/values.yaml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ manager:
6868
metricsBindAddress: "0"
6969
# -- Bind address for health/readiness probes.
7070
healthProbeBindAddress: ":8081"
71+
# -- Bind port for health/readiness probes (referenced by liveness/readiness probes).
72+
healthProbeBindPort: 8081
7173
# -- GPU resource name used for quota calculation.
7274
gpuResourceName: "nvidia.com/gpu"
7375

@@ -94,6 +96,8 @@ registry:
9496
type: ClusterIP
9597
# -- Bind address for the in-operator registry HTTP server
9698
bindAddress: ":9090"
99+
# -- Bind port for the registry HTTP server (referenced by container port and targetPort).
100+
bindPort: 9090
97101
# -- Registry entry TTL (e.g. "90s")
98102
ttl: "90s"
99103

@@ -103,6 +107,5 @@ mcp:
103107
healthInterval: "30s"
104108

105109
# -- Environment variables injected into the manager container.
106-
env:
107-
AGENTRAX_MCP_HEALTH_INTERVAL: "30s"
108-
AGENTRAX_REGISTRY_TTL: "90s"
110+
# These values are automatically populated from registry.ttl and mcp.healthInterval above.
111+
env: {}

cmd/main.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,24 @@ func main() {
217217
registryNamespace = "agentrax-system"
218218
}
219219

220+
registryTTL := registry.DefaultTTL
221+
if v := os.Getenv("AGENTRAX_REGISTRY_TTL"); v != "" {
222+
if parsed, err := time.ParseDuration(v); err == nil {
223+
registryTTL = parsed
224+
} else {
225+
setupLog.Error(err, "invalid AGENTRAX_REGISTRY_TTL, using default", "default", registry.DefaultTTL)
226+
}
227+
}
228+
229+
mcpHealthInterval := 60 * time.Second
230+
if v := os.Getenv("AGENTRAX_MCP_HEALTH_INTERVAL"); v != "" {
231+
if parsed, err := time.ParseDuration(v); err == nil {
232+
mcpHealthInterval = parsed
233+
} else {
234+
setupLog.Error(err, "invalid AGENTRAX_MCP_HEALTH_INTERVAL, using default", "default", mcpHealthInterval)
235+
}
236+
}
237+
220238
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
221239
Scheme: scheme,
222240
Metrics: metricsServerOptions,
@@ -272,7 +290,7 @@ func main() {
272290
}
273291

274292
// Initialize MCP discovery registry and registrar.
275-
mcpRegistry := registry.NewRegistry(mgr.GetClient(), registryNamespace, registry.DefaultTTL)
293+
mcpRegistry := registry.NewRegistry(mgr.GetClient(), registryNamespace, registryTTL)
276294
mcpRegistrar := registry.NewRegistrar(mcpRegistry, registry.NewHTTPMCPClient())
277295

278296
if registryAddr != "" && registryAddr != "0" {
@@ -287,11 +305,12 @@ func main() {
287305
}
288306

289307
agentDeploymentReconciler := &controller.AgentDeploymentReconciler{
290-
Client: mgr.GetClient(),
291-
Scheme: mgr.GetScheme(),
292-
GPUResourceName: gpuResourceName,
293-
CanaryController: canaryController,
294-
Registrar: mcpRegistrar,
308+
Client: mgr.GetClient(),
309+
Scheme: mgr.GetScheme(),
310+
GPUResourceName: gpuResourceName,
311+
CanaryController: canaryController,
312+
Registrar: mcpRegistrar,
313+
MCPHealthInterval: mcpHealthInterval,
295314
}
296315
if canaryController != nil {
297316
canaryController.Registrar = mcpRegistrar

config/manager/kustomization.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
55
kind: Kustomization
66
images:
77
- name: controller
8-
newName: example.com/agentrax
9-
newTag: v0.1.0
8+
newName: ghcr.io/gitcommitankit/agentrax
9+
newTag: latest

docs/ARCHITECTURE.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,16 @@ flowchart TB
8989

9090
The repository enforces strict directional boundaries to prevent circular dependencies and isolate business logic from Kubernetes plumbing:
9191

92-
| Package | Scope & Responsibility | Key Invariants |
93-
| ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
94-
| [`api/v1alpha1/`](file:///home/ankit/workspace/my-projects/agentrax/api/v1alpha1) | CRD type definitions, OpenAPI markers, schema validation rules, and status condition constants. | **Zero business logic**; only struct declarations and generated deep-copy methods. |
95-
| [`internal/controller/`](file:///home/ankit/workspace/my-projects/agentrax/internal/controller) | Controller-runtime reconcile loops (`AgentDeployment`, `TenantQuota`). | Only layer that executes write calls against the Kubernetes API. Consumes subsystems via interfaces. |
96-
| [`internal/quota/`](file:///home/ankit/workspace/my-projects/agentrax/internal/quota) | Quota arithmetic and concurrency-safe in-flight reservation cache. | Pure arithmetic; mutex-guarded state map; zero direct API server network calls in calculation paths. |
97-
| [`internal/webhook/`](file:///home/ankit/workspace/my-projects/agentrax/internal/webhook) | Validating and Mutating admission webhooks. | Shared with `internal/quota` to enforce admission rules before objects are persisted. |
98-
| [`internal/scaling/`](file:///home/ankit/workspace/my-projects/agentrax/internal/scaling) | HPA synthesis, velocity rules, and dynamic quota ceiling headroom. | Calculates `QuotaHeadroom()` to cap HPA `maxReplicas` and applies stabilization windows. |
99-
| [`internal/rollout/`](file:///home/ankit/workspace/my-projects/agentrax/internal/rollout) | Canary state machine, PromQL query construction, and threshold evaluation. | Re-entrant state machine; sample-size gating; fail-safe timeout evaluation. |
100-
| [`internal/registry/`](file:///home/ankit/workspace/my-projects/agentrax/internal/registry) | MCP registrar, JSON-RPC 2.0 handshake, TTL sweeper, and discovery REST API. | In-memory registry with ConfigMap write-through; background health probes and TTL sweep. |
101-
| [`internal/metrics/`](file:///home/ankit/workspace/my-projects/agentrax/internal/metrics) | Bounded HTTP Prometheus query client. | Wraps all responses with `io.LimitReader` (1 MiB ceiling) to prevent memory exhaustion. |
92+
| Package | Scope & Responsibility | Key Invariants |
93+
| ---------------------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
94+
| `api/v1alpha1/` | CRD type definitions, OpenAPI markers, schema validation rules, and status condition constants. | **Zero business logic**; only struct declarations and generated deep-copy methods. |
95+
| `internal/controller/` | Controller-runtime reconcile loops (`AgentDeployment`, `TenantQuota`). | Only layer that executes write calls against the Kubernetes API for core-owned resources (Deployments, Services, HPAs, HTTPRoutes). Consumes subsystems via interfaces. |
96+
| `internal/quota/` | Quota arithmetic and concurrency-safe in-flight reservation cache. | Pure arithmetic; mutex-guarded state map; zero direct API server network calls in calculation paths. |
97+
| `internal/webhook/` | Validating and Mutating admission webhooks. | Shared with `internal/quota` to enforce admission rules before objects are persisted. |
98+
| `internal/scaling/` | HPA synthesis, velocity rules, and dynamic quota ceiling headroom. | Calculates `QuotaHeadroom()` to cap HPA `maxReplicas` and applies stabilization windows. |
99+
| `internal/rollout/` | Canary state machine, PromQL query construction, and threshold evaluation. | Re-entrant state machine; sample-size gating; fail-safe timeout evaluation. |
100+
| `internal/registry/` | MCP registrar, JSON-RPC 2.0 handshake, TTL sweeper, and discovery REST API. | In-memory registry with ConfigMap write-through for persistence; background health probes and TTL sweep. Explicitly allowed to write the `agentrax-registry` ConfigMap for state recovery. |
101+
| `internal/metrics/` | Bounded HTTP Prometheus query client. | Wraps all responses with `io.LimitReader` (1 MiB ceiling) to prevent memory exhaustion. |
102102

103103
---
104104

internal/controller/agentdeployment_controller.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ type AgentDeploymentReconciler struct {
9797
// When nil, MCP registration features are disabled.
9898
Registrar AgentRegistrar
9999

100+
// MCPHealthInterval is the requeue interval used to drive periodic MCP
101+
// heartbeat probes. Must stay shorter than the registry TTL so heartbeats
102+
// land before entries expire. Defaults to 60s when zero.
103+
MCPHealthInterval time.Duration
104+
100105
// hasServiceMonitorCRD is set once during SetupWithManager and determines
101106
// whether ServiceMonitor reconciliation is attempted at all.
102107
hasServiceMonitorCRD bool
@@ -618,8 +623,11 @@ func (r *AgentDeploymentReconciler) reconcileMCPRegistration(ctx context.Context
618623
return 0
619624
}
620625

621-
// Requeue interval shorter than TTL (90s) to ensure heartbeats occur before expiry.
622-
requeueInterval := 60 * time.Second
626+
// Requeue interval shorter than the registry TTL to ensure heartbeats occur before expiry.
627+
requeueInterval := r.MCPHealthInterval
628+
if requeueInterval <= 0 {
629+
requeueInterval = 60 * time.Second
630+
}
623631

624632
// If already registered, perform heartbeat probe.
625633
if ad.Status.Registered {

internal/controller/agentdeployment_controller_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,15 +208,15 @@ var _ = Describe("AgentDeployment Controller", func() {
208208
// (called on the reconciler goroutine) can pass its observation to the
209209
// test goroutine without a data race on plain booleans.
210210
resultCh := make(chan bool, 1)
211-
origRegistrar := testReconciler.Registrar
212-
testReconciler.Registrar = &mockAgentRegistrar{
211+
mockReg := &mockAgentRegistrar{
213212
deregisterFn: func(hctx context.Context, had *agentraxv1alpha1.AgentDeployment) error {
214213
err := k8sClient.Get(hctx, key, &corev1.Service{})
215214
resultCh <- (err == nil)
216215
return nil
217216
},
218217
}
219-
DeferCleanup(func() { testReconciler.Registrar = origRegistrar })
218+
testRegistrarProxy.SetDelegate(mockReg)
219+
DeferCleanup(func() { testRegistrarProxy.SetDelegate(testRegistrar) })
220220

221221
// Delete the object — the reconciler must call Deregister, then remove the finalizer.
222222
Expect(k8sClient.Delete(ctx, ad)).To(Succeed())

0 commit comments

Comments
 (0)