From 28372810f23af6070fc3985763fc9fc81e4caf04 Mon Sep 17 00:00:00 2001 From: "Per G. da Silva" Date: Tue, 20 Oct 2026 14:55:26 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20remove=20.status.activeRevisions=20?= =?UTF-8?q?from=20ClusterExtension?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the experimental ClusterExtension status.activeRevisions field and the RevisionStatus type it used, along with all related code: the setActiveRevisionsFromRevisionStates status derivation and its call in the boxcutter apply step, the e2e "reports ... as active revision(s)" step and its uses, and the dedicated "Report all active revisions" e2e scenario. Update the apply-step unit test, the draft concepts doc, and regenerate deepcopy, apply configurations, the experimental CRD, manifests, and the API reference. The field was experimental-only, so the standard ClusterExtension CRD is unaffected. Co-Authored-By: Claude Opus 4.8 Signed-off-by: Per G. da Silva --- api/v1/clusterextension_types.go | 23 ------ api/v1/zz_generated.deepcopy.go | 29 ------- .../api/v1/clusterextensionstatus.go | 17 ---- applyconfigurations/api/v1/revisionstatus.go | 64 --------------- applyconfigurations/internal/internal.go | 22 ----- applyconfigurations/utils.go | 2 - docs/api-reference/olmv1-api-reference.md | 18 ---- docs/draft/concepts/clusterobjectsets.md | 2 +- ...peratorframework.io_clusterextensions.yaml | 82 ------------------- .../controllers/boxcutter_reconcile_steps.go | 2 - .../boxcutter_reconcile_steps_apply_test.go | 54 +++++------- .../controllers/common_controller.go | 16 ---- manifests/experimental-e2e.yaml | 82 ------------------- manifests/experimental.yaml | 82 ------------------- test/e2e/features/group.feature | 1 - test/e2e/features/update.feature | 27 ------ test/e2e/steps/steps.go | 28 ------- 17 files changed, 20 insertions(+), 531 deletions(-) delete mode 100644 applyconfigurations/api/v1/revisionstatus.go diff --git a/api/v1/clusterextension_types.go b/api/v1/clusterextension_types.go index a289e926af..8d14b9cb89 100644 --- a/api/v1/clusterextension_types.go +++ b/api/v1/clusterextension_types.go @@ -515,21 +515,6 @@ type BundleMetadata struct { Release *string `json:"release,omitempty"` } -// RevisionStatus defines the observed state of a ClusterObjectSet. -type RevisionStatus struct { - // name of the ClusterObjectSet resource - Name string `json:"name"` - // conditions optionally expose the Available condition of the revision, - // in case when it is not yet marked as successfully installed (completedAt is not set). - // Given that a ClusterExtension should remain available during upgrades, an observer may use these conditions - // to get more insights about reasons for its current state. - // - // +listType=map - // +listMapKey=type - // +optional - Conditions []metav1.Condition `json:"conditions,omitempty"` -} - // ClusterExtensionStatus defines the observed state of a ClusterExtension. type ClusterExtensionStatus struct { // conditions represents the current state of the ClusterExtension. @@ -564,14 +549,6 @@ type ClusterExtensionStatus struct { // // +optional Install *ClusterExtensionInstallStatus `json:"install,omitempty"` - - // activeRevisions holds a list of currently active (non-archived) ClusterObjectSets, - // including both installed and rolling out revisions. - // +listType=map - // +listMapKey=name - // +optional - // - ActiveRevisions []RevisionStatus `json:"activeRevisions,omitempty"` } // ClusterExtensionInstallStatus is a representation of the status of the identified bundle. diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 0f679a1384..dda447c81b 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -404,13 +404,6 @@ func (in *ClusterExtensionStatus) DeepCopyInto(out *ClusterExtensionStatus) { *out = new(ClusterExtensionInstallStatus) (*in).DeepCopyInto(*out) } - if in.ActiveRevisions != nil { - in, out := &in.ActiveRevisions, &out.ActiveRevisions - *out = make([]RevisionStatus, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterExtensionStatus. @@ -925,28 +918,6 @@ func (in *ResolvedImageSource) DeepCopy() *ResolvedImageSource { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RevisionStatus) DeepCopyInto(out *RevisionStatus) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RevisionStatus. -func (in *RevisionStatus) DeepCopy() *RevisionStatus { - if in == nil { - return nil - } - out := new(RevisionStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceAccountReference) DeepCopyInto(out *ServiceAccountReference) { *out = *in diff --git a/applyconfigurations/api/v1/clusterextensionstatus.go b/applyconfigurations/api/v1/clusterextensionstatus.go index 0df4177ec3..1f70329d6b 100644 --- a/applyconfigurations/api/v1/clusterextensionstatus.go +++ b/applyconfigurations/api/v1/clusterextensionstatus.go @@ -52,10 +52,6 @@ type ClusterExtensionStatusApplyConfiguration struct { Conditions []metav1.ConditionApplyConfiguration `json:"conditions,omitempty"` // install is a representation of the current installation status for this ClusterExtension. Install *ClusterExtensionInstallStatusApplyConfiguration `json:"install,omitempty"` - // activeRevisions holds a list of currently active (non-archived) ClusterObjectSets, - // including both installed and rolling out revisions. - // - ActiveRevisions []RevisionStatusApplyConfiguration `json:"activeRevisions,omitempty"` } // ClusterExtensionStatusApplyConfiguration constructs a declarative configuration of the ClusterExtensionStatus type for use with @@ -84,16 +80,3 @@ func (b *ClusterExtensionStatusApplyConfiguration) WithInstall(value *ClusterExt b.Install = value return b } - -// WithActiveRevisions adds the given value to the ActiveRevisions field in the declarative configuration -// and returns the receiver, so that objects can be build by chaining "With" function invocations. -// If called multiple times, values provided by each call will be appended to the ActiveRevisions field. -func (b *ClusterExtensionStatusApplyConfiguration) WithActiveRevisions(values ...*RevisionStatusApplyConfiguration) *ClusterExtensionStatusApplyConfiguration { - for i := range values { - if values[i] == nil { - panic("nil value passed to WithActiveRevisions") - } - b.ActiveRevisions = append(b.ActiveRevisions, *values[i]) - } - return b -} diff --git a/applyconfigurations/api/v1/revisionstatus.go b/applyconfigurations/api/v1/revisionstatus.go deleted file mode 100644 index da44aea434..0000000000 --- a/applyconfigurations/api/v1/revisionstatus.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2026. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by controller-gen-v0.21. DO NOT EDIT. - -package v1 - -import ( - metav1 "k8s.io/client-go/applyconfigurations/meta/v1" -) - -// RevisionStatusApplyConfiguration represents a declarative configuration of the RevisionStatus type for use -// with apply. -// -// RevisionStatus defines the observed state of a ClusterObjectSet. -type RevisionStatusApplyConfiguration struct { - // name of the ClusterObjectSet resource - Name *string `json:"name,omitempty"` - // conditions optionally expose the Available condition of the revision, - // in case when it is not yet marked as successfully installed (completedAt is not set). - // Given that a ClusterExtension should remain available during upgrades, an observer may use these conditions - // to get more insights about reasons for its current state. - Conditions []metav1.ConditionApplyConfiguration `json:"conditions,omitempty"` -} - -// RevisionStatusApplyConfiguration constructs a declarative configuration of the RevisionStatus type for use with -// apply. -func RevisionStatus() *RevisionStatusApplyConfiguration { - return &RevisionStatusApplyConfiguration{} -} - -// WithName sets the Name field in the declarative configuration to the given value -// and returns the receiver, so that objects can be built by chaining "With" function invocations. -// If called multiple times, the Name field is set to the value of the last call. -func (b *RevisionStatusApplyConfiguration) WithName(value string) *RevisionStatusApplyConfiguration { - b.Name = &value - return b -} - -// WithConditions adds the given value to the Conditions field in the declarative configuration -// and returns the receiver, so that objects can be build by chaining "With" function invocations. -// If called multiple times, values provided by each call will be appended to the Conditions field. -func (b *RevisionStatusApplyConfiguration) WithConditions(values ...*metav1.ConditionApplyConfiguration) *RevisionStatusApplyConfiguration { - for i := range values { - if values[i] == nil { - panic("nil value passed to WithConditions") - } - b.Conditions = append(b.Conditions, *values[i]) - } - return b -} diff --git a/applyconfigurations/internal/internal.go b/applyconfigurations/internal/internal.go index 0c03ea2e92..67ef19d5e7 100644 --- a/applyconfigurations/internal/internal.go +++ b/applyconfigurations/internal/internal.go @@ -230,14 +230,6 @@ var schemaYAML = typed.YAMLObject(`types: - name: com.github.operator-framework.operator-controller.api.v1.ClusterExtensionStatus map: fields: - - name: activeRevisions - type: - list: - elementType: - namedType: com.github.operator-framework.operator-controller.api.v1.RevisionStatus - elementRelationship: associative - keys: - - name - name: conditions type: list: @@ -538,20 +530,6 @@ var schemaYAML = typed.YAMLObject(`types: - name: ref type: scalar: string -- name: com.github.operator-framework.operator-controller.api.v1.RevisionStatus - map: - fields: - - name: conditions - type: - list: - elementType: - namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Condition - elementRelationship: associative - keys: - - type - - name: name - type: - scalar: string - name: com.github.operator-framework.operator-controller.api.v1.SelectorType scalar: string - name: com.github.operator-framework.operator-controller.api.v1.ServiceAccountReference diff --git a/applyconfigurations/utils.go b/applyconfigurations/utils.go index 11d86eb61a..f5fb6b393d 100644 --- a/applyconfigurations/utils.go +++ b/applyconfigurations/utils.go @@ -106,8 +106,6 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &apiv1.ResolvedCatalogSourceApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("ResolvedImageSource"): return &apiv1.ResolvedImageSourceApplyConfiguration{} - case v1.SchemeGroupVersion.WithKind("RevisionStatus"): - return &apiv1.RevisionStatusApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("ServiceAccountReference"): return &apiv1.ServiceAccountReferenceApplyConfiguration{} case v1.SchemeGroupVersion.WithKind("SourceConfig"): diff --git a/docs/api-reference/olmv1-api-reference.md b/docs/api-reference/olmv1-api-reference.md index 8d2df41777..05d4d6f41f 100644 --- a/docs/api-reference/olmv1-api-reference.md +++ b/docs/api-reference/olmv1-api-reference.md @@ -383,7 +383,6 @@ _Appears in:_ | --- | --- | --- | --- | | `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | conditions represents the current state of the ClusterExtension.
The set of condition types which apply to all spec.source variations are Installed and Progressing.
The Installed condition represents whether the bundle has been installed for this ClusterExtension:
- When Installed is True and the Reason is Succeeded, the bundle has been successfully installed.
- When Installed is False and the Reason is Failed, the bundle has failed to install.
The Progressing condition represents whether or not the ClusterExtension is advancing towards a new state.
When Progressing is True and the Reason is Succeeded, the ClusterExtension is making progress towards a new state.
When Progressing is True and the Reason is Retrying, the ClusterExtension has encountered an error that could be resolved on subsequent reconciliation attempts.
When Progressing is False and the Reason is Blocked, the ClusterExtension has encountered an error that requires manual intervention for recovery.
**Experimental channel:**
When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterObjectSets in active roll out.

When the ClusterExtension is sourced from a catalog, it surfaces deprecation conditions based on catalog metadata.
These are indications from a package owner to guide users away from a particular package, channel, or bundle:
- BundleDeprecated is True if the installed bundle is marked deprecated, False if not deprecated, or Unknown if no bundle is installed yet or if catalog data is unavailable.
- ChannelDeprecated is True if any requested channel is marked deprecated, False if not deprecated, or Unknown if catalog data is unavailable.
- PackageDeprecated is True if the requested package is marked deprecated, False if not deprecated, or Unknown if catalog data is unavailable.
- Deprecated is a rollup condition that is True when any deprecation exists, False when none exist, or Unknown when catalog data is unavailable. | | Optional: \{\}
| | `install` _[ClusterExtensionInstallStatus](#clusterextensioninstallstatus)_ | install is a representation of the current installation status for this ClusterExtension. | | Optional: \{\}
| -| `activeRevisions` _[RevisionStatus](#revisionstatus) array_ | activeRevisions holds a list of currently active (non-archived) ClusterObjectSets,
including both installed and rolling out revisions.
**Experimental channel:** | | Optional: \{\}
| #### ClusterObjectDeployment @@ -753,23 +752,6 @@ _Appears in:_ | `ref` _string_ | ref contains the resolved image digest-based reference.
The digest format allows you to use other tooling to fetch the exact OCI manifests
that were used to extract the catalog contents. | | MaxLength: 1000
Required: \{\}
| -#### RevisionStatus - - - -RevisionStatus defines the observed state of a ClusterObjectSet. - - - -_Appears in:_ -- [ClusterExtensionStatus](#clusterextensionstatus) - -| Field | Description | Default | Validation | -| --- | --- | --- | --- | -| `name` _string_ | name of the ClusterObjectSet resource | | | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | conditions optionally expose the Available condition of the revision,
in case when it is not yet marked as successfully installed (completedAt is not set).
Given that a ClusterExtension should remain available during upgrades, an observer may use these conditions
to get more insights about reasons for its current state. | | Optional: \{\}
| - - #### SelectorType _Underlying type:_ _string_ diff --git a/docs/draft/concepts/clusterobjectsets.md b/docs/draft/concepts/clusterobjectsets.md index 86843aa51b..50f4999aca 100644 --- a/docs/draft/concepts/clusterobjectsets.md +++ b/docs/draft/concepts/clusterobjectsets.md @@ -257,7 +257,7 @@ When a ClusterExtension is upgraded to a new version: ### Relationship with ClusterExtension -A `ClusterExtension` owns one or more `ClusterObjectSet` resources. The ClusterExtension's `.status.activeRevisions` field lists all currently active (non-archived) revisions along with their status conditions. +A `ClusterExtension` owns one or more `ClusterObjectSet` resources. Operator-controller sets `spec.group` to the ClusterExtension's name and retains the ClusterExtension controller owner reference for garbage collection. Revision diff --git a/helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensions.yaml b/helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensions.yaml index 0cdcf27375..143cbf7fed 100644 --- a/helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensions.yaml +++ b/helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensions.yaml @@ -508,88 +508,6 @@ spec: description: status is an optional field that defines the observed state of the ClusterExtension. properties: - activeRevisions: - description: |- - activeRevisions holds a list of currently active (non-archived) ClusterObjectSets, - including both installed and rolling out revisions. - items: - description: RevisionStatus defines the observed state of a ClusterObjectSet. - properties: - conditions: - description: |- - conditions optionally expose the Available condition of the revision, - in case when it is not yet marked as successfully installed (completedAt is not set). - Given that a ClusterExtension should remain available during upgrades, an observer may use these conditions - to get more insights about reasons for its current state. - items: - description: Condition contains details for one aspect of - the current state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - name: - description: name of the ClusterObjectSet resource - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map conditions: description: |- conditions represents the current state of the ClusterExtension. diff --git a/internal/operator-controller/controllers/boxcutter_reconcile_steps.go b/internal/operator-controller/controllers/boxcutter_reconcile_steps.go index 466eb51a3f..12e9c8294d 100644 --- a/internal/operator-controller/controllers/boxcutter_reconcile_steps.go +++ b/internal/operator-controller/controllers/boxcutter_reconcile_steps.go @@ -126,8 +126,6 @@ func ApplyBundleWithBoxcutter(apply func(ctx context.Context, contentFS fs.FS, e return nil, err } - setActiveRevisionsFromRevisionStates(ext, state.revisionStates) - setAvailableFromRevisionStates(ext, state.revisionStates) setProgressingFromRevisionStates(ext, state.revisionStates) setInstalledStatusFromRevisionStates(ext, state.revisionStates) diff --git a/internal/operator-controller/controllers/boxcutter_reconcile_steps_apply_test.go b/internal/operator-controller/controllers/boxcutter_reconcile_steps_apply_test.go index 3b0e901628..ba5a61c0d7 100644 --- a/internal/operator-controller/controllers/boxcutter_reconcile_steps_apply_test.go +++ b/internal/operator-controller/controllers/boxcutter_reconcile_steps_apply_test.go @@ -31,13 +31,11 @@ import ( func TestApplyBundleWithBoxcutter(t *testing.T) { type args struct { - activeRevisions []ocv1.RevisionStatus initialConditions []metav1.Condition revisionStates *RevisionStates } type want struct { - activeRevisions []ocv1.RevisionStatus - progressing *metav1.Condition + progressing *metav1.Condition } for _, tc := range []struct { @@ -46,11 +44,8 @@ func TestApplyBundleWithBoxcutter(t *testing.T) { want want }{ { - name: "two active revisions during update", + name: "installed and rolling out revision during update", args: args{ - activeRevisions: []ocv1.RevisionStatus{ - {Name: "ce-1"}, - }, revisionStates: &RevisionStates{ Installed: &RevisionMetadata{ RevisionName: "ce-1", @@ -65,18 +60,17 @@ func TestApplyBundleWithBoxcutter(t *testing.T) { }, }, want: want{ - activeRevisions: []ocv1.RevisionStatus{ - {Name: "ce-1"}, - {Name: "ce-2"}, + progressing: &metav1.Condition{ + Type: ocv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: ocv1.ReasonRollingOut, + Message: "Revision is rolling out.", }, }, }, { - name: "replaces existing with new active revisions", + name: "new installed revision after update", args: args{ - activeRevisions: []ocv1.RevisionStatus{ - {Name: "ce-1"}, - }, revisionStates: &RevisionStates{ Installed: &RevisionMetadata{ RevisionName: "ce-2", @@ -88,17 +82,17 @@ func TestApplyBundleWithBoxcutter(t *testing.T) { }, }, want: want{ - activeRevisions: []ocv1.RevisionStatus{ - {Name: "ce-2"}, + progressing: &metav1.Condition{ + Type: ocv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: ocv1.ReasonSucceeded, + Message: "Desired state reached", }, }, }, { name: "ongoing installation", args: args{ - activeRevisions: []ocv1.RevisionStatus{ - {Name: "ce-1"}, - }, revisionStates: &RevisionStates{ RollingOut: []*RevisionMetadata{ {RevisionName: "ce-1"}, @@ -106,17 +100,17 @@ func TestApplyBundleWithBoxcutter(t *testing.T) { }, }, want: want{ - activeRevisions: []ocv1.RevisionStatus{ - {Name: "ce-1"}, + progressing: &metav1.Condition{ + Type: ocv1.TypeProgressing, + Status: metav1.ConditionTrue, + Reason: ocv1.ReasonRollingOut, + Message: "Revision is rolling out.", }, }, }, { name: "rolling revision without Ready resets stale Progressing to RollingOut default", args: args{ - activeRevisions: []ocv1.RevisionStatus{ - {Name: "ce-1"}, - }, initialConditions: []metav1.Condition{ { Type: ocv1.TypeProgressing, @@ -134,9 +128,6 @@ func TestApplyBundleWithBoxcutter(t *testing.T) { }, }, want: want{ - activeRevisions: []ocv1.RevisionStatus{ - {Name: "ce-1"}, - }, progressing: &metav1.Condition{ Type: ocv1.TypeProgressing, Status: metav1.ConditionTrue, @@ -155,8 +146,7 @@ func TestApplyBundleWithBoxcutter(t *testing.T) { Generation: 1, }, Status: ocv1.ClusterExtensionStatus{ - ActiveRevisions: tc.args.activeRevisions, - Conditions: tc.args.initialConditions, + Conditions: tc.args.initialConditions, }, } @@ -178,12 +168,6 @@ func TestApplyBundleWithBoxcutter(t *testing.T) { require.NoError(t, err) require.Nil(t, result) - require.Len(t, ext.Status.ActiveRevisions, len(tc.want.activeRevisions)) - for i, expected := range tc.want.activeRevisions { - require.Equal(t, expected.Name, ext.Status.ActiveRevisions[i].Name, - "ActiveRevisions[%d].Name mismatch", i) - } - if tc.want.progressing != nil { got := apimeta.FindStatusCondition(ext.Status.Conditions, ocv1.TypeProgressing) require.NotNil(t, got, "Progressing condition not found") diff --git a/internal/operator-controller/controllers/common_controller.go b/internal/operator-controller/controllers/common_controller.go index 9c037df3e7..58c98fc1d6 100644 --- a/internal/operator-controller/controllers/common_controller.go +++ b/internal/operator-controller/controllers/common_controller.go @@ -88,22 +88,6 @@ func availableFromReady(ready metav1.Condition, generation int64) metav1.Conditi return a } -// setActiveRevisionsFromRevisionStates derives the active revisions for the ClusterExtension status -func setActiveRevisionsFromRevisionStates(ext *ocv1.ClusterExtension, revisionStates *RevisionStates) { - ext.Status.ActiveRevisions = make([]ocv1.RevisionStatus, 0, 1+len(revisionStates.RollingOut)) - if i := revisionStates.Installed; i != nil { - ext.Status.ActiveRevisions = append(ext.Status.ActiveRevisions, ocv1.RevisionStatus{Name: i.RevisionName}) - } - for _, r := range revisionStates.RollingOut { - rs := ocv1.RevisionStatus{Name: r.RevisionName} - ready := apimeta.FindStatusCondition(r.Conditions, ocv1.ClusterObjectSetTypeReady) - if ready != nil { - apimeta.SetStatusCondition(&rs.Conditions, availableFromReady(*ready, ext.GetGeneration())) - } - ext.Status.ActiveRevisions = append(ext.Status.ActiveRevisions, rs) - } -} - // setAvailableFromRevisionStates sets the Available status condition based on the given revision states func setAvailableFromRevisionStates(ext *ocv1.ClusterExtension, revisionStates *RevisionStates) { if i := revisionStates.Installed; i != nil { diff --git a/manifests/experimental-e2e.yaml b/manifests/experimental-e2e.yaml index d79111109d..8ba8103e93 100644 --- a/manifests/experimental-e2e.yaml +++ b/manifests/experimental-e2e.yaml @@ -1177,88 +1177,6 @@ spec: description: status is an optional field that defines the observed state of the ClusterExtension. properties: - activeRevisions: - description: |- - activeRevisions holds a list of currently active (non-archived) ClusterObjectSets, - including both installed and rolling out revisions. - items: - description: RevisionStatus defines the observed state of a ClusterObjectSet. - properties: - conditions: - description: |- - conditions optionally expose the Available condition of the revision, - in case when it is not yet marked as successfully installed (completedAt is not set). - Given that a ClusterExtension should remain available during upgrades, an observer may use these conditions - to get more insights about reasons for its current state. - items: - description: Condition contains details for one aspect of - the current state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - name: - description: name of the ClusterObjectSet resource - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map conditions: description: |- conditions represents the current state of the ClusterExtension. diff --git a/manifests/experimental.yaml b/manifests/experimental.yaml index 31f9c4232e..903ea1e5fb 100644 --- a/manifests/experimental.yaml +++ b/manifests/experimental.yaml @@ -1138,88 +1138,6 @@ spec: description: status is an optional field that defines the observed state of the ClusterExtension. properties: - activeRevisions: - description: |- - activeRevisions holds a list of currently active (non-archived) ClusterObjectSets, - including both installed and rolling out revisions. - items: - description: RevisionStatus defines the observed state of a ClusterObjectSet. - properties: - conditions: - description: |- - conditions optionally expose the Available condition of the revision, - in case when it is not yet marked as successfully installed (completedAt is not set). - Given that a ClusterExtension should remain available during upgrades, an observer may use these conditions - to get more insights about reasons for its current state. - items: - description: Condition contains details for one aspect of - the current state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - name: - description: name of the ClusterObjectSet resource - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map conditions: description: |- conditions represents the current state of the ClusterExtension. diff --git a/test/e2e/features/group.feature b/test/e2e/features/group.feature index ceb3352923..39acf94d4f 100644 --- a/test/e2e/features/group.feature +++ b/test/e2e/features/group.feature @@ -218,7 +218,6 @@ Feature: Track ClusterObjectSet revisions by group When ClusterExtension version is updated to "1.0.6" Then ClusterExtension is rolled out And ClusterExtension is available - And ClusterExtension reports "${NAME}-7" as active revision And ClusterObjectSet "${NAME}-7" has group "${NAME}" And resource "clusterobjectset/${NAME}-1" is eventually not found # The existing retention policy keeps five prior revisions plus the current one. diff --git a/test/e2e/features/update.feature b/test/e2e/features/update.feature index 3c39d34cbc..648752547b 100644 --- a/test/e2e/features/update.feature +++ b/test/e2e/features/update.feature @@ -316,39 +316,12 @@ Feature: Update ClusterExtension Then bundle "${PACKAGE:test}.1.2.0" is installed in version "1.2.0" And ClusterExtension is rolled out And ClusterExtension is available - And ClusterExtension reports "${NAME}-2" as active revision And ClusterObjectSet "${NAME}-2" reports Ready as True with Reason AllObjectsReady And ClusterObjectSet "${NAME}-1" is archived And ClusterObjectSet "${NAME}-1" phase objects are not found or not owned by the revision And ClusterObjectSet "${NAME}-2" has group "${NAME}" And ClusterObjectSet "${NAME}-2" phase objects use SSA manager "cos-group/${NAME}" - @BoxcutterRuntime - Scenario: Report all active revisions on ClusterExtension - Given ClusterExtension is applied - """ - apiVersion: olm.operatorframework.io/v1 - kind: ClusterExtension - metadata: - name: ${NAME} - spec: - namespace: ${TEST_NAMESPACE} - source: - sourceType: Catalog - catalog: - packageName: ${PACKAGE:test} - selector: - matchLabels: - "olm.operatorframework.io/metadata.name": ${CATALOG:test} - version: 1.0.0 - upgradeConstraintPolicy: SelfCertified - """ - And ClusterExtension is rolled out - And ClusterExtension is available - When ClusterExtension version is updated to "1.0.2" - Then ClusterExtension reports "${NAME}-1, ${NAME}-2" as active revisions - And ClusterObjectSet "${NAME}-2" reports Ready as False with Reason ObjectsNotReady - Scenario: Clearing deprecated serviceAccount field is reconciled without warnings Given ClusterExtension is applied """ diff --git a/test/e2e/steps/steps.go b/test/e2e/steps/steps.go index 271e88bed7..a78bf2d083 100644 --- a/test/e2e/steps/steps.go +++ b/test/e2e/steps/steps.go @@ -119,7 +119,6 @@ func RegisterSteps(sc *godog.ScenarioContext) { sc.Step(`^(?i)ClusterExtension is removed$`, ClusterExtensionIsRemoved) sc.Step(`^(?i)ClusterExtension (?:latest generation )?has (?:been )?reconciled(?: the latest generation)?$`, ClusterExtensionReconciledLatestGeneration) sc.Step(`^(?i)the ClusterExtension's constituent resources are removed$`, ClusterExtensionResourcesRemoved) - sc.Step(`^(?i)ClusterExtension reports "([^"]+)" as active revision(s?)$`, ClusterExtensionReportsActiveRevisions) sc.Step(`^(?i)ClusterExtension reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+) and Message:$`, ClusterExtensionReportsCondition) sc.Step(`^(?i)ClusterExtension reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+) and Message includes:$`, ClusterExtensionReportsConditionWithMessageFragment) sc.Step(`^(?i)ClusterExtension reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+)$`, ClusterExtensionReportsConditionWithoutMsg) @@ -964,33 +963,6 @@ func ClusterExtensionReportsConditionTransitionTime(ctx context.Context, conditi return nil } -// ClusterExtensionReportsActiveRevisions waits for the ClusterExtension's active revisions to match the expected -// set of revision names. Polls with timeout. -func ClusterExtensionReportsActiveRevisions(ctx context.Context, rawRevisionNames string) error { - sc := scenarioCtx(ctx) - expectedRevisionNames := sets.New[string]() - for _, rev := range strings.Split(rawRevisionNames, ",") { - expectedRevisionNames.Insert(substituteScenarioVars(strings.TrimSpace(rev), sc)) - } - - waitFor(ctx, func() bool { - v, err := k8sClient(ctx, "get", "clusterextension", sc.clusterExtensionName, "-o", "jsonpath={.status.activeRevisions}") - if err != nil { - return false - } - var activeRevisions []ocv1.RevisionStatus - if err := json.Unmarshal([]byte(v), &activeRevisions); err != nil { - return false - } - activeRevisionsNames := sets.New[string]() - for _, rev := range activeRevisions { - activeRevisionsNames.Insert(rev.Name) - } - return activeRevisionsNames.Equal(expectedRevisionNames) - }) - return nil -} - // ClusterObjectSetReportsConditionWithoutMsg waits for the named ClusterObjectSet to have a condition // matching type, status, and reason. Polls with timeout. func ClusterObjectSetReportsConditionWithoutMsg(ctx context.Context, revisionName, conditionType, conditionStatus, conditionReason string) error {