Skip to content

Commit 07f4de9

Browse files
harcheclaude
andcommitted
pkg/cvo: Add Lightspeed proposal integration (OCPSTRAT-2618)
Integrate CVO with the Lightspeed agent framework by creating Proposal CRs when available updates are discovered. This includes OLM operator lifecycle readiness checks, product lifecycle (PLCC) data via a shared agentic-skills image, and proposal creation gated behind the LightspeedProposals feature gate. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e6aa7d4 commit 07f4de9

33 files changed

Lines changed: 6053 additions & 4 deletions

AGENTS.md

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,84 @@ Subsystems include: `pkg/cvo`, `pkg/payload`, `lib/resourceapply`, `hack`, etc.
188188

189189
### Development and Testing
190190
- Never test against production clusters - always use disposable test environments
191-
- CVO has significant control over cluster state and can disrupt operations during development
191+
- CVO has significant control over cluster state and can disrupt operations during development
192+
193+
## Lightspeed Proposal Integration
194+
195+
The CVO creates `Proposal` CRs (API group `agentic.openshift.io/v1alpha1`) when available updates are discovered, gated behind the `LightspeedProposals` feature gate.
196+
197+
### Key files
198+
- `pkg/proposal/proposal.go` — Creates Proposal CRs with pre-collected readiness data
199+
- `pkg/proposal/proposal_test.go` — Unit tests for proposal creation and dedup
200+
- `pkg/cvo/cvo.go:maybeCreateLightspeedProposal` — Runs readiness checks, calls proposal creator
201+
- `pkg/cvo/availableupdates.go:188` — Entry point after Cincinnati sync
202+
- `pkg/featuregates/featuregates.go``LightspeedProposals()` feature gate
203+
- `install/*lightspeed*` — Agent, Workflow, and system prompt manifests (applied by CVO from payload)
204+
- Skills are consumed from the shared `agentic-skills` image (openshift/agentic-skills repo)
205+
206+
### Deploying dev CVO with Lightspeed proposals
207+
208+
Requires: lightspeed-operator already deployed on the cluster (CRDs, agent, sandbox).
209+
210+
```bash
211+
# 1. Build binary and payload override (excludes CVO deployment manifest to prevent self-revert)
212+
cd /path/to/cluster-version-operator
213+
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod=vendor \
214+
-o _output/linux/amd64/cluster-version-operator ./cmd/cluster-version-operator/
215+
216+
# 2. Create payload override directory with release-metadata (so CVO detects correct version)
217+
mkdir -p _output/payload-override/{manifests,release-manifests}
218+
cp install/* _output/payload-override/manifests/
219+
rm _output/payload-override/manifests/*30_deployment* # prevent self-revert
220+
CLUSTER_VERSION=$(oc get clusterversion version -o jsonpath='{.status.desired.version}')
221+
cat > _output/payload-override/release-manifests/release-metadata <<EOF
222+
{"kind":"cincinnati-metadata-v0","version":"${CLUSTER_VERSION}"}
223+
EOF
224+
cat > _output/payload-override/release-manifests/image-references <<EOF
225+
{"kind":"ImageStream","apiVersion":"image.openshift.io/v1","metadata":{"name":"${CLUSTER_VERSION}"},"spec":{"tags":[]}}
226+
EOF
227+
228+
# 3. Build and push container image
229+
cat > Dockerfile.dev <<'EOF'
230+
FROM registry.access.redhat.com/ubi9-minimal:latest
231+
COPY _output/linux/amd64/cluster-version-operator /usr/bin/cluster-version-operator
232+
COPY install /manifests
233+
COPY _output/payload-override /payload
234+
ENTRYPOINT ["/usr/bin/cluster-version-operator"]
235+
EOF
236+
TAG="v$(date +%s)"
237+
docker build --platform linux/amd64 -f Dockerfile.dev -t quay.io/harpatil/cvo-lightspeed:${TAG} .
238+
docker push quay.io/harpatil/cvo-lightspeed:${TAG}
239+
240+
# 4. Deploy: single atomic patch (image + args + env) to avoid partial reverts
241+
RELEASE_IMAGE=$(oc get clusterversion version -o jsonpath='{.status.desired.image}')
242+
API_HOST=$(oc get infrastructure cluster -o jsonpath='{.status.apiServerInternalURI}' | sed 's|https://||' | cut -d: -f1)
243+
oc patch deployment cluster-version-operator -n openshift-cluster-version --type json -p "[
244+
{\"op\":\"replace\",\"path\":\"/spec/template/spec/containers/0/image\",\"value\":\"quay.io/harpatil/cvo-lightspeed:${TAG}\"},
245+
{\"op\":\"replace\",\"path\":\"/spec/template/spec/containers/0/imagePullPolicy\",\"value\":\"Always\"},
246+
{\"op\":\"replace\",\"path\":\"/spec/template/spec/containers/0/args\",\"value\":[
247+
\"start\",\"--release-image=${RELEASE_IMAGE}\",\"--enable-auto-update=false\",
248+
\"--listen=0.0.0.0:9099\",\"--serving-cert-file=/etc/tls/serving-cert/tls.crt\",
249+
\"--serving-key-file=/etc/tls/serving-cert/tls.key\",\"--v=4\",\"--always-enable-capabilities=Ingress\"
250+
]},
251+
{\"op\":\"replace\",\"path\":\"/spec/template/spec/containers/0/env\",\"value\":[
252+
{\"name\":\"OPERATOR_IMAGE_VERSION\",\"value\":\"${CLUSTER_VERSION}\"},
253+
{\"name\":\"KUBERNETES_SERVICE_PORT\",\"value\":\"6443\"},
254+
{\"name\":\"KUBERNETES_SERVICE_HOST\",\"value\":\"${API_HOST}\"},
255+
{\"name\":\"NODE_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"spec.nodeName\"}}},
256+
{\"name\":\"CLUSTER_PROFILE\",\"value\":\"self-managed-high-availability\"},
257+
{\"name\":\"PAYLOAD_OVERRIDE\",\"value\":\"/payload\"}
258+
]}
259+
]"
260+
261+
# 5. Watch for proposal creation (happens after first Cincinnati update check, ~2-5 min)
262+
oc get proposals -n openshift-lightspeed -w
263+
```
264+
265+
### Gotchas
266+
- **PAYLOAD_OVERRIDE is critical** — without it, the CVO reads `/release-manifests/release-metadata` (which doesn't exist in the dev image) and falls back to version `0.0.1-snapshot`, disabling all feature gates including `LightspeedProposals`.
267+
- **Remove the CVO deployment manifest** from `_output/payload-override/manifests/` — otherwise the CVO reconciles its own deployment and reverts the image/env changes.
268+
- **KUBERNETES_SERVICE_HOST must be the API hostname** (e.g., `api-int.cluster.example.com`), not a node IP. Using `fieldRef: status.hostIP` causes TLS errors.
269+
- **All deployment changes must be in a single `oc patch`** — sequential patches trigger rollouts that can lose env vars.
270+
- **Leader lease timeout** — after patching, the new pod must wait up to ~2 min for the old pod's lease to expire before it can start reconciling.
271+
- **Skills image** comes from the shared `agentic-skills` repo (`registry.ci.openshift.org/ocp/4.22:agentic-skills`). The Agent CR selects specific skills via `paths`.

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,5 @@ require (
108108
)
109109

110110
replace github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12
111+
112+
replace github.com/openshift/api => github.com/harche/api v0.0.0-20260414192630-b7a8e3d157cb

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
7070
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
7171
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
7272
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
73+
github.com/harche/api v0.0.0-20260414192630-b7a8e3d157cb h1:8rHr8NpecxNNNjEqLJBLprSit1WFWJTEHsKePFnlURc=
74+
github.com/harche/api v0.0.0-20260414192630-b7a8e3d157cb/go.mod h1:pyVjK0nZ4sRs4fuQVQ4rubsJdahI1PB94LnQ8sGdvxo=
7375
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
7476
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
7577
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -104,8 +106,6 @@ github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
104106
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
105107
github.com/openshift-eng/openshift-tests-extension v0.0.0-20250220212757-b9c4d98a0c45 h1:hXpbYtP3iTh8oy/RKwKkcMziwchY3fIk95ciczf7cOA=
106108
github.com/openshift-eng/openshift-tests-extension v0.0.0-20250220212757-b9c4d98a0c45/go.mod h1:6gkP5f2HL0meusT0Aim8icAspcD1cG055xxBZ9yC68M=
107-
github.com/openshift/api v0.0.0-20260302174620-dcac36b908db h1:MOQ5JSIlbP4apwTrEdNpApT6PsnB0/1S6y9aKODp5Ks=
108-
github.com/openshift/api v0.0.0-20260302174620-dcac36b908db/go.mod h1:pyVjK0nZ4sRs4fuQVQ4rubsJdahI1PB94LnQ8sGdvxo=
109109
github.com/openshift/client-go v0.0.0-20260302182750-20813ce71ca6 h1:wJv4Ia+R4OxoaJcTUyvMtBc5rWFvfTiEA8d5f1MBPqI=
110110
github.com/openshift/client-go v0.0.0-20260302182750-20813ce71ca6/go.mod h1:3lkVff575BlbDUUhMsrD1IyvfkZ+oKUB7iZuVy1m0W0=
111111
github.com/openshift/library-go v0.0.0-20260303171201-5d9eb6295ff6 h1:xjqy0OolrFdJ+ofI/aD0+2k9+MSk5anP5dXifFt539Q=

0 commit comments

Comments
 (0)