Skip to content

Commit fa129da

Browse files
Merge pull request #1382 from hongkailiu/OTA-1966-b
OTA-1966: Manage proposals
2 parents bb338d4 + 7428ac1 commit fa129da

20 files changed

Lines changed: 1685 additions & 122 deletions

File tree

.openshift-tests-extension/openshift_payload_cluster-version-operator.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
"name": "[Jira:\"Cluster Version Operator\"] cluster-version-operator should create proposals",
102102
"labels": {
103103
"Lifecycle:informing": {},
104+
"OTA-1966": {},
104105
"Serial": {}
105106
},
106107
"resources": {

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ require (
1414
github.com/openshift/api v0.0.0-20260416105050-3c6b218b8a80
1515
github.com/openshift/client-go v0.0.0-20260416131737-a19e91702ab5
1616
github.com/openshift/library-go v0.0.0-20260413093329-d2db42c961e1
17-
github.com/openshift/lightspeed-agentic-operator/api v0.0.0-20260507160300-84a97541c3e0
17+
github.com/openshift/lightspeed-agentic-operator/api v0.0.0-20260521135452-44bd61b9b92a
1818
github.com/operator-framework/api v0.17.1
1919
github.com/operator-framework/operator-lifecycle-manager v0.22.0
2020
github.com/pkg/errors v0.9.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ github.com/openshift/client-go v0.0.0-20260416131737-a19e91702ab5 h1:R5gdIA+R7MO
114114
github.com/openshift/client-go v0.0.0-20260416131737-a19e91702ab5/go.mod h1:u56GmXEMF6bvws8ipkT1ZRNJH52RF5sZ/yRP+6PwkH4=
115115
github.com/openshift/library-go v0.0.0-20260413093329-d2db42c961e1 h1:NdVGxmPGwWoMlhSmTxMMgp2SszLtAH3nJ6AMGBpXclY=
116116
github.com/openshift/library-go v0.0.0-20260413093329-d2db42c961e1/go.mod h1:3bi4pLpYRdVd1aEhsHfRTJkwxwPLfRZ+ZePn3RmJd2k=
117-
github.com/openshift/lightspeed-agentic-operator/api v0.0.0-20260507160300-84a97541c3e0 h1:ORAZYemGOmlB+2ulDHqxuUg69FaoCe8cUdablBX7LNo=
118-
github.com/openshift/lightspeed-agentic-operator/api v0.0.0-20260507160300-84a97541c3e0/go.mod h1:tZlKXEZJ4/qxPPh6mamWrkwK+EQjudHt8AypudHttVs=
117+
github.com/openshift/lightspeed-agentic-operator/api v0.0.0-20260521135452-44bd61b9b92a h1:bUTmfSz1JIB8U8JiHsJ+8xWJH9jvrRBzSUWo0wbB9aU=
118+
github.com/openshift/lightspeed-agentic-operator/api v0.0.0-20260521135452-44bd61b9b92a/go.mod h1:tZlKXEZJ4/qxPPh6mamWrkwK+EQjudHt8AypudHttVs=
119119
github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 h1:AKx/w1qpS8We43bsRgf8Nll3CGlDHpr/WAXvuedTNZI=
120120
github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
121121
github.com/operator-framework/api v0.17.1 h1:J/6+Xj4IEV8C7hcirqUFwOiZAU3PbnJhWvB0/bB51c4=
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: openshift-lightspeed
5+
annotations:
6+
kubernetes.io/description: This manifest is only for testing purpose and will be removed when its own operator becomes available on the cluster.
7+
include.release.openshift.io/self-managed-high-availability: "true"
8+
workload.openshift.io/allowed: "management"
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
apiVersion: v1
3+
kind: ConfigMap
4+
metadata:
5+
name: ota-advisory-prompt
6+
namespace: openshift-lightspeed
7+
annotations:
8+
include.release.openshift.io/self-managed-high-availability: "true"
9+
release.openshift.io/feature-set: TechPreviewNoUpgrade
10+
data:
11+
prompt: |
12+
You are an OpenShift upgrade advisor. Analyze the cluster readiness
13+
data in the proposal request and produce an upgrade risk assessment.
14+
15+
The request contains a "Cluster Readiness Data" section with a JSON
16+
block. This was collected by the Cluster Version Operator — do not
17+
re-collect it. Parse the JSON, evaluate each check's results, and
18+
classify findings as blockers, warnings, or informational.
19+
20+
Use the ota-upgrade-advisor skill for the decision framework and
21+
blocker classification rules. When findings need deeper investigation,
22+
use prometheus, platform-docs, redhat-support, or product-lifecycle
23+
skills.
24+
25+
When the readiness data includes olm_operator_lifecycle results, use
26+
the product-lifecycle skill to cross-reference each operator's package
27+
name against the Red Hat Product Life Cycle API. Report support phase,
28+
EOL dates, and OCP compatibility from PLCC alongside the OLM data.
29+
30+
Do not guess or assume cluster state. Do not execute upgrade commands.

pkg/cvo/availableupdates_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,12 @@ func newOperator(url string, cluster release, promqlMock clusterconditions.Condi
211211
fake.NewClientBuilder().Build(), func(_ string) (*configv1.ClusterVersion, error) {
212212
return &configv1.ClusterVersion{}, nil
213213
},
214+
func(_ context.Context, namespace, name string, _ metav1.GetOptions) (*corev1.ConfigMap, error) {
215+
return &corev1.ConfigMap{}, nil
216+
},
217+
func() string {
218+
return operator.release.Version
219+
},
214220
)
215221
return availableUpdates, operator
216222
}

pkg/cvo/cvo.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -345,13 +345,23 @@ func New(
345345

346346
optr.configuration = configuration.NewClusterVersionOperatorConfiguration(operatorClient, operatorInformerFactory)
347347

348-
optr.proposalController = proposal.NewController(func() ([]configv1.Release, []configv1.ConditionalUpdate, error) {
349-
availableUpdates := optr.getAvailableUpdates()
350-
if availableUpdates == nil {
351-
return nil, nil, nil
352-
}
353-
return availableUpdates.Updates, availableUpdates.ConditionalUpdates, nil
354-
}, rtClient, cvInformer.Lister().Get)
348+
optr.proposalController = proposal.NewController(
349+
func() ([]configv1.Release, []configv1.ConditionalUpdate, error) {
350+
availableUpdates := optr.getAvailableUpdates()
351+
if availableUpdates == nil {
352+
return nil, nil, nil
353+
}
354+
return availableUpdates.Updates, availableUpdates.ConditionalUpdates, nil
355+
},
356+
rtClient,
357+
cvInformer.Lister().Get,
358+
func(ctx context.Context, namespace, name string, opts metav1.GetOptions) (*corev1.ConfigMap, error) {
359+
return kubeClient.CoreV1().ConfigMaps(namespace).Get(ctx, name, opts)
360+
},
361+
func() string {
362+
return optr.release.Version
363+
},
364+
)
355365

356366
return optr, nil
357367
}

pkg/cvo/cvo_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2758,6 +2758,10 @@ func TestOperator_availableUpdatesSync(t *testing.T) {
27582758
return nil, nil, nil
27592759
}, ctrlruntimefake.NewClientBuilder().Build(), func(_ string) (*configv1.ClusterVersion, error) {
27602760
return &configv1.ClusterVersion{}, nil
2761+
}, func(_ context.Context, namespace, name string, _ metav1.GetOptions) (*corev1.ConfigMap, error) {
2762+
return &corev1.ConfigMap{}, nil
2763+
}, func() string {
2764+
return optr.release.Version
27612765
})
27622766
err := optr.availableUpdatesSync(ctx, optr.queueKey())
27632767
if err != nil && tt.wantErr == nil {

pkg/cvo/status.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@ func (optr *Operator) syncStatus(ctx context.Context, original, config *configv1
179179
if klog.V(6).Enabled() {
180180
klog.Infof("Apply config: %s", cmp.Diff(original, config))
181181
}
182+
if optr.shouldEnableProposalController() {
183+
if original != nil && len(config.Status.History) < len(original.Status.History) {
184+
klog.V(internal.Normal).Infof("Reconciling proposals because ClusterVersion.status.history got pruned")
185+
optr.proposalController.Queue().Add(optr.proposalController.QueueKey())
186+
}
187+
}
182188
updated, err := applyClusterVersionStatus(ctx, optr.client.ConfigV1(), config, original)
183189
optr.rememberLastUpdate(updated)
184190
return err

pkg/internal/constants.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"strings"
66

7+
"github.com/blang/semver/v4"
8+
79
"k8s.io/apimachinery/pkg/util/sets"
810
"k8s.io/klog/v2"
911

@@ -131,3 +133,24 @@ func IsAlertConditionReason(reason string) bool {
131133
func AlertConditionMessage(alertName, severity, state, impact, details string) string {
132134
return fmt.Sprintf("%s alert %s %s, %s. %s", severity, alertName, state, impact, details)
133135
}
136+
137+
const (
138+
UpdateTypeMajor = "Major"
139+
UpdateTypeMinor = "Minor"
140+
UpdateTypePatch = "Patch"
141+
UpdateTypeUnknown = "Unknown"
142+
)
143+
144+
// UpdateType returns the type of the update from the source to the target versions
145+
func UpdateType(source, target semver.Version) string {
146+
if source.Major < target.Major {
147+
return UpdateTypeMajor
148+
}
149+
if source.Major == target.Major && source.Minor < target.Minor {
150+
return UpdateTypeMinor
151+
}
152+
if source.LT(target) {
153+
return UpdateTypePatch
154+
}
155+
return UpdateTypeUnknown
156+
}

0 commit comments

Comments
 (0)