Skip to content

OTA-2084: Conditionally deploy console plugin when AgenticRun CRD is present#1425

Open
jhadvig wants to merge 3 commits into
openshift:mainfrom
jhadvig:OTA-2084
Open

OTA-2084: Conditionally deploy console plugin when AgenticRun CRD is present#1425
jhadvig wants to merge 3 commits into
openshift:mainfrom
jhadvig:OTA-2084

Conversation

@jhadvig

@jhadvig jhadvig commented Jul 20, 2026

Copy link
Copy Markdown
Member

Summary

  • Move console plugin manifests from install/ into embedded assets (pkg/agenticrun/bindata/)
  • Deploy the plugin conditionally based on AgenticRun CRD presence, not feature-set
  • Clean up plugin resources when OLS is uninstalled

Why

The OCPSTRAT-2241 descoping decision requires the feature to be TP but not TechPreviewNoUpgrade. The plugin should install on any cluster where the lightspeed-agentic-operator provides the AgenticRun CRD, regardless of feature set.

Keeping manifests in install/ without the TP annotation would deploy the plugin on every cluster, wasting resources. This PR follows the console-operator bindata pattern: embed manifests via //go:embed, apply them conditionally from the agenticrun controller.

Changes

Bindata structure (pkg/agenticrun/bindata/):

  • assets.go//go:embed assets/* wrapper
  • assets/*.yaml — 7 plugin manifests (namespace, serviceaccount, networkpolicy, configmap, deployment, service, consoleplugin) with gating annotations stripped and ${IMAGE} placeholder for the deployment image

Controller (pkg/agenticrun/controller.go):

  • crdAvailable() — checks for agenticruns.agentic.openshift.io via dynamic client with 5-minute TTL cache
  • ensureConsolePlugin() — loads embedded manifests, substitutes image, applies via controller-runtime client
  • cleanupConsolePlugin() — deletes plugin resources when CRD is absent (OLS uninstalled)
  • consolePluginEnsured flag — skips redundant applies on subsequent syncs
  • SetConsolePluginImage() — receives image from image-references, resets ensured flag on change

CVO wiring (pkg/cvo/cvo.go):

  • Removed shouldEnableAgenticRunController() — CRD check is now inside the controller's Sync()
  • Controller goroutine always starts (self-gating)
  • Plugin image passed from image-references in InitializeFromPayload()

Queue management (availableupdates.go, status.go):

  • Removed shouldEnableAgenticRunController() guards — controller queue always receives items

Sync() flow

1. if !crdAvailable():
     cleanupConsolePlugin()
     return nil
2. if !consolePluginEnsured:
     ensureConsolePlugin()
     consolePluginEnsured = true
3. (existing AgenticRun lifecycle logic)

Test plan

  • Unit tests pass (go test ./pkg/agenticrun/ ./pkg/cvo/)
  • Build passes (make build)
  • TechPreview cluster with OLS: plugin deploys automatically
  • Default-feature-set cluster without OLS: no plugin deployed
  • OLS installed after CVO boot: plugin deploys within 5 minutes
  • OLS uninstalled: plugin resources cleaned up

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Automatically ensures console plugin manifests are applied or removed based on console-plugin support (CRD availability), using the plugin image from the release payload.
    • Added a NetworkPolicy to allow console ingress to the plugin on TCP port 9001.
  • Improvements
    • Console plugin resources are re-applied when the configured plugin image changes.
    • The agentic-run controller is started and queued consistently, including after status history pruning; when support is unavailable, manifests are cleaned up.
    • Updated console plugin manifest naming/annotations and simplified OpenShift-specific annotations.

@openshift-ci-robot

openshift-ci-robot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

@jhadvig: This pull request references OTA-2084 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Move console plugin manifests from install/ into embedded assets (pkg/agenticrun/bindata/)
  • Deploy the plugin conditionally based on AgenticRun CRD presence, not feature-set
  • Clean up plugin resources when OLS is uninstalled

Why

The OCPSTRAT-2241 descoping decision requires the feature to be TP but not TechPreviewNoUpgrade. The plugin should install on any cluster where the lightspeed-agentic-operator provides the AgenticRun CRD, regardless of feature set.

Keeping manifests in install/ without the TP annotation would deploy the plugin on every cluster, wasting resources. This PR follows the console-operator bindata pattern: embed manifests via //go:embed, apply them conditionally from the agenticrun controller.

Changes

Bindata structure (pkg/agenticrun/bindata/):

  • assets.go//go:embed assets/* wrapper
  • assets/*.yaml — 7 plugin manifests (namespace, serviceaccount, networkpolicy, configmap, deployment, service, consoleplugin) with gating annotations stripped and ${IMAGE} placeholder for the deployment image

Controller (pkg/agenticrun/controller.go):

  • crdAvailable() — checks for agenticruns.agentic.openshift.io via dynamic client with 5-minute TTL cache
  • ensureConsolePlugin() — loads embedded manifests, substitutes image, applies via controller-runtime client
  • cleanupConsolePlugin() — deletes plugin resources when CRD is absent (OLS uninstalled)
  • consolePluginEnsured flag — skips redundant applies on subsequent syncs
  • SetConsolePluginImage() — receives image from image-references, resets ensured flag on change

CVO wiring (pkg/cvo/cvo.go):

  • Removed shouldEnableAgenticRunController() — CRD check is now inside the controller's Sync()
  • Controller goroutine always starts (self-gating)
  • Plugin image passed from image-references in InitializeFromPayload()

Queue management (availableupdates.go, status.go):

  • Removed shouldEnableAgenticRunController() guards — controller queue always receives items

Sync() flow

1. if !crdAvailable():
    cleanupConsolePlugin()
    return nil
2. if !consolePluginEnsured:
    ensureConsolePlugin()
    consolePluginEnsured = true
3. (existing AgenticRun lifecycle logic)

Test plan

  • Unit tests pass (go test ./pkg/agenticrun/ ./pkg/cvo/)
  • Build passes (make build)
  • TechPreview cluster with OLS: plugin deploys automatically
  • Default-feature-set cluster without OLS: no plugin deployed
  • OLS installed after CVO boot: plugin deploys within 5 minutes
  • OLS uninstalled: plugin resources cleaned up

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 20, 2026
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The change embeds console-plugin manifests, adds create/update/delete operations, gates them on CRD availability, wires the plugin image from payload data, and makes the agentic-run controller worker and queue triggers unconditional.

Changes

Agentic Run Console Plugin

Layer / File(s) Summary
Embedded manifest assets
pkg/agenticrun/bindata/assets.go, pkg/agenticrun/bindata/assets/*.yaml
YAML assets are embedded and exposed through asset helpers; release annotations are removed, the deployment image uses ${IMAGE}, the Service name is updated, and console ingress is allowed on TCP port 9001.
Manifest lifecycle and CRD gating
pkg/agenticrun/consoleplugin.go, pkg/agenticrun/controller.go, pkg/agenticrun/controller_test.go
Manifests are decoded and created or updated with image substitution, deleted in reverse order during cleanup, and reconciled based on cached CRD availability and image state.
CVO worker and queue wiring
pkg/cvo/cvo.go, pkg/cvo/availableupdates.go, pkg/cvo/status.go, pkg/cvo/availableupdates_test.go, pkg/payload/render_test.go
The payload supplies the console-plugin image, the worker starts unconditionally, queue triggers no longer use feature gating, and affected tests initialize the controller or remove the image override.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CVO
  participant AgenticRunController
  participant EmbeddedAssets
  participant KubernetesAPI
  CVO->>AgenticRunController: Set console plugin image
  CVO->>AgenticRunController: Queue reconciliation
  AgenticRunController->>KubernetesAPI: Check agenticruns CRD
  AgenticRunController->>EmbeddedAssets: Load manifests
  EmbeddedAssets-->>AgenticRunController: Return YAML assets
  AgenticRunController->>KubernetesAPI: Create or update console plugin resources
Loading
🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: conditional console plugin deployment based on AgenticRun CRD presence.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed No Ginkgo specs were added; touched tests use static testing names, and the one versioned subtest name is derived from hardcoded literals.
Test Structure And Quality ✅ Passed Changed tests are table-driven unit tests; no Ginkgo waits/resources, and cleanup uses defer Close() where needed.
Microshift Test Compatibility ✅ Passed The patch only changes pkg/agenticrun/consoleplugin.go; no new Ginkgo e2e tests were added.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; changed test files are standard Go unit tests and contain no SNO-sensitive assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed No topology-fragile scheduling was added: the new deployment has only kubernetes.io/os=linux and an infra toleration, with no anti-affinity, spread constraints, control-plane nodeSelectors, or PDBs.
Ote Binary Stdout Contract ✅ Passed No fmt.Print/os.Stdout writes appear in main/init/TestMain/RunSpecs paths; entrypoints set klog to stderr.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo/e2e tests were added; touched tests are unit tests and show no IPv4-only or external connectivity assumptions.
No-Weak-Crypto ✅ Passed No weak crypto, custom crypto, or secret comparisons were added; the new code only handles YAML manifests and controller CRUD.
Container-Privileges ✅ Passed No added manifest sets privileged/hostPID/hostNetwork/hostIPC, SYS_ADMIN, or allowPrivilegeEscalation=true; the deployment explicitly uses restricted settings.
No-Sensitive-Data-In-Logs ✅ Passed No new logs print secrets/PII/hostnames; added console plugin logs only resource kind/name and errors, with no sensitive fields emitted.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
pkg/cvo/cvo.go (1)

594-601: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Update the nearby controller documentation.

Operator.agenticRunController still says “if enabled”, but this worker now always starts and the controller gates itself on CRD availability. Update that field comment to describe the current lifecycle.

As per path instructions, “When modifying code, check that nearby comments, kubernetes.io/description annotations, and doc strings still accurately describe the new behavior.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/cvo/cvo.go` around lines 594 - 601, Update the documentation comment for
Operator.agenticRunController to state that its worker always starts and the
controller gates operation based on CRD availability, removing the outdated “if
enabled” wording. Do not change the worker implementation or unrelated comments.

Source: Path instructions

pkg/agenticrun/consoleplugin.go (1)

3-16: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Run gofmt on pkg/agenticrun/consoleplugin.go. The Kubernetes imports are out of gofmt order.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/agenticrun/consoleplugin.go` around lines 3 - 16, Run gofmt on
consoleplugin.go to reorder the Kubernetes imports into standard formatting
order; do not change the import set or other behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/agenticrun/controller.go`:
- Around line 141-153: Update Controller.crdAvailable to accept a
context.Context parameter and pass that context to the dynamicClient
Resource(...).List call instead of context.Background(). Update every caller to
provide its reconciliation context, preserving the existing CRD availability
caching and error handling.
- Around line 174-188: Update the plugin lifecycle handling around
cleanupConsolePluginManifests and c.ensureConsolePlugin so any cleanup or ensure
failure is returned from the sync method after logging, rather than returning
success. Preserve the existing state updates only on successful operations,
allowing the queue’s retry path to retry transient API failures.

---

Nitpick comments:
In `@pkg/agenticrun/consoleplugin.go`:
- Around line 3-16: Run gofmt on consoleplugin.go to reorder the Kubernetes
imports into standard formatting order; do not change the import set or other
behavior.

In `@pkg/cvo/cvo.go`:
- Around line 594-601: Update the documentation comment for
Operator.agenticRunController to state that its worker always starts and the
controller gates operation based on CRD availability, removing the outdated “if
enabled” wording. Do not change the worker implementation or unrelated comments.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 2cd51b30-9df9-4c6e-b2df-51a0fec57c2d

📥 Commits

Reviewing files that changed from the base of the PR and between f232fe1 and a0d5d89.

📒 Files selected for processing (16)
  • pkg/agenticrun/bindata/assets.go
  • pkg/agenticrun/bindata/assets/configmap.yaml
  • pkg/agenticrun/bindata/assets/consoleplugin.yaml
  • pkg/agenticrun/bindata/assets/deployment.yaml
  • pkg/agenticrun/bindata/assets/namespace.yaml
  • pkg/agenticrun/bindata/assets/networkpolicy.yaml
  • pkg/agenticrun/bindata/assets/service.yaml
  • pkg/agenticrun/bindata/assets/serviceaccount.yaml
  • pkg/agenticrun/consoleplugin.go
  • pkg/agenticrun/controller.go
  • pkg/agenticrun/controller_test.go
  • pkg/cvo/availableupdates.go
  • pkg/cvo/availableupdates_test.go
  • pkg/cvo/cvo.go
  • pkg/cvo/status.go
  • pkg/payload/render_test.go
💤 Files with no reviewable changes (7)
  • pkg/agenticrun/bindata/assets/service.yaml
  • pkg/agenticrun/bindata/assets/networkpolicy.yaml
  • pkg/agenticrun/bindata/assets/consoleplugin.yaml
  • pkg/agenticrun/bindata/assets/configmap.yaml
  • pkg/payload/render_test.go
  • pkg/agenticrun/bindata/assets/serviceaccount.yaml
  • pkg/agenticrun/bindata/assets/namespace.yaml

Comment on lines +141 to +153
func (c *Controller) crdAvailable() bool {
if time.Since(c.crdLastChecked) < crdCheckInterval {
return c.crdAvailableCache
}
c.crdLastChecked = time.Now()
if c.dynamicClient == nil {
c.crdAvailableCache = false
return false
}
agenticRunGVR := schema.GroupVersionResource{Group: "agentic.openshift.io", Version: "v1alpha1", Resource: "agenticruns"}
_, err := c.dynamicClient.Resource(agenticRunGVR).List(context.Background(), metav1.ListOptions{Limit: 1})
c.crdAvailableCache = err == nil || !kerrors.IsNotFound(err) && !isNoMatchError(err)
return c.crdAvailableCache

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Use the reconciliation context for the CRD probe.

context.Background() disconnects the discovery request from shutdown and request cancellation. Accept ctx in crdAvailable and pass it to List.

As per path instructions, “context.Context for cancellation and timeouts.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/agenticrun/controller.go` around lines 141 - 153, Update
Controller.crdAvailable to accept a context.Context parameter and pass that
context to the dynamicClient Resource(...).List call instead of
context.Background(). Update every caller to provide its reconciliation context,
preserving the existing CRD availability caching and error handling.

Source: Path instructions

Comment on lines +174 to +188
if !c.crdAvailable() {
if err := cleanupConsolePluginManifests(ctx, c.client); err != nil {
klog.V(i.Normal).Infof("Failed to clean up console plugin: %v", err)
}
c.consolePluginEnsured = false
return nil
}

if !c.consolePluginEnsured {
if err := c.ensureConsolePlugin(ctx); err != nil {
klog.V(i.Normal).Infof("Failed to ensure console plugin: %v", err)
} else {
c.consolePluginEnsured = true
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Propagate plugin lifecycle failures for retry.

Cleanup and apply failures are logged but reported as a successful sync. This prevents the queue’s error retry path from promptly retrying a transient API failure, leaving stale or missing plugin resources until another unrelated enqueue.

Proposed fix
 if !c.crdAvailable(ctx) {
 	if err := cleanupConsolePluginManifests(ctx, c.client); err != nil {
-		klog.V(i.Normal).Infof("Failed to clean up console plugin: %v", err)
+		return fmt.Errorf("cleaning up console plugin: %w", err)
 	}
 	c.consolePluginEnsured = false
 	return nil
 }

 if !c.consolePluginEnsured {
 	if err := c.ensureConsolePlugin(ctx); err != nil {
-		klog.V(i.Normal).Infof("Failed to ensure console plugin: %v", err)
+		return fmt.Errorf("ensuring console plugin: %w", err)
 	} else {
 		c.consolePluginEnsured = true
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/agenticrun/controller.go` around lines 174 - 188, Update the plugin
lifecycle handling around cleanupConsolePluginManifests and
c.ensureConsolePlugin so any cleanup or ensure failure is returned from the sync
method after logging, rather than returning success. Preserve the existing state
updates only on successful operations, allowing the queue’s retry path to retry
transient API failures.

@jhadvig

jhadvig commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

Manually validated on a cluster-bot cluster (5.0.0-0-2026-07-20-121922):

Scenario Result
Cluster without OLS (no AgenticRun CRD) → no plugin deployed Pass
Apply AgenticRun CRD → plugin auto-deploys Pass — all 7 resources created (namespace, SA, networkpolicy, configmap, deployment, service, consoleplugin), pod Running 1/1
Remove AgenticRun CRD → plugin resources cleaned up Pass — all resources deleted after cache TTL (5 min)
Re-apply AgenticRun CRD → plugin re-deploys Testing now

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/agenticrun/bindata/assets/networkpolicy-allow-console.yaml`:
- Around line 12-15: Update the ingress rule in the network policy to add a from
clause containing namespaceSelector and podSelector selectors matching the
OpenShift console labels, while preserving TCP port 9001. Ensure only console
pods can access the plugin assets.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: a798cbad-4be8-4a6f-94a5-499c252f50e3

📥 Commits

Reviewing files that changed from the base of the PR and between a0d5d89 and 8c31b4a.

📒 Files selected for processing (2)
  • pkg/agenticrun/bindata/assets/networkpolicy-allow-console.yaml
  • pkg/agenticrun/consoleplugin.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/agenticrun/consoleplugin.go

Comment on lines +12 to +15
ingress:
- ports:
- port: 9001
protocol: TCP

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== file list ==\n'
git ls-files 'pkg/agenticrun/bindata/assets/*' | sed -n '1,120p'

printf '\n== target file ==\n'
cat -n pkg/agenticrun/bindata/assets/networkpolicy-allow-console.yaml

printf '\n== related networkpolicy assets ==\n'
rg -n --no-heading -A6 -B4 'kind: NetworkPolicy|podSelector:|namespaceSelector:|policyTypes:|ingress:' pkg/agenticrun/bindata/assets -g '*.yaml' -g '*.yml'

Repository: openshift/cluster-version-operator

Length of output: 3749


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== console plugin manifest ==\n'
cat -n pkg/agenticrun/bindata/assets/consoleplugin.yaml

printf '\n== service/deployment excerpts ==\n'
rg -n --no-heading -A8 -B4 'kind: (Service|Deployment)|labels:|selector:|ports:|9001|console' pkg/agenticrun/bindata/assets/{service.yaml,deployment.yaml,consoleplugin.yaml} -g '*.yaml'

Repository: openshift/cluster-version-operator

Length of output: 8737


Restrict ingress to the OpenShift console.
This rule omits from, so any source can reach port 9001 on the plugin pods. Add a namespaceSelector/podSelector for the console’s labels so only the console can fetch the plugin assets.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/agenticrun/bindata/assets/networkpolicy-allow-console.yaml` around lines
12 - 15, Update the ingress rule in the network policy to add a from clause
containing namespaceSelector and podSelector selectors matching the OpenShift
console labels, while preserving TCP port 9001. Ensure only console pods can
access the plugin assets.

Comment thread pkg/agenticrun/bindata/assets/consoleplugin.yaml Outdated
}

obj.SetResourceVersion(existing.GetResourceVersion())
if err := client.Update(ctx, obj); err != nil {

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.

This looks like it might hot-loop on updates? Without AgenticRun in the CI runs, I guess we don't have Kube API audit logs to know, but I'd have expected us to be using lib/resourceapply client-side existing-vs.-required diff logic to compare the existing we pulled from the cluster with our local-manifest expectations, and to only update when we saw changes we thought needed to be pushed into the cluster.

Comment thread pkg/agenticrun/controller.go Outdated
Comment thread pkg/agenticrun/controller.go
Comment thread pkg/cvo/status.go
}
if original != nil && len(config.Status.History) < len(original.Status.History) {
klog.V(internal.Normal).Infof("Reconciling agentic runs because ClusterVersion.status.history got pruned")
optr.agenticRunController.Queue().Add(optr.agenticRunController.QueueKey())

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.

Hmm, I see this logic dates back to 6de7f5a (#1382), but I'm personally not clear on why a history prune would need an agentic-run controller poke. @hongkailiu, do you remember why you'd needed to do that?

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.

if err := deleteProposals(ctx, c.client, updates, conditionalUpdates, cv.Status.History, currentVersion); err != nil {

IIRC, CVO has the logic to prune CV.history when it grows to some length.
The proposals on the cluster are related to the versions in CV.history.
Thus, in my mind, CVO pruning CV.history leads to reconciliation on proposals .

@jhadvig jhadvig Jul 21, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

ok so if I read it correctly the logic should stay as is ...

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.

The proposals on the cluster are related to the versions in CV.history.

Are they? The AgenticRuns themselves are based on forward-looking available and conditional updates, not history. dynamicClient gives the ability to pull in whatever data though, so we also need to drop into runReadinessJSON. Looking at the current readiness checks, there is a history mention:

$ git grep -il history pkg/readiness
pkg/readiness/checks_test.go
pkg/readiness/cluster_conditions.go

That's including the most recent 5 history entries in recent_history. But I don't see anything in either the CVO repo or https://github.com/openshift/agentic-skills trying to consume recent_history. Maybe we can drop it? And we're currently strongly preferring to preserve the 5 most recent history entries when pruning anyway, so it seems unlikely to me that history pruning would need fresh AgenticRun prompt generation, even if we do need to keep recent_history in the prompt for some reason.

@jhadvig jhadvig Jul 21, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

You're right that AgenticRuns are forward-looking (based on available/conditional updates, not history). But deleteAgenticRuns also uses history as a keep-list — line 344 preserves runs whose target version appears in cv.Status.History, so they don't get deleted as "irrelevant" just because the version is no longer an available update target (e.g. after the cluster already upgraded to it).

When history is pruned (>100 entries), a version drops from that keep-list. Without the trigger, the associated run would linger until the next non-cached syncAvailableUpdates poke, which could be 2-4 minutes away (the controller has no self-requeue — it only runs when explicitly poked).

That said, it's a belt-and-suspenders measure.. the 2-4 minute delay is inconsequential for stale metadata, and history pruning only fires on clusters with 100+ update history entries. But the trigger is 4 lines, negligible cost, and makes the intent explicit... thats why Id lean toward keeping it, but honestly I ok with both approches.

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.

...so they don't get deleted as "irrelevant" ...

I thought we needed to never delete any AgenticRuns in the CVO, with OLS-3278 adding OLS-side garbage-collection, and OLS-3328 tracking log-preservation. Am I stale?

…present

Move the cluster-update-console-plugin manifests from install/ into
embedded assets (pkg/agenticrun/bindata/). The agenticrun controller
conditionally applies them at runtime when it detects the AgenticRun
CRD via API discovery, replacing the TechPreviewNoUpgrade annotation
gating.

This allows the console plugin to deploy on any cluster where OLS
agentic is installed, regardless of feature set, while avoiding
unnecessary deployments on clusters without OLS.

Key changes:
- Embed 8 plugin manifests via //go:embed, strip gating annotations
- Add crdAvailable() with 5-minute cached CRD check via apiextensions
- Always start the controller goroutine (self-gating via CRD check)
- Add ensureConsolePlugin() with diff-based updates and skip flag
- Add cleanupConsolePlugin() when CRD disappears (OLS uninstalled)
- Add HyperShift and Console capability guards
- Remove shouldEnableAgenticRunController() from cvo.go
- Pass plugin image from image-references via SetConsolePluginImage()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jhadvig

jhadvig commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

/test e2e-hypershift e2e-aws-ovn-techpreview e2e-agnostic-ovn-techpreview-serial-2of3

After deploying the console plugin resources, enable it by adding
cluster-update-console-plugin to spec.plugins on the console operator
config. On cleanup (CRD removed), disable it by removing the entry.

This makes the plugin automatically visible in the console without
manual patching of the console operator config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread pkg/agenticrun/controller.go Outdated

if !c.crdAvailable() {
if err := disableConsolePlugin(ctx, c.client); err != nil {
klog.V(i.Normal).Infof("Failed to disable console plugin: %v", err)

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.

If we fail to disable the console plugin, we want to avoid cleaning up those manifests, right? I'm not clear on all the conditions where disabling the console plugin would fail, but cleaning out the backing resources while the console plugin was still requested in the console configuration seems like it might cause console-loading problems.

if c.shouldDeployConsolePlugin() && !c.consolePluginEnsured {
if err := c.ensureConsolePlugin(ctx); err != nil {
klog.V(i.Normal).Infof("Failed to ensure console plugin: %v", err)
} else if err := enableConsolePlugin(ctx, c.client); err != nil {

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.

The docs include:

Make sure the Operator finishes installing the dynamic plugin before you run the following patch command.

It's not entirely clear what "finishes installing" means. Is it "wait until at least one Pod that backs the Service is Ready=True"? Or how gracefully does the console handle the enabled ConsolePlugin being down? I'm noticing now that we don't set replicas in the Deployment manifest, so it defaults to 1. And we don't have a covering PodDisruptionBudget (yet!). So I imagine we're often down for a bit (and possibly for an extended period) while Nodes are being drained and whatnot, and if that is handled fairly smoothly (just our cluster-update page 503ing for a bit, but the console otherwise working?), maybe we don't need anything more sophisticated here to smooth out initial-enablement time?

return nil
}

if c.shouldDeployConsolePlugin() && !c.consolePluginEnsured {

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.

!c.consolePluginEnsured here assumes our local-memory-cached consolePluginEnsured is accurate. Possibly fine for a tech-preview offering. But before we hit production, we'll probably want something that more actively reconciles the owned resources (like the sync worker manifest reconciliation this pull is moving us away from]) that will notice and stomp any concerning changes that leak into these managed resources (e.g. from careless admins). Hmm, and we'll also want to look at the other knobs that drive manifest inclusion like ClusterVersion's spec.overrides, to allow careful admins to wave off the CVO when we're doing a poor job of managing a particular resource and the cluster admin wants to take over until they can update to pick up a fix.

@jhadvig

jhadvig commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

/retest

- Skip manifest cleanup if disableConsolePlugin fails, to avoid
  removing backing resources while the plugin is still registered
  in the console config (wking review openshift#1)
- Wait for at least one available replica before enabling the plugin
  in the console config, so the console doesn't try to load a plugin
  whose backing pod isn't ready yet (wking review openshift#2)
- consolePluginEnsured remains a TP-acceptable volatile cache; active
  reconciliation of owned resources is deferred to pre-GA (wking openshift#3)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jhadvig

jhadvig commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

/retest

1 similar comment
@jhadvig

jhadvig commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

/retest

@wking wking 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.

There are some outstanding nits, but nothing here that's so serious that I see a reason to block this tech-preview feature work. The oc adm upgrade recommend output divergence is also unrelated to this pull.

/override ci/prow/e2e-agnostic-ovn-techpreview-serial-1of3
/lgtm
/verified by CI

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Jul 22, 2026
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@wking: This PR has been marked as verified by CI.

Details

In response to this:

There are some outstanding nits, but nothing here that's so serious that I see a reason to block this tech-preview feature work. The oc adm upgrade recommend output divergence is also unrelated to this pull.

/override ci/prow/e2e-agnostic-ovn-techpreview-serial-1of3
/lgtm
/verified by CI

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jul 22, 2026
@openshift-ci

openshift-ci Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jhadvig, wking

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 22, 2026
@openshift-ci

openshift-ci Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@wking: Overrode contexts on behalf of wking: ci/prow/e2e-agnostic-ovn-techpreview-serial-1of3

Details

In response to this:

There are some outstanding nits, but nothing here that's so serious that I see a reason to block this tech-preview feature work. The oc adm upgrade recommend output divergence is also unrelated to this pull.

/override ci/prow/e2e-agnostic-ovn-techpreview-serial-1of3
/lgtm
/verified by CI

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@openshift-ci

openshift-ci Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@jhadvig: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-agnostic-ovn-techpreview-serial-3of3 efa5f6c link unknown /test e2e-agnostic-ovn-techpreview-serial-3of3
ci/prow/e2e-agnostic-ovn-techpreview-serial-2of3 efa5f6c link unknown /test e2e-agnostic-ovn-techpreview-serial-2of3
ci/prow/e2e-agnostic-ovn efa5f6c link unknown /test e2e-agnostic-ovn

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants