diff --git a/go.mod b/go.mod index 8517189c3..ffc3878ae 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-20241023193402-db83b673eaec diff --git a/go.sum b/go.sum index 7822ce92d..7d8785c97 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-20241023193402-db83b673eaec h1:owj+sAs7tofeOq2sKI5sqJdJW9l+ExgViVtm7osfA8c= +github.com/deads2k/library-go v0.0.0-20241023193402-db83b673eaec/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-20241021151851-4c5ecb35c294 h1:wz02/A1CsKVqNJD+Yg4NLw9SnNpGX9JK5lEb4qxM81k= -github.com/openshift/library-go v0.0.0-20241021151851-4c5ecb35c294/go.mod h1:9B1MYPoLtP9tqjWxcbUNVpwxy68zOH/3EIP6c31dAM0= github.com/openshift/multi-operator-manager v0.0.0-20241017140751-8b22f6c45da3 h1:/rOm5CjL8W8sSeSzf/bg8wySP98+juT2SbVhBhmROLo= github.com/openshift/multi-operator-manager v0.0.0-20241017140751-8b22f6c45da3/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/crypto/crypto.go b/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go index 63184d2eb..e6651fecc 100644 --- a/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go +++ b/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go @@ -150,9 +150,9 @@ var ciphers = map[string]uint16{ // ref: https://www.iana.org/assignments/tls-parameters/tls-parameters.xml var openSSLToIANACiphersMap = map[string]string{ // TLS 1.3 ciphers - not configurable in go 1.13, all of them are used in TLSv1.3 flows - // "TLS_AES_128_GCM_SHA256": "TLS_AES_128_GCM_SHA256", // 0x13,0x01 - // "TLS_AES_256_GCM_SHA384": "TLS_AES_256_GCM_SHA384", // 0x13,0x02 - // "TLS_CHACHA20_POLY1305_SHA256": "TLS_CHACHA20_POLY1305_SHA256", // 0x13,0x03 + "TLS_AES_128_GCM_SHA256": "TLS_AES_128_GCM_SHA256", // 0x13,0x01 + "TLS_AES_256_GCM_SHA384": "TLS_AES_256_GCM_SHA384", // 0x13,0x02 + "TLS_CHACHA20_POLY1305_SHA256": "TLS_CHACHA20_POLY1305_SHA256", // 0x13,0x03 // TLS 1.2 "ECDHE-ECDSA-AES128-GCM-SHA256": "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", // 0xC0,0x2B 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 ed1425f7a..4364cb353 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 @@ -159,10 +159,11 @@ func serializedRequestFromFile(action Action, actionFS fs.FS, bodyFilename strin Version: versionName, Resource: resourceName, }, - KindType: retObj.(*unstructured.Unstructured).GroupVersionKind(), - Namespace: retObj.(*unstructured.Unstructured).GetNamespace(), - Name: metadataName, - Body: bodyContent, + KindType: retObj.(*unstructured.Unstructured).GroupVersionKind(), + Namespace: retObj.(*unstructured.Unstructured).GetNamespace(), + Name: metadataName, + GenerateName: retObj.(*unstructured.Unstructured).GetGenerateName(), + Body: bodyContent, }, } if optionsExist { diff --git a/vendor/github.com/openshift/library-go/pkg/manifestclient/mutation_tracker.go b/vendor/github.com/openshift/library-go/pkg/manifestclient/mutation_tracker.go index bdab4cab1..bfa24700d 100644 --- a/vendor/github.com/openshift/library-go/pkg/manifestclient/mutation_tracker.go +++ b/vendor/github.com/openshift/library-go/pkg/manifestclient/mutation_tracker.go @@ -35,10 +35,11 @@ type AllActionsTracker[T SerializedRequestish] struct { } type ActionMetadata struct { - Action Action - GVR schema.GroupVersionResource - Namespace string - Name string + Action Action + GVR schema.GroupVersionResource + Namespace string + Name string + GenerateName string } type actionTracker[T SerializedRequestish] struct { diff --git a/vendor/github.com/openshift/library-go/pkg/manifestclient/serialized_request.go b/vendor/github.com/openshift/library-go/pkg/manifestclient/serialized_request.go index d8d60b910..1420fd9ed 100644 --- a/vendor/github.com/openshift/library-go/pkg/manifestclient/serialized_request.go +++ b/vendor/github.com/openshift/library-go/pkg/manifestclient/serialized_request.go @@ -34,6 +34,7 @@ type SerializedRequest struct { KindType schema.GroupVersionKind Namespace string Name string + GenerateName string Options []byte Body []byte @@ -206,6 +207,9 @@ func CompareSerializedRequest(lhs, rhs *SerializedRequest) int { if cmp := strings.Compare(lhs.Name, rhs.Name); cmp != 0 { return cmp } + if cmp := strings.Compare(lhs.GenerateName, rhs.GenerateName); cmp != 0 { + return cmp + } if cmp := bytes.Compare(lhs.Body, rhs.Body); cmp != 0 { return cmp @@ -262,7 +266,7 @@ func suggestedFilenames(a SerializedRequest, uniqueNumber int) (string, string) scopingString, groupName, a.ResourceType.Resource, - fmt.Sprintf("%03d-body-%s.yaml", uniqueNumber, a.Name), + fmt.Sprintf("%03d-body-%s%s.yaml", uniqueNumber, a.Name, a.GenerateName), ), ) optionsFilename := "" @@ -273,7 +277,7 @@ func suggestedFilenames(a SerializedRequest, uniqueNumber int) (string, string) scopingString, groupName, a.ResourceType.Resource, - fmt.Sprintf("%03d-options-%s.yaml", uniqueNumber, a.Name), + fmt.Sprintf("%03d-options-%s%s.yaml", uniqueNumber, a.Name, a.GenerateName), ), ) } @@ -302,20 +306,22 @@ func (a SerializedRequest) DeepCopy() SerializedRequestish { KindType: a.KindType, Namespace: a.Namespace, Name: a.Name, + GenerateName: a.GenerateName, Options: bytes.Clone(a.Options), Body: bytes.Clone(a.Body), } } func (a SerializedRequest) StringID() string { - return fmt.Sprintf("%s-%s.%s.%s/%s[%s]", a.Action, a.KindType.Kind, a.KindType.Version, a.KindType.Group, a.Name, a.Namespace) + return fmt.Sprintf("%s-%s.%s.%s/%s%s[%s]", a.Action, a.KindType.Kind, a.KindType.Version, a.KindType.Group, a.Name, a.GenerateName, a.Namespace) } func (a SerializedRequest) GetLookupMetadata() ActionMetadata { return ActionMetadata{ - Action: a.Action, - GVR: a.ResourceType, - Namespace: a.Namespace, - Name: a.Name, + Action: a.Action, + GVR: a.ResourceType, + Namespace: a.Namespace, + Name: a.Name, + GenerateName: a.GenerateName, } } diff --git a/vendor/github.com/openshift/library-go/pkg/manifestclient/write_roundtripper.go b/vendor/github.com/openshift/library-go/pkg/manifestclient/write_roundtripper.go index 407c0f65f..79cfdba0c 100644 --- a/vendor/github.com/openshift/library-go/pkg/manifestclient/write_roundtripper.go +++ b/vendor/github.com/openshift/library-go/pkg/manifestclient/write_roundtripper.go @@ -168,6 +168,7 @@ func (mrt *writeTrackingRoundTripper) roundTrip(req *http.Request) ([]byte, erro KindType: bodyObj.GetObjectKind().GroupVersionKind(), Namespace: requestInfo.Namespace, Name: metadataName, + GenerateName: bodyObj.(*unstructured.Unstructured).GetGenerateName(), Options: optionsBytes, Body: bodyYAMLBytes, } 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/resource/resourceread/admission.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceread/admission.go index 572b915bc..11326c89d 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceread/admission.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceread/admission.go @@ -53,3 +53,21 @@ func ReadValidatingAdmissionPolicyBindingV1beta1OrDie(objBytes []byte) *admissio return requiredObj.(*admissionv1beta1.ValidatingAdmissionPolicyBinding) } + +func ReadValidatingAdmissionPolicyV1OrDie(objBytes []byte) *admissionv1.ValidatingAdmissionPolicy { + requiredObj, err := runtime.Decode(admissionCodecs.UniversalDecoder(admissionv1.SchemeGroupVersion), objBytes) + if err != nil { + panic(err) + } + + return requiredObj.(*admissionv1.ValidatingAdmissionPolicy) +} + +func ReadValidatingAdmissionPolicyBindingV1OrDie(objBytes []byte) *admissionv1.ValidatingAdmissionPolicyBinding { + requiredObj, err := runtime.Decode(admissionCodecs.UniversalDecoder(admissionv1.SchemeGroupVersion), objBytes) + if err != nil { + panic(err) + } + + return requiredObj.(*admissionv1.ValidatingAdmissionPolicyBinding) +} 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..edcafa0b6 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,6 +2,8 @@ package status import ( "fmt" + applyconfigv1 "github.com/openshift/client-go/config/applyconfigurations/config/v1" + "k8s.io/utils/ptr" "sort" "strings" "time" @@ -89,18 +91,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 { +func UnionClusterCondition(conditionType configv1.ClusterStatusConditionType, defaultConditionStatus operatorv1.ConditionStatus, inertia Inertia, allConditions ...operatorv1.OperatorCondition) *applyconfigv1.ClusterOperatorStatusConditionApplyConfiguration { cnd := UnionCondition(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..9a08a4e1b 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,205 @@ 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(configv1.OperatorDegraded, operatorv1.ConditionFalse, c.degradedInertia, currentDetailedStatus.Conditions...), + UnionClusterCondition(configv1.OperatorProgressing, operatorv1.ConditionFalse, nil, currentDetailedStatus.Conditions...), + UnionClusterCondition(configv1.OperatorAvailable, operatorv1.ConditionTrue, nil, currentDetailedStatus.Conditions...), + UnionClusterCondition(configv1.OperatorUpgradeable, operatorv1.ConditionTrue, nil, currentDetailedStatus.Conditions...), + UnionClusterCondition(configv1.EvaluationConditionsDetected, operatorv1.ConditionFalse, nil, currentDetailedStatus.Conditions...), + ) - 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/github.com/openshift/library-go/pkg/operator/v1helpers/test_helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/test_helpers.go index 5f37e5255..7a00ec8b3 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/test_helpers.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/test_helpers.go @@ -167,13 +167,13 @@ func (c *fakeStaticPodOperatorClient) ApplyOperatorSpec(ctx context.Context, fie func (c *fakeStaticPodOperatorClient) ApplyOperatorStatus(ctx context.Context, fieldManager string, applyConfiguration *applyoperatorv1.OperatorStatusApplyConfiguration) (err error) { if c.triggerStatusUpdateError != nil { - operatorStatus := &operatorv1.StaticPodOperatorStatus{OperatorStatus: *convertOperatorStatusApplyConfiguration(applyConfiguration)} + operatorStatus := &operatorv1.StaticPodOperatorStatus{OperatorStatus: *mergeOperatorStatusApplyConfiguration(&c.fakeStaticPodOperatorStatus.OperatorStatus, applyConfiguration)} if err := c.triggerStatusUpdateError("", operatorStatus); err != nil { return err } } c.fakeStaticPodOperatorStatus = &operatorv1.StaticPodOperatorStatus{ - OperatorStatus: *convertOperatorStatusApplyConfiguration(applyConfiguration), + OperatorStatus: *mergeOperatorStatusApplyConfiguration(&c.fakeStaticPodOperatorStatus.OperatorStatus, applyConfiguration), } return nil } @@ -183,7 +183,13 @@ func (c *fakeStaticPodOperatorClient) ApplyStaticPodOperatorSpec(ctx context.Con } func (c *fakeStaticPodOperatorClient) ApplyStaticPodOperatorStatus(ctx context.Context, fieldManager string, applyConfiguration *applyoperatorv1.StaticPodOperatorStatusApplyConfiguration) (err error) { - c.fakeStaticPodOperatorStatus = convertStaticPodOperatorStatusApplyConfiguration(applyConfiguration) + if c.triggerStatusUpdateError != nil { + operatorStatus := mergeStaticPodOperatorStatusApplyConfiguration(&c.fakeStaticPodOperatorStatus.OperatorStatus, applyConfiguration) + if err := c.triggerStatusUpdateError("", operatorStatus); err != nil { + return err + } + } + c.fakeStaticPodOperatorStatus = mergeStaticPodOperatorStatusApplyConfiguration(&c.fakeStaticPodOperatorStatus.OperatorStatus, applyConfiguration) return nil } @@ -336,7 +342,7 @@ func (c *fakeOperatorClient) ApplyOperatorSpec(ctx context.Context, fieldManager } func (c *fakeOperatorClient) ApplyOperatorStatus(ctx context.Context, fieldManager string, applyConfiguration *applyoperatorv1.OperatorStatusApplyConfiguration) (err error) { - c.fakeOperatorStatus = convertOperatorStatusApplyConfiguration(applyConfiguration) + c.fakeOperatorStatus = mergeOperatorStatusApplyConfiguration(c.fakeOperatorStatus, applyConfiguration) return nil } @@ -373,12 +379,12 @@ func (c *fakeOperatorClient) SetObjectMeta(meta *metav1.ObjectMeta) { c.fakeObjectMeta = meta } -func convertOperatorStatusApplyConfiguration(applyConfiguration *applyoperatorv1.OperatorStatusApplyConfiguration) *v1.OperatorStatus { +func mergeOperatorStatusApplyConfiguration(currentOperatorStatus *v1.OperatorStatus, applyConfiguration *applyoperatorv1.OperatorStatusApplyConfiguration) *v1.OperatorStatus { status := &v1.OperatorStatus{ - ObservedGeneration: ptr.Deref(applyConfiguration.ObservedGeneration, 0), - Version: ptr.Deref(applyConfiguration.Version, ""), - ReadyReplicas: ptr.Deref(applyConfiguration.ReadyReplicas, 0), - LatestAvailableRevision: ptr.Deref(applyConfiguration.LatestAvailableRevision, 0), + ObservedGeneration: ptr.Deref(applyConfiguration.ObservedGeneration, currentOperatorStatus.ObservedGeneration), + Version: ptr.Deref(applyConfiguration.Version, currentOperatorStatus.Version), + ReadyReplicas: ptr.Deref(applyConfiguration.ReadyReplicas, currentOperatorStatus.ReadyReplicas), + LatestAvailableRevision: ptr.Deref(applyConfiguration.LatestAvailableRevision, currentOperatorStatus.LatestAvailableRevision), } for _, condition := range applyConfiguration.Conditions { @@ -390,6 +396,20 @@ func convertOperatorStatusApplyConfiguration(applyConfiguration *applyoperatorv1 } status.Conditions = append(status.Conditions, newCondition) } + var existingConditions []v1.OperatorCondition + for _, condition := range currentOperatorStatus.Conditions { + var foundCondition bool + for _, statusCondition := range status.Conditions { + if condition.Type == statusCondition.Type { + foundCondition = true + break + } + } + if !foundCondition { + existingConditions = append(existingConditions, condition) + } + } + status.Conditions = append(status.Conditions, existingConditions...) for _, generation := range applyConfiguration.Generations { newGeneration := operatorv1.GenerationStatus{ @@ -402,13 +422,27 @@ func convertOperatorStatusApplyConfiguration(applyConfiguration *applyoperatorv1 } status.Generations = append(status.Generations, newGeneration) } + var existingGenerations []v1.GenerationStatus + for _, generation := range currentOperatorStatus.Generations { + var foundGeneration bool + for _, statusGeneration := range status.Generations { + if generation.Namespace == statusGeneration.Namespace && generation.Name == statusGeneration.Name { + foundGeneration = true + break + } + } + if !foundGeneration { + existingGenerations = append(existingGenerations, generation) + } + } + status.Generations = append(status.Generations, existingGenerations...) return status } -func convertStaticPodOperatorStatusApplyConfiguration(applyConfiguration *applyoperatorv1.StaticPodOperatorStatusApplyConfiguration) *v1.StaticPodOperatorStatus { +func mergeStaticPodOperatorStatusApplyConfiguration(currentOperatorStatus *v1.OperatorStatus, applyConfiguration *applyoperatorv1.StaticPodOperatorStatusApplyConfiguration) *v1.StaticPodOperatorStatus { status := &v1.StaticPodOperatorStatus{ - OperatorStatus: *convertOperatorStatusApplyConfiguration(&applyConfiguration.OperatorStatusApplyConfiguration), + OperatorStatus: *mergeOperatorStatusApplyConfiguration(currentOperatorStatus, &applyConfiguration.OperatorStatusApplyConfiguration), } for _, nodeStatus := range applyConfiguration.NodeStatuses { diff --git a/vendor/modules.txt b/vendor/modules.txt index 749b46514..8814b411c 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-20241021151851-4c5ecb35c294 +# github.com/openshift/library-go v0.0.0-20241021151851-4c5ecb35c294 => github.com/deads2k/library-go v0.0.0-20241023193402-db83b673eaec ## explicit; go 1.22.0 github.com/openshift/library-go/pkg/apiserver/jsonpatch github.com/openshift/library-go/pkg/apps/deployment @@ -1471,3 +1471,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-20241023193402-db83b673eaec