diff --git a/go.mod b/go.mod index 563b8f4f9..9a2ea7cf8 100644 --- a/go.mod +++ b/go.mod @@ -118,3 +118,5 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) + +replace github.com/openshift/library-go => github.com/deads2k/library-go v0.0.0-20241024233548-385187f0041d diff --git a/go.sum b/go.sum index b404a6b56..d716f2353 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deads2k/library-go v0.0.0-20241024233548-385187f0041d h1:VYJjIyidkZUXRDx0KU9RDHAY5td7p6lBHG30dznW9Vs= +github.com/deads2k/library-go v0.0.0-20241024233548-385187f0041d/go.mod h1:9B1MYPoLtP9tqjWxcbUNVpwxy68zOH/3EIP6c31dAM0= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= @@ -148,8 +150,6 @@ github.com/openshift/build-machinery-go v0.0.0-20240613134303-8359781da660 h1:F0 github.com/openshift/build-machinery-go v0.0.0-20240613134303-8359781da660/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= github.com/openshift/client-go v0.0.0-20241001162912-da6d55e4611f h1:FRc0bVNWprihWS0GqQWzb3dY4dkCwpOP3mDw5NwSoR4= github.com/openshift/client-go v0.0.0-20241001162912-da6d55e4611f/go.mod h1:KiZi2mJRH1TOJ3FtBDYS6YvUL30s/iIXaGSUrSa36mo= -github.com/openshift/library-go v0.0.0-20241023193830-022ad9c25e39 h1:QUoMgNRHKDX0BXCbsdYHwoIyqYBGSJy9dNBAph9WqEU= -github.com/openshift/library-go v0.0.0-20241023193830-022ad9c25e39/go.mod h1:9B1MYPoLtP9tqjWxcbUNVpwxy68zOH/3EIP6c31dAM0= github.com/openshift/multi-operator-manager v0.0.0-20241022160113-b880eaae93fc h1:DPatMo6iid7ruxVr3LEu0EHe3oll9CYZYO4A8vV3RYU= github.com/openshift/multi-operator-manager v0.0.0-20241022160113-b880eaae93fc/go.mod h1:7u7Wj5yctFzwixEJdrnpZCCNuJwdwls3SwqHoxRlN7E= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= diff --git a/vendor/github.com/openshift/library-go/pkg/config/clusteroperator/v1helpers/status.go b/vendor/github.com/openshift/library-go/pkg/config/clusteroperator/v1helpers/status.go index 8491bc9e9..923651620 100644 --- a/vendor/github.com/openshift/library-go/pkg/config/clusteroperator/v1helpers/status.go +++ b/vendor/github.com/openshift/library-go/pkg/config/clusteroperator/v1helpers/status.go @@ -3,57 +3,20 @@ package v1helpers import ( "bytes" "fmt" - "strings" - "time" - + applyconfigv1 "github.com/openshift/client-go/config/applyconfigurations/config/v1" "k8s.io/apimachinery/pkg/api/equality" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/json" + "k8s.io/utils/ptr" + "strings" configv1 "github.com/openshift/api/config/v1" ) -// SetStatusCondition sets the corresponding condition in conditions to newCondition. -func SetStatusCondition(conditions *[]configv1.ClusterOperatorStatusCondition, newCondition configv1.ClusterOperatorStatusCondition) { - if conditions == nil { - conditions = &[]configv1.ClusterOperatorStatusCondition{} - } - existingCondition := FindStatusCondition(*conditions, newCondition.Type) - if existingCondition == nil { - newCondition.LastTransitionTime = metav1.NewTime(time.Now()) - *conditions = append(*conditions, newCondition) - return - } - - if existingCondition.Status != newCondition.Status { - existingCondition.Status = newCondition.Status - existingCondition.LastTransitionTime = metav1.NewTime(time.Now()) - } - - existingCondition.Reason = newCondition.Reason - existingCondition.Message = newCondition.Message -} - -// RemoveStatusCondition removes the corresponding conditionType from conditions. -func RemoveStatusCondition(conditions *[]configv1.ClusterOperatorStatusCondition, conditionType configv1.ClusterStatusConditionType) { - if conditions == nil { - conditions = &[]configv1.ClusterOperatorStatusCondition{} - } - newConditions := []configv1.ClusterOperatorStatusCondition{} - for _, condition := range *conditions { - if condition.Type != conditionType { - newConditions = append(newConditions, condition) - } - } - - *conditions = newConditions -} - // FindStatusCondition finds the conditionType in conditions. -func FindStatusCondition(conditions []configv1.ClusterOperatorStatusCondition, conditionType configv1.ClusterStatusConditionType) *configv1.ClusterOperatorStatusCondition { +func FindStatusCondition(conditions []applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration, conditionType *configv1.ClusterStatusConditionType) *applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration { for i := range conditions { - if conditions[i].Type == conditionType { + if ptr.Deref(conditions[i].Type, "") == ptr.Deref(conditionType, "") { return &conditions[i] } } @@ -62,38 +25,52 @@ func FindStatusCondition(conditions []configv1.ClusterOperatorStatusCondition, c } // GetStatusDiff returns a string representing change in condition status in human readable form. -func GetStatusDiff(oldStatus configv1.ClusterOperatorStatus, newStatus configv1.ClusterOperatorStatus) string { +func GetStatusDiff(oldStatus, newStatus *applyconfigv1.ClusterOperatorStatusApplyConfiguration) string { + switch { + case oldStatus == nil && newStatus == nil: + case oldStatus != nil && newStatus == nil: + return "status was removed" + } messages := []string{} for _, newCondition := range newStatus.Conditions { + if oldStatus == nil { + messages = append(messages, fmt.Sprintf("%s set to %s (%q)", ptr.Deref(newCondition.Type, ""), ptr.Deref(newCondition.Status, ""), ptr.Deref(newCondition.Message, ""))) + continue + } existingStatusCondition := FindStatusCondition(oldStatus.Conditions, newCondition.Type) if existingStatusCondition == nil { - messages = append(messages, fmt.Sprintf("%s set to %s (%q)", newCondition.Type, newCondition.Status, newCondition.Message)) + messages = append(messages, fmt.Sprintf("%s set to %s (%q)", ptr.Deref(newCondition.Type, ""), ptr.Deref(newCondition.Status, ""), ptr.Deref(newCondition.Message, ""))) continue } - if existingStatusCondition.Status != newCondition.Status { - messages = append(messages, fmt.Sprintf("%s changed from %s to %s (%q)", existingStatusCondition.Type, existingStatusCondition.Status, newCondition.Status, newCondition.Message)) + if ptr.Deref(existingStatusCondition.Status, "") != ptr.Deref(newCondition.Status, "") { + messages = append(messages, fmt.Sprintf("%s changed from %s to %s (%q)", ptr.Deref(existingStatusCondition.Type, ""), ptr.Deref(existingStatusCondition.Status, ""), ptr.Deref(newCondition.Status, ""), ptr.Deref(newCondition.Message, ""))) continue } - if existingStatusCondition.Message != newCondition.Message { - messages = append(messages, fmt.Sprintf("%s message changed from %q to %q", existingStatusCondition.Type, existingStatusCondition.Message, newCondition.Message)) + existingMessage := strings.TrimPrefix(ptr.Deref(existingStatusCondition.Message, ""), "\ufeff") + newMessage := strings.TrimPrefix(ptr.Deref(newCondition.Message, ""), "\ufeff") + if existingMessage != newMessage { + messages = append(messages, fmt.Sprintf("%s message changed from %q to %q", ptr.Deref(existingStatusCondition.Type, ""), existingMessage, newMessage)) } } - for _, oldCondition := range oldStatus.Conditions { - // This should not happen. It means we removed old condition entirely instead of just changing its status - if c := FindStatusCondition(newStatus.Conditions, oldCondition.Type); c == nil { - messages = append(messages, fmt.Sprintf("%s was removed", oldCondition.Type)) + if oldStatus != nil { + for _, oldCondition := range oldStatus.Conditions { + // This should not happen. It means we removed old condition entirely instead of just changing its status + if c := FindStatusCondition(newStatus.Conditions, oldCondition.Type); c == nil { + messages = append(messages, fmt.Sprintf("%s was removed", ptr.Deref(oldCondition.Type, ""))) + } } } - if !equality.Semantic.DeepEqual(oldStatus.RelatedObjects, newStatus.RelatedObjects) { - messages = append(messages, fmt.Sprintf("status.relatedObjects changed from %q to %q", oldStatus.RelatedObjects, newStatus.RelatedObjects)) - } - if !equality.Semantic.DeepEqual(oldStatus.Extension, newStatus.Extension) { - messages = append(messages, fmt.Sprintf("status.extension changed from %q to %q", oldStatus.Extension, newStatus.Extension)) - } - - if !equality.Semantic.DeepEqual(oldStatus.Versions, newStatus.Versions) { - messages = append(messages, fmt.Sprintf("status.versions changed from %q to %q", oldStatus.Versions, newStatus.Versions)) + if oldStatus != nil { + if !equality.Semantic.DeepEqual(oldStatus.RelatedObjects, newStatus.RelatedObjects) { + messages = append(messages, fmt.Sprintf("status.relatedObjects changed from %#v to %#v", oldStatus.RelatedObjects, newStatus.RelatedObjects)) + } + if !equality.Semantic.DeepEqual(oldStatus.Extension, newStatus.Extension) { + messages = append(messages, fmt.Sprintf("status.extension changed from %#v to %#v", oldStatus.Extension, newStatus.Extension)) + } + if !equality.Semantic.DeepEqual(oldStatus.Versions, newStatus.Versions) { + messages = append(messages, fmt.Sprintf("status.versions changed from %#v to %#v", oldStatus.Versions, newStatus.Versions)) + } } if len(messages) == 0 { diff --git a/vendor/github.com/openshift/library-go/pkg/manifestclient/group_resource_discovery.go b/vendor/github.com/openshift/library-go/pkg/manifestclient/group_resource_discovery.go index 1b4a10f7a..6759302fa 100644 --- a/vendor/github.com/openshift/library-go/pkg/manifestclient/group_resource_discovery.go +++ b/vendor/github.com/openshift/library-go/pkg/manifestclient/group_resource_discovery.go @@ -5,7 +5,6 @@ import ( "fmt" "io/fs" "k8s.io/apimachinery/pkg/util/json" - "os" "path/filepath" "sigs.k8s.io/yaml" "strings" @@ -18,13 +17,13 @@ func (mrt *manifestRoundTripper) getGroupResourceDiscovery(requestInfo *apireque switch { case requestInfo.Path == "/api": ret, err := mrt.getAggregatedDiscoveryForURL("aggregated-discovery-api.yaml", requestInfo.Path) - if os.IsNotExist(err) { + if errors.Is(err, fs.ErrNotExist) { return mrt.getLegacyGroupResourceDiscovery(requestInfo) } return ret, err case requestInfo.Path == "/apis": ret, err := mrt.getAggregatedDiscoveryForURL("aggregated-discovery-apis.yaml", requestInfo.Path) - if os.IsNotExist(err) { + if errors.Is(err, fs.ErrNotExist) { return mrt.getLegacyGroupResourceDiscovery(requestInfo) } return ret, err @@ -36,7 +35,7 @@ func (mrt *manifestRoundTripper) getGroupResourceDiscovery(requestInfo *apireque func (mrt *manifestRoundTripper) getAggregatedDiscoveryForURL(filename, url string) ([]byte, error) { discoveryBytes, err := fs.ReadFile(mrt.sourceFS, filename) - if os.IsNotExist(err) { + if errors.Is(err, fs.ErrNotExist) { discoveryBytes, err = fs.ReadFile(defaultDiscovery, filepath.Join("default-discovery", filename)) } if err != nil { diff --git a/vendor/github.com/openshift/library-go/pkg/manifestclient/list.go b/vendor/github.com/openshift/library-go/pkg/manifestclient/list.go index 211684e1b..b59c517f3 100644 --- a/vendor/github.com/openshift/library-go/pkg/manifestclient/list.go +++ b/vendor/github.com/openshift/library-go/pkg/manifestclient/list.go @@ -46,7 +46,10 @@ func (mrt *manifestRoundTripper) listAll(requestInfo *apirequest.RequestInfo) ([ return nil, fmt.Errorf("unable to determine list kind: %w", err) } possibleListFiles, err := allPossibleListFileLocations(mrt.sourceFS, requestInfo) - if err != nil { + switch { + case errors.Is(err, fs.ErrNotExist): + // continue to see if something else is present to return + case err != nil: return nil, fmt.Errorf("unable to determine list file locations: %w", err) } for _, listFile := range possibleListFiles { @@ -84,7 +87,10 @@ func (mrt *manifestRoundTripper) listAll(requestInfo *apirequest.RequestInfo) ([ } retList.SetGroupVersionKind(kind.listKind) individualFiles, err := allIndividualFileLocations(mrt.sourceFS, requestInfo) - if err != nil { + switch { + case errors.Is(err, fs.ErrNotExist): + // continue to see if something else is present to return + case err != nil: return nil, fmt.Errorf("unable to determine individual file locations: %w", err) } for _, individualFile := range individualFiles { @@ -122,9 +128,12 @@ func (mrt *manifestRoundTripper) listAll(requestInfo *apirequest.RequestInfo) ([ func (mrt *manifestRoundTripper) listAllNamespaces() ([]byte, error) { possibleNamespaceFiles, err := allPossibleNamespaceFiles(mrt.sourceFS) - if err != nil { + switch { + case errors.Is(err, fs.ErrNotExist): + case err != nil: return nil, fmt.Errorf("unable to determine list file alternative individual files: %w", err) } + namespaces := []unstructured.Unstructured{} for _, individualFile := range possibleNamespaceFiles { currNamespace, err := readIndividualFile(mrt.sourceFS, individualFile) @@ -174,7 +183,7 @@ func allIndividualFileLocations(sourceFS fs.FS, requestInfo *apirequest.RequestI namespaces, err := allNamespacesWithData(sourceFS) if err != nil { - return nil, fmt.Errorf("unable to read namespaces") + return nil, fmt.Errorf("unable to read namespaces: %w", err) } for _, ns := range namespaces { nsParts := append([]string{"namespaces", ns}, resourceDirectoryParts...) diff --git a/vendor/github.com/openshift/library-go/pkg/manifestclient/mutation_directory_reader.go b/vendor/github.com/openshift/library-go/pkg/manifestclient/mutation_directory_reader.go index 4364cb353..18990eca2 100644 --- a/vendor/github.com/openshift/library-go/pkg/manifestclient/mutation_directory_reader.go +++ b/vendor/github.com/openshift/library-go/pkg/manifestclient/mutation_directory_reader.go @@ -33,7 +33,7 @@ func readMutationFS(inFS fs.FS) (*AllActionsTracker[FileOriginatedSerializedRequ file.Close() } switch { - case os.IsNotExist(err): + case errors.Is(err, fs.ErrNotExist): continue case err != nil: errs = append(errs, fmt.Errorf("unable to read %q : %w", action, err)) @@ -115,7 +115,7 @@ func serializedRequestFromFile(action Action, actionFS fs.FS, bodyFilename strin optionsExist := false optionsContent, err := fs.ReadFile(actionFS, optionsFilename) switch { - case os.IsNotExist(err): + case errors.Is(err, fs.ErrNotExist): // not required, do nothing case err != nil: return nil, fmt.Errorf("failed to read %q: %w", optionsFilename, err) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/apiserver/controllerset/apiservercontrollerset.go b/vendor/github.com/openshift/library-go/pkg/operator/apiserver/controllerset/apiservercontrollerset.go index 59a43d630..b6813c39a 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/apiserver/controllerset/apiservercontrollerset.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/apiserver/controllerset/apiservercontrollerset.go @@ -3,6 +3,7 @@ package apiservercontrollerset import ( "context" "fmt" + "k8s.io/utils/clock" "regexp" "time" @@ -74,6 +75,7 @@ type APIServerControllerSet struct { name string operatorClient v1helpers.OperatorClient eventRecorder events.Recorder + clock clock.PassiveClock apiServiceController controllerWrapper auditPolicyController controllerWrapper @@ -92,11 +94,13 @@ func NewAPIServerControllerSet( name string, operatorClient v1helpers.OperatorClient, eventRecorder events.Recorder, + clock clock.PassiveClock, ) *APIServerControllerSet { apiServerControllerSet := &APIServerControllerSet{ name: name, operatorClient: operatorClient, eventRecorder: eventRecorder, + clock: clock, } return apiServerControllerSet @@ -143,6 +147,7 @@ func (cs *APIServerControllerSet) WithClusterOperatorStatusController( cs.operatorClient, versionRecorder, cs.eventRecorder, + cs.clock, ) for _, opt := range options { s = opt(s) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/status/condition.go b/vendor/github.com/openshift/library-go/pkg/operator/status/condition.go index 56e1496b8..aeeec191c 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/status/condition.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/status/condition.go @@ -2,11 +2,12 @@ package status import ( "fmt" + applyconfigv1 "github.com/openshift/client-go/config/applyconfigurations/config/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/clock" + "k8s.io/utils/ptr" "sort" "strings" - "time" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" configv1 "github.com/openshift/api/config/v1" operatorv1 "github.com/openshift/api/operator/v1" @@ -18,7 +19,7 @@ import ( // on true, but Available merges on false. Thing of it like an anti-default. // // If inertia is non-nil, then resist returning a condition with a status opposite the defaultConditionStatus. -func UnionCondition(conditionType string, defaultConditionStatus operatorv1.ConditionStatus, inertia Inertia, allConditions ...operatorv1.OperatorCondition) operatorv1.OperatorCondition { +func UnionCondition(clock clock.PassiveClock, conditionType string, defaultConditionStatus operatorv1.ConditionStatus, inertia Inertia, allConditions ...operatorv1.OperatorCondition) operatorv1.OperatorCondition { var oppositeConditionStatus operatorv1.ConditionStatus if defaultConditionStatus == operatorv1.ConditionTrue { oppositeConditionStatus = operatorv1.ConditionFalse @@ -54,7 +55,7 @@ func UnionCondition(conditionType string, defaultConditionStatus operatorv1.Cond if inertia == nil { elderBadConditions = badConditions } else { - now := time.Now() + now := clock.Now() for _, condition := range badConditions { if condition.LastTransitionTime.Time.Before(now.Add(-inertia(condition))) { elderBadConditions = append(elderBadConditions, condition) @@ -89,18 +90,18 @@ func UnionCondition(conditionType string, defaultConditionStatus operatorv1.Cond // on true, but Available merges on false. Thing of it like an anti-default. // // If inertia is non-nil, then resist returning a condition with a status opposite the defaultConditionStatus. -func UnionClusterCondition(conditionType configv1.ClusterStatusConditionType, defaultConditionStatus operatorv1.ConditionStatus, inertia Inertia, allConditions ...operatorv1.OperatorCondition) configv1.ClusterOperatorStatusCondition { - cnd := UnionCondition(string(conditionType), defaultConditionStatus, inertia, allConditions...) +func UnionClusterCondition(clock clock.PassiveClock, conditionType configv1.ClusterStatusConditionType, defaultConditionStatus operatorv1.ConditionStatus, inertia Inertia, allConditions ...operatorv1.OperatorCondition) *applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration { + cnd := UnionCondition(clock, string(conditionType), defaultConditionStatus, inertia, allConditions...) return OperatorConditionToClusterOperatorCondition(cnd) } -func OperatorConditionToClusterOperatorCondition(condition operatorv1.OperatorCondition) configv1.ClusterOperatorStatusCondition { - return configv1.ClusterOperatorStatusCondition{ - Type: configv1.ClusterStatusConditionType(condition.Type), - Status: configv1.ConditionStatus(condition.Status), - LastTransitionTime: condition.LastTransitionTime, - Reason: condition.Reason, - Message: condition.Message, +func OperatorConditionToClusterOperatorCondition(condition operatorv1.OperatorCondition) *applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration { + return &applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration{ + Type: ptr.To(configv1.ClusterStatusConditionType(condition.Type)), + Status: ptr.To(configv1.ConditionStatus(condition.Status)), + LastTransitionTime: ptr.To(condition.LastTransitionTime), + Reason: ptr.To(condition.Reason), + Message: ptr.To(condition.Message), } } func latestTransitionTime(conditions []operatorv1.OperatorCondition) metav1.Time { diff --git a/vendor/github.com/openshift/library-go/pkg/operator/status/status_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/status/status_controller.go index 2f7bf95d7..3b79e3c96 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/status/status_controller.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/status/status_controller.go @@ -2,6 +2,10 @@ package status import ( "context" + "fmt" + applyconfigv1 "github.com/openshift/client-go/config/applyconfigurations/config/v1" + "k8s.io/utils/clock" + "k8s.io/utils/ptr" "strings" "time" @@ -12,7 +16,6 @@ import ( configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1" configv1informers "github.com/openshift/client-go/config/informers/externalversions/config/v1" configv1listers "github.com/openshift/client-go/config/listers/config/v1" - "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -37,9 +40,11 @@ type VersionGetter interface { type RelatedObjectsFunc func() (isset bool, objs []configv1.ObjectReference) type StatusSyncer struct { - clusterOperatorName string - relatedObjects []configv1.ObjectReference - relatedObjectsFunc RelatedObjectsFunc + controllerInstanceName string + clusterOperatorName string + relatedObjects []configv1.ObjectReference + relatedObjectsFunc RelatedObjectsFunc + clock clock.PassiveClock versionGetter VersionGetter operatorClient operatorv1helpers.OperatorClient @@ -67,15 +72,19 @@ func NewClusterOperatorStatusController( operatorClient operatorv1helpers.OperatorClient, versionGetter VersionGetter, recorder events.Recorder, + clock clock.PassiveClock, ) *StatusSyncer { + instanceName := name return &StatusSyncer{ - clusterOperatorName: name, - relatedObjects: relatedObjects, - versionGetter: versionGetter, - clusterOperatorClient: clusterOperatorClient, - clusterOperatorLister: clusterOperatorInformer.Lister(), - operatorClient: operatorClient, - degradedInertia: MustNewInertia(2 * time.Minute).Inertia, + controllerInstanceName: factory.ControllerInstanceName(instanceName, "ClusterOperatorStatus"), + clusterOperatorName: name, + relatedObjects: relatedObjects, + clock: clock, + versionGetter: versionGetter, + clusterOperatorClient: clusterOperatorClient, + clusterOperatorLister: clusterOperatorInformer.Lister(), + operatorClient: operatorClient, + degradedInertia: MustNewInertia(2 * time.Minute).Inertia, controllerFactory: factory.New().ResyncEvery(time.Minute).WithInformers( operatorClient.Informer(), clusterOperatorInformer.Informer(), @@ -104,7 +113,7 @@ func (c *StatusSyncer) Run(ctx context.Context, workers int) { WithPostStartHooks(c.watchVersionGetterPostRunHook). WithSync(c.Sync). ToController( - "StatusSyncer_"+c.Name(), // don't change what is passed here unless you also remove the old FooDegraded condition + c.controllerInstanceName, c.recorder, ). Run(ctx, workers) @@ -151,9 +160,7 @@ func (c StatusSyncer) Sync(ctx context.Context, syncCtx factory.SyncContext) err if originalClusterOperatorObj == nil || apierrors.IsNotFound(err) { klog.Infof("clusteroperator/%s not found", c.clusterOperatorName) var createErr error - originalClusterOperatorObj, createErr = c.clusterOperatorClient.ClusterOperators().Create(ctx, &configv1.ClusterOperator{ - ObjectMeta: metav1.ObjectMeta{Name: c.clusterOperatorName}, - }, metav1.CreateOptions{}) + _, createErr = c.clusterOperatorClient.ClusterOperators().Apply(ctx, applyconfigv1.ClusterOperator(c.clusterOperatorName), metav1.ApplyOptions{FieldManager: c.controllerInstanceName}) if apierrors.IsNotFound(createErr) { // this means that the API isn't present. We did not fail. Try again later klog.Infof("ClusterOperator API not created") @@ -164,110 +171,210 @@ func (c StatusSyncer) Sync(ctx context.Context, syncCtx factory.SyncContext) err syncCtx.Recorder().Warningf("StatusCreateFailed", "Failed to create operator status: %v", createErr) return createErr } + // it's ok to create and then ApplyStatus with different content because Appy and ApplyStatus are tracked as different fieldManagers in metadata + // re-enter the loop + return nil } - clusterOperatorObj := originalClusterOperatorObj.DeepCopy() - if detailedSpec.ManagementState == operatorv1.Unmanaged && !management.IsOperatorAlwaysManaged() { - configv1helpers.SetStatusCondition(&clusterOperatorObj.Status.Conditions, configv1.ClusterOperatorStatusCondition{Type: configv1.OperatorAvailable, Status: configv1.ConditionUnknown, Reason: "Unmanaged"}) - configv1helpers.SetStatusCondition(&clusterOperatorObj.Status.Conditions, configv1.ClusterOperatorStatusCondition{Type: configv1.OperatorProgressing, Status: configv1.ConditionUnknown, Reason: "Unmanaged"}) - configv1helpers.SetStatusCondition(&clusterOperatorObj.Status.Conditions, configv1.ClusterOperatorStatusCondition{Type: configv1.OperatorDegraded, Status: configv1.ConditionUnknown, Reason: "Unmanaged"}) - configv1helpers.SetStatusCondition(&clusterOperatorObj.Status.Conditions, configv1.ClusterOperatorStatusCondition{Type: configv1.OperatorUpgradeable, Status: configv1.ConditionUnknown, Reason: "Unmanaged"}) - configv1helpers.SetStatusCondition(&clusterOperatorObj.Status.Conditions, configv1.ClusterOperatorStatusCondition{Type: configv1.EvaluationConditionsDetected, Status: configv1.ConditionUnknown, Reason: "Unmanaged"}) + previouslyDesiredStatus, err := applyconfigv1.ExtractClusterOperatorStatus(originalClusterOperatorObj, c.controllerInstanceName) + if err != nil && !apierrors.IsNotFound(err) { + syncCtx.Recorder().Warningf("StatusFailed", "Unable to get extract operator status for clusteroperator/%s: %v", c.clusterOperatorName, err) + return err + } - if equality.Semantic.DeepEqual(clusterOperatorObj, originalClusterOperatorObj) { + if detailedSpec.ManagementState == operatorv1.Unmanaged && !management.IsOperatorAlwaysManaged() { + desiredStatus := applyconfigv1.ClusterOperatorStatus() + desiredStatus.WithConditions( + applyconfigv1.ClusterOperatorStatusCondition(). + WithType(configv1.OperatorAvailable). + WithStatus(configv1.ConditionUnknown). + WithReason("Unmanaged"), + applyconfigv1.ClusterOperatorStatusCondition(). + WithType(configv1.OperatorProgressing). + WithStatus(configv1.ConditionUnknown). + WithReason("Unmanaged"), + applyconfigv1.ClusterOperatorStatusCondition(). + WithType(configv1.OperatorDegraded). + WithStatus(configv1.ConditionUnknown). + WithReason("Unmanaged"), + applyconfigv1.ClusterOperatorStatusCondition(). + WithType(configv1.OperatorUpgradeable). + WithStatus(configv1.ConditionUnknown). + WithReason("Unmanaged"), + applyconfigv1.ClusterOperatorStatusCondition(). + WithType(configv1.EvaluationConditionsDetected). + WithStatus(configv1.ConditionUnknown). + WithReason("Unmanaged"), + ) + operatorv1helpers.SetClusterOperatorApplyConditionsLastTransitionTime(c.clock, &desiredStatus.Conditions, previouslyDesiredStatus.Status.Conditions) + + if equivalent, err := operatorv1helpers.AreClusterOperatorStatusEquivalent(desiredStatus, previouslyDesiredStatus.Status); err != nil { + return fmt.Errorf("unable to compare desired and existing: %w", err) + } else if equivalent { return nil } - if _, err := c.clusterOperatorClient.ClusterOperators().UpdateStatus(ctx, clusterOperatorObj, metav1.UpdateOptions{}); err != nil { + + if _, err := c.clusterOperatorClient.ClusterOperators().ApplyStatus(ctx, applyconfigv1.ClusterOperator(c.Name()).WithStatus(desiredStatus), metav1.ApplyOptions{ + Force: true, + FieldManager: c.controllerInstanceName, + }); err != nil { return err } - if !skipOperatorStatusChangedEvent(originalClusterOperatorObj.Status, clusterOperatorObj.Status) { - syncCtx.Recorder().Eventf("OperatorStatusChanged", "Status for operator %s changed: %s", c.clusterOperatorName, configv1helpers.GetStatusDiff(originalClusterOperatorObj.Status, clusterOperatorObj.Status)) + + if !skipOperatorStatusChangedEvent(previouslyDesiredStatus.Status, desiredStatus) { + syncCtx.Recorder().Eventf("OperatorStatusChanged", "Status for operator %s changed: %s", c.clusterOperatorName, configv1helpers.GetStatusDiff(previouslyDesiredStatus.Status, desiredStatus)) } return nil } + desiredStatus := applyconfigv1.ClusterOperatorStatus() if c.relatedObjectsFunc != nil { isSet, ro := c.relatedObjectsFunc() + + newRelatedObjects := []*applyconfigv1.ObjectReferenceApplyConfiguration{} if !isSet { // temporarily unknown - copy over from existing object - ro = clusterOperatorObj.Status.RelatedObjects + if previouslyDesiredStatus.Status != nil { + for i := range previouslyDesiredStatus.Status.RelatedObjects { + newRelatedObjects = append(newRelatedObjects, &previouslyDesiredStatus.Status.RelatedObjects[i]) + } + } + } else { + for _, obj := range ro { + newRelatedObjects = append(newRelatedObjects, operatorv1helpers.ToApplyClusterOperatorRelatedObj(obj)) + } } // merge in any static objects for _, obj := range c.relatedObjects { + applyObj := operatorv1helpers.ToApplyClusterOperatorRelatedObj(obj) found := false - for _, existingObj := range ro { - if obj == existingObj { + for _, existingObj := range newRelatedObjects { + if applyObj == existingObj { found = true break } } if !found { - ro = append(ro, obj) + newRelatedObjects = append(newRelatedObjects, applyObj) } } - clusterOperatorObj.Status.RelatedObjects = ro + desiredStatus.WithRelatedObjects(newRelatedObjects...) } else { - clusterOperatorObj.Status.RelatedObjects = c.relatedObjects + for _, obj := range c.relatedObjects { + desiredStatus.WithRelatedObjects(operatorv1helpers.ToApplyClusterOperatorRelatedObj(obj)) + } } - configv1helpers.SetStatusCondition(&clusterOperatorObj.Status.Conditions, UnionClusterCondition(configv1.OperatorDegraded, operatorv1.ConditionFalse, c.degradedInertia, currentDetailedStatus.Conditions...)) - configv1helpers.SetStatusCondition(&clusterOperatorObj.Status.Conditions, UnionClusterCondition(configv1.OperatorProgressing, operatorv1.ConditionFalse, nil, currentDetailedStatus.Conditions...)) - configv1helpers.SetStatusCondition(&clusterOperatorObj.Status.Conditions, UnionClusterCondition(configv1.OperatorAvailable, operatorv1.ConditionTrue, nil, currentDetailedStatus.Conditions...)) - configv1helpers.SetStatusCondition(&clusterOperatorObj.Status.Conditions, UnionClusterCondition(configv1.OperatorUpgradeable, operatorv1.ConditionTrue, nil, currentDetailedStatus.Conditions...)) - configv1helpers.SetStatusCondition(&clusterOperatorObj.Status.Conditions, UnionClusterCondition(configv1.EvaluationConditionsDetected, operatorv1.ConditionFalse, nil, currentDetailedStatus.Conditions...)) + desiredStatus.WithConditions( + UnionClusterCondition(c.clock, configv1.OperatorDegraded, operatorv1.ConditionFalse, c.degradedInertia, currentDetailedStatus.Conditions...), + UnionClusterCondition(c.clock, configv1.OperatorProgressing, operatorv1.ConditionFalse, nil, currentDetailedStatus.Conditions...), + UnionClusterCondition(c.clock, configv1.OperatorAvailable, operatorv1.ConditionTrue, nil, currentDetailedStatus.Conditions...), + UnionClusterCondition(c.clock, configv1.OperatorUpgradeable, operatorv1.ConditionTrue, nil, currentDetailedStatus.Conditions...), + UnionClusterCondition(c.clock, configv1.EvaluationConditionsDetected, operatorv1.ConditionFalse, nil, currentDetailedStatus.Conditions...), + ) + var previousConditions []applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration + if previouslyDesiredStatus != nil && previouslyDesiredStatus.Status != nil { + previousConditions = previouslyDesiredStatus.Status.Conditions + } + operatorv1helpers.SetClusterOperatorApplyConditionsLastTransitionTime(c.clock, &desiredStatus.Conditions, previousConditions) - c.syncStatusVersions(clusterOperatorObj, syncCtx) + desiredStatus.WithVersions(c.createNewOperatorVersions(previouslyDesiredStatus.Status, syncCtx)...) // if we have no diff, just return - if equality.Semantic.DeepEqual(clusterOperatorObj, originalClusterOperatorObj) { + if equivalent, err := operatorv1helpers.AreClusterOperatorStatusEquivalent(desiredStatus, previouslyDesiredStatus.Status); err != nil { + return fmt.Errorf("unable to compare desired and existing: %w", err) + } else if equivalent { return nil } - klog.V(2).Infof("clusteroperator/%s diff %v", c.clusterOperatorName, resourceapply.JSONPatchNoError(originalClusterOperatorObj, clusterOperatorObj)) - if _, updateErr := c.clusterOperatorClient.ClusterOperators().UpdateStatus(ctx, clusterOperatorObj, metav1.UpdateOptions{}); updateErr != nil { + if klog.V(2).Enabled() { + previousClusterOperator := &configv1.ClusterOperator{} + if previouslyDesiredStatus != nil { + s, _ := operatorv1helpers.ToClusterOperator(previouslyDesiredStatus.Status) + if s != nil { + previousClusterOperator.Status = *s + } + } + desiredClusterOperator := &configv1.ClusterOperator{} + s, _ := operatorv1helpers.ToClusterOperator(desiredStatus) + desiredClusterOperator.Status = *s + + klog.V(2).Infof("clusteroperator/%s diff %v", c.clusterOperatorName, resourceapply.JSONPatchNoError(previousClusterOperator, desiredClusterOperator)) + } + + if _, updateErr := c.clusterOperatorClient.ClusterOperators().ApplyStatus(ctx, applyconfigv1.ClusterOperator(c.Name()).WithStatus(desiredStatus), metav1.ApplyOptions{ + Force: true, + FieldManager: c.controllerInstanceName, + }); updateErr != nil { return updateErr } - if !skipOperatorStatusChangedEvent(originalClusterOperatorObj.Status, clusterOperatorObj.Status) { - syncCtx.Recorder().Eventf("OperatorStatusChanged", "Status for clusteroperator/%s changed: %s", c.clusterOperatorName, configv1helpers.GetStatusDiff(originalClusterOperatorObj.Status, clusterOperatorObj.Status)) + if !skipOperatorStatusChangedEvent(previouslyDesiredStatus.Status, desiredStatus) { + syncCtx.Recorder().Eventf("OperatorStatusChanged", "Status for clusteroperator/%s changed: %s", c.clusterOperatorName, configv1helpers.GetStatusDiff(previouslyDesiredStatus.Status, desiredStatus)) } return nil } -func skipOperatorStatusChangedEvent(originalStatus, newStatus configv1.ClusterOperatorStatus) bool { - originalCopy := *originalStatus.DeepCopy() - for i, condition := range originalCopy.Conditions { - switch condition.Type { - case configv1.OperatorAvailable, configv1.OperatorDegraded, configv1.OperatorProgressing, configv1.OperatorUpgradeable: - originalCopy.Conditions[i].Message = strings.TrimPrefix(condition.Message, "\ufeff") +func skipOperatorStatusChangedEvent(originalStatus, newStatus *applyconfigv1.ClusterOperatorStatusApplyConfiguration) bool { + originalWithScrubbedConditions := originalStatus + if originalStatus != nil { + originalWithScrubbedConditions = &applyconfigv1.ClusterOperatorStatusApplyConfiguration{ + Conditions: nil, + Versions: originalStatus.Versions, + RelatedObjects: originalStatus.RelatedObjects, + Extension: originalStatus.Extension, + } + + for _, curr := range originalStatus.Conditions { + switch ptr.Deref(curr.Type, "") { + case configv1.OperatorAvailable, configv1.OperatorDegraded, configv1.OperatorProgressing, configv1.OperatorUpgradeable: + scrubbedCondition := &applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration{ + Type: curr.Type, + Status: curr.Status, + LastTransitionTime: curr.LastTransitionTime, + Reason: curr.Reason, + Message: ptr.To(strings.TrimPrefix(ptr.Deref(curr.Message, ""), "\ufeff")), + } + originalWithScrubbedConditions.WithConditions(scrubbedCondition) + default: + originalWithScrubbedConditions.WithConditions(&curr) + } } } - return len(configv1helpers.GetStatusDiff(originalCopy, newStatus)) == 0 + return len(configv1helpers.GetStatusDiff(originalWithScrubbedConditions, newStatus)) == 0 } -func (c *StatusSyncer) syncStatusVersions(clusterOperatorObj *configv1.ClusterOperator, syncCtx factory.SyncContext) { +func (c *StatusSyncer) createNewOperatorVersions(previousStatus *applyconfigv1.ClusterOperatorStatusApplyConfiguration, syncCtx factory.SyncContext) []*applyconfigv1.OperandVersionApplyConfiguration { + ret := []*applyconfigv1.OperandVersionApplyConfiguration{} versions := c.versionGetter.GetVersions() // Add new versions from versionGetter to status for operand, version := range versions { - previousVersion := operatorv1helpers.SetOperandVersion(&clusterOperatorObj.Status.Versions, configv1.OperandVersion{Name: operand, Version: version}) - if previousVersion != version { - // having this message will give us a marker in events when the operator updated compared to when the operand is updated - syncCtx.Recorder().Eventf("OperatorVersionChanged", "clusteroperator/%s version %q changed from %q to %q", c.clusterOperatorName, operand, previousVersion, version) + ret = append(ret, applyconfigv1.OperandVersion().WithName(operand).WithVersion(version)) + + if previousStatus != nil { + previousVersion := operatorv1helpers.FindOperandVersion(previousStatus.Versions, operand) + if previousVersion == nil || ptr.Deref(previousVersion.Version, "") != version { + // having this message will give us a marker in events when the operator updated compared to when the operand is updated + syncCtx.Recorder().Eventf("OperatorVersionChanged", "clusteroperator/%s version %q changed from %q to %q", c.clusterOperatorName, operand, previousVersion, version) + } } } - if !c.removeUnusedVersions { - return + if c.removeUnusedVersions { + return ret } - // Filter out all versions from status that are not in versionGetter - filteredVersions := make([]configv1.OperandVersion, 0, len(clusterOperatorObj.Status.Versions)) - for _, version := range clusterOperatorObj.Status.Versions { - if _, found := versions[version.Name]; found { - filteredVersions = append(filteredVersions, version) + // if we are here, we should keep all existing versions. This seems a little weird, but I don't remember the history + if previousStatus != nil { + for i := range previousStatus.Versions { + previousOperandVersion := previousStatus.Versions[i] + desiredVersion := operatorv1helpers.FindOperandVersionPtr(ret, ptr.Deref(previousOperandVersion.Name, "")) + if desiredVersion == nil { + ret = append(ret, &previousOperandVersion) + } } } - clusterOperatorObj.Status.Versions = filteredVersions + return ret } func (c *StatusSyncer) watchVersionGetterPostRunHook(ctx context.Context, syncCtx factory.SyncContext) error { diff --git a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/clusteroperator_status_helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/clusteroperator_status_helpers.go new file mode 100644 index 000000000..7fb7350b5 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/clusteroperator_status_helpers.go @@ -0,0 +1,130 @@ +package v1helpers + +import ( + "fmt" + configv1 "github.com/openshift/api/config/v1" + applyconfigv1 "github.com/openshift/client-go/config/applyconfigurations/config/v1" + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/util/json" + "slices" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/clock" + "k8s.io/utils/ptr" +) + +func AreClusterOperatorStatusEquivalent(lhs, rhs *applyconfigv1.ClusterOperatorStatusApplyConfiguration) (bool, error) { + CanonicalizeClusterOperatorStatus(lhs) + CanonicalizeClusterOperatorStatus(rhs) + lhsObj, err := ToClusterOperator(lhs) + if err != nil { + return false, err + } + rhsObj, err := ToClusterOperator(rhs) + if err != nil { + return false, err + } + if equality.Semantic.DeepEqual(rhsObj, lhsObj) { + return true, nil + } + + return false, nil +} + +func ToApplyClusterOperatorRelatedObj(in configv1.ObjectReference) *applyconfigv1.ObjectReferenceApplyConfiguration { + return applyconfigv1.ObjectReference().WithName(in.Name).WithNamespace(in.Namespace).WithGroup(in.Group).WithResource(in.Resource) +} + +// ToStaticPodOperator returns the equivalent typed kind for the applyconfiguration. Due to differences in serialization like +// omitempty on strings versus pointers, the returned values can be slightly different. This is an expensive way to diff the +// result, but it is an effective one. +func ToClusterOperator(in *applyconfigv1.ClusterOperatorStatusApplyConfiguration) (*configv1.ClusterOperatorStatus, error) { + if in == nil { + return nil, nil + } + jsonBytes, err := json.Marshal(in) + if err != nil { + return nil, fmt.Errorf("unable to serialize: %w", err) + } + + ret := &configv1.ClusterOperatorStatus{} + if err := json.Unmarshal(jsonBytes, ret); err != nil { + return nil, fmt.Errorf("unable to deserialize: %w", err) + } + + return ret, nil +} + +func SetClusterOperatorApplyConditionsLastTransitionTime(clock clock.PassiveClock, newConditions *[]applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration, oldConditions []applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration) { + if newConditions == nil { + return + } + + now := metav1.NewTime(clock.Now()) + for i := range *newConditions { + newCondition := (*newConditions)[i] + + // if the condition status is the same, then the lastTransitionTime doesn't change + if existingCondition := FindClusterOperatorApplyCondition(oldConditions, newCondition.Type); existingCondition != nil && ptr.Equal(existingCondition.Status, newCondition.Status) { + newCondition.LastTransitionTime = existingCondition.LastTransitionTime + } + + // backstop to handle upgrade case too. If the newCondition doesn't have a lastTransitionTime it needs something + if newCondition.LastTransitionTime == nil { + newCondition.LastTransitionTime = &now + } + + (*newConditions)[i] = newCondition + } +} + +func FindClusterOperatorApplyCondition(haystack []applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration, conditionType *configv1.ClusterStatusConditionType) *applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration { + for i := range haystack { + curr := haystack[i] + if ptr.Equal(curr.Type, conditionType) { + return &curr + } + } + + return nil +} + +func CanonicalizeClusterOperatorStatus(obj *applyconfigv1.ClusterOperatorStatusApplyConfiguration) { + if obj == nil { + return + } + slices.SortStableFunc(obj.Conditions, CompareClusterOperatorConditionByType) + slices.SortStableFunc(obj.Versions, CompareClusterOperatorVersionsByName) + slices.SortStableFunc(obj.RelatedObjects, CompareClusterOperatorRelatedObjects) +} + +func CompareClusterOperatorConditionByType(a, b applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration) int { + return strings.Compare(string(ptr.Deref(a.Type, "")), string(ptr.Deref(b.Type, ""))) +} + +func CompareClusterOperatorVersionsByName(a, b applyconfigv1.OperandVersionApplyConfiguration) int { + if cmp := strings.Compare(ptr.Deref(a.Name, ""), ptr.Deref(b.Name, "")); cmp != 0 { + return cmp + } + if cmp := strings.Compare(ptr.Deref(a.Version, ""), ptr.Deref(b.Version, "")); cmp != 0 { + return cmp + } + return 0 +} + +func CompareClusterOperatorRelatedObjects(a, b applyconfigv1.ObjectReferenceApplyConfiguration) int { + if cmp := strings.Compare(ptr.Deref(a.Group, ""), ptr.Deref(b.Group, "")); cmp != 0 { + return cmp + } + if cmp := strings.Compare(ptr.Deref(a.Resource, ""), ptr.Deref(b.Resource, "")); cmp != 0 { + return cmp + } + if cmp := strings.Compare(ptr.Deref(a.Namespace, ""), ptr.Deref(b.Namespace, "")); cmp != 0 { + return cmp + } + if cmp := strings.Compare(ptr.Deref(a.Name, ""), ptr.Deref(b.Name, "")); cmp != 0 { + return cmp + } + return 0 +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go index e69ec34af..a1fc1e2e3 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/helpers.go @@ -4,13 +4,14 @@ import ( "context" "errors" "fmt" + applyconfigv1 "github.com/openshift/client-go/config/applyconfigurations/config/v1" + "k8s.io/utils/ptr" "os" "sort" "strings" "time" "github.com/google/go-cmp/cmp" - configv1 "github.com/openshift/api/config/v1" operatorv1 "github.com/openshift/api/operator/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" @@ -23,29 +24,25 @@ import ( "sigs.k8s.io/yaml" ) -// SetOperandVersion sets the new version and returns the previous value. -func SetOperandVersion(versions *[]configv1.OperandVersion, operandVersion configv1.OperandVersion) string { +func FindOperandVersion(versions []applyconfigv1.OperandVersionApplyConfiguration, name string) *applyconfigv1.OperandVersionApplyConfiguration { if versions == nil { - versions = &[]configv1.OperandVersion{} + return nil } - existingVersion := FindOperandVersion(*versions, operandVersion.Name) - if existingVersion == nil { - *versions = append(*versions, operandVersion) - return "" + for i := range versions { + if ptr.Deref(versions[i].Name, "") == name { + return &versions[i] + } } - - previous := existingVersion.Version - existingVersion.Version = operandVersion.Version - return previous + return nil } -func FindOperandVersion(versions []configv1.OperandVersion, name string) *configv1.OperandVersion { +func FindOperandVersionPtr(versions []*applyconfigv1.OperandVersionApplyConfiguration, name string) *applyconfigv1.OperandVersionApplyConfiguration { if versions == nil { return nil } for i := range versions { - if versions[i].Name == name { - return &versions[i] + if ptr.Deref(versions[i].Name, "") == name { + return versions[i] } } return nil diff --git a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/canonicalize.go b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/operator_status_helpers.go similarity index 100% rename from vendor/github.com/openshift/library-go/pkg/operator/v1helpers/canonicalize.go rename to vendor/github.com/openshift/library-go/pkg/operator/v1helpers/operator_status_helpers.go diff --git a/vendor/modules.txt b/vendor/modules.txt index 487ec2d28..0cefb4d85 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -309,7 +309,7 @@ github.com/openshift/client-go/user/applyconfigurations/internal github.com/openshift/client-go/user/applyconfigurations/user/v1 github.com/openshift/client-go/user/clientset/versioned/scheme github.com/openshift/client-go/user/clientset/versioned/typed/user/v1 -# github.com/openshift/library-go v0.0.0-20241023193830-022ad9c25e39 +# github.com/openshift/library-go v0.0.0-20241023193830-022ad9c25e39 => github.com/deads2k/library-go v0.0.0-20241024233548-385187f0041d ## explicit; go 1.22.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/apps/deployment @@ -1472,3 +1472,4 @@ sigs.k8s.io/structured-merge-diff/v4/value ## explicit; go 1.12 sigs.k8s.io/yaml sigs.k8s.io/yaml/goyaml.v2 +# github.com/openshift/library-go => github.com/deads2k/library-go v0.0.0-20241024233548-385187f0041d