diff --git a/.claude/commands/list-e2e-steps.md b/.claude/commands/list-e2e-steps.md
index 8817d4806d..6dfc2ecfda 100644
--- a/.claude/commands/list-e2e-steps.md
+++ b/.claude/commands/list-e2e-steps.md
@@ -66,7 +66,7 @@ Organize steps into these 10 categories. For each step, document:
2. **Catalog Management** - ClusterCatalog creation, updates, image tagging, deletion
3. **ClusterExtension Lifecycle** - Apply, update, remove ClusterExtension resources
4. **ClusterExtension Status & Conditions** - Condition checks, transition times, reconciliation
-5. **ClusterExtensionRevision** - Revision-specific condition checks, archival, annotations, labels, active revisions
+5. **ObjectSet** - Revision-specific condition checks, archival, annotations, labels, active revisions
6. **Generic Resource Operations** - Get, delete, restore, match arbitrary resources
7. **Test Operator Control** - Marking test-operator deployment ready/not-ready
8. **Metrics** - Fetching and validating Prometheus metrics
diff --git a/AGENTS.md b/AGENTS.md
index 07dd2e6be8..a93e065c39 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -11,7 +11,7 @@ operator-controller is the central component of Operator Lifecycle Manager (OLM)
install and manage cluster extensions. The project follows a microservices architecture with two main binaries:
**operator-controller**
- - manages `ClusterExtension` and `ClusterExtensionRevision` CRDs
+ - manages `ClusterExtension` and `ObjectSet` CRDs
- resolves bundles from configured source
- unpacks bundles and renders manifests from them
- applies manifests with phase-based rollouts
@@ -193,7 +193,7 @@ make generate
- **Primary CRDs:**
- `ClusterExtension` - declares desired extension installations
- - `ClusterExtensionRevision` - revision management (experimental)
+ - `ObjectSet` - revision management (experimental)
- `ClusterCatalog` - catalog source definitions
- **API domain:** `olm.operatorframework.io`
- This is the API group of our user-facing CRDs
@@ -204,7 +204,7 @@ make generate
Two manifest variants exist:
- **Standard:** Production-ready features
-- **Experimental:** Features under development/testing (includes `ClusterExtensionRevision` API)
+- **Experimental:** Features under development/testing (includes `ObjectSet` API)
---
@@ -330,7 +330,7 @@ Two manifest variants exist:
**operator-controller:**
- `ClusterExtension` controller - manages extension installations
-- `ClusterExtensionRevision` controller - manages revision lifecycle
+- `ObjectSet` controller - manages revision lifecycle
- Resolver - bundle version selection
- Applier - applies manifests to cluster
- Content Manager - manages extension content
diff --git a/api/v1/clusterextension_types.go b/api/v1/clusterextension_types.go
index 18f982725b..437b41cbb4 100644
--- a/api/v1/clusterextension_types.go
+++ b/api/v1/clusterextension_types.go
@@ -468,9 +468,9 @@ type BundleMetadata struct {
Version string `json:"version"`
}
-// RevisionStatus defines the observed state of a ClusterExtensionRevision.
+// RevisionStatus defines the observed state of a ObjectSet.
type RevisionStatus struct {
- // name of the ClusterExtensionRevision resource
+ // name of the ObjectSet resource
Name string `json:"name"`
// conditions optionally expose Progressing and Available condition of the revision,
// in case when it is not yet marked as successfully installed (condition Succeeded is not set to True).
@@ -498,7 +498,7 @@ type ClusterExtensionStatus struct {
// 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.
//
- // When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterExtensionRevisions in active roll out.
+ // When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ObjectSets in active roll out.
//
//
// When the ClusterExtension is sourced from a catalog, it surfaces deprecation conditions based on catalog metadata.
@@ -518,7 +518,7 @@ type ClusterExtensionStatus struct {
// +optional
Install *ClusterExtensionInstallStatus `json:"install,omitempty"`
- // activeRevisions holds a list of currently active (non-archived) ClusterExtensionRevisions,
+ // activeRevisions holds a list of currently active (non-archived) ObjectSets,
// including both installed and rolling out revisions.
// +listType=map
// +listMapKey=name
diff --git a/api/v1/clusterextensionrevision_types.go b/api/v1/objectset_types.go
similarity index 82%
rename from api/v1/clusterextensionrevision_types.go
rename to api/v1/objectset_types.go
index 208d96d9ff..e5b27edc55 100644
--- a/api/v1/clusterextensionrevision_types.go
+++ b/api/v1/objectset_types.go
@@ -22,25 +22,25 @@ import (
)
const (
- ClusterExtensionRevisionKind = "ClusterExtensionRevision"
+ ObjectSetKind = "ObjectSet"
// Condition Types
- ClusterExtensionRevisionTypeAvailable = "Available"
- ClusterExtensionRevisionTypeProgressing = "Progressing"
- ClusterExtensionRevisionTypeSucceeded = "Succeeded"
+ ObjectSetTypeAvailable = "Available"
+ ObjectSetTypeProgressing = "Progressing"
+ ObjectSetTypeSucceeded = "Succeeded"
// Condition Reasons
- ClusterExtensionRevisionReasonArchived = "Archived"
- ClusterExtensionRevisionReasonBlocked = "Blocked"
- ClusterExtensionRevisionReasonProbeFailure = "ProbeFailure"
- ClusterExtensionRevisionReasonProbesSucceeded = "ProbesSucceeded"
- ClusterExtensionRevisionReasonReconciling = "Reconciling"
- ClusterExtensionRevisionReasonRetrying = "Retrying"
+ ObjectSetReasonArchived = "Archived"
+ ObjectSetReasonBlocked = "Blocked"
+ ObjectSetReasonProbeFailure = "ProbeFailure"
+ ObjectSetReasonProbesSucceeded = "ProbesSucceeded"
+ ObjectSetReasonReconciling = "Reconciling"
+ ObjectSetReasonRetrying = "Retrying"
)
-// ClusterExtensionRevisionSpec defines the desired state of ClusterExtensionRevision.
-type ClusterExtensionRevisionSpec struct {
- // lifecycleState specifies the lifecycle state of the ClusterExtensionRevision.
+// ObjectSetSpec defines the desired state of ObjectSet.
+type ObjectSetSpec struct {
+ // lifecycleState specifies the lifecycle state of the ObjectSet.
//
// When set to "Active", the revision is actively managed and reconciled.
// When set to "Archived", the revision is inactive and any resources not managed by a subsequent revision are deleted.
@@ -56,13 +56,13 @@ type ClusterExtensionRevisionSpec struct {
// +required
// +kubebuilder:validation:Enum=Active;Archived
// +kubebuilder:validation:XValidation:rule="oldSelf == 'Active' || oldSelf == 'Archived' && oldSelf == self", message="cannot un-archive"
- LifecycleState ClusterExtensionRevisionLifecycleState `json:"lifecycleState,omitempty"`
+ LifecycleState ObjectSetLifecycleState `json:"lifecycleState,omitempty"`
// revision is a required, immutable sequence number representing a specific revision
// of the parent ClusterExtension.
//
// The revision field must be a positive integer.
- // Each ClusterExtensionRevision belonging to the same parent ClusterExtension must have a unique revision number.
+ // Each ObjectSet belonging to the same parent ClusterExtension must have a unique revision number.
// The revision number must always be the previous revision number plus one, or 1 for the first revision.
//
// +required
@@ -93,7 +93,7 @@ type ClusterExtensionRevisionSpec struct {
// +listType=map
// +listMapKey=name
// +optional
- Phases []ClusterExtensionRevisionPhase `json:"phases,omitempty"`
+ Phases []ObjectSetPhase `json:"phases,omitempty"`
// progressDeadlineMinutes is an optional field that defines the maximum period
// of time in minutes after which an installation should be considered failed and
@@ -338,21 +338,21 @@ type FieldValueProbe struct {
Value string `json:"value,omitempty"`
}
-// ClusterExtensionRevisionLifecycleState specifies the lifecycle state of the ClusterExtensionRevision.
-type ClusterExtensionRevisionLifecycleState string
+// ObjectSetLifecycleState specifies the lifecycle state of the ObjectSet.
+type ObjectSetLifecycleState string
const (
- // ClusterExtensionRevisionLifecycleStateActive / "Active" is the default lifecycle state.
- ClusterExtensionRevisionLifecycleStateActive ClusterExtensionRevisionLifecycleState = "Active"
- // ClusterExtensionRevisionLifecycleStateArchived / "Archived" archives the revision for historical or auditing purposes.
+ // ObjectSetLifecycleStateActive / "Active" is the default lifecycle state.
+ ObjectSetLifecycleStateActive ObjectSetLifecycleState = "Active"
+ // ObjectSetLifecycleStateArchived / "Archived" archives the revision for historical or auditing purposes.
// The revision is removed from the owner list of all other objects previously under management and all objects
// that did not transition to a succeeding revision are deleted.
- ClusterExtensionRevisionLifecycleStateArchived ClusterExtensionRevisionLifecycleState = "Archived"
+ ObjectSetLifecycleStateArchived ObjectSetLifecycleState = "Archived"
)
-// ClusterExtensionRevisionPhase represents a group of objects that are applied together. The phase is considered
+// ObjectSetPhase represents a group of objects that are applied together. The phase is considered
// complete only after all objects pass their status probes.
-type ClusterExtensionRevisionPhase struct {
+type ObjectSetPhase struct {
// name is a required identifier for this phase.
//
// phase names must follow the DNS label standard as defined in [RFC 1123].
@@ -374,7 +374,7 @@ type ClusterExtensionRevisionPhase struct {
// All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50.
// +required
// +kubebuilder:validation:MaxItems=50
- Objects []ClusterExtensionRevisionObject `json:"objects"`
+ Objects []ObjectSetObject `json:"objects"`
// collisionProtection specifies the default collision protection strategy for all objects
// in this phase. Individual objects can override this value.
@@ -390,9 +390,9 @@ type ClusterExtensionRevisionPhase struct {
CollisionProtection CollisionProtection `json:"collisionProtection,omitempty"`
}
-// ClusterExtensionRevisionObject represents a Kubernetes object to be applied as part
+// ObjectSetObject represents a Kubernetes object to be applied as part
// of a phase, along with its collision protection settings.
-type ClusterExtensionRevisionObject struct {
+type ObjectSetObject struct {
// object is a required embedded Kubernetes object to be applied.
//
// This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields.
@@ -442,27 +442,27 @@ const (
CollisionProtectionNone CollisionProtection = "None"
)
-// ClusterExtensionRevisionStatus defines the observed state of a ClusterExtensionRevision.
-type ClusterExtensionRevisionStatus struct {
+// ObjectSetStatus defines the observed state of a ObjectSet.
+type ObjectSetStatus struct {
// conditions is an optional list of status conditions describing the state of the
- // ClusterExtensionRevision.
+ // ObjectSet.
//
// The Progressing condition represents whether the revision is actively rolling out:
- // - When status is True and reason is RollingOut, the ClusterExtensionRevision rollout is actively making progress and is in transition.
- // - When status is True and reason is Retrying, the ClusterExtensionRevision has encountered an error that could be resolved on subsequent reconciliation attempts.
- // - When status is True and reason is Succeeded, the ClusterExtensionRevision has reached the desired state.
- // - When status is False and reason is Blocked, the ClusterExtensionRevision has encountered an error that requires manual intervention for recovery.
- // - When status is False and reason is Archived, the ClusterExtensionRevision is archived and not being actively reconciled.
+ // - When status is True and reason is RollingOut, the ObjectSet rollout is actively making progress and is in transition.
+ // - When status is True and reason is Retrying, the ObjectSet has encountered an error that could be resolved on subsequent reconciliation attempts.
+ // - When status is True and reason is Succeeded, the ObjectSet has reached the desired state.
+ // - When status is False and reason is Blocked, the ObjectSet has encountered an error that requires manual intervention for recovery.
+ // - When status is False and reason is Archived, the ObjectSet is archived and not being actively reconciled.
//
// The Available condition represents whether the revision has been successfully rolled out and is available:
- // - When status is True and reason is ProbesSucceeded, the ClusterExtensionRevision has been successfully rolled out and all objects pass their readiness probes.
+ // - When status is True and reason is ProbesSucceeded, the ObjectSet has been successfully rolled out and all objects pass their readiness probes.
// - When status is False and reason is ProbeFailure, one or more objects are failing their readiness probes during rollout.
- // - When status is Unknown and reason is Reconciling, the ClusterExtensionRevision has encountered an error that prevented it from observing the probes.
- // - When status is Unknown and reason is Archived, the ClusterExtensionRevision has been archived and its objects have been torn down.
- // - When status is Unknown and reason is Migrated, the ClusterExtensionRevision was migrated from an existing release and object status probe results have not yet been observed.
+ // - When status is Unknown and reason is Reconciling, the ObjectSet has encountered an error that prevented it from observing the probes.
+ // - When status is Unknown and reason is Archived, the ObjectSet has been archived and its objects have been torn down.
+ // - When status is Unknown and reason is Migrated, the ObjectSet was migrated from an existing release and object status probe results have not yet been observed.
//
// The Succeeded condition represents whether the revision has successfully completed its rollout:
- // - When status is True and reason is Succeeded, the ClusterExtensionRevision has successfully completed its rollout. This condition is set once and persists even if the revision later becomes unavailable.
+ // - When status is True and reason is Succeeded, the ObjectSet has successfully completed its rollout. This condition is set once and persists even if the revision later becomes unavailable.
//
// +listType=map
// +listMapKey=type
@@ -479,13 +479,13 @@ type ClusterExtensionRevisionStatus struct {
// +kubebuilder:printcolumn:name="Progressing",type=string,JSONPath=`.status.conditions[?(@.type=='Progressing')].status`
// +kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp`
-// ClusterExtensionRevision represents an immutable snapshot of Kubernetes objects
+// ObjectSet represents an immutable snapshot of Kubernetes objects
// for a specific version of a ClusterExtension. Each revision contains objects
// organized into phases that roll out sequentially. The same object can only be managed by a single revision
// at a time. Ownership of objects is transitioned from one revision to the next as the extension is upgraded
// or reconfigured. Once the latest revision has rolled out successfully, previous active revisions are archived for
// posterity.
-type ClusterExtensionRevision struct {
+type ObjectSet struct {
metav1.TypeMeta `json:",inline"`
// metadata is the standard object's metadata.
@@ -493,30 +493,30 @@ type ClusterExtensionRevision struct {
// +optional
metav1.ObjectMeta `json:"metadata,omitempty"`
- // spec defines the desired state of the ClusterExtensionRevision.
+ // spec defines the desired state of the ObjectSet.
// +optional
- Spec ClusterExtensionRevisionSpec `json:"spec,omitempty"`
+ Spec ObjectSetSpec `json:"spec,omitempty"`
- // status is optional and defines the observed state of the ClusterExtensionRevision.
+ // status is optional and defines the observed state of the ObjectSet.
// +optional
- Status ClusterExtensionRevisionStatus `json:"status,omitempty"`
+ Status ObjectSetStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
-// ClusterExtensionRevisionList contains a list of ClusterExtensionRevision
-type ClusterExtensionRevisionList struct {
+// ObjectSetList contains a list of ObjectSet
+type ObjectSetList struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ListMeta `json:"metadata,omitempty"`
- // items is a required list of ClusterExtensionRevision objects.
+ // items is a required list of ObjectSet objects.
//
// +required
- Items []ClusterExtensionRevision `json:"items"`
+ Items []ObjectSet `json:"items"`
}
func init() {
- SchemeBuilder.Register(&ClusterExtensionRevision{}, &ClusterExtensionRevisionList{})
+ SchemeBuilder.Register(&ObjectSet{}, &ObjectSetList{})
}
diff --git a/api/v1/clusterextensionrevision_types_test.go b/api/v1/objectset_types_test.go
similarity index 56%
rename from api/v1/clusterextensionrevision_types_test.go
rename to api/v1/objectset_types_test.go
index 75a1a6cc3b..569bd0d00c 100644
--- a/api/v1/clusterextensionrevision_types_test.go
+++ b/api/v1/objectset_types_test.go
@@ -11,92 +11,92 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
-func TestClusterExtensionRevisionImmutability(t *testing.T) {
+func TestObjectSetImmutability(t *testing.T) {
c := newClient(t)
ctx := context.Background()
i := 0
for name, tc := range map[string]struct {
- spec ClusterExtensionRevisionSpec
- updateFunc func(*ClusterExtensionRevision)
+ spec ObjectSetSpec
+ updateFunc func(*ObjectSet)
allowed bool
}{
"revision is immutable": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
},
- updateFunc: func(cer *ClusterExtensionRevision) {
+ updateFunc: func(cer *ObjectSet) {
cer.Spec.Revision = 2
},
},
"phases may be initially empty": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
- Phases: []ClusterExtensionRevisionPhase{},
+ Phases: []ObjectSetPhase{},
},
- updateFunc: func(cer *ClusterExtensionRevision) {
- cer.Spec.Phases = []ClusterExtensionRevisionPhase{
+ updateFunc: func(cer *ObjectSet) {
+ cer.Spec.Phases = []ObjectSetPhase{
{
Name: "foo",
- Objects: []ClusterExtensionRevisionObject{},
+ Objects: []ObjectSetObject{},
},
}
},
allowed: true,
},
"phases may be initially unset": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
},
- updateFunc: func(cer *ClusterExtensionRevision) {
- cer.Spec.Phases = []ClusterExtensionRevisionPhase{
+ updateFunc: func(cer *ObjectSet) {
+ cer.Spec.Phases = []ObjectSetPhase{
{
Name: "foo",
- Objects: []ClusterExtensionRevisionObject{},
+ Objects: []ObjectSetObject{},
},
}
},
allowed: true,
},
"phases are immutable if not empty": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
- Phases: []ClusterExtensionRevisionPhase{
+ Phases: []ObjectSetPhase{
{
Name: "foo",
- Objects: []ClusterExtensionRevisionObject{},
+ Objects: []ObjectSetObject{},
},
},
},
- updateFunc: func(cer *ClusterExtensionRevision) {
- cer.Spec.Phases = []ClusterExtensionRevisionPhase{
+ updateFunc: func(cer *ObjectSet) {
+ cer.Spec.Phases = []ObjectSetPhase{
{
Name: "foo2",
- Objects: []ClusterExtensionRevisionObject{},
+ Objects: []ObjectSetObject{},
},
}
},
},
"spec collisionProtection is immutable": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
},
- updateFunc: func(cer *ClusterExtensionRevision) {
+ updateFunc: func(cer *ObjectSet) {
cer.Spec.CollisionProtection = CollisionProtectionNone
},
},
} {
t.Run(name, func(t *testing.T) {
- cer := &ClusterExtensionRevision{
+ cer := &ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("foo%d", i),
},
@@ -116,67 +116,67 @@ func TestClusterExtensionRevisionImmutability(t *testing.T) {
}
}
-func TestClusterExtensionRevisionValidity(t *testing.T) {
+func TestObjectSetValidity(t *testing.T) {
c := newClient(t)
ctx := context.Background()
i := 0
for name, tc := range map[string]struct {
- spec ClusterExtensionRevisionSpec
+ spec ObjectSetSpec
valid bool
}{
"revision cannot be negative": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: -1,
},
valid: false,
},
"revision cannot be zero": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
},
valid: false,
},
"revision must be positive": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
},
valid: true,
},
"lifecycleState must be set": {
- spec: ClusterExtensionRevisionSpec{
+ spec: ObjectSetSpec{
Revision: 1,
},
valid: false,
},
"phases must have no more than 20 phases": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
- Phases: make([]ClusterExtensionRevisionPhase, 21),
+ Phases: make([]ObjectSetPhase, 21),
},
valid: false,
},
"phases entries must have no more than 50 objects": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
- Phases: []ClusterExtensionRevisionPhase{
+ Phases: []ObjectSetPhase{
{
Name: "too-many-objects",
- Objects: make([]ClusterExtensionRevisionObject, 51),
+ Objects: make([]ObjectSetObject, 51),
},
},
},
valid: false,
},
"phases entry names cannot be empty": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
- Phases: []ClusterExtensionRevisionPhase{
+ Phases: []ObjectSetPhase{
{
Name: "",
},
@@ -185,10 +185,10 @@ func TestClusterExtensionRevisionValidity(t *testing.T) {
valid: false,
},
"phases entry names cannot start with symbols": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
- Phases: []ClusterExtensionRevisionPhase{
+ Phases: []ObjectSetPhase{
{
Name: "-invalid",
},
@@ -197,10 +197,10 @@ func TestClusterExtensionRevisionValidity(t *testing.T) {
valid: false,
},
"phases entry names cannot start with numeric characters": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
- Phases: []ClusterExtensionRevisionPhase{
+ Phases: []ObjectSetPhase{
{
Name: "1-invalid",
},
@@ -209,60 +209,60 @@ func TestClusterExtensionRevisionValidity(t *testing.T) {
valid: false,
},
"spec collisionProtection accepts Prevent": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
},
valid: true,
},
"spec collisionProtection accepts IfNoController": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionIfNoController,
},
valid: true,
},
"spec collisionProtection accepts None": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionNone,
},
valid: true,
},
"spec collisionProtection is required": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
},
valid: false,
},
"spec collisionProtection rejects invalid values": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtection("Invalid"),
},
valid: false,
},
"spec collisionProtection must be set": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
},
valid: false,
},
"object collisionProtection is optional": {
- spec: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ spec: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
Revision: 1,
CollisionProtection: CollisionProtectionPrevent,
- Phases: []ClusterExtensionRevisionPhase{
+ Phases: []ObjectSetPhase{
{
Name: "deploy",
- Objects: []ClusterExtensionRevisionObject{
+ Objects: []ObjectSetObject{
{
Object: configMap(),
},
@@ -274,7 +274,7 @@ func TestClusterExtensionRevisionValidity(t *testing.T) {
},
} {
t.Run(name, func(t *testing.T) {
- cer := &ClusterExtensionRevision{
+ cer := &ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("bar%d", i),
},
diff --git a/api/v1/validation_test.go b/api/v1/validation_test.go
index c2f8574930..b925ab7fbd 100644
--- a/api/v1/validation_test.go
+++ b/api/v1/validation_test.go
@@ -34,7 +34,7 @@ func TestValidate(t *testing.T) {
}
return s
}
- defaultRevisionSpec := func(s *ClusterExtensionRevisionSpec) *ClusterExtensionRevisionSpec {
+ defaultRevisionSpec := func(s *ObjectSetSpec) *ObjectSetSpec {
s.Revision = 1
s.CollisionProtection = CollisionProtectionPrevent
return s
@@ -89,55 +89,55 @@ func TestValidate(t *testing.T) {
},
want: want{valid: true},
},
- "ClusterExtensionRevision: invalid progress deadline < 10": {
+ "ObjectSet: invalid progress deadline < 10": {
args: args{
- object: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ object: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
ProgressDeadlineMinutes: 9,
},
},
want: want{valid: false},
},
- "ClusterExtensionRevision: valid progress deadline = 10": {
+ "ObjectSet: valid progress deadline = 10": {
args: args{
- object: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ object: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
ProgressDeadlineMinutes: 10,
},
},
want: want{valid: true},
},
- "ClusterExtensionRevision: valid progress deadline = 360": {
+ "ObjectSet: valid progress deadline = 360": {
args: args{
- object: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ object: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
ProgressDeadlineMinutes: 360,
},
},
want: want{valid: true},
},
- "ClusterExtensionRevision: valid progress deadline = 720": {
+ "ObjectSet: valid progress deadline = 720": {
args: args{
- object: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ object: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
ProgressDeadlineMinutes: 720,
},
},
want: want{valid: true},
},
- "ClusterExtensionRevision: invalid progress deadline > 720": {
+ "ObjectSet: invalid progress deadline > 720": {
args: args{
- object: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ object: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
ProgressDeadlineMinutes: 721,
},
},
want: want{valid: false},
},
- "ClusterExtensionRevision: no progress deadline set": {
+ "ObjectSet: no progress deadline set": {
args: args{
- object: ClusterExtensionRevisionSpec{
- LifecycleState: ClusterExtensionRevisionLifecycleStateActive,
+ object: ObjectSetSpec{
+ LifecycleState: ObjectSetLifecycleStateActive,
},
},
want: want{valid: true},
@@ -157,8 +157,8 @@ func TestValidate(t *testing.T) {
defaultExtensionSpec(&ce.Spec)
}
obj = ce
- case ClusterExtensionRevisionSpec:
- cer := &ClusterExtensionRevision{
+ case ObjectSetSpec:
+ cer := &ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("cer-%d", i),
},
diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go
index 9c801ca773..1221f7a33c 100644
--- a/api/v1/zz_generated.deepcopy.go
+++ b/api/v1/zz_generated.deepcopy.go
@@ -358,292 +358,292 @@ func (in *ClusterExtensionList) DeepCopyObject() runtime.Object {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ClusterExtensionRevision) DeepCopyInto(out *ClusterExtensionRevision) {
+func (in *ClusterExtensionSpec) DeepCopyInto(out *ClusterExtensionSpec) {
*out = *in
- out.TypeMeta = in.TypeMeta
- in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
- in.Spec.DeepCopyInto(&out.Spec)
- in.Status.DeepCopyInto(&out.Status)
+ out.ServiceAccount = in.ServiceAccount
+ in.Source.DeepCopyInto(&out.Source)
+ if in.Install != nil {
+ in, out := &in.Install, &out.Install
+ *out = new(ClusterExtensionInstallConfig)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.Config != nil {
+ in, out := &in.Config, &out.Config
+ *out = new(ClusterExtensionConfig)
+ (*in).DeepCopyInto(*out)
+ }
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterExtensionRevision.
-func (in *ClusterExtensionRevision) DeepCopy() *ClusterExtensionRevision {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterExtensionSpec.
+func (in *ClusterExtensionSpec) DeepCopy() *ClusterExtensionSpec {
if in == nil {
return nil
}
- out := new(ClusterExtensionRevision)
+ out := new(ClusterExtensionSpec)
in.DeepCopyInto(out)
return out
}
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *ClusterExtensionRevision) DeepCopyObject() runtime.Object {
- if c := in.DeepCopy(); c != nil {
- return c
- }
- return nil
-}
-
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ClusterExtensionRevisionList) DeepCopyInto(out *ClusterExtensionRevisionList) {
+func (in *ClusterExtensionStatus) DeepCopyInto(out *ClusterExtensionStatus) {
*out = *in
- out.TypeMeta = in.TypeMeta
- in.ListMeta.DeepCopyInto(&out.ListMeta)
- if in.Items != nil {
- in, out := &in.Items, &out.Items
- *out = make([]ClusterExtensionRevision, len(*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])
+ }
+ }
+ if in.Install != nil {
+ in, out := &in.Install, &out.Install
+ *out = new(ClusterExtensionInstallStatus)
+ **out = **in
+ }
+ 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 ClusterExtensionRevisionList.
-func (in *ClusterExtensionRevisionList) DeepCopy() *ClusterExtensionRevisionList {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterExtensionStatus.
+func (in *ClusterExtensionStatus) DeepCopy() *ClusterExtensionStatus {
if in == nil {
return nil
}
- out := new(ClusterExtensionRevisionList)
+ out := new(ClusterExtensionStatus)
in.DeepCopyInto(out)
return out
}
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *ClusterExtensionRevisionList) DeepCopyObject() runtime.Object {
- if c := in.DeepCopy(); c != nil {
- return c
- }
- return nil
-}
-
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ClusterExtensionRevisionObject) DeepCopyInto(out *ClusterExtensionRevisionObject) {
+func (in *ConditionEqualProbe) DeepCopyInto(out *ConditionEqualProbe) {
*out = *in
- in.Object.DeepCopyInto(&out.Object)
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterExtensionRevisionObject.
-func (in *ClusterExtensionRevisionObject) DeepCopy() *ClusterExtensionRevisionObject {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConditionEqualProbe.
+func (in *ConditionEqualProbe) DeepCopy() *ConditionEqualProbe {
if in == nil {
return nil
}
- out := new(ClusterExtensionRevisionObject)
+ out := new(ConditionEqualProbe)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ClusterExtensionRevisionPhase) DeepCopyInto(out *ClusterExtensionRevisionPhase) {
+func (in *FieldValueProbe) DeepCopyInto(out *FieldValueProbe) {
*out = *in
- if in.Objects != nil {
- in, out := &in.Objects, &out.Objects
- *out = make([]ClusterExtensionRevisionObject, len(*in))
- for i := range *in {
- (*in)[i].DeepCopyInto(&(*out)[i])
- }
- }
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterExtensionRevisionPhase.
-func (in *ClusterExtensionRevisionPhase) DeepCopy() *ClusterExtensionRevisionPhase {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FieldValueProbe.
+func (in *FieldValueProbe) DeepCopy() *FieldValueProbe {
if in == nil {
return nil
}
- out := new(ClusterExtensionRevisionPhase)
+ out := new(FieldValueProbe)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ClusterExtensionRevisionSpec) DeepCopyInto(out *ClusterExtensionRevisionSpec) {
+func (in *FieldsEqualProbe) DeepCopyInto(out *FieldsEqualProbe) {
*out = *in
- if in.Phases != nil {
- in, out := &in.Phases, &out.Phases
- *out = make([]ClusterExtensionRevisionPhase, len(*in))
- for i := range *in {
- (*in)[i].DeepCopyInto(&(*out)[i])
- }
- }
- if in.ProgressionProbes != nil {
- in, out := &in.ProgressionProbes, &out.ProgressionProbes
- *out = make([]ProgressionProbe, len(*in))
- for i := range *in {
- (*in)[i].DeepCopyInto(&(*out)[i])
- }
- }
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterExtensionRevisionSpec.
-func (in *ClusterExtensionRevisionSpec) DeepCopy() *ClusterExtensionRevisionSpec {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FieldsEqualProbe.
+func (in *FieldsEqualProbe) DeepCopy() *FieldsEqualProbe {
if in == nil {
return nil
}
- out := new(ClusterExtensionRevisionSpec)
+ out := new(FieldsEqualProbe)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ClusterExtensionRevisionStatus) DeepCopyInto(out *ClusterExtensionRevisionStatus) {
+func (in *ImageSource) DeepCopyInto(out *ImageSource) {
*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])
- }
+ if in.PollIntervalMinutes != nil {
+ in, out := &in.PollIntervalMinutes, &out.PollIntervalMinutes
+ *out = new(int)
+ **out = **in
}
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterExtensionRevisionStatus.
-func (in *ClusterExtensionRevisionStatus) DeepCopy() *ClusterExtensionRevisionStatus {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageSource.
+func (in *ImageSource) DeepCopy() *ImageSource {
if in == nil {
return nil
}
- out := new(ClusterExtensionRevisionStatus)
+ out := new(ImageSource)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ClusterExtensionSpec) DeepCopyInto(out *ClusterExtensionSpec) {
+func (in *ObjectSelector) DeepCopyInto(out *ObjectSelector) {
*out = *in
- out.ServiceAccount = in.ServiceAccount
- in.Source.DeepCopyInto(&out.Source)
- if in.Install != nil {
- in, out := &in.Install, &out.Install
- *out = new(ClusterExtensionInstallConfig)
- (*in).DeepCopyInto(*out)
- }
- if in.Config != nil {
- in, out := &in.Config, &out.Config
- *out = new(ClusterExtensionConfig)
- (*in).DeepCopyInto(*out)
- }
+ in.GroupKind.DeepCopyInto(&out.GroupKind)
+ in.Label.DeepCopyInto(&out.Label)
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterExtensionSpec.
-func (in *ClusterExtensionSpec) DeepCopy() *ClusterExtensionSpec {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectSelector.
+func (in *ObjectSelector) DeepCopy() *ObjectSelector {
if in == nil {
return nil
}
- out := new(ClusterExtensionSpec)
+ out := new(ObjectSelector)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ClusterExtensionStatus) DeepCopyInto(out *ClusterExtensionStatus) {
+func (in *ObjectSet) DeepCopyInto(out *ObjectSet) {
*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])
- }
- }
- if in.Install != nil {
- in, out := &in.Install, &out.Install
- *out = new(ClusterExtensionInstallStatus)
- **out = **in
- }
- if in.ActiveRevisions != nil {
- in, out := &in.ActiveRevisions, &out.ActiveRevisions
- *out = make([]RevisionStatus, len(*in))
- for i := range *in {
- (*in)[i].DeepCopyInto(&(*out)[i])
- }
- }
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ in.Spec.DeepCopyInto(&out.Spec)
+ in.Status.DeepCopyInto(&out.Status)
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterExtensionStatus.
-func (in *ClusterExtensionStatus) DeepCopy() *ClusterExtensionStatus {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectSet.
+func (in *ObjectSet) DeepCopy() *ObjectSet {
if in == nil {
return nil
}
- out := new(ClusterExtensionStatus)
+ out := new(ObjectSet)
in.DeepCopyInto(out)
return out
}
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ObjectSet) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ConditionEqualProbe) DeepCopyInto(out *ConditionEqualProbe) {
+func (in *ObjectSetList) DeepCopyInto(out *ObjectSetList) {
*out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]ObjectSet, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConditionEqualProbe.
-func (in *ConditionEqualProbe) DeepCopy() *ConditionEqualProbe {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectSetList.
+func (in *ObjectSetList) DeepCopy() *ObjectSetList {
if in == nil {
return nil
}
- out := new(ConditionEqualProbe)
+ out := new(ObjectSetList)
in.DeepCopyInto(out)
return out
}
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ObjectSetList) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *FieldValueProbe) DeepCopyInto(out *FieldValueProbe) {
+func (in *ObjectSetObject) DeepCopyInto(out *ObjectSetObject) {
*out = *in
+ in.Object.DeepCopyInto(&out.Object)
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FieldValueProbe.
-func (in *FieldValueProbe) DeepCopy() *FieldValueProbe {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectSetObject.
+func (in *ObjectSetObject) DeepCopy() *ObjectSetObject {
if in == nil {
return nil
}
- out := new(FieldValueProbe)
+ out := new(ObjectSetObject)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *FieldsEqualProbe) DeepCopyInto(out *FieldsEqualProbe) {
+func (in *ObjectSetPhase) DeepCopyInto(out *ObjectSetPhase) {
*out = *in
+ if in.Objects != nil {
+ in, out := &in.Objects, &out.Objects
+ *out = make([]ObjectSetObject, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FieldsEqualProbe.
-func (in *FieldsEqualProbe) DeepCopy() *FieldsEqualProbe {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectSetPhase.
+func (in *ObjectSetPhase) DeepCopy() *ObjectSetPhase {
if in == nil {
return nil
}
- out := new(FieldsEqualProbe)
+ out := new(ObjectSetPhase)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ImageSource) DeepCopyInto(out *ImageSource) {
+func (in *ObjectSetSpec) DeepCopyInto(out *ObjectSetSpec) {
*out = *in
- if in.PollIntervalMinutes != nil {
- in, out := &in.PollIntervalMinutes, &out.PollIntervalMinutes
- *out = new(int)
- **out = **in
+ if in.Phases != nil {
+ in, out := &in.Phases, &out.Phases
+ *out = make([]ObjectSetPhase, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+ if in.ProgressionProbes != nil {
+ in, out := &in.ProgressionProbes, &out.ProgressionProbes
+ *out = make([]ProgressionProbe, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
}
}
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageSource.
-func (in *ImageSource) DeepCopy() *ImageSource {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectSetSpec.
+func (in *ObjectSetSpec) DeepCopy() *ObjectSetSpec {
if in == nil {
return nil
}
- out := new(ImageSource)
+ out := new(ObjectSetSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ObjectSelector) DeepCopyInto(out *ObjectSelector) {
+func (in *ObjectSetStatus) DeepCopyInto(out *ObjectSetStatus) {
*out = *in
- in.GroupKind.DeepCopyInto(&out.GroupKind)
- in.Label.DeepCopyInto(&out.Label)
+ 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 ObjectSelector.
-func (in *ObjectSelector) DeepCopy() *ObjectSelector {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectSetStatus.
+func (in *ObjectSetStatus) DeepCopy() *ObjectSetStatus {
if in == nil {
return nil
}
- out := new(ObjectSelector)
+ out := new(ObjectSetStatus)
in.DeepCopyInto(out)
return out
}
diff --git a/applyconfigurations/api/v1/clusterextensionrevisionstatus.go b/applyconfigurations/api/v1/clusterextensionrevisionstatus.go
deleted file mode 100644
index f867971152..0000000000
--- a/applyconfigurations/api/v1/clusterextensionrevisionstatus.go
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-Copyright 2022.
-
-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.20. DO NOT EDIT.
-
-package v1
-
-import (
- metav1 "k8s.io/client-go/applyconfigurations/meta/v1"
-)
-
-// ClusterExtensionRevisionStatusApplyConfiguration represents a declarative configuration of the ClusterExtensionRevisionStatus type for use
-// with apply.
-//
-// ClusterExtensionRevisionStatus defines the observed state of a ClusterExtensionRevision.
-type ClusterExtensionRevisionStatusApplyConfiguration struct {
- // conditions is an optional list of status conditions describing the state of the
- // ClusterExtensionRevision.
- //
- // The Progressing condition represents whether the revision is actively rolling out:
- // - When status is True and reason is RollingOut, the ClusterExtensionRevision rollout is actively making progress and is in transition.
- // - When status is True and reason is Retrying, the ClusterExtensionRevision has encountered an error that could be resolved on subsequent reconciliation attempts.
- // - When status is True and reason is Succeeded, the ClusterExtensionRevision has reached the desired state.
- // - When status is False and reason is Blocked, the ClusterExtensionRevision has encountered an error that requires manual intervention for recovery.
- // - When status is False and reason is Archived, the ClusterExtensionRevision is archived and not being actively reconciled.
- //
- // The Available condition represents whether the revision has been successfully rolled out and is available:
- // - When status is True and reason is ProbesSucceeded, the ClusterExtensionRevision has been successfully rolled out and all objects pass their readiness probes.
- // - When status is False and reason is ProbeFailure, one or more objects are failing their readiness probes during rollout.
- // - When status is Unknown and reason is Reconciling, the ClusterExtensionRevision has encountered an error that prevented it from observing the probes.
- // - When status is Unknown and reason is Archived, the ClusterExtensionRevision has been archived and its objects have been torn down.
- // - When status is Unknown and reason is Migrated, the ClusterExtensionRevision was migrated from an existing release and object status probe results have not yet been observed.
- //
- // The Succeeded condition represents whether the revision has successfully completed its rollout:
- // - When status is True and reason is Succeeded, the ClusterExtensionRevision has successfully completed its rollout. This condition is set once and persists even if the revision later becomes unavailable.
- Conditions []metav1.ConditionApplyConfiguration `json:"conditions,omitempty"`
-}
-
-// ClusterExtensionRevisionStatusApplyConfiguration constructs a declarative configuration of the ClusterExtensionRevisionStatus type for use with
-// apply.
-func ClusterExtensionRevisionStatus() *ClusterExtensionRevisionStatusApplyConfiguration {
- return &ClusterExtensionRevisionStatusApplyConfiguration{}
-}
-
-// 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 *ClusterExtensionRevisionStatusApplyConfiguration) WithConditions(values ...*metav1.ConditionApplyConfiguration) *ClusterExtensionRevisionStatusApplyConfiguration {
- 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/api/v1/clusterextensionstatus.go b/applyconfigurations/api/v1/clusterextensionstatus.go
index dd76e76a19..f43039d102 100644
--- a/applyconfigurations/api/v1/clusterextensionstatus.go
+++ b/applyconfigurations/api/v1/clusterextensionstatus.go
@@ -39,7 +39,7 @@ type ClusterExtensionStatusApplyConfiguration struct {
// 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.
//
- // When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterExtensionRevisions in active roll out.
+ // When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ObjectSets in active roll out.
//
//
// When the ClusterExtension is sourced from a catalog, it surfaces deprecation conditions based on catalog metadata.
@@ -51,7 +51,7 @@ 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) ClusterExtensionRevisions,
+ // activeRevisions holds a list of currently active (non-archived) ObjectSets,
// including both installed and rolling out revisions.
//
ActiveRevisions []RevisionStatusApplyConfiguration `json:"activeRevisions,omitempty"`
diff --git a/applyconfigurations/api/v1/clusterextensionrevision.go b/applyconfigurations/api/v1/objectset.go
similarity index 72%
rename from applyconfigurations/api/v1/clusterextensionrevision.go
rename to applyconfigurations/api/v1/objectset.go
index 5ccee31c23..e76c9222cb 100644
--- a/applyconfigurations/api/v1/clusterextensionrevision.go
+++ b/applyconfigurations/api/v1/objectset.go
@@ -23,42 +23,42 @@ import (
metav1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
-// ClusterExtensionRevisionApplyConfiguration represents a declarative configuration of the ClusterExtensionRevision type for use
+// ObjectSetApplyConfiguration represents a declarative configuration of the ObjectSet type for use
// with apply.
//
-// ClusterExtensionRevision represents an immutable snapshot of Kubernetes objects
+// ObjectSet represents an immutable snapshot of Kubernetes objects
// for a specific version of a ClusterExtension. Each revision contains objects
// organized into phases that roll out sequentially. The same object can only be managed by a single revision
// at a time. Ownership of objects is transitioned from one revision to the next as the extension is upgraded
// or reconfigured. Once the latest revision has rolled out successfully, previous active revisions are archived for
// posterity.
-type ClusterExtensionRevisionApplyConfiguration struct {
+type ObjectSetApplyConfiguration struct {
metav1.TypeMetaApplyConfiguration `json:",inline"`
// metadata is the standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
*metav1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
- // spec defines the desired state of the ClusterExtensionRevision.
- Spec *ClusterExtensionRevisionSpecApplyConfiguration `json:"spec,omitempty"`
- // status is optional and defines the observed state of the ClusterExtensionRevision.
- Status *ClusterExtensionRevisionStatusApplyConfiguration `json:"status,omitempty"`
+ // spec defines the desired state of the ObjectSet.
+ Spec *ObjectSetSpecApplyConfiguration `json:"spec,omitempty"`
+ // status is optional and defines the observed state of the ObjectSet.
+ Status *ObjectSetStatusApplyConfiguration `json:"status,omitempty"`
}
-// ClusterExtensionRevision constructs a declarative configuration of the ClusterExtensionRevision type for use with
+// ObjectSet constructs a declarative configuration of the ObjectSet type for use with
// apply.
-func ClusterExtensionRevision(name string) *ClusterExtensionRevisionApplyConfiguration {
- b := &ClusterExtensionRevisionApplyConfiguration{}
+func ObjectSet(name string) *ObjectSetApplyConfiguration {
+ b := &ObjectSetApplyConfiguration{}
b.WithName(name)
- b.WithKind("ClusterExtensionRevision")
+ b.WithKind("ObjectSet")
b.WithAPIVersion("olm.operatorframework.io/v1")
return b
}
-func (b ClusterExtensionRevisionApplyConfiguration) IsApplyConfiguration() {}
+func (b ObjectSetApplyConfiguration) IsApplyConfiguration() {}
// WithKind sets the Kind 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 Kind field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithKind(value string) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithKind(value string) *ObjectSetApplyConfiguration {
b.TypeMetaApplyConfiguration.Kind = &value
return b
}
@@ -66,7 +66,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithKind(value string) *Clu
// WithAPIVersion sets the APIVersion 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 APIVersion field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithAPIVersion(value string) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithAPIVersion(value string) *ObjectSetApplyConfiguration {
b.TypeMetaApplyConfiguration.APIVersion = &value
return b
}
@@ -74,7 +74,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithAPIVersion(value string
// 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 *ClusterExtensionRevisionApplyConfiguration) WithName(value string) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithName(value string) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Name = &value
return b
@@ -83,7 +83,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithName(value string) *Clu
// WithGenerateName sets the GenerateName 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 GenerateName field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithGenerateName(value string) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithGenerateName(value string) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.GenerateName = &value
return b
@@ -92,7 +92,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithGenerateName(value stri
// WithNamespace sets the Namespace 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 Namespace field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithNamespace(value string) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithNamespace(value string) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Namespace = &value
return b
@@ -101,7 +101,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithNamespace(value string)
// WithUID sets the UID 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 UID field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithUID(value types.UID) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithUID(value types.UID) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.UID = &value
return b
@@ -110,7 +110,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithUID(value types.UID) *C
// WithResourceVersion sets the ResourceVersion 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 ResourceVersion field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithResourceVersion(value string) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithResourceVersion(value string) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.ResourceVersion = &value
return b
@@ -119,7 +119,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithResourceVersion(value s
// WithGeneration sets the Generation 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 Generation field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithGeneration(value int64) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithGeneration(value int64) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Generation = &value
return b
@@ -128,7 +128,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithGeneration(value int64)
// WithCreationTimestamp sets the CreationTimestamp 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 CreationTimestamp field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithCreationTimestamp(value apismetav1.Time) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithCreationTimestamp(value apismetav1.Time) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.CreationTimestamp = &value
return b
@@ -137,7 +137,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithCreationTimestamp(value
// WithDeletionTimestamp sets the DeletionTimestamp 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 DeletionTimestamp field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithDeletionTimestamp(value apismetav1.Time) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithDeletionTimestamp(value apismetav1.Time) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.DeletionTimestamp = &value
return b
@@ -146,7 +146,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithDeletionTimestamp(value
// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds 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 DeletionGracePeriodSeconds field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.DeletionGracePeriodSeconds = &value
return b
@@ -156,7 +156,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithDeletionGracePeriodSeco
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, the entries provided by each call will be put on the Labels field,
// overwriting an existing map entries in Labels field with the same key.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithLabels(entries map[string]string) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithLabels(entries map[string]string) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
if b.ObjectMetaApplyConfiguration.Labels == nil && len(entries) > 0 {
b.ObjectMetaApplyConfiguration.Labels = make(map[string]string, len(entries))
@@ -171,7 +171,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithLabels(entries map[stri
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, the entries provided by each call will be put on the Annotations field,
// overwriting an existing map entries in Annotations field with the same key.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithAnnotations(entries map[string]string) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithAnnotations(entries map[string]string) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
if b.ObjectMetaApplyConfiguration.Annotations == nil && len(entries) > 0 {
b.ObjectMetaApplyConfiguration.Annotations = make(map[string]string, len(entries))
@@ -185,7 +185,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithAnnotations(entries map
// WithOwnerReferences adds the given value to the OwnerReferences 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 OwnerReferences field.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithOwnerReferences(values ...*metav1.OwnerReferenceApplyConfiguration) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithOwnerReferences(values ...*metav1.OwnerReferenceApplyConfiguration) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
for i := range values {
if values[i] == nil {
@@ -199,7 +199,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithOwnerReferences(values
// WithFinalizers adds the given value to the Finalizers 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 Finalizers field.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithFinalizers(values ...string) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithFinalizers(values ...string) *ObjectSetApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
for i := range values {
b.ObjectMetaApplyConfiguration.Finalizers = append(b.ObjectMetaApplyConfiguration.Finalizers, values[i])
@@ -207,7 +207,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithFinalizers(values ...st
return b
}
-func (b *ClusterExtensionRevisionApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
+func (b *ObjectSetApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
if b.ObjectMetaApplyConfiguration == nil {
b.ObjectMetaApplyConfiguration = &metav1.ObjectMetaApplyConfiguration{}
}
@@ -216,7 +216,7 @@ func (b *ClusterExtensionRevisionApplyConfiguration) ensureObjectMetaApplyConfig
// WithSpec sets the Spec 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 Spec field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithSpec(value *ClusterExtensionRevisionSpecApplyConfiguration) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithSpec(value *ObjectSetSpecApplyConfiguration) *ObjectSetApplyConfiguration {
b.Spec = value
return b
}
@@ -224,29 +224,29 @@ func (b *ClusterExtensionRevisionApplyConfiguration) WithSpec(value *ClusterExte
// WithStatus sets the Status 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 Status field is set to the value of the last call.
-func (b *ClusterExtensionRevisionApplyConfiguration) WithStatus(value *ClusterExtensionRevisionStatusApplyConfiguration) *ClusterExtensionRevisionApplyConfiguration {
+func (b *ObjectSetApplyConfiguration) WithStatus(value *ObjectSetStatusApplyConfiguration) *ObjectSetApplyConfiguration {
b.Status = value
return b
}
// GetKind retrieves the value of the Kind field in the declarative configuration.
-func (b *ClusterExtensionRevisionApplyConfiguration) GetKind() *string {
+func (b *ObjectSetApplyConfiguration) GetKind() *string {
return b.TypeMetaApplyConfiguration.Kind
}
// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration.
-func (b *ClusterExtensionRevisionApplyConfiguration) GetAPIVersion() *string {
+func (b *ObjectSetApplyConfiguration) GetAPIVersion() *string {
return b.TypeMetaApplyConfiguration.APIVersion
}
// GetName retrieves the value of the Name field in the declarative configuration.
-func (b *ClusterExtensionRevisionApplyConfiguration) GetName() *string {
+func (b *ObjectSetApplyConfiguration) GetName() *string {
b.ensureObjectMetaApplyConfigurationExists()
return b.ObjectMetaApplyConfiguration.Name
}
// GetNamespace retrieves the value of the Namespace field in the declarative configuration.
-func (b *ClusterExtensionRevisionApplyConfiguration) GetNamespace() *string {
+func (b *ObjectSetApplyConfiguration) GetNamespace() *string {
b.ensureObjectMetaApplyConfigurationExists()
return b.ObjectMetaApplyConfiguration.Namespace
}
diff --git a/applyconfigurations/api/v1/clusterextensionrevisionobject.go b/applyconfigurations/api/v1/objectsetobject.go
similarity index 74%
rename from applyconfigurations/api/v1/clusterextensionrevisionobject.go
rename to applyconfigurations/api/v1/objectsetobject.go
index fc482bf884..d565cc5bf0 100644
--- a/applyconfigurations/api/v1/clusterextensionrevisionobject.go
+++ b/applyconfigurations/api/v1/objectsetobject.go
@@ -22,12 +22,12 @@ import (
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
-// ClusterExtensionRevisionObjectApplyConfiguration represents a declarative configuration of the ClusterExtensionRevisionObject type for use
+// ObjectSetObjectApplyConfiguration represents a declarative configuration of the ObjectSetObject type for use
// with apply.
//
-// ClusterExtensionRevisionObject represents a Kubernetes object to be applied as part
+// ObjectSetObject represents a Kubernetes object to be applied as part
// of a phase, along with its collision protection settings.
-type ClusterExtensionRevisionObjectApplyConfiguration struct {
+type ObjectSetObjectApplyConfiguration struct {
// object is a required embedded Kubernetes object to be applied.
//
// This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields.
@@ -53,16 +53,16 @@ type ClusterExtensionRevisionObjectApplyConfiguration struct {
CollisionProtection *apiv1.CollisionProtection `json:"collisionProtection,omitempty"`
}
-// ClusterExtensionRevisionObjectApplyConfiguration constructs a declarative configuration of the ClusterExtensionRevisionObject type for use with
+// ObjectSetObjectApplyConfiguration constructs a declarative configuration of the ObjectSetObject type for use with
// apply.
-func ClusterExtensionRevisionObject() *ClusterExtensionRevisionObjectApplyConfiguration {
- return &ClusterExtensionRevisionObjectApplyConfiguration{}
+func ObjectSetObject() *ObjectSetObjectApplyConfiguration {
+ return &ObjectSetObjectApplyConfiguration{}
}
// WithObject sets the Object 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 Object field is set to the value of the last call.
-func (b *ClusterExtensionRevisionObjectApplyConfiguration) WithObject(value unstructured.Unstructured) *ClusterExtensionRevisionObjectApplyConfiguration {
+func (b *ObjectSetObjectApplyConfiguration) WithObject(value unstructured.Unstructured) *ObjectSetObjectApplyConfiguration {
b.Object = &value
return b
}
@@ -70,7 +70,7 @@ func (b *ClusterExtensionRevisionObjectApplyConfiguration) WithObject(value unst
// WithCollisionProtection sets the CollisionProtection 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 CollisionProtection field is set to the value of the last call.
-func (b *ClusterExtensionRevisionObjectApplyConfiguration) WithCollisionProtection(value apiv1.CollisionProtection) *ClusterExtensionRevisionObjectApplyConfiguration {
+func (b *ObjectSetObjectApplyConfiguration) WithCollisionProtection(value apiv1.CollisionProtection) *ObjectSetObjectApplyConfiguration {
b.CollisionProtection = &value
return b
}
diff --git a/applyconfigurations/api/v1/clusterextensionrevisionphase.go b/applyconfigurations/api/v1/objectsetphase.go
similarity index 72%
rename from applyconfigurations/api/v1/clusterextensionrevisionphase.go
rename to applyconfigurations/api/v1/objectsetphase.go
index 462b0e7212..05570f132f 100644
--- a/applyconfigurations/api/v1/clusterextensionrevisionphase.go
+++ b/applyconfigurations/api/v1/objectsetphase.go
@@ -21,12 +21,12 @@ import (
apiv1 "github.com/operator-framework/operator-controller/api/v1"
)
-// ClusterExtensionRevisionPhaseApplyConfiguration represents a declarative configuration of the ClusterExtensionRevisionPhase type for use
+// ObjectSetPhaseApplyConfiguration represents a declarative configuration of the ObjectSetPhase type for use
// with apply.
//
-// ClusterExtensionRevisionPhase represents a group of objects that are applied together. The phase is considered
+// ObjectSetPhase represents a group of objects that are applied together. The phase is considered
// complete only after all objects pass their status probes.
-type ClusterExtensionRevisionPhaseApplyConfiguration struct {
+type ObjectSetPhaseApplyConfiguration struct {
// name is a required identifier for this phase.
//
// phase names must follow the DNS label standard as defined in [RFC 1123].
@@ -40,7 +40,7 @@ type ClusterExtensionRevisionPhaseApplyConfiguration struct {
// objects is a required list of all Kubernetes objects that belong to this phase.
//
// All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50.
- Objects []ClusterExtensionRevisionObjectApplyConfiguration `json:"objects,omitempty"`
+ Objects []ObjectSetObjectApplyConfiguration `json:"objects,omitempty"`
// collisionProtection specifies the default collision protection strategy for all objects
// in this phase. Individual objects can override this value.
//
@@ -52,16 +52,16 @@ type ClusterExtensionRevisionPhaseApplyConfiguration struct {
CollisionProtection *apiv1.CollisionProtection `json:"collisionProtection,omitempty"`
}
-// ClusterExtensionRevisionPhaseApplyConfiguration constructs a declarative configuration of the ClusterExtensionRevisionPhase type for use with
+// ObjectSetPhaseApplyConfiguration constructs a declarative configuration of the ObjectSetPhase type for use with
// apply.
-func ClusterExtensionRevisionPhase() *ClusterExtensionRevisionPhaseApplyConfiguration {
- return &ClusterExtensionRevisionPhaseApplyConfiguration{}
+func ObjectSetPhase() *ObjectSetPhaseApplyConfiguration {
+ return &ObjectSetPhaseApplyConfiguration{}
}
// 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 *ClusterExtensionRevisionPhaseApplyConfiguration) WithName(value string) *ClusterExtensionRevisionPhaseApplyConfiguration {
+func (b *ObjectSetPhaseApplyConfiguration) WithName(value string) *ObjectSetPhaseApplyConfiguration {
b.Name = &value
return b
}
@@ -69,7 +69,7 @@ func (b *ClusterExtensionRevisionPhaseApplyConfiguration) WithName(value string)
// WithObjects adds the given value to the Objects 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 Objects field.
-func (b *ClusterExtensionRevisionPhaseApplyConfiguration) WithObjects(values ...*ClusterExtensionRevisionObjectApplyConfiguration) *ClusterExtensionRevisionPhaseApplyConfiguration {
+func (b *ObjectSetPhaseApplyConfiguration) WithObjects(values ...*ObjectSetObjectApplyConfiguration) *ObjectSetPhaseApplyConfiguration {
for i := range values {
if values[i] == nil {
panic("nil value passed to WithObjects")
@@ -82,7 +82,7 @@ func (b *ClusterExtensionRevisionPhaseApplyConfiguration) WithObjects(values ...
// WithCollisionProtection sets the CollisionProtection 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 CollisionProtection field is set to the value of the last call.
-func (b *ClusterExtensionRevisionPhaseApplyConfiguration) WithCollisionProtection(value apiv1.CollisionProtection) *ClusterExtensionRevisionPhaseApplyConfiguration {
+func (b *ObjectSetPhaseApplyConfiguration) WithCollisionProtection(value apiv1.CollisionProtection) *ObjectSetPhaseApplyConfiguration {
b.CollisionProtection = &value
return b
}
diff --git a/applyconfigurations/api/v1/clusterextensionrevisionspec.go b/applyconfigurations/api/v1/objectsetspec.go
similarity index 78%
rename from applyconfigurations/api/v1/clusterextensionrevisionspec.go
rename to applyconfigurations/api/v1/objectsetspec.go
index df638b6127..a95577db93 100644
--- a/applyconfigurations/api/v1/clusterextensionrevisionspec.go
+++ b/applyconfigurations/api/v1/objectsetspec.go
@@ -21,12 +21,12 @@ import (
apiv1 "github.com/operator-framework/operator-controller/api/v1"
)
-// ClusterExtensionRevisionSpecApplyConfiguration represents a declarative configuration of the ClusterExtensionRevisionSpec type for use
+// ObjectSetSpecApplyConfiguration represents a declarative configuration of the ObjectSetSpec type for use
// with apply.
//
-// ClusterExtensionRevisionSpec defines the desired state of ClusterExtensionRevision.
-type ClusterExtensionRevisionSpecApplyConfiguration struct {
- // lifecycleState specifies the lifecycle state of the ClusterExtensionRevision.
+// ObjectSetSpec defines the desired state of ObjectSet.
+type ObjectSetSpecApplyConfiguration struct {
+ // lifecycleState specifies the lifecycle state of the ObjectSet.
//
// When set to "Active", the revision is actively managed and reconciled.
// When set to "Archived", the revision is inactive and any resources not managed by a subsequent revision are deleted.
@@ -38,12 +38,12 @@ type ClusterExtensionRevisionSpecApplyConfiguration struct {
// It is possible for more than one revision to be "Active" simultaneously. This will occur when
// moving from one revision to another. The old revision will not be set to "Archived" until the
// new revision has been completely rolled out.
- LifecycleState *apiv1.ClusterExtensionRevisionLifecycleState `json:"lifecycleState,omitempty"`
+ LifecycleState *apiv1.ObjectSetLifecycleState `json:"lifecycleState,omitempty"`
// revision is a required, immutable sequence number representing a specific revision
// of the parent ClusterExtension.
//
// The revision field must be a positive integer.
- // Each ClusterExtensionRevision belonging to the same parent ClusterExtension must have a unique revision number.
+ // Each ObjectSet belonging to the same parent ClusterExtension must have a unique revision number.
// The revision number must always be the previous revision number plus one, or 1 for the first revision.
Revision *int64 `json:"revision,omitempty"`
// phases is an optional, immutable list of phases that group objects to be applied together.
@@ -63,7 +63,7 @@ type ClusterExtensionRevisionSpecApplyConfiguration struct {
// Once set, even if empty, the phases field is immutable.
//
// Each phase in the list must have a unique name. The maximum number of phases is 20.
- Phases []ClusterExtensionRevisionPhaseApplyConfiguration `json:"phases,omitempty"`
+ Phases []ObjectSetPhaseApplyConfiguration `json:"phases,omitempty"`
// progressDeadlineMinutes is an optional field that defines the maximum period
// of time in minutes after which an installation should be considered failed and
// require manual intervention. This functionality is disabled when no value
@@ -95,16 +95,16 @@ type ClusterExtensionRevisionSpecApplyConfiguration struct {
CollisionProtection *apiv1.CollisionProtection `json:"collisionProtection,omitempty"`
}
-// ClusterExtensionRevisionSpecApplyConfiguration constructs a declarative configuration of the ClusterExtensionRevisionSpec type for use with
+// ObjectSetSpecApplyConfiguration constructs a declarative configuration of the ObjectSetSpec type for use with
// apply.
-func ClusterExtensionRevisionSpec() *ClusterExtensionRevisionSpecApplyConfiguration {
- return &ClusterExtensionRevisionSpecApplyConfiguration{}
+func ObjectSetSpec() *ObjectSetSpecApplyConfiguration {
+ return &ObjectSetSpecApplyConfiguration{}
}
// WithLifecycleState sets the LifecycleState 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 LifecycleState field is set to the value of the last call.
-func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithLifecycleState(value apiv1.ClusterExtensionRevisionLifecycleState) *ClusterExtensionRevisionSpecApplyConfiguration {
+func (b *ObjectSetSpecApplyConfiguration) WithLifecycleState(value apiv1.ObjectSetLifecycleState) *ObjectSetSpecApplyConfiguration {
b.LifecycleState = &value
return b
}
@@ -112,7 +112,7 @@ func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithLifecycleState(valu
// WithRevision sets the Revision 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 Revision field is set to the value of the last call.
-func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithRevision(value int64) *ClusterExtensionRevisionSpecApplyConfiguration {
+func (b *ObjectSetSpecApplyConfiguration) WithRevision(value int64) *ObjectSetSpecApplyConfiguration {
b.Revision = &value
return b
}
@@ -120,7 +120,7 @@ func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithRevision(value int6
// WithPhases adds the given value to the Phases 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 Phases field.
-func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithPhases(values ...*ClusterExtensionRevisionPhaseApplyConfiguration) *ClusterExtensionRevisionSpecApplyConfiguration {
+func (b *ObjectSetSpecApplyConfiguration) WithPhases(values ...*ObjectSetPhaseApplyConfiguration) *ObjectSetSpecApplyConfiguration {
for i := range values {
if values[i] == nil {
panic("nil value passed to WithPhases")
@@ -133,7 +133,7 @@ func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithPhases(values ...*C
// WithProgressDeadlineMinutes sets the ProgressDeadlineMinutes 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 ProgressDeadlineMinutes field is set to the value of the last call.
-func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithProgressDeadlineMinutes(value int32) *ClusterExtensionRevisionSpecApplyConfiguration {
+func (b *ObjectSetSpecApplyConfiguration) WithProgressDeadlineMinutes(value int32) *ObjectSetSpecApplyConfiguration {
b.ProgressDeadlineMinutes = &value
return b
}
@@ -141,7 +141,7 @@ func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithProgressDeadlineMin
// WithProgressionProbes adds the given value to the ProgressionProbes 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 ProgressionProbes field.
-func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithProgressionProbes(values ...*ProgressionProbeApplyConfiguration) *ClusterExtensionRevisionSpecApplyConfiguration {
+func (b *ObjectSetSpecApplyConfiguration) WithProgressionProbes(values ...*ProgressionProbeApplyConfiguration) *ObjectSetSpecApplyConfiguration {
for i := range values {
if values[i] == nil {
panic("nil value passed to WithProgressionProbes")
@@ -154,7 +154,7 @@ func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithProgressionProbes(v
// WithCollisionProtection sets the CollisionProtection 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 CollisionProtection field is set to the value of the last call.
-func (b *ClusterExtensionRevisionSpecApplyConfiguration) WithCollisionProtection(value apiv1.CollisionProtection) *ClusterExtensionRevisionSpecApplyConfiguration {
+func (b *ObjectSetSpecApplyConfiguration) WithCollisionProtection(value apiv1.CollisionProtection) *ObjectSetSpecApplyConfiguration {
b.CollisionProtection = &value
return b
}
diff --git a/applyconfigurations/api/v1/objectsetstatus.go b/applyconfigurations/api/v1/objectsetstatus.go
new file mode 100644
index 0000000000..35a1619d0b
--- /dev/null
+++ b/applyconfigurations/api/v1/objectsetstatus.go
@@ -0,0 +1,68 @@
+/*
+Copyright 2022.
+
+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.20. DO NOT EDIT.
+
+package v1
+
+import (
+ metav1 "k8s.io/client-go/applyconfigurations/meta/v1"
+)
+
+// ObjectSetStatusApplyConfiguration represents a declarative configuration of the ObjectSetStatus type for use
+// with apply.
+//
+// ObjectSetStatus defines the observed state of a ObjectSet.
+type ObjectSetStatusApplyConfiguration struct {
+ // conditions is an optional list of status conditions describing the state of the
+ // ObjectSet.
+ //
+ // The Progressing condition represents whether the revision is actively rolling out:
+ // - When status is True and reason is RollingOut, the ObjectSet rollout is actively making progress and is in transition.
+ // - When status is True and reason is Retrying, the ObjectSet has encountered an error that could be resolved on subsequent reconciliation attempts.
+ // - When status is True and reason is Succeeded, the ObjectSet has reached the desired state.
+ // - When status is False and reason is Blocked, the ObjectSet has encountered an error that requires manual intervention for recovery.
+ // - When status is False and reason is Archived, the ObjectSet is archived and not being actively reconciled.
+ //
+ // The Available condition represents whether the revision has been successfully rolled out and is available:
+ // - When status is True and reason is ProbesSucceeded, the ObjectSet has been successfully rolled out and all objects pass their readiness probes.
+ // - When status is False and reason is ProbeFailure, one or more objects are failing their readiness probes during rollout.
+ // - When status is Unknown and reason is Reconciling, the ObjectSet has encountered an error that prevented it from observing the probes.
+ // - When status is Unknown and reason is Archived, the ObjectSet has been archived and its objects have been torn down.
+ // - When status is Unknown and reason is Migrated, the ObjectSet was migrated from an existing release and object status probe results have not yet been observed.
+ //
+ // The Succeeded condition represents whether the revision has successfully completed its rollout:
+ // - When status is True and reason is Succeeded, the ObjectSet has successfully completed its rollout. This condition is set once and persists even if the revision later becomes unavailable.
+ Conditions []metav1.ConditionApplyConfiguration `json:"conditions,omitempty"`
+}
+
+// ObjectSetStatusApplyConfiguration constructs a declarative configuration of the ObjectSetStatus type for use with
+// apply.
+func ObjectSetStatus() *ObjectSetStatusApplyConfiguration {
+ return &ObjectSetStatusApplyConfiguration{}
+}
+
+// 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 *ObjectSetStatusApplyConfiguration) WithConditions(values ...*metav1.ConditionApplyConfiguration) *ObjectSetStatusApplyConfiguration {
+ 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/api/v1/revisionstatus.go b/applyconfigurations/api/v1/revisionstatus.go
index d8a2e248f4..aba23c172c 100644
--- a/applyconfigurations/api/v1/revisionstatus.go
+++ b/applyconfigurations/api/v1/revisionstatus.go
@@ -24,9 +24,9 @@ import (
// RevisionStatusApplyConfiguration represents a declarative configuration of the RevisionStatus type for use
// with apply.
//
-// RevisionStatus defines the observed state of a ClusterExtensionRevision.
+// RevisionStatus defines the observed state of a ObjectSet.
type RevisionStatusApplyConfiguration struct {
- // name of the ClusterExtensionRevision resource
+ // name of the ObjectSet resource
Name *string `json:"name,omitempty"`
// conditions optionally expose Progressing and Available condition of the revision,
// in case when it is not yet marked as successfully installed (condition Succeeded is not set to True).
diff --git a/applyconfigurations/utils.go b/applyconfigurations/utils.go
index d8e2bb9da3..7f29e0eb36 100644
--- a/applyconfigurations/utils.go
+++ b/applyconfigurations/utils.go
@@ -55,16 +55,6 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
return &apiv1.ClusterExtensionInstallConfigApplyConfiguration{}
case v1.SchemeGroupVersion.WithKind("ClusterExtensionInstallStatus"):
return &apiv1.ClusterExtensionInstallStatusApplyConfiguration{}
- case v1.SchemeGroupVersion.WithKind("ClusterExtensionRevision"):
- return &apiv1.ClusterExtensionRevisionApplyConfiguration{}
- case v1.SchemeGroupVersion.WithKind("ClusterExtensionRevisionObject"):
- return &apiv1.ClusterExtensionRevisionObjectApplyConfiguration{}
- case v1.SchemeGroupVersion.WithKind("ClusterExtensionRevisionPhase"):
- return &apiv1.ClusterExtensionRevisionPhaseApplyConfiguration{}
- case v1.SchemeGroupVersion.WithKind("ClusterExtensionRevisionSpec"):
- return &apiv1.ClusterExtensionRevisionSpecApplyConfiguration{}
- case v1.SchemeGroupVersion.WithKind("ClusterExtensionRevisionStatus"):
- return &apiv1.ClusterExtensionRevisionStatusApplyConfiguration{}
case v1.SchemeGroupVersion.WithKind("ClusterExtensionSpec"):
return &apiv1.ClusterExtensionSpecApplyConfiguration{}
case v1.SchemeGroupVersion.WithKind("ClusterExtensionStatus"):
@@ -81,6 +71,16 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
return &apiv1.ImageSourceApplyConfiguration{}
case v1.SchemeGroupVersion.WithKind("ObjectSelector"):
return &apiv1.ObjectSelectorApplyConfiguration{}
+ case v1.SchemeGroupVersion.WithKind("ObjectSet"):
+ return &apiv1.ObjectSetApplyConfiguration{}
+ case v1.SchemeGroupVersion.WithKind("ObjectSetObject"):
+ return &apiv1.ObjectSetObjectApplyConfiguration{}
+ case v1.SchemeGroupVersion.WithKind("ObjectSetPhase"):
+ return &apiv1.ObjectSetPhaseApplyConfiguration{}
+ case v1.SchemeGroupVersion.WithKind("ObjectSetSpec"):
+ return &apiv1.ObjectSetSpecApplyConfiguration{}
+ case v1.SchemeGroupVersion.WithKind("ObjectSetStatus"):
+ return &apiv1.ObjectSetStatusApplyConfiguration{}
case v1.SchemeGroupVersion.WithKind("PreflightConfig"):
return &apiv1.PreflightConfigApplyConfiguration{}
case v1.SchemeGroupVersion.WithKind("ProgressionProbe"):
diff --git a/cmd/operator-controller/main.go b/cmd/operator-controller/main.go
index f905d105dd..aa7a2ef788 100644
--- a/cmd/operator-controller/main.go
+++ b/cmd/operator-controller/main.go
@@ -264,7 +264,7 @@ func run() error {
}
if features.OperatorControllerFeatureGate.Enabled(features.BoxcutterRuntime) {
- cacheOptions.ByObject[&ocv1.ClusterExtensionRevision{}] = crcache.ByObject{
+ cacheOptions.ByObject[&ocv1.ObjectSet{}] = crcache.ByObject{
Label: k8slabels.Everything(),
}
}
@@ -476,7 +476,7 @@ func run() error {
var ctrlBuilderOpts []controllers.ControllerBuilderOption
if features.OperatorControllerFeatureGate.Enabled(features.BoxcutterRuntime) {
- ctrlBuilderOpts = append(ctrlBuilderOpts, controllers.WithOwns(&ocv1.ClusterExtensionRevision{}))
+ ctrlBuilderOpts = append(ctrlBuilderOpts, controllers.WithOwns(&ocv1.ObjectSet{}))
}
ceReconciler := &controllers.ClusterExtensionReconciler{
@@ -679,7 +679,7 @@ func (c *boxcutterReconcilerConfigurator) Configure(ceReconciler *controllers.Cl
cerCoreClient, err := corev1client.NewForConfig(c.mgr.GetConfig())
if err != nil {
- return fmt.Errorf("unable to create client for ClusterExtensionRevision controller: %w", err)
+ return fmt.Errorf("unable to create client for ObjectSet controller: %w", err)
}
cerTokenGetter := authentication.NewTokenGetter(cerCoreClient, authentication.WithExpirationDuration(1*time.Hour))
@@ -696,12 +696,12 @@ func (c *boxcutterReconcilerConfigurator) Configure(ceReconciler *controllers.Cl
return fmt.Errorf("unable to create revision engine factory: %w", err)
}
- if err = (&controllers.ClusterExtensionRevisionReconciler{
+ if err = (&controllers.ObjectSetReconciler{
Client: c.mgr.GetClient(),
RevisionEngineFactory: revisionEngineFactory,
TrackingCache: trackingCache,
}).SetupWithManager(c.mgr); err != nil {
- return fmt.Errorf("unable to setup ClusterExtensionRevision controller: %w", err)
+ return fmt.Errorf("unable to setup ObjectSet controller: %w", err)
}
return nil
}
diff --git a/config/samples/olm_v1_clusterextension.yaml b/config/samples/olm_v1_clusterextension.yaml
index 14c8e167e0..e1e5ad6f4f 100644
--- a/config/samples/olm_v1_clusterextension.yaml
+++ b/config/samples/olm_v1_clusterextension.yaml
@@ -33,9 +33,9 @@ rules:
resources: [clusterextensions/finalizers]
verbs: [update]
resourceNames: [argocd]
-# Allow ClusterExtensionRevisions to set blockOwnerDeletion ownerReferences
+# Allow ObjectSets to set blockOwnerDeletion ownerReferences
- apiGroups: [olm.operatorframework.io]
- resources: [clusterextensionrevisions/finalizers]
+ resources: [objectsets/finalizers]
verbs: [update]
# Manage ArgoCD CRDs
- apiGroups: [apiextensions.k8s.io]
diff --git a/docs/api-reference/crd-ref-docs-gen-config.yaml b/docs/api-reference/crd-ref-docs-gen-config.yaml
index c8efa15c19..6ebb21db20 100644
--- a/docs/api-reference/crd-ref-docs-gen-config.yaml
+++ b/docs/api-reference/crd-ref-docs-gen-config.yaml
@@ -1,5 +1,5 @@
processor:
- ignoreTypes: [ClusterExtensionRevision, ClusterExtensionRevisionList]
+ ignoreTypes: [ObjectSet, ObjectSetList]
ignoreFields: []
render:
diff --git a/docs/api-reference/olmv1-api-reference.md b/docs/api-reference/olmv1-api-reference.md
index 29731f2cd0..9d0d4ec816 100644
--- a/docs/api-reference/olmv1-api-reference.md
+++ b/docs/api-reference/olmv1-api-reference.md
@@ -379,9 +379,9 @@ _Appears in:_
| Field | Description | Default | Validation |
| --- | --- | --- | --- |
-| `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.
When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterExtensionRevisions 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: \{\}
|
+| `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.
When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ObjectSets 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) ClusterExtensionRevisions,
including both installed and rolling out revisions.
| | Optional: \{\}
|
+| `activeRevisions` _[RevisionStatus](#revisionstatus) array_ | activeRevisions holds a list of currently active (non-archived) ObjectSets,
including both installed and rolling out revisions.
| | Optional: \{\}
|
@@ -549,7 +549,7 @@ _Appears in:_
-RevisionStatus defines the observed state of a ClusterExtensionRevision.
+RevisionStatus defines the observed state of a ObjectSet.
@@ -558,7 +558,7 @@ _Appears in:_
| Field | Description | Default | Validation |
| --- | --- | --- | --- |
-| `name` _string_ | name of the ClusterExtensionRevision resource | | |
+| `name` _string_ | name of the ObjectSet resource | | |
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | conditions optionally expose Progressing and Available condition of the revision,
in case when it is not yet marked as successfully installed (condition Succeeded is not set to True).
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: \{\}
|
diff --git a/hack/tools/update-crds.sh b/hack/tools/update-crds.sh
index e379b59896..9a701c52ed 100755
--- a/hack/tools/update-crds.sh
+++ b/hack/tools/update-crds.sh
@@ -7,7 +7,7 @@ set -e
# The names of the generated CRDs
CE="olm.operatorframework.io_clusterextensions.yaml"
CC="olm.operatorframework.io_clustercatalogs.yaml"
-CR="olm.operatorframework.io_clusterextensionrevisions.yaml"
+CR="olm.operatorframework.io_objectsets.yaml"
# order for modules and crds must match
# each item in crds must be unique, and should be associated with a module
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 83631dc27b..5a51e78e57 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
@@ -504,10 +504,10 @@ spec:
properties:
activeRevisions:
description: |-
- activeRevisions holds a list of currently active (non-archived) ClusterExtensionRevisions,
+ activeRevisions holds a list of currently active (non-archived) ObjectSets,
including both installed and rolling out revisions.
items:
- description: RevisionStatus defines the observed state of a ClusterExtensionRevision.
+ description: RevisionStatus defines the observed state of a ObjectSet.
properties:
conditions:
description: |-
@@ -575,7 +575,7 @@ spec:
- type
x-kubernetes-list-type: map
name:
- description: name of the ClusterExtensionRevision resource
+ description: name of the ObjectSet resource
type: string
required:
- name
@@ -599,7 +599,7 @@ spec:
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.
- When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterExtensionRevisions in active roll out.
+ When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ObjectSets 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:
diff --git a/helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensionrevisions.yaml b/helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_objectsets.yaml
similarity index 94%
rename from helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensionrevisions.yaml
rename to helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_objectsets.yaml
index 491f8327d7..ac1dd32a61 100644
--- a/helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensionrevisions.yaml
+++ b/helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_objectsets.yaml
@@ -5,14 +5,14 @@ metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.20.1
olm.operatorframework.io/generator: experimental
- name: clusterextensionrevisions.olm.operatorframework.io
+ name: objectsets.olm.operatorframework.io
spec:
group: olm.operatorframework.io
names:
- kind: ClusterExtensionRevision
- listKind: ClusterExtensionRevisionList
- plural: clusterextensionrevisions
- singular: clusterextensionrevision
+ kind: ObjectSet
+ listKind: ObjectSetList
+ plural: objectsets
+ singular: objectset
scope: Cluster
versions:
- additionalPrinterColumns:
@@ -29,7 +29,7 @@ spec:
schema:
openAPIV3Schema:
description: |-
- ClusterExtensionRevision represents an immutable snapshot of Kubernetes objects
+ ObjectSet represents an immutable snapshot of Kubernetes objects
for a specific version of a ClusterExtension. Each revision contains objects
organized into phases that roll out sequentially. The same object can only be managed by a single revision
at a time. Ownership of objects is transitioned from one revision to the next as the extension is upgraded
@@ -54,7 +54,7 @@ spec:
metadata:
type: object
spec:
- description: spec defines the desired state of the ClusterExtensionRevision.
+ description: spec defines the desired state of the ObjectSet.
properties:
collisionProtection:
description: |-
@@ -75,7 +75,7 @@ spec:
rule: self == oldSelf
lifecycleState:
description: |-
- lifecycleState specifies the lifecycle state of the ClusterExtensionRevision.
+ lifecycleState specifies the lifecycle state of the ObjectSet.
When set to "Active", the revision is actively managed and reconciled.
When set to "Archived", the revision is inactive and any resources not managed by a subsequent revision are deleted.
@@ -116,7 +116,7 @@ spec:
Each phase in the list must have a unique name. The maximum number of phases is 20.
items:
description: |-
- ClusterExtensionRevisionPhase represents a group of objects that are applied together. The phase is considered
+ ObjectSetPhase represents a group of objects that are applied together. The phase is considered
complete only after all objects pass their status probes.
properties:
collisionProtection:
@@ -160,7 +160,7 @@ spec:
All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50.
items:
description: |-
- ClusterExtensionRevisionObject represents a Kubernetes object to be applied as part
+ ObjectSetObject represents a Kubernetes object to be applied as part
of a phase, along with its collision protection settings.
properties:
collisionProtection:
@@ -488,7 +488,7 @@ spec:
of the parent ClusterExtension.
The revision field must be a positive integer.
- Each ClusterExtensionRevision belonging to the same parent ClusterExtension must have a unique revision number.
+ Each ObjectSet belonging to the same parent ClusterExtension must have a unique revision number.
The revision number must always be the previous revision number plus one, or 1 for the first revision.
format: int64
minimum: 1
@@ -503,29 +503,29 @@ spec:
type: object
status:
description: status is optional and defines the observed state of the
- ClusterExtensionRevision.
+ ObjectSet.
properties:
conditions:
description: |-
conditions is an optional list of status conditions describing the state of the
- ClusterExtensionRevision.
+ ObjectSet.
The Progressing condition represents whether the revision is actively rolling out:
- - When status is True and reason is RollingOut, the ClusterExtensionRevision rollout is actively making progress and is in transition.
- - When status is True and reason is Retrying, the ClusterExtensionRevision has encountered an error that could be resolved on subsequent reconciliation attempts.
- - When status is True and reason is Succeeded, the ClusterExtensionRevision has reached the desired state.
- - When status is False and reason is Blocked, the ClusterExtensionRevision has encountered an error that requires manual intervention for recovery.
- - When status is False and reason is Archived, the ClusterExtensionRevision is archived and not being actively reconciled.
+ - When status is True and reason is RollingOut, the ObjectSet rollout is actively making progress and is in transition.
+ - When status is True and reason is Retrying, the ObjectSet has encountered an error that could be resolved on subsequent reconciliation attempts.
+ - When status is True and reason is Succeeded, the ObjectSet has reached the desired state.
+ - When status is False and reason is Blocked, the ObjectSet has encountered an error that requires manual intervention for recovery.
+ - When status is False and reason is Archived, the ObjectSet is archived and not being actively reconciled.
The Available condition represents whether the revision has been successfully rolled out and is available:
- - When status is True and reason is ProbesSucceeded, the ClusterExtensionRevision has been successfully rolled out and all objects pass their readiness probes.
+ - When status is True and reason is ProbesSucceeded, the ObjectSet has been successfully rolled out and all objects pass their readiness probes.
- When status is False and reason is ProbeFailure, one or more objects are failing their readiness probes during rollout.
- - When status is Unknown and reason is Reconciling, the ClusterExtensionRevision has encountered an error that prevented it from observing the probes.
- - When status is Unknown and reason is Archived, the ClusterExtensionRevision has been archived and its objects have been torn down.
- - When status is Unknown and reason is Migrated, the ClusterExtensionRevision was migrated from an existing release and object status probe results have not yet been observed.
+ - When status is Unknown and reason is Reconciling, the ObjectSet has encountered an error that prevented it from observing the probes.
+ - When status is Unknown and reason is Archived, the ObjectSet has been archived and its objects have been torn down.
+ - When status is Unknown and reason is Migrated, the ObjectSet was migrated from an existing release and object status probe results have not yet been observed.
The Succeeded condition represents whether the revision has successfully completed its rollout:
- - When status is True and reason is Succeeded, the ClusterExtensionRevision has successfully completed its rollout. This condition is set once and persists even if the revision later becomes unavailable.
+ - When status is True and reason is Succeeded, the ObjectSet has successfully completed its rollout. This condition is set once and persists even if the revision later becomes unavailable.
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
diff --git a/helm/olmv1/templates/crds/customresourcedefinition-clusterextensionrevisions.olm.operatorframework.io.yml b/helm/olmv1/templates/crds/customresourcedefinition-objectsets.olm.operatorframework.io.yml
similarity index 78%
rename from helm/olmv1/templates/crds/customresourcedefinition-clusterextensionrevisions.olm.operatorframework.io.yml
rename to helm/olmv1/templates/crds/customresourcedefinition-objectsets.olm.operatorframework.io.yml
index e52614d6e3..140702539b 100644
--- a/helm/olmv1/templates/crds/customresourcedefinition-clusterextensionrevisions.olm.operatorframework.io.yml
+++ b/helm/olmv1/templates/crds/customresourcedefinition-objectsets.olm.operatorframework.io.yml
@@ -1,9 +1,9 @@
{{- if .Values.options.operatorController.enabled }}
{{- if (eq .Values.options.featureSet "standard") }}
-{{- /* Add when GA: tpl (.Files.Get "base/operator-controller/crd/standard/olm.operatorframework.io_clusterextensionrevisionss.yaml") . */}}
+{{- /* Add when GA: tpl (.Files.Get "base/operator-controller/crd/standard/olm.operatorframework.io_objectsets.yaml") . */}}
{{- else if (eq .Values.options.featureSet "experimental") }}
{{- if has "BoxcutterRuntime" .Values.options.operatorController.features.enabled }}
-{{ tpl (.Files.Get "base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensionrevisions.yaml") . }}
+{{ tpl (.Files.Get "base/operator-controller/crd/experimental/olm.operatorframework.io_objectsets.yaml") . }}
{{- end }}
{{- else }}
{{- fail "options.featureSet must be set to one of: {standard,experimental}" }}
diff --git a/helm/olmv1/templates/rbac/clusterrole-operator-controller-manager-role.yml b/helm/olmv1/templates/rbac/clusterrole-operator-controller-manager-role.yml
index 9f187e8924..50f7eef399 100644
--- a/helm/olmv1/templates/rbac/clusterrole-operator-controller-manager-role.yml
+++ b/helm/olmv1/templates/rbac/clusterrole-operator-controller-manager-role.yml
@@ -89,7 +89,7 @@ rules:
- apiGroups:
- olm.operatorframework.io
resources:
- - clusterextensionrevisions
+ - objectsets
verbs:
- create
- delete
@@ -101,14 +101,14 @@ rules:
- apiGroups:
- olm.operatorframework.io
resources:
- - clusterextensionrevisions/status
+ - objectsets/status
verbs:
- patch
- update
- apiGroups:
- olm.operatorframework.io
resources:
- - clusterextensionrevisions/finalizers
+ - objectsets/finalizers
verbs:
- update
{{- end }}
diff --git a/internal/operator-controller/applier/boxcutter.go b/internal/operator-controller/applier/boxcutter.go
index cb4da7e534..7b1413246b 100644
--- a/internal/operator-controller/applier/boxcutter.go
+++ b/internal/operator-controller/applier/boxcutter.go
@@ -39,16 +39,16 @@ import (
)
const (
- ClusterExtensionRevisionRetentionLimit = 5
+ ObjectSetRetentionLimit = 5
)
-type ClusterExtensionRevisionGenerator interface {
- GenerateRevision(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error)
+type ObjectSetGenerator interface {
+ GenerateRevision(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error)
GenerateRevisionFromHelmRelease(
ctx context.Context,
helmRelease *release.Release, ext *ocv1.ClusterExtension,
objectLabels map[string]string,
- ) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error)
+ ) (*ocv1ac.ObjectSetApplyConfiguration, error)
}
type SimpleRevisionGenerator struct {
@@ -60,9 +60,9 @@ func (r *SimpleRevisionGenerator) GenerateRevisionFromHelmRelease(
ctx context.Context,
helmRelease *release.Release, ext *ocv1.ClusterExtension,
objectLabels map[string]string,
-) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
+) (*ocv1ac.ObjectSetApplyConfiguration, error) {
docs := splitManifestDocuments(helmRelease.Manifest)
- objs := make([]ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration, 0, len(docs))
+ objs := make([]ocv1ac.ObjectSetObjectApplyConfiguration, 0, len(docs))
for _, doc := range docs {
obj := unstructured.Unstructured{}
if err := yaml.Unmarshal([]byte(doc), &obj); err != nil {
@@ -75,11 +75,11 @@ func (r *SimpleRevisionGenerator) GenerateRevisionFromHelmRelease(
_ = cache.ApplyStripAnnotationsTransform(&obj)
sanitizedUnstructured(ctx, &obj)
- objs = append(objs, *ocv1ac.ClusterExtensionRevisionObject().
+ objs = append(objs, *ocv1ac.ObjectSetObject().
WithObject(obj))
}
- rev := r.buildClusterExtensionRevision(objs, ext, map[string]string{
+ rev := r.buildObjectSet(objs, ext, map[string]string{
labels.BundleNameKey: helmRelease.Labels[labels.BundleNameKey],
labels.PackageNameKey: helmRelease.Labels[labels.PackageNameKey],
labels.BundleVersionKey: helmRelease.Labels[labels.BundleVersionKey],
@@ -95,7 +95,7 @@ func (r *SimpleRevisionGenerator) GenerateRevision(
ctx context.Context,
bundleFS fs.FS, ext *ocv1.ClusterExtension,
objectLabels, revisionAnnotations map[string]string,
-) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
+) (*ocv1ac.ObjectSetApplyConfiguration, error) {
// extract plain manifests
plain, err := r.ManifestProvider.Get(bundleFS, ext)
if err != nil {
@@ -124,7 +124,7 @@ func (r *SimpleRevisionGenerator) GenerateRevision(
}
// objectLabels
- objs := make([]ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration, 0, len(plain))
+ objs := make([]ocv1ac.ObjectSetObjectApplyConfiguration, 0, len(plain))
for _, obj := range plain {
obj.SetLabels(mergeLabelMaps(obj.GetLabels(), objectLabels))
@@ -146,10 +146,10 @@ func (r *SimpleRevisionGenerator) GenerateRevision(
}
sanitizedUnstructured(ctx, &unstr)
- objs = append(objs, *ocv1ac.ClusterExtensionRevisionObject().
+ objs = append(objs, *ocv1ac.ObjectSetObject().
WithObject(unstr))
}
- rev := r.buildClusterExtensionRevision(objs, ext, revisionAnnotations)
+ rev := r.buildObjectSet(objs, ext, revisionAnnotations)
rev.Spec.WithCollisionProtection(ocv1.CollisionProtectionPrevent)
return rev, nil
}
@@ -196,11 +196,11 @@ func sanitizedUnstructured(ctx context.Context, unstr *unstructured.Unstructured
obj["metadata"] = metadataSanitized
}
-func (r *SimpleRevisionGenerator) buildClusterExtensionRevision(
- objects []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration,
+func (r *SimpleRevisionGenerator) buildObjectSet(
+ objects []ocv1ac.ObjectSetObjectApplyConfiguration,
ext *ocv1.ClusterExtension,
annotations map[string]string,
-) *ocv1ac.ClusterExtensionRevisionApplyConfiguration {
+) *ocv1ac.ObjectSetApplyConfiguration {
if annotations == nil {
annotations = make(map[string]string)
}
@@ -209,14 +209,14 @@ func (r *SimpleRevisionGenerator) buildClusterExtensionRevision(
phases := PhaseSort(objects)
- spec := ocv1ac.ClusterExtensionRevisionSpec().
- WithLifecycleState(ocv1.ClusterExtensionRevisionLifecycleStateActive).
+ spec := ocv1ac.ObjectSetSpec().
+ WithLifecycleState(ocv1.ObjectSetLifecycleStateActive).
WithPhases(phases...)
if p := ext.Spec.ProgressDeadlineMinutes; p > 0 {
spec.WithProgressDeadlineMinutes(p)
}
- return ocv1ac.ClusterExtensionRevision("").
+ return ocv1ac.ObjectSet("").
WithAnnotations(annotations).
WithLabels(map[string]string{
labels.OwnerKindKey: ocv1.ClusterExtensionKind,
@@ -226,10 +226,10 @@ func (r *SimpleRevisionGenerator) buildClusterExtensionRevision(
}
// BoxcutterStorageMigrator migrates ClusterExtensions from Helm-based storage to
-// ClusterExtensionRevision storage, enabling upgrades from older operator-controller versions.
+// ObjectSet storage, enabling upgrades from older operator-controller versions.
type BoxcutterStorageMigrator struct {
ActionClientGetter helmclient.ActionClientGetter
- RevisionGenerator ClusterExtensionRevisionGenerator
+ RevisionGenerator ObjectSetGenerator
Client boxcutterStorageMigratorClient
Scheme *runtime.Scheme
FieldOwner string
@@ -242,14 +242,14 @@ type boxcutterStorageMigratorClient interface {
Status() client.StatusWriter
}
-// Migrate creates a ClusterExtensionRevision from an existing Helm release if no revisions exist yet.
+// Migrate creates a ObjectSet from an existing Helm release if no revisions exist yet.
// The migration is idempotent and skipped if revisions already exist or no Helm release is found.
func (m *BoxcutterStorageMigrator) Migrate(ctx context.Context, ext *ocv1.ClusterExtension, objectLabels map[string]string) error {
- existingRevisionList := ocv1.ClusterExtensionRevisionList{}
+ existingRevisionList := ocv1.ObjectSetList{}
if err := m.Client.List(ctx, &existingRevisionList, client.MatchingLabels{
labels.OwnerNameKey: ext.Name,
}); err != nil {
- return fmt.Errorf("listing ClusterExtensionRevisions before attempting migration: %w", err)
+ return fmt.Errorf("listing ObjectSets before attempting migration: %w", err)
}
if len(existingRevisionList.Items) != 0 {
return m.ensureMigratedRevisionStatus(ctx, existingRevisionList.Items)
@@ -323,7 +323,7 @@ func (m *BoxcutterStorageMigrator) Migrate(ctx context.Context, ext *ocv1.Cluste
// - Status reporting (installed bundle appears as nil)
// - Subsequent upgrades (resolution fails without knowing current version)
//
- // While the ClusterExtensionRevision controller would eventually reconcile and set this status,
+ // While the ObjectSet controller would eventually reconcile and set this status,
// that creates a timing gap where the ClusterExtension reconciliation happens before the status
// is set, causing failures during the OLM upgrade window.
//
@@ -335,13 +335,13 @@ func (m *BoxcutterStorageMigrator) Migrate(ctx context.Context, ext *ocv1.Cluste
// ensureMigratedRevisionStatus checks if revision 1 exists and needs its status set.
// This handles the case where revision creation succeeded but status update failed.
// Returns nil if no action is needed.
-func (m *BoxcutterStorageMigrator) ensureMigratedRevisionStatus(ctx context.Context, revisions []ocv1.ClusterExtensionRevision) error {
+func (m *BoxcutterStorageMigrator) ensureMigratedRevisionStatus(ctx context.Context, revisions []ocv1.ObjectSet) error {
for i := range revisions {
if revisions[i].Spec.Revision != 1 {
continue
}
// Skip if already succeeded - status is already set correctly.
- if meta.IsStatusConditionTrue(revisions[i].Status.Conditions, ocv1.ClusterExtensionRevisionTypeSucceeded) {
+ if meta.IsStatusConditionTrue(revisions[i].Status.Conditions, ocv1.ObjectSetTypeSucceeded) {
return nil
}
// Ensure revision 1 status is set correctly, including for previously migrated
@@ -384,7 +384,7 @@ func (m *BoxcutterStorageMigrator) findLatestDeployedRelease(ac helmclient.Actio
// Returns nil if the status is already set or after successfully setting it.
// Only sets status on revisions that were actually migrated from Helm (marked with MigratedFromHelmKey label).
func (m *BoxcutterStorageMigrator) ensureRevisionStatus(ctx context.Context, name string) error {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
if err := m.Client.Get(ctx, client.ObjectKey{Name: name}, rev); err != nil {
return fmt.Errorf("getting existing revision for status check: %w", err)
}
@@ -397,13 +397,13 @@ func (m *BoxcutterStorageMigrator) ensureRevisionStatus(ctx context.Context, nam
}
// Check if status is already set to Succeeded=True
- if meta.IsStatusConditionTrue(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeSucceeded) {
+ if meta.IsStatusConditionTrue(rev.Status.Conditions, ocv1.ObjectSetTypeSucceeded) {
return nil
}
// Set the Succeeded status condition
meta.SetStatusCondition(&rev.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeSucceeded,
+ Type: ocv1.ObjectSetTypeSucceeded,
Status: metav1.ConditionTrue,
Reason: ocv1.ReasonSucceeded,
Message: "Revision succeeded - migrated from Helm release",
@@ -420,7 +420,7 @@ func (m *BoxcutterStorageMigrator) ensureRevisionStatus(ctx context.Context, nam
type Boxcutter struct {
Client client.Client
Scheme *runtime.Scheme
- RevisionGenerator ClusterExtensionRevisionGenerator
+ RevisionGenerator ObjectSetGenerator
Preflights []Preflight
PreAuthorizer authorization.PreAuthorizer
FieldOwner string
@@ -428,7 +428,7 @@ type Boxcutter struct {
// apply applies the revision object using server-side apply. PreAuthorization checks are performed
// to ensure the user has sufficient permissions to manage the revision and its resources.
-func (bc *Boxcutter) apply(ctx context.Context, user user.Info, rev *ocv1ac.ClusterExtensionRevisionApplyConfiguration) error {
+func (bc *Boxcutter) apply(ctx context.Context, user user.Info, rev *ocv1ac.ObjectSetApplyConfiguration) error {
// Run auth preflight checks
if err := bc.runPreAuthorizationChecks(ctx, user, rev); err != nil {
return err
@@ -440,7 +440,7 @@ func (bc *Boxcutter) apply(ctx context.Context, user user.Info, rev *ocv1ac.Clus
func (bc *Boxcutter) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (bool, string, error) {
// List existing revisions first to validate cluster connectivity before checking contentFS.
// This ensures we fail fast on API errors rather than attempting fallback behavior when
- // cluster access is unavailable (since the ClusterExtensionRevision controller also requires
+ // cluster access is unavailable (since the ObjectSet controller also requires
// API access to maintain resources). The revision list is also needed to determine if fallback
// is possible when contentFS is nil (at least one revision must exist).
existingRevisions, err := bc.getExistingRevisions(ctx, ext.GetName())
@@ -455,7 +455,7 @@ func (bc *Boxcutter) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.Clust
return false, "", fmt.Errorf("catalog content unavailable and no revision installed")
}
// Returning true here signals that the rollout has succeeded using the current revision.
- // This assumes the ClusterExtensionRevision controller is running and will continue to
+ // This assumes the ObjectSet controller is running and will continue to
// reconcile, apply, and maintain the resources defined in that revision via Server-Side Apply,
// ensuring the workload keeps running even when catalog access is unavailable.
return true, "", nil
@@ -479,7 +479,7 @@ func (bc *Boxcutter) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.Clust
WithBlockOwnerDeletion(true).
WithController(true))
- currentRevision := &ocv1.ClusterExtensionRevision{}
+ currentRevision := &ocv1.ObjectSet{}
state := StateNeedsInstall
// check if we can update the current revision.
if len(existingRevisions) > 0 {
@@ -548,7 +548,7 @@ func (bc *Boxcutter) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.Clust
// runPreAuthorizationChecks runs PreAuthorization checks if the PreAuthorizer is set. An error will be returned if
// the ClusterExtension service account does not have the necessary permissions to manage the revision's resources
-func (bc *Boxcutter) runPreAuthorizationChecks(ctx context.Context, user user.Info, rev *ocv1ac.ClusterExtensionRevisionApplyConfiguration) error {
+func (bc *Boxcutter) runPreAuthorizationChecks(ctx context.Context, user user.Info, rev *ocv1ac.ObjectSetApplyConfiguration) error {
if bc.PreAuthorizer == nil {
return nil
}
@@ -563,13 +563,13 @@ func (bc *Boxcutter) runPreAuthorizationChecks(ctx context.Context, user user.In
return formatPreAuthorizerOutput(bc.PreAuthorizer.PreAuthorize(ctx, user, manifestReader, revisionManagementPerms(rev)))
}
-// garbageCollectOldRevisions deletes archived revisions beyond ClusterExtensionRevisionRetentionLimit.
+// garbageCollectOldRevisions deletes archived revisions beyond ObjectSetRetentionLimit.
// Active revisions are never deleted. revisionList must be sorted oldest to newest.
-func (bc *Boxcutter) garbageCollectOldRevisions(ctx context.Context, revisionList []ocv1.ClusterExtensionRevision) error {
+func (bc *Boxcutter) garbageCollectOldRevisions(ctx context.Context, revisionList []ocv1.ObjectSet) error {
for index, r := range revisionList {
// Only delete archived revisions that are beyond the limit
- if index < len(revisionList)-ClusterExtensionRevisionRetentionLimit && r.Spec.LifecycleState == ocv1.ClusterExtensionRevisionLifecycleStateArchived {
- if err := bc.Client.Delete(ctx, &ocv1.ClusterExtensionRevision{
+ if index < len(revisionList)-ObjectSetRetentionLimit && r.Spec.LifecycleState == ocv1.ObjectSetLifecycleStateArchived {
+ if err := bc.Client.Delete(ctx, &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: r.Name,
},
@@ -581,21 +581,21 @@ func (bc *Boxcutter) garbageCollectOldRevisions(ctx context.Context, revisionLis
return nil
}
-// getExistingRevisions returns the list of ClusterExtensionRevisions for a ClusterExtension with name extName in revision order (oldest to newest)
-func (bc *Boxcutter) getExistingRevisions(ctx context.Context, extName string) ([]ocv1.ClusterExtensionRevision, error) {
- existingRevisionList := &ocv1.ClusterExtensionRevisionList{}
+// getExistingRevisions returns the list of ObjectSets for a ClusterExtension with name extName in revision order (oldest to newest)
+func (bc *Boxcutter) getExistingRevisions(ctx context.Context, extName string) ([]ocv1.ObjectSet, error) {
+ existingRevisionList := &ocv1.ObjectSetList{}
if err := bc.Client.List(ctx, existingRevisionList, client.MatchingLabels{
labels.OwnerNameKey: extName,
}); err != nil {
return nil, fmt.Errorf("listing revisions: %w", err)
}
- slices.SortFunc(existingRevisionList.Items, func(a, b ocv1.ClusterExtensionRevision) int {
+ slices.SortFunc(existingRevisionList.Items, func(a, b ocv1.ObjectSet) int {
return cmp.Compare(a.Spec.Revision, b.Spec.Revision)
})
return existingRevisionList.Items, nil
}
-func latestRevisionNumber(prevRevisions []ocv1.ClusterExtensionRevision) int64 {
+func latestRevisionNumber(prevRevisions []ocv1.ObjectSet) int64 {
if len(prevRevisions) == 0 {
return 0
}
@@ -623,7 +623,7 @@ func splitManifestDocuments(file string) []string {
}
// getObjects returns a slice of all objects in the revision
-func getObjects(rev *ocv1ac.ClusterExtensionRevisionApplyConfiguration) []client.Object {
+func getObjects(rev *ocv1ac.ObjectSetApplyConfiguration) []client.Object {
if rev.Spec == nil {
return nil
}
@@ -643,7 +643,7 @@ func getObjects(rev *ocv1ac.ClusterExtensionRevisionApplyConfiguration) []client
}
// revisionManifestReader returns an io.Reader containing all manifests in the revision
-func revisionManifestReader(rev *ocv1ac.ClusterExtensionRevisionApplyConfiguration) (io.Reader, error) {
+func revisionManifestReader(rev *ocv1ac.ObjectSetApplyConfiguration) (io.Reader, error) {
printer := printers.YAMLPrinter{}
buf := new(bytes.Buffer)
for _, obj := range getObjects(rev) {
@@ -655,7 +655,7 @@ func revisionManifestReader(rev *ocv1ac.ClusterExtensionRevisionApplyConfigurati
return buf, nil
}
-func revisionManagementPerms(rev *ocv1ac.ClusterExtensionRevisionApplyConfiguration) func(user.Info) []authorizer.AttributesRecord {
+func revisionManagementPerms(rev *ocv1ac.ObjectSetApplyConfiguration) func(user.Info) []authorizer.AttributesRecord {
return func(user user.Info) []authorizer.AttributesRecord {
return []authorizer.AttributesRecord{
{
@@ -663,7 +663,7 @@ func revisionManagementPerms(rev *ocv1ac.ClusterExtensionRevisionApplyConfigurat
Name: *rev.GetName(),
APIGroup: ocv1.GroupVersion.Group,
APIVersion: ocv1.GroupVersion.Version,
- Resource: "clusterextensionrevisions/finalizers",
+ Resource: "objectsets/finalizers",
ResourceRequest: true,
Verb: "update",
},
diff --git a/internal/operator-controller/applier/boxcutter_test.go b/internal/operator-controller/applier/boxcutter_test.go
index 4f84612509..79606d88f1 100644
--- a/internal/operator-controller/applier/boxcutter_test.go
+++ b/internal/operator-controller/applier/boxcutter_test.go
@@ -98,7 +98,7 @@ func Test_SimpleRevisionGenerator_GenerateRevisionFromHelmRelease(t *testing.T)
rev, err := g.GenerateRevisionFromHelmRelease(t.Context(), helmRelease, ext, objectLabels)
require.NoError(t, err)
- expected := ocv1ac.ClusterExtensionRevision("test-123-1").
+ expected := ocv1ac.ObjectSet("test-123-1").
WithAnnotations(map[string]string{
"olm.operatorframework.io/bundle-name": "my-bundle",
"olm.operatorframework.io/bundle-reference": "bundle-ref",
@@ -111,15 +111,15 @@ func Test_SimpleRevisionGenerator_GenerateRevisionFromHelmRelease(t *testing.T)
labels.OwnerKindKey: ocv1.ClusterExtensionKind,
labels.OwnerNameKey: "test-123",
}).
- WithSpec(ocv1ac.ClusterExtensionRevisionSpec().
- WithLifecycleState(ocv1.ClusterExtensionRevisionLifecycleStateActive).
+ WithSpec(ocv1ac.ObjectSetSpec().
+ WithLifecycleState(ocv1.ObjectSetLifecycleStateActive).
WithCollisionProtection(ocv1.CollisionProtectionNone).
WithRevision(1).
WithPhases(
- ocv1ac.ClusterExtensionRevisionPhase().
+ ocv1ac.ObjectSetPhase().
WithName("configuration").
WithObjects(
- ocv1ac.ClusterExtensionRevisionObject().
+ ocv1ac.ObjectSetObject().
WithObject(unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
@@ -131,7 +131,7 @@ func Test_SimpleRevisionGenerator_GenerateRevisionFromHelmRelease(t *testing.T)
},
},
}),
- ocv1ac.ClusterExtensionRevisionObject().
+ ocv1ac.ObjectSetObject().
WithObject(unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
@@ -212,11 +212,11 @@ func Test_SimpleRevisionGenerator_GenerateRevision(t *testing.T) {
t.Log("by checking the spec-level collisionProtection is set")
require.Equal(t, ptr.To(ocv1.CollisionProtectionPrevent), rev.Spec.CollisionProtection)
t.Log("by checking the rendered objects are present in the correct phases")
- require.Equal(t, []ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
- *ocv1ac.ClusterExtensionRevisionPhase().
+ require.Equal(t, []ocv1ac.ObjectSetPhaseApplyConfiguration{
+ *ocv1ac.ObjectSetPhase().
WithName(string(applier.PhaseInfrastructure)).
WithObjects(
- ocv1ac.ClusterExtensionRevisionObject().
+ ocv1ac.ObjectSetObject().
WithObject(unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
@@ -228,10 +228,10 @@ func Test_SimpleRevisionGenerator_GenerateRevision(t *testing.T) {
},
}),
),
- *ocv1ac.ClusterExtensionRevisionPhase().
+ *ocv1ac.ObjectSetPhase().
WithName(string(applier.PhaseDeploy)).
WithObjects(
- ocv1ac.ClusterExtensionRevisionObject().
+ ocv1ac.ObjectSetObject().
WithObject(unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
@@ -516,7 +516,7 @@ func TestBoxcutter_Apply(t *testing.T) {
UID: "test-uid",
},
}
- defaultDesiredRevision := &ocv1.ClusterExtensionRevision{
+ defaultDesiredRevision := &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-ext-1",
UID: "rev-uid-1",
@@ -524,12 +524,12 @@ func TestBoxcutter_Apply(t *testing.T) {
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
+ Spec: ocv1.ObjectSetSpec{
Revision: 1,
- Phases: []ocv1.ClusterExtensionRevisionPhase{
+ Phases: []ocv1.ObjectSetPhase{
{
Name: string(applier.PhaseDeploy),
- Objects: []ocv1.ClusterExtensionRevisionObject{
+ Objects: []ocv1.ObjectSetObject{
{
Object: unstructured.Unstructured{
Object: map[string]interface{}{
@@ -550,12 +550,12 @@ func TestBoxcutter_Apply(t *testing.T) {
allowedRevisionValue := func(revNum int64) *interceptor.Funcs {
return &interceptor.Funcs{
Apply: func(ctx context.Context, client client.WithWatch, obj runtime.ApplyConfiguration, opts ...client.ApplyOption) error {
- cer, ok := obj.(*ocv1ac.ClusterExtensionRevisionApplyConfiguration)
+ cer, ok := obj.(*ocv1ac.ObjectSetApplyConfiguration)
if !ok {
- return fmt.Errorf("expected ClusterExtensionRevisionApplyConfiguration, got %T", obj)
+ return fmt.Errorf("expected ObjectSetApplyConfiguration, got %T", obj)
}
if cer.Spec == nil || cer.Spec.Revision == nil || *cer.Spec.Revision != revNum {
- gk := ocv1.SchemeGroupVersion.WithKind("ClusterExtensionRevision").GroupKind()
+ gk := ocv1.SchemeGroupVersion.WithKind("ObjectSet").GroupKind()
name := ""
if n := cer.GetName(); n != nil {
name = *n
@@ -568,7 +568,7 @@ func TestBoxcutter_Apply(t *testing.T) {
}
testCases := []struct {
name string
- mockBuilder applier.ClusterExtensionRevisionGenerator
+ mockBuilder applier.ObjectSetGenerator
existingObjs []client.Object
expectedErr string
validate func(t *testing.T, c client.Client)
@@ -577,18 +577,18 @@ func TestBoxcutter_Apply(t *testing.T) {
{
name: "first revision",
mockBuilder: &mockBundleRevisionBuilder{
- makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
- return ocv1ac.ClusterExtensionRevision("").
+ makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error) {
+ return ocv1ac.ObjectSet("").
WithAnnotations(revisionAnnotations).
WithLabels(map[string]string{
labels.OwnerNameKey: ext.Name,
}).
- WithSpec(ocv1ac.ClusterExtensionRevisionSpec().
+ WithSpec(ocv1ac.ObjectSetSpec().
WithPhases(
- ocv1ac.ClusterExtensionRevisionPhase().
+ ocv1ac.ObjectSetPhase().
WithName(string(applier.PhaseDeploy)).
WithObjects(
- ocv1ac.ClusterExtensionRevisionObject().
+ ocv1ac.ObjectSetObject().
WithObject(unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
@@ -604,7 +604,7 @@ func TestBoxcutter_Apply(t *testing.T) {
},
},
validate: func(t *testing.T, c client.Client) {
- revList := &ocv1.ClusterExtensionRevisionList{}
+ revList := &ocv1.ObjectSetList{}
err := c.List(t.Context(), revList, client.MatchingLabels{labels.OwnerNameKey: ext.Name})
require.NoError(t, err)
require.Len(t, revList.Items, 1)
@@ -620,18 +620,18 @@ func TestBoxcutter_Apply(t *testing.T) {
{
name: "no change, revision exists",
mockBuilder: &mockBundleRevisionBuilder{
- makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
- return ocv1ac.ClusterExtensionRevision("").
+ makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error) {
+ return ocv1ac.ObjectSet("").
WithAnnotations(revisionAnnotations).
WithLabels(map[string]string{
labels.OwnerNameKey: ext.Name,
}).
- WithSpec(ocv1ac.ClusterExtensionRevisionSpec().
+ WithSpec(ocv1ac.ObjectSetSpec().
WithPhases(
- ocv1ac.ClusterExtensionRevisionPhase().
+ ocv1ac.ObjectSetPhase().
WithName(string(applier.PhaseDeploy)).
WithObjects(
- ocv1ac.ClusterExtensionRevisionObject().
+ ocv1ac.ObjectSetObject().
WithObject(unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
@@ -650,7 +650,7 @@ func TestBoxcutter_Apply(t *testing.T) {
defaultDesiredRevision,
},
validate: func(t *testing.T, c client.Client) {
- revList := &ocv1.ClusterExtensionRevisionList{}
+ revList := &ocv1.ObjectSetList{}
err := c.List(context.Background(), revList, client.MatchingLabels{labels.OwnerNameKey: ext.Name})
require.NoError(t, err)
// No new revision should be created
@@ -661,18 +661,18 @@ func TestBoxcutter_Apply(t *testing.T) {
{
name: "new revision created when objects in new revision are different",
mockBuilder: &mockBundleRevisionBuilder{
- makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
- return ocv1ac.ClusterExtensionRevision("").
+ makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error) {
+ return ocv1ac.ObjectSet("").
WithAnnotations(revisionAnnotations).
WithLabels(map[string]string{
labels.OwnerNameKey: ext.Name,
}).
- WithSpec(ocv1ac.ClusterExtensionRevisionSpec().
+ WithSpec(ocv1ac.ObjectSetSpec().
WithPhases(
- ocv1ac.ClusterExtensionRevisionPhase().
+ ocv1ac.ObjectSetPhase().
WithName(string(applier.PhaseDeploy)).
WithObjects(
- ocv1ac.ClusterExtensionRevisionObject().
+ ocv1ac.ObjectSetObject().
WithObject(unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
@@ -692,13 +692,13 @@ func TestBoxcutter_Apply(t *testing.T) {
defaultDesiredRevision,
},
validate: func(t *testing.T, c client.Client) {
- revList := &ocv1.ClusterExtensionRevisionList{}
+ revList := &ocv1.ObjectSetList{}
err := c.List(context.Background(), revList, client.MatchingLabels{labels.OwnerNameKey: ext.Name})
require.NoError(t, err)
require.Len(t, revList.Items, 2)
// Find the new revision (rev 2)
- var newRev ocv1.ClusterExtensionRevision
+ var newRev ocv1.ObjectSet
for _, r := range revList.Items {
if r.Spec.Revision == 2 {
newRev = r
@@ -714,14 +714,14 @@ func TestBoxcutter_Apply(t *testing.T) {
{
name: "error from GenerateRevision",
mockBuilder: &mockBundleRevisionBuilder{
- makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
+ makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error) {
return nil, errors.New("render boom")
},
},
expectedErr: "render boom",
validate: func(t *testing.T, c client.Client) {
// Ensure no revisions were created
- revList := &ocv1.ClusterExtensionRevisionList{}
+ revList := &ocv1.ObjectSetList{}
err := c.List(context.Background(), revList, client.MatchingLabels{labels.OwnerNameKey: ext.Name})
require.NoError(t, err)
assert.Empty(t, revList.Items)
@@ -730,217 +730,217 @@ func TestBoxcutter_Apply(t *testing.T) {
{
name: "keep at most 5 past revisions",
mockBuilder: &mockBundleRevisionBuilder{
- makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
- return ocv1ac.ClusterExtensionRevision("").
+ makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error) {
+ return ocv1ac.ObjectSet("").
WithAnnotations(revisionAnnotations).
WithLabels(map[string]string{
labels.OwnerNameKey: ext.Name,
}).
- WithSpec(ocv1ac.ClusterExtensionRevisionSpec()), nil
+ WithSpec(ocv1ac.ObjectSetSpec()), nil
},
},
existingObjs: []client.Object{
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-1",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateArchived,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateArchived,
Revision: 1,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-2",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateArchived,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateArchived,
Revision: 2,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-3",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateArchived,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateArchived,
Revision: 3,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-4",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateArchived,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateArchived,
Revision: 4,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-5",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateArchived,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateArchived,
Revision: 5,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-6",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateArchived,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateArchived,
Revision: 6,
},
},
},
clientIterceptor: allowedRevisionValue(7),
validate: func(t *testing.T, c client.Client) {
- rev1 := &ocv1.ClusterExtensionRevision{}
+ rev1 := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{Name: "rev-1"}, rev1)
require.Error(t, err)
assert.True(t, apierrors.IsNotFound(err))
// Verify garbage collection: should only keep the limit + 1 (current) revisions
- revList := &ocv1.ClusterExtensionRevisionList{}
+ revList := &ocv1.ObjectSetList{}
err = c.List(t.Context(), revList)
require.NoError(t, err)
- // Should have ClusterExtensionRevisionRetentionLimit (5) + current (1) = 6 revisions max
- assert.LessOrEqual(t, len(revList.Items), applier.ClusterExtensionRevisionRetentionLimit+1)
+ // Should have ObjectSetRetentionLimit (5) + current (1) = 6 revisions max
+ assert.LessOrEqual(t, len(revList.Items), applier.ObjectSetRetentionLimit+1)
},
},
{
name: "keep active revisions when they are out of limit",
mockBuilder: &mockBundleRevisionBuilder{
- makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
- return ocv1ac.ClusterExtensionRevision("").
+ makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error) {
+ return ocv1ac.ObjectSet("").
WithAnnotations(revisionAnnotations).
WithLabels(map[string]string{
labels.OwnerNameKey: ext.Name,
}).
- WithSpec(ocv1ac.ClusterExtensionRevisionSpec()), nil
+ WithSpec(ocv1ac.ObjectSetSpec()), nil
},
},
existingObjs: []client.Object{
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-1",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateArchived,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateArchived,
Revision: 1,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-2",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
+ Spec: ocv1.ObjectSetSpec{
// index beyond the retention limit but active; should be preserved
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateActive,
+ LifecycleState: ocv1.ObjectSetLifecycleStateActive,
Revision: 2,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-3",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateActive,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateActive,
Revision: 3,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-4",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
+ Spec: ocv1.ObjectSetSpec{
// archived but should be preserved since it is within the limit
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateArchived,
+ LifecycleState: ocv1.ObjectSetLifecycleStateArchived,
Revision: 4,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-5",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateActive,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateActive,
Revision: 5,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-6",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateActive,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateActive,
Revision: 6,
},
},
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "rev-7",
Labels: map[string]string{
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateActive,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateActive,
Revision: 7,
},
},
},
clientIterceptor: allowedRevisionValue(8),
validate: func(t *testing.T, c client.Client) {
- rev1 := &ocv1.ClusterExtensionRevision{}
+ rev1 := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{Name: "rev-1"}, rev1)
require.Error(t, err)
assert.True(t, apierrors.IsNotFound(err))
- rev2 := &ocv1.ClusterExtensionRevision{}
+ rev2 := &ocv1.ObjectSet{}
err = c.Get(t.Context(), client.ObjectKey{Name: "rev-2"}, rev2)
require.NoError(t, err)
// Verify active revisions are kept even if beyond the limit
- rev4 := &ocv1.ClusterExtensionRevision{}
+ rev4 := &ocv1.ObjectSet{}
err = c.Get(t.Context(), client.ObjectKey{Name: "rev-4"}, rev4)
require.NoError(t, err, "active revision 4 should still exist even though it's beyond the limit")
},
@@ -948,18 +948,18 @@ func TestBoxcutter_Apply(t *testing.T) {
{
name: "annotation-only update (same phases, different annotations)",
mockBuilder: &mockBundleRevisionBuilder{
- makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
- return ocv1ac.ClusterExtensionRevision("").
+ makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error) {
+ return ocv1ac.ObjectSet("").
WithAnnotations(revisionAnnotations).
WithLabels(map[string]string{
labels.OwnerNameKey: ext.Name,
}).
- WithSpec(ocv1ac.ClusterExtensionRevisionSpec().
+ WithSpec(ocv1ac.ObjectSetSpec().
WithPhases(
- ocv1ac.ClusterExtensionRevisionPhase().
+ ocv1ac.ObjectSetPhase().
WithName(string(applier.PhaseDeploy)).
WithObjects(
- ocv1ac.ClusterExtensionRevisionObject().
+ ocv1ac.ObjectSetObject().
WithObject(unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
@@ -976,7 +976,7 @@ func TestBoxcutter_Apply(t *testing.T) {
},
existingObjs: []client.Object{
ext,
- &ocv1.ClusterExtensionRevision{
+ &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-ext-1",
Annotations: map[string]string{
@@ -987,12 +987,12 @@ func TestBoxcutter_Apply(t *testing.T) {
labels.OwnerNameKey: ext.Name,
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
+ Spec: ocv1.ObjectSetSpec{
Revision: 1,
- Phases: []ocv1.ClusterExtensionRevisionPhase{
+ Phases: []ocv1.ObjectSetPhase{
{
Name: string(applier.PhaseDeploy),
- Objects: []ocv1.ClusterExtensionRevisionObject{
+ Objects: []ocv1.ObjectSetObject{
{
Object: unstructured.Unstructured{
Object: map[string]interface{}{
@@ -1011,7 +1011,7 @@ func TestBoxcutter_Apply(t *testing.T) {
},
},
validate: func(t *testing.T, c client.Client) {
- revList := &ocv1.ClusterExtensionRevisionList{}
+ revList := &ocv1.ObjectSetList{}
err := c.List(context.Background(), revList, client.MatchingLabels{labels.OwnerNameKey: ext.Name})
require.NoError(t, err)
// Should still be only 1 revision (in-place update, not new revision)
@@ -1103,14 +1103,14 @@ func Test_PreAuthorizer_Integration(t *testing.T) {
}
fakeClient := fake.NewClientBuilder().WithScheme(testScheme).Build()
dummyGenerator := &mockBundleRevisionBuilder{
- makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotation map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
- return ocv1ac.ClusterExtensionRevision("").
- WithSpec(ocv1ac.ClusterExtensionRevisionSpec().
+ makeRevisionFunc: func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotation map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error) {
+ return ocv1ac.ObjectSet("").
+ WithSpec(ocv1ac.ObjectSetSpec().
WithPhases(
- ocv1ac.ClusterExtensionRevisionPhase().
+ ocv1ac.ObjectSetPhase().
WithName("some-phase").
WithObjects(
- ocv1ac.ClusterExtensionRevisionObject().
+ ocv1ac.ObjectSetObject().
WithObject(unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
@@ -1153,7 +1153,7 @@ func Test_PreAuthorizer_Integration(t *testing.T) {
Name: "test-ext-1",
APIGroup: "olm.operatorframework.io",
APIVersion: "v1",
- Resource: "clusterextensionrevisions/finalizers",
+ Resource: "objectsets/finalizers",
ResourceRequest: true,
Verb: "update",
}, perms[0])
@@ -1293,23 +1293,23 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
}
client.
- On("List", mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevisionList"), mock.Anything).
+ On("List", mock.Anything, mock.AnythingOfType("*v1.ObjectSetList"), mock.Anything).
Return(nil)
client.
- On("Apply", mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevisionApplyConfiguration"), mock.Anything).
+ On("Apply", mock.Anything, mock.AnythingOfType("*v1.ObjectSetApplyConfiguration"), mock.Anything).
Once().
Run(func(args mock.Arguments) {
// Verify the migration marker label is set before apply
- rev := args.Get(1).(*ocv1ac.ClusterExtensionRevisionApplyConfiguration)
+ rev := args.Get(1).(*ocv1ac.ObjectSetApplyConfiguration)
require.Equal(t, "true", rev.Labels[labels.MigratedFromHelmKey], "Migration marker label should be set")
}).
Return(nil)
client.
- On("Get", mock.Anything, mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevision"), mock.Anything).
+ On("Get", mock.Anything, mock.Anything, mock.AnythingOfType("*v1.ObjectSet"), mock.Anything).
Once().
Run(func(args mock.Arguments) {
// Simulate Get() returning the created revision with server-managed fields
- rev := args.Get(2).(*ocv1.ClusterExtensionRevision)
+ rev := args.Get(2).(*ocv1.ObjectSet)
rev.Name = "test-revision"
rev.Generation = 1
rev.ResourceVersion = "1"
@@ -1329,10 +1329,10 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
require.True(t, statusWriter.updateCalled, "Status().Update() should be called during migration")
require.NotNil(t, statusWriter.updatedObj, "Updated object should not be nil")
- rev, ok := statusWriter.updatedObj.(*ocv1.ClusterExtensionRevision)
- require.True(t, ok, "Updated object should be a ClusterExtensionRevision")
+ rev, ok := statusWriter.updatedObj.(*ocv1.ObjectSet)
+ require.True(t, ok, "Updated object should be a ObjectSet")
- succeededCond := apimeta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeSucceeded)
+ succeededCond := apimeta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeSucceeded)
require.NotNil(t, succeededCond, "Succeeded condition should be set")
assert.Equal(t, metav1.ConditionTrue, succeededCond.Status, "Succeeded condition should be True")
assert.Equal(t, ocv1.ReasonSucceeded, succeededCond.Reason, "Reason should be Succeeded")
@@ -1359,7 +1359,7 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
}
- existingRev := ocv1.ClusterExtensionRevision{
+ existingRev := ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-revision",
Generation: 2,
@@ -1367,13 +1367,13 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
labels.MigratedFromHelmKey: "true",
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
+ Spec: ocv1.ObjectSetSpec{
Revision: 1, // Migration creates revision 1
},
- Status: ocv1.ClusterExtensionRevisionStatus{
+ Status: ocv1.ObjectSetStatus{
Conditions: []metav1.Condition{
{
- Type: ocv1.ClusterExtensionRevisionTypeSucceeded,
+ Type: ocv1.ObjectSetTypeSucceeded,
Status: metav1.ConditionTrue,
Reason: ocv1.ReasonSucceeded,
},
@@ -1382,10 +1382,10 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
}
client.
- On("List", mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevisionList"), mock.Anything).
+ On("List", mock.Anything, mock.AnythingOfType("*v1.ObjectSetList"), mock.Anything).
Run(func(args mock.Arguments) {
- list := args.Get(1).(*ocv1.ClusterExtensionRevisionList)
- list.Items = []ocv1.ClusterExtensionRevision{existingRev}
+ list := args.Get(1).(*ocv1.ObjectSetList)
+ list.Items = []ocv1.ObjectSet{existingRev}
}).
Return(nil)
@@ -1414,7 +1414,7 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
}
- existingRev := ocv1.ClusterExtensionRevision{
+ existingRev := ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-revision",
Generation: 2,
@@ -1422,24 +1422,24 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
labels.MigratedFromHelmKey: "true",
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
+ Spec: ocv1.ObjectSetSpec{
Revision: 1, // Migration creates revision 1
},
// Status is empty - simulating the case where creation succeeded but status update failed
}
client.
- On("List", mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevisionList"), mock.Anything).
+ On("List", mock.Anything, mock.AnythingOfType("*v1.ObjectSetList"), mock.Anything).
Run(func(args mock.Arguments) {
- list := args.Get(1).(*ocv1.ClusterExtensionRevisionList)
- list.Items = []ocv1.ClusterExtensionRevision{existingRev}
+ list := args.Get(1).(*ocv1.ObjectSetList)
+ list.Items = []ocv1.ObjectSet{existingRev}
}).
Return(nil)
client.
- On("Get", mock.Anything, mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevision"), mock.Anything).
+ On("Get", mock.Anything, mock.Anything, mock.AnythingOfType("*v1.ObjectSet"), mock.Anything).
Run(func(args mock.Arguments) {
- rev := args.Get(2).(*ocv1.ClusterExtensionRevision)
+ rev := args.Get(2).(*ocv1.ObjectSet)
*rev = existingRev
}).
Return(nil)
@@ -1454,10 +1454,10 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
require.True(t, statusWriter.updateCalled, "Status().Update() should be called to set missing status")
require.NotNil(t, statusWriter.updatedObj, "Updated object should not be nil")
- rev, ok := statusWriter.updatedObj.(*ocv1.ClusterExtensionRevision)
- require.True(t, ok, "Updated object should be a ClusterExtensionRevision")
+ rev, ok := statusWriter.updatedObj.(*ocv1.ObjectSet)
+ require.True(t, ok, "Updated object should be a ObjectSet")
- succeededCond := apimeta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeSucceeded)
+ succeededCond := apimeta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeSucceeded)
require.NotNil(t, succeededCond, "Succeeded condition should be set")
assert.Equal(t, metav1.ConditionTrue, succeededCond.Status, "Succeeded condition should be True")
assert.Equal(t, ocv1.ReasonSucceeded, succeededCond.Reason, "Reason should be Succeeded")
@@ -1484,7 +1484,7 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
// Migrated revision with Succeeded=False (e.g., from a previous failed status update attempt)
// This simulates a revision whose Succeeded condition should be corrected from False to True during migration.
- existingRev := ocv1.ClusterExtensionRevision{
+ existingRev := ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-revision",
Generation: 2,
@@ -1492,13 +1492,13 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
labels.MigratedFromHelmKey: "true",
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
+ Spec: ocv1.ObjectSetSpec{
Revision: 1,
},
- Status: ocv1.ClusterExtensionRevisionStatus{
+ Status: ocv1.ObjectSetStatus{
Conditions: []metav1.Condition{
{
- Type: ocv1.ClusterExtensionRevisionTypeSucceeded,
+ Type: ocv1.ObjectSetTypeSucceeded,
Status: metav1.ConditionFalse, // Important: False, not missing
Reason: "InProgress",
},
@@ -1507,17 +1507,17 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
}
client.
- On("List", mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevisionList"), mock.Anything).
+ On("List", mock.Anything, mock.AnythingOfType("*v1.ObjectSetList"), mock.Anything).
Run(func(args mock.Arguments) {
- list := args.Get(1).(*ocv1.ClusterExtensionRevisionList)
- list.Items = []ocv1.ClusterExtensionRevision{existingRev}
+ list := args.Get(1).(*ocv1.ObjectSetList)
+ list.Items = []ocv1.ObjectSet{existingRev}
}).
Return(nil)
client.
- On("Get", mock.Anything, mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevision"), mock.Anything).
+ On("Get", mock.Anything, mock.Anything, mock.AnythingOfType("*v1.ObjectSet"), mock.Anything).
Run(func(args mock.Arguments) {
- rev := args.Get(2).(*ocv1.ClusterExtensionRevision)
+ rev := args.Get(2).(*ocv1.ObjectSet)
*rev = existingRev
}).
Return(nil)
@@ -1532,10 +1532,10 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
require.True(t, statusWriter.updateCalled, "Status().Update() should be called to update False to True")
require.NotNil(t, statusWriter.updatedObj, "Updated object should not be nil")
- rev, ok := statusWriter.updatedObj.(*ocv1.ClusterExtensionRevision)
- require.True(t, ok, "Updated object should be a ClusterExtensionRevision")
+ rev, ok := statusWriter.updatedObj.(*ocv1.ObjectSet)
+ require.True(t, ok, "Updated object should be a ObjectSet")
- succeededCond := apimeta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeSucceeded)
+ succeededCond := apimeta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeSucceeded)
require.NotNil(t, succeededCond, "Succeeded condition should be set")
assert.Equal(t, metav1.ConditionTrue, succeededCond.Status, "Succeeded condition should be updated to True")
assert.Equal(t, ocv1.ReasonSucceeded, succeededCond.Reason, "Reason should be Succeeded")
@@ -1562,31 +1562,31 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
// Revision 1 created by normal Boxcutter operation (no migration label)
// This simulates the first rollout - status should NOT be set as it may still be in progress
- existingRev := ocv1.ClusterExtensionRevision{
+ existingRev := ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-revision",
Generation: 2,
// No migration label - this is a normal Boxcutter revision
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
+ Spec: ocv1.ObjectSetSpec{
Revision: 1,
},
}
client.
- On("List", mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevisionList"), mock.Anything).
+ On("List", mock.Anything, mock.AnythingOfType("*v1.ObjectSetList"), mock.Anything).
Run(func(args mock.Arguments) {
- list := args.Get(1).(*ocv1.ClusterExtensionRevisionList)
- list.Items = []ocv1.ClusterExtensionRevision{existingRev}
+ list := args.Get(1).(*ocv1.ObjectSetList)
+ list.Items = []ocv1.ObjectSet{existingRev}
}).
Return(nil)
// The migration flow calls Get() to re-fetch the revision before checking its status.
// Even for non-migrated revisions, Get() is called to determine if status needs to be set.
client.
- On("Get", mock.Anything, mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevision"), mock.Anything).
+ On("Get", mock.Anything, mock.Anything, mock.AnythingOfType("*v1.ObjectSet"), mock.Anything).
Run(func(args mock.Arguments) {
- rev := args.Get(2).(*ocv1.ClusterExtensionRevision)
+ rev := args.Get(2).(*ocv1.ObjectSet)
*rev = existingRev
}).
Return(nil)
@@ -1644,23 +1644,23 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
}
client.
- On("List", mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevisionList"), mock.Anything).
+ On("List", mock.Anything, mock.AnythingOfType("*v1.ObjectSetList"), mock.Anything).
Return(nil)
client.
- On("Apply", mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevisionApplyConfiguration"), mock.Anything).
+ On("Apply", mock.Anything, mock.AnythingOfType("*v1.ObjectSetApplyConfiguration"), mock.Anything).
Once().
Run(func(args mock.Arguments) {
// Verify the migration marker label is set before apply
- rev := args.Get(1).(*ocv1ac.ClusterExtensionRevisionApplyConfiguration)
+ rev := args.Get(1).(*ocv1ac.ObjectSetApplyConfiguration)
require.Equal(t, "true", rev.Labels[labels.MigratedFromHelmKey], "Migration marker label should be set")
}).
Return(nil)
client.
- On("Get", mock.Anything, mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevision"), mock.Anything).
+ On("Get", mock.Anything, mock.Anything, mock.AnythingOfType("*v1.ObjectSet"), mock.Anything).
Run(func(args mock.Arguments) {
- rev := args.Get(2).(*ocv1.ClusterExtensionRevision)
+ rev := args.Get(2).(*ocv1.ObjectSet)
rev.ObjectMeta.Name = "test-revision"
rev.ObjectMeta.Generation = 1
rev.ObjectMeta.ResourceVersion = "1"
@@ -1685,10 +1685,10 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
require.True(t, statusWriter.updateCalled, "Status().Update() should be called during migration")
require.NotNil(t, statusWriter.updatedObj, "Updated object should not be nil")
- rev, ok := statusWriter.updatedObj.(*ocv1.ClusterExtensionRevision)
- require.True(t, ok, "Updated object should be a ClusterExtensionRevision")
+ rev, ok := statusWriter.updatedObj.(*ocv1.ObjectSet)
+ require.True(t, ok, "Updated object should be a ObjectSet")
- succeededCond := apimeta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeSucceeded)
+ succeededCond := apimeta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeSucceeded)
require.NotNil(t, succeededCond, "Succeeded condition should be set")
assert.Equal(t, metav1.ConditionTrue, succeededCond.Status, "Succeeded condition should be True")
})
@@ -1730,7 +1730,7 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
}
client.
- On("List", mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevisionList"), mock.Anything).
+ On("List", mock.Anything, mock.AnythingOfType("*v1.ObjectSetList"), mock.Anything).
Return(nil)
err := sm.Migrate(t.Context(), ext, map[string]string{"my-label": "my-value"})
@@ -1763,7 +1763,7 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
}
client.
- On("List", mock.Anything, mock.AnythingOfType("*v1.ClusterExtensionRevisionList"), mock.Anything).
+ On("List", mock.Anything, mock.AnythingOfType("*v1.ObjectSetList"), mock.Anything).
Return(nil)
err := sm.Migrate(t.Context(), ext, map[string]string{"my-label": "my-value"})
@@ -1773,14 +1773,14 @@ func TestBoxcutterStorageMigrator(t *testing.T) {
})
}
-// mockBundleRevisionBuilder is a mock implementation of the ClusterExtensionRevisionGenerator for testing.
+// mockBundleRevisionBuilder is a mock implementation of the ObjectSetGenerator for testing.
type mockBundleRevisionBuilder struct {
- makeRevisionFunc func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotation map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error)
+ makeRevisionFunc func(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotation map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error)
generateRevisionFromHelmReleaseCalled bool
helmReleaseUsed *release.Release
}
-func (m *mockBundleRevisionBuilder) GenerateRevision(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
+func (m *mockBundleRevisionBuilder) GenerateRevision(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1ac.ObjectSetApplyConfiguration, error) {
return m.makeRevisionFunc(ctx, bundleFS, ext, objectLabels, revisionAnnotations)
}
@@ -1788,14 +1788,14 @@ func (m *mockBundleRevisionBuilder) GenerateRevisionFromHelmRelease(
ctx context.Context,
helmRelease *release.Release, ext *ocv1.ClusterExtension,
objectLabels map[string]string,
-) (*ocv1ac.ClusterExtensionRevisionApplyConfiguration, error) {
+) (*ocv1ac.ObjectSetApplyConfiguration, error) {
m.generateRevisionFromHelmReleaseCalled = true
m.helmReleaseUsed = helmRelease
- return ocv1ac.ClusterExtensionRevision("test-revision").
+ return ocv1ac.ObjectSet("test-revision").
WithLabels(map[string]string{
labels.OwnerNameKey: ext.Name,
}).
- WithSpec(ocv1ac.ClusterExtensionRevisionSpec()), nil
+ WithSpec(ocv1ac.ObjectSetSpec()), nil
}
type clientMock struct {
diff --git a/internal/operator-controller/applier/phase.go b/internal/operator-controller/applier/phase.go
index 7a495ee5aa..c4a884136b 100644
--- a/internal/operator-controller/applier/phase.go
+++ b/internal/operator-controller/applier/phase.go
@@ -163,7 +163,7 @@ func init() {
// to ensure consistent ordering regardless of input order. This is critical for
// Helm-to-Boxcutter migration where the same resources may come from different sources
// (Helm release manifest vs bundle manifest) and need to produce identical phases.
-func compareClusterExtensionRevisionObjectApplyConfigurations(a, b ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration) int {
+func compareObjectSetObjectApplyConfigurations(a, b ocv1ac.ObjectSetObjectApplyConfiguration) int {
aGVK := a.Object.GroupVersionKind()
bGVK := b.Object.GroupVersionKind()
@@ -179,9 +179,9 @@ func compareClusterExtensionRevisionObjectApplyConfigurations(a, b ocv1ac.Cluste
// PhaseSort takes an unsorted list of objects and organizes them into sorted phases.
// Each phase will be applied in order according to DefaultPhaseOrder. Objects
// within a single phase are applied simultaneously.
-func PhaseSort(unsortedObjs []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration) []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration {
- phasesSorted := make([]*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration, 0)
- phaseMap := make(map[Phase][]ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration)
+func PhaseSort(unsortedObjs []ocv1ac.ObjectSetObjectApplyConfiguration) []*ocv1ac.ObjectSetPhaseApplyConfiguration {
+ phasesSorted := make([]*ocv1ac.ObjectSetPhaseApplyConfiguration, 0)
+ phaseMap := make(map[Phase][]ocv1ac.ObjectSetObjectApplyConfiguration)
for _, obj := range unsortedObjs {
phase := determinePhase(obj.Object.GroupVersionKind().GroupKind())
@@ -191,14 +191,14 @@ func PhaseSort(unsortedObjs []ocv1ac.ClusterExtensionRevisionObjectApplyConfigur
for _, phaseName := range defaultPhaseOrder {
if objs, ok := phaseMap[phaseName]; ok {
// Sort objects within the phase deterministically
- slices.SortFunc(objs, compareClusterExtensionRevisionObjectApplyConfigurations)
+ slices.SortFunc(objs, compareObjectSetObjectApplyConfigurations)
// Convert to pointers for WithObjects
- objPtrs := make([]*ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration, len(objs))
+ objPtrs := make([]*ocv1ac.ObjectSetObjectApplyConfiguration, len(objs))
for i := range objs {
objPtrs[i] = &objs[i]
}
- phasesSorted = append(phasesSorted, ocv1ac.ClusterExtensionRevisionPhase().
+ phasesSorted = append(phasesSorted, ocv1ac.ObjectSetPhase().
WithName(string(phaseName)).
WithObjects(objPtrs...))
}
diff --git a/internal/operator-controller/applier/phase_test.go b/internal/operator-controller/applier/phase_test.go
index 8a4554be0e..c7a250940d 100644
--- a/internal/operator-controller/applier/phase_test.go
+++ b/internal/operator-controller/applier/phase_test.go
@@ -19,12 +19,12 @@ import (
func Test_PhaseSort(t *testing.T) {
for _, tt := range []struct {
name string
- objs []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration
- want []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration
+ objs []ocv1ac.ObjectSetObjectApplyConfiguration
+ want []*ocv1ac.ObjectSetPhaseApplyConfiguration
}{
{
name: "single deploy obj",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -34,10 +34,10 @@ func Test_PhaseSort(t *testing.T) {
},
},
},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{
{
Name: ptr.To(string(applier.PhaseDeploy)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -52,7 +52,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
name: "all phases",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -182,10 +182,10 @@ func Test_PhaseSort(t *testing.T) {
},
},
},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{
{
Name: ptr.To(string(applier.PhaseNamespaces)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -198,7 +198,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhasePolicies)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -211,7 +211,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseIdentity)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -224,7 +224,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseConfiguration)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -237,7 +237,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseStorage)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -250,7 +250,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseCRDs)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -263,7 +263,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseRoles)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -284,7 +284,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseBindings)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -305,7 +305,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseInfrastructure)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -318,7 +318,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseDeploy)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -339,7 +339,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseScaling)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -352,7 +352,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhasePublish)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -365,7 +365,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseAdmission)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -380,7 +380,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
name: "sorted and batched",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -406,10 +406,10 @@ func Test_PhaseSort(t *testing.T) {
},
},
},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{
{
Name: ptr.To(string(applier.PhaseIdentity)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -422,7 +422,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseConfiguration)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -435,7 +435,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseDeploy)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -450,12 +450,12 @@ func Test_PhaseSort(t *testing.T) {
},
{
name: "no objects",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{},
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{},
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{},
},
{
name: "sort by group within same phase",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -479,10 +479,10 @@ func Test_PhaseSort(t *testing.T) {
},
},
},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{
{
Name: ptr.To(string(applier.PhaseDeploy)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -511,7 +511,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
name: "sort by version within same group and phase",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -535,10 +535,10 @@ func Test_PhaseSort(t *testing.T) {
},
},
},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{
{
Name: ptr.To(string(applier.PhaseDeploy)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -567,7 +567,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
name: "sort by kind within same group, version, and phase",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -591,10 +591,10 @@ func Test_PhaseSort(t *testing.T) {
},
},
},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{
{
Name: ptr.To(string(applier.PhaseConfiguration)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -623,7 +623,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
name: "sort by namespace within same GVK and phase",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -661,10 +661,10 @@ func Test_PhaseSort(t *testing.T) {
},
},
},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{
{
Name: ptr.To(string(applier.PhaseConfiguration)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -707,7 +707,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
name: "sort by name within same GVK, namespace, and phase",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -745,10 +745,10 @@ func Test_PhaseSort(t *testing.T) {
},
},
},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{
{
Name: ptr.To(string(applier.PhaseConfiguration)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -791,7 +791,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
name: "comprehensive sorting - all dimensions",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -865,10 +865,10 @@ func Test_PhaseSort(t *testing.T) {
},
},
},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{
{
Name: ptr.To(string(applier.PhaseConfiguration)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -921,7 +921,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
Name: ptr.To(string(applier.PhaseDeploy)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -952,7 +952,7 @@ func Test_PhaseSort(t *testing.T) {
},
{
name: "cluster-scoped vs namespaced resources - empty namespace sorts first",
- objs: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ objs: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
@@ -988,10 +988,10 @@ func Test_PhaseSort(t *testing.T) {
},
},
},
- want: []*ocv1ac.ClusterExtensionRevisionPhaseApplyConfiguration{
+ want: []*ocv1ac.ObjectSetPhaseApplyConfiguration{
{
Name: ptr.To(string(applier.PhaseRoles)),
- Objects: []ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration{
+ Objects: []ocv1ac.ObjectSetObjectApplyConfiguration{
{
Object: &unstructured.Unstructured{
Object: map[string]interface{}{
diff --git a/internal/operator-controller/controllers/boxcutter_reconcile_steps.go b/internal/operator-controller/controllers/boxcutter_reconcile_steps.go
index dfb5dad145..af5264ee30 100644
--- a/internal/operator-controller/controllers/boxcutter_reconcile_steps.go
+++ b/internal/operator-controller/controllers/boxcutter_reconcile_steps.go
@@ -42,19 +42,19 @@ func (d *BoxcutterRevisionStatesGetter) GetRevisionStates(ctx context.Context, e
// TODO: boxcutter applier has a nearly identical bit of code for listing and sorting revisions
// only difference here is that it sorts in reverse order to start iterating with the most
// recent revisions. We should consolidate to avoid code duplication.
- existingRevisionList := &ocv1.ClusterExtensionRevisionList{}
+ existingRevisionList := &ocv1.ObjectSetList{}
if err := d.Reader.List(ctx, existingRevisionList, client.MatchingLabels{
labels.OwnerNameKey: ext.Name,
}); err != nil {
return nil, fmt.Errorf("listing revisions: %w", err)
}
- slices.SortFunc(existingRevisionList.Items, func(a, b ocv1.ClusterExtensionRevision) int {
+ slices.SortFunc(existingRevisionList.Items, func(a, b ocv1.ObjectSet) int {
return cmp.Compare(a.Spec.Revision, b.Spec.Revision)
})
rs := &RevisionStates{}
for _, rev := range existingRevisionList.Items {
- if rev.Spec.LifecycleState == ocv1.ClusterExtensionRevisionLifecycleStateArchived {
+ if rev.Spec.LifecycleState == ocv1.ObjectSetLifecycleStateArchived {
continue
}
@@ -72,7 +72,7 @@ func (d *BoxcutterRevisionStatesGetter) GetRevisionStates(ctx context.Context, e
},
}
- if apimeta.IsStatusConditionTrue(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeSucceeded) {
+ if apimeta.IsStatusConditionTrue(rev.Status.Conditions, ocv1.ObjectSetTypeSucceeded) {
rs.Installed = rm
} else {
rs.RollingOut = append(rs.RollingOut, rm)
@@ -128,7 +128,7 @@ func ApplyBundleWithBoxcutter(apply func(ctx context.Context, contentFS fs.FS, e
ext.Status.ActiveRevisions = []ocv1.RevisionStatus{}
// Mirror Available/Progressing conditions from the installed revision
if i := state.revisionStates.Installed; i != nil {
- for _, cndType := range []string{ocv1.ClusterExtensionRevisionTypeAvailable, ocv1.ClusterExtensionRevisionTypeProgressing} {
+ for _, cndType := range []string{ocv1.ObjectSetTypeAvailable, ocv1.ObjectSetTypeProgressing} {
if cnd := apimeta.FindStatusCondition(i.Conditions, cndType); cnd != nil {
cnd.ObservedGeneration = ext.GetGeneration()
apimeta.SetStatusCondition(&ext.Status.Conditions, *cnd)
@@ -141,7 +141,7 @@ func ApplyBundleWithBoxcutter(apply func(ctx context.Context, contentFS fs.FS, e
}
for idx, r := range state.revisionStates.RollingOut {
rs := ocv1.RevisionStatus{Name: r.RevisionName}
- for _, cndType := range []string{ocv1.ClusterExtensionRevisionTypeAvailable, ocv1.ClusterExtensionRevisionTypeProgressing} {
+ for _, cndType := range []string{ocv1.ObjectSetTypeAvailable, ocv1.ObjectSetTypeProgressing} {
if cnd := apimeta.FindStatusCondition(r.Conditions, cndType); cnd != nil {
cnd.ObservedGeneration = ext.GetGeneration()
apimeta.SetStatusCondition(&rs.Conditions, *cnd)
@@ -149,7 +149,7 @@ func ApplyBundleWithBoxcutter(apply func(ctx context.Context, contentFS fs.FS, e
}
// Mirror Progressing condition from the latest active revision
if idx == len(state.revisionStates.RollingOut)-1 {
- if pcnd := apimeta.FindStatusCondition(r.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing); pcnd != nil {
+ if pcnd := apimeta.FindStatusCondition(r.Conditions, ocv1.ObjectSetTypeProgressing); pcnd != nil {
pcnd.ObservedGeneration = ext.GetGeneration()
apimeta.SetStatusCondition(&ext.Status.Conditions, *pcnd)
}
diff --git a/internal/operator-controller/controllers/clusterextension_reconcile_steps.go b/internal/operator-controller/controllers/clusterextension_reconcile_steps.go
index 14ad717853..c850e3c447 100644
--- a/internal/operator-controller/controllers/clusterextension_reconcile_steps.go
+++ b/internal/operator-controller/controllers/clusterextension_reconcile_steps.go
@@ -378,7 +378,7 @@ func UnpackBundle(i imageutil.Puller, cache imageutil.Cache) ReconcileStepFunc {
if bundleUnchanged {
// Bundle hasn't changed and Pull failed (likely cache miss + catalog unavailable).
// This happens in fallback mode after catalog deletion. Set imageFS to nil so the
- // applier can maintain the workload using existing Helm release or ClusterExtensionRevision.
+ // applier can maintain the workload using existing Helm release or ObjectSet.
l.V(1).Info("bundle content unavailable but version unchanged, maintaining current installation",
"bundle", state.resolvedRevisionMetadata.Name,
"version", state.resolvedRevisionMetadata.Version,
diff --git a/internal/operator-controller/controllers/common_controller.go b/internal/operator-controller/controllers/common_controller.go
index e1991e4d16..0f84c7d2ad 100644
--- a/internal/operator-controller/controllers/common_controller.go
+++ b/internal/operator-controller/controllers/common_controller.go
@@ -96,8 +96,8 @@ func determineFailureReason(rollingRevisions []*RevisionMetadata) string {
// Check if the LATEST rolling revision indicates an error (Retrying reason)
// Latest revision is the last element in the array (sorted ascending by Spec.Revision)
latestRevision := rollingRevisions[len(rollingRevisions)-1]
- progressingCond := apimeta.FindStatusCondition(latestRevision.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing)
- if progressingCond != nil && progressingCond.Reason == string(ocv1.ClusterExtensionRevisionReasonRetrying) {
+ progressingCond := apimeta.FindStatusCondition(latestRevision.Conditions, ocv1.ObjectSetTypeProgressing)
+ if progressingCond != nil && progressingCond.Reason == string(ocv1.ObjectSetReasonRetrying) {
// Retrying indicates an error occurred (config, apply, validation, etc.)
// Use Failed for semantic correctness: installation failed due to error
return ocv1.ReasonFailed
diff --git a/internal/operator-controller/controllers/common_controller_test.go b/internal/operator-controller/controllers/common_controller_test.go
index 2055a2b891..af641be8b1 100644
--- a/internal/operator-controller/controllers/common_controller_test.go
+++ b/internal/operator-controller/controllers/common_controller_test.go
@@ -325,9 +325,9 @@ func TestSetInstalledStatusFromRevisionStates_ConfigValidationError(t *testing.T
RevisionName: "rev-1",
Conditions: []metav1.Condition{
{
- Type: ocv1.ClusterExtensionRevisionTypeProgressing,
+ Type: ocv1.ObjectSetTypeProgressing,
Status: metav1.ConditionTrue,
- Reason: ocv1.ClusterExtensionRevisionReasonRetrying,
+ Reason: ocv1.ObjectSetReasonRetrying,
Message: "some error occurred",
},
},
@@ -349,7 +349,7 @@ func TestSetInstalledStatusFromRevisionStates_ConfigValidationError(t *testing.T
RevisionName: "rev-1",
Conditions: []metav1.Condition{
{
- Type: ocv1.ClusterExtensionRevisionTypeProgressing,
+ Type: ocv1.ObjectSetTypeProgressing,
Status: metav1.ConditionTrue,
Reason: ocv1.ReasonRollingOut,
Message: "Revision is rolling out",
@@ -360,9 +360,9 @@ func TestSetInstalledStatusFromRevisionStates_ConfigValidationError(t *testing.T
RevisionName: "rev-2",
Conditions: []metav1.Condition{
{
- Type: ocv1.ClusterExtensionRevisionTypeProgressing,
+ Type: ocv1.ObjectSetTypeProgressing,
Status: metav1.ConditionTrue,
- Reason: ocv1.ClusterExtensionRevisionReasonRetrying,
+ Reason: ocv1.ObjectSetReasonRetrying,
Message: "validation error occurred",
},
},
@@ -384,7 +384,7 @@ func TestSetInstalledStatusFromRevisionStates_ConfigValidationError(t *testing.T
RevisionName: "rev-1",
Conditions: []metav1.Condition{
{
- Type: ocv1.ClusterExtensionRevisionTypeProgressing,
+ Type: ocv1.ObjectSetTypeProgressing,
Status: metav1.ConditionTrue,
Reason: ocv1.ReasonRollingOut,
Message: "Revision is rolling out",
@@ -408,9 +408,9 @@ func TestSetInstalledStatusFromRevisionStates_ConfigValidationError(t *testing.T
RevisionName: "rev-1",
Conditions: []metav1.Condition{
{
- Type: ocv1.ClusterExtensionRevisionTypeProgressing,
+ Type: ocv1.ObjectSetTypeProgressing,
Status: metav1.ConditionTrue,
- Reason: ocv1.ClusterExtensionRevisionReasonRetrying,
+ Reason: ocv1.ObjectSetReasonRetrying,
Message: "old error that was superseded",
},
},
@@ -419,7 +419,7 @@ func TestSetInstalledStatusFromRevisionStates_ConfigValidationError(t *testing.T
RevisionName: "rev-2",
Conditions: []metav1.Condition{
{
- Type: ocv1.ClusterExtensionRevisionTypeProgressing,
+ Type: ocv1.ObjectSetTypeProgressing,
Status: metav1.ConditionTrue,
Reason: ocv1.ReasonRollingOut,
Message: "Latest revision is rolling out healthy",
diff --git a/internal/operator-controller/controllers/clusterextensionrevision_controller.go b/internal/operator-controller/controllers/objectset_controller.go
similarity index 80%
rename from internal/operator-controller/controllers/clusterextensionrevision_controller.go
rename to internal/operator-controller/controllers/objectset_controller.go
index 2e9d2fce65..a87cf5479b 100644
--- a/internal/operator-controller/controllers/clusterextensionrevision_controller.go
+++ b/internal/operator-controller/controllers/objectset_controller.go
@@ -41,12 +41,12 @@ import (
)
const (
- clusterExtensionRevisionTeardownFinalizer = "olm.operatorframework.io/teardown"
+ objectSetTeardownFinalizer = "olm.operatorframework.io/teardown"
)
-// ClusterExtensionRevisionReconciler actions individual snapshots of ClusterExtensions,
+// ObjectSetReconciler actions individual snapshots of ClusterExtensions,
// as part of the boxcutter integration.
-type ClusterExtensionRevisionReconciler struct {
+type ObjectSetReconciler struct {
Client client.Client
RevisionEngineFactory RevisionEngineFactory
TrackingCache trackingCache
@@ -60,15 +60,15 @@ type trackingCache interface {
Free(ctx context.Context, user client.Object) error
}
-//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clusterextensionrevisions,verbs=get;list;watch;update;patch;create;delete
-//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clusterextensionrevisions/status,verbs=update;patch
-//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=clusterextensionrevisions/finalizers,verbs=update
+//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=objectsets,verbs=get;list;watch;update;patch;create;delete
+//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=objectsets/status,verbs=update;patch
+//+kubebuilder:rbac:groups=olm.operatorframework.io,resources=objectsets/finalizers,verbs=update
-func (c *ClusterExtensionRevisionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
- l := log.FromContext(ctx).WithName("cluster-extension-revision")
+func (c *ObjectSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
+ l := log.FromContext(ctx).WithName("object-set")
ctx = log.IntoContext(ctx, l)
- existingRev := &ocv1.ClusterExtensionRevision{}
+ existingRev := &ocv1.ObjectSet{}
if err := c.Client.Get(ctx, req.NamespacedName, existingRev); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
@@ -80,9 +80,9 @@ func (c *ClusterExtensionRevisionReconciler) Reconcile(ctx context.Context, req
res, reconcileErr := c.reconcile(ctx, reconciledRev)
if pd := existingRev.Spec.ProgressDeadlineMinutes; pd > 0 {
- cnd := meta.FindStatusCondition(reconciledRev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing)
+ cnd := meta.FindStatusCondition(reconciledRev.Status.Conditions, ocv1.ObjectSetTypeProgressing)
isStillProgressing := cnd != nil && cnd.Status == metav1.ConditionTrue && cnd.Reason != ocv1.ReasonSucceeded
- succeeded := meta.IsStatusConditionTrue(reconciledRev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeSucceeded)
+ succeeded := meta.IsStatusConditionTrue(reconciledRev.Status.Conditions, ocv1.ObjectSetTypeSucceeded)
// check if we reached the progress deadline only if the revision is still progressing and has not succeeded yet
if isStillProgressing && !succeeded {
timeout := time.Duration(pd) * time.Minute
@@ -105,7 +105,7 @@ func (c *ClusterExtensionRevisionReconciler) Reconcile(ctx context.Context, req
// Do checks before any Update()s, as Update() may modify the resource structure!
updateStatus := !equality.Semantic.DeepEqual(existingRev.Status, reconciledRev.Status)
- unexpectedFieldsChanged := checkForUnexpectedClusterExtensionRevisionFieldChange(*existingRev, *reconciledRev)
+ unexpectedFieldsChanged := checkForUnexpectedObjectSetFieldChange(*existingRev, *reconciledRev)
if unexpectedFieldsChanged {
panic("spec or metadata changed by reconciler")
}
@@ -124,8 +124,8 @@ func (c *ClusterExtensionRevisionReconciler) Reconcile(ctx context.Context, req
}
// Compare resources - ignoring status & metadata.finalizers
-func checkForUnexpectedClusterExtensionRevisionFieldChange(a, b ocv1.ClusterExtensionRevision) bool {
- a.Status, b.Status = ocv1.ClusterExtensionRevisionStatus{}, ocv1.ClusterExtensionRevisionStatus{}
+func checkForUnexpectedObjectSetFieldChange(a, b ocv1.ObjectSet) bool {
+ a.Status, b.Status = ocv1.ObjectSetStatus{}, ocv1.ObjectSetStatus{}
// when finalizers are updated during reconcile, we expect finalizers, managedFields, and resourceVersion
// to be updated, so we ignore changes in these fields.
@@ -135,7 +135,7 @@ func checkForUnexpectedClusterExtensionRevisionFieldChange(a, b ocv1.ClusterExte
return !equality.Semantic.DeepEqual(a.Spec, b.Spec)
}
-func (c *ClusterExtensionRevisionReconciler) reconcile(ctx context.Context, cer *ocv1.ClusterExtensionRevision) (ctrl.Result, error) {
+func (c *ObjectSetReconciler) reconcile(ctx context.Context, cer *ocv1.ObjectSet) (ctrl.Result, error) {
l := log.FromContext(ctx)
if !cer.DeletionTimestamp.IsZero() {
@@ -162,15 +162,15 @@ func (c *ClusterExtensionRevisionReconciler) reconcile(ctx context.Context, cer
ownerhandling.NewNative(c.Client.Scheme()),
)
- if cer.Spec.LifecycleState == ocv1.ClusterExtensionRevisionLifecycleStateArchived {
+ if cer.Spec.LifecycleState == ocv1.ObjectSetLifecycleStateArchived {
if err := c.TrackingCache.Free(ctx, cer); err != nil {
- markAsAvailableUnknown(cer, ocv1.ClusterExtensionRevisionReasonReconciling, err.Error())
+ markAsAvailableUnknown(cer, ocv1.ObjectSetReasonReconciling, err.Error())
return ctrl.Result{}, fmt.Errorf("error stopping informers: %v", err)
}
return c.archive(ctx, revisionEngine, cer, revision)
}
- if err := c.ensureFinalizer(ctx, cer, clusterExtensionRevisionTeardownFinalizer); err != nil {
+ if err := c.ensureFinalizer(ctx, cer, objectSetTeardownFinalizer); err != nil {
return ctrl.Result{}, fmt.Errorf("error ensuring teardown finalizer: %v", err)
}
@@ -242,13 +242,13 @@ func (c *ClusterExtensionRevisionReconciler) reconcile(ctx context.Context, cer
}
markAsProgressing(cer, ocv1.ReasonSucceeded, fmt.Sprintf("Revision %s has rolled out.", revVersion))
- markAsAvailable(cer, ocv1.ClusterExtensionRevisionReasonProbesSucceeded, "Objects are available and pass all probes.")
+ markAsAvailable(cer, ocv1.ObjectSetReasonProbesSucceeded, "Objects are available and pass all probes.")
// We'll probably only want to remove this once we are done updating the ClusterExtension conditions
// as its one of the interfaces between the revision and the extension. If we still have the Succeeded for now
// that's fine.
meta.SetStatusCondition(&cer.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeSucceeded,
+ Type: ocv1.ObjectSetTypeSucceeded,
Status: metav1.ConditionTrue,
Reason: ocv1.ReasonSucceeded,
Message: "Revision succeeded rolling out.",
@@ -282,11 +282,11 @@ func (c *ClusterExtensionRevisionReconciler) reconcile(ctx context.Context, cer
}
if len(probeFailureMsgs) > 0 {
- markAsUnavailable(cer, ocv1.ClusterExtensionRevisionReasonProbeFailure, strings.Join(probeFailureMsgs, "\n"))
+ markAsUnavailable(cer, ocv1.ObjectSetReasonProbeFailure, strings.Join(probeFailureMsgs, "\n"))
} else {
markAsUnavailable(cer, ocv1.ReasonRollingOut, fmt.Sprintf("Revision %s is rolling out.", revVersion))
}
- if meta.FindStatusCondition(cer.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing) == nil {
+ if meta.FindStatusCondition(cer.Status.Conditions, ocv1.ObjectSetTypeProgressing) == nil {
markAsProgressing(cer, ocv1.ReasonRollingOut, fmt.Sprintf("Revision %s is rolling out.", revVersion))
}
}
@@ -294,18 +294,18 @@ func (c *ClusterExtensionRevisionReconciler) reconcile(ctx context.Context, cer
return ctrl.Result{}, nil
}
-func (c *ClusterExtensionRevisionReconciler) delete(ctx context.Context, cer *ocv1.ClusterExtensionRevision) (ctrl.Result, error) {
+func (c *ObjectSetReconciler) delete(ctx context.Context, cer *ocv1.ObjectSet) (ctrl.Result, error) {
if err := c.TrackingCache.Free(ctx, cer); err != nil {
- markAsAvailableUnknown(cer, ocv1.ClusterExtensionRevisionReasonReconciling, err.Error())
+ markAsAvailableUnknown(cer, ocv1.ObjectSetReasonReconciling, err.Error())
return ctrl.Result{}, fmt.Errorf("error stopping informers: %v", err)
}
- if err := c.removeFinalizer(ctx, cer, clusterExtensionRevisionTeardownFinalizer); err != nil {
+ if err := c.removeFinalizer(ctx, cer, objectSetTeardownFinalizer); err != nil {
return ctrl.Result{}, fmt.Errorf("error removing teardown finalizer: %v", err)
}
return ctrl.Result{}, nil
}
-func (c *ClusterExtensionRevisionReconciler) archive(ctx context.Context, revisionEngine RevisionEngine, cer *ocv1.ClusterExtensionRevision, revision boxcutter.RevisionBuilder) (ctrl.Result, error) {
+func (c *ObjectSetReconciler) archive(ctx context.Context, revisionEngine RevisionEngine, cer *ocv1.ObjectSet, revision boxcutter.RevisionBuilder) (ctrl.Result, error) {
tdres, err := revisionEngine.Teardown(ctx, revision)
if err != nil {
err = fmt.Errorf("error archiving revision: %v", err)
@@ -320,7 +320,7 @@ func (c *ClusterExtensionRevisionReconciler) archive(ctx context.Context, revisi
if markAsArchived(cer) {
return ctrl.Result{}, nil
}
- if err := c.removeFinalizer(ctx, cer, clusterExtensionRevisionTeardownFinalizer); err != nil {
+ if err := c.removeFinalizer(ctx, cer, objectSetTeardownFinalizer); err != nil {
return ctrl.Result{}, fmt.Errorf("error removing teardown finalizer: %v", err)
}
return ctrl.Result{}, nil
@@ -330,10 +330,10 @@ type Sourcerer interface {
Source(handler handler.EventHandler, predicates ...predicate.Predicate) source.Source
}
-func (c *ClusterExtensionRevisionReconciler) SetupWithManager(mgr ctrl.Manager) error {
+func (c *ObjectSetReconciler) SetupWithManager(mgr ctrl.Manager) error {
skipProgressDeadlineExceededPredicate := predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
- rev, ok := e.ObjectNew.(*ocv1.ClusterExtensionRevision)
+ rev, ok := e.ObjectNew.(*ocv1.ObjectSet)
if !ok {
return true
}
@@ -341,7 +341,7 @@ func (c *ClusterExtensionRevisionReconciler) SetupWithManager(mgr ctrl.Manager)
if !rev.DeletionTimestamp.IsZero() {
return true
}
- if cnd := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing); cnd != nil && cnd.Status == metav1.ConditionFalse && cnd.Reason == ocv1.ReasonProgressDeadlineExceeded {
+ if cnd := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeProgressing); cnd != nil && cnd.Status == metav1.ConditionFalse && cnd.Reason == ocv1.ReasonProgressDeadlineExceeded {
return false
}
return true
@@ -350,7 +350,7 @@ func (c *ClusterExtensionRevisionReconciler) SetupWithManager(mgr ctrl.Manager)
c.Clock = clock.RealClock{}
return ctrl.NewControllerManagedBy(mgr).
For(
- &ocv1.ClusterExtensionRevision{},
+ &ocv1.ObjectSet{},
builder.WithPredicates(
predicate.ResourceVersionChangedPredicate{},
skipProgressDeadlineExceededPredicate,
@@ -358,14 +358,14 @@ func (c *ClusterExtensionRevisionReconciler) SetupWithManager(mgr ctrl.Manager)
).
WatchesRawSource(
c.TrackingCache.Source(
- handler.EnqueueRequestForOwner(mgr.GetScheme(), mgr.GetRESTMapper(), &ocv1.ClusterExtensionRevision{}),
+ handler.EnqueueRequestForOwner(mgr.GetScheme(), mgr.GetRESTMapper(), &ocv1.ObjectSet{}),
predicate.ResourceVersionChangedPredicate{},
),
).
Complete(c)
}
-func (c *ClusterExtensionRevisionReconciler) establishWatch(ctx context.Context, cer *ocv1.ClusterExtensionRevision, revision boxcutter.RevisionBuilder) error {
+func (c *ObjectSetReconciler) establishWatch(ctx context.Context, cer *ocv1.ObjectSet, revision boxcutter.RevisionBuilder) error {
gvks := sets.New[schema.GroupVersionKind]()
for _, phase := range revision.GetPhases() {
for _, obj := range phase.GetObjects() {
@@ -376,7 +376,7 @@ func (c *ClusterExtensionRevisionReconciler) establishWatch(ctx context.Context,
return c.TrackingCache.Watch(ctx, cer, gvks)
}
-func (c *ClusterExtensionRevisionReconciler) ensureFinalizer(
+func (c *ObjectSetReconciler) ensureFinalizer(
ctx context.Context, obj client.Object, finalizer string,
) error {
if controllerutil.ContainsFinalizer(obj, finalizer) {
@@ -400,7 +400,7 @@ func (c *ClusterExtensionRevisionReconciler) ensureFinalizer(
return nil
}
-func (c *ClusterExtensionRevisionReconciler) removeFinalizer(ctx context.Context, obj client.Object, finalizer string) error {
+func (c *ObjectSetReconciler) removeFinalizer(ctx context.Context, obj client.Object, finalizer string) error {
if !controllerutil.ContainsFinalizer(obj, finalizer) {
return nil
}
@@ -425,28 +425,28 @@ func (c *ClusterExtensionRevisionReconciler) removeFinalizer(ctx context.Context
// listPreviousRevisions returns active revisions belonging to the same ClusterExtension with lower revision numbers.
// Filters out the current revision, archived revisions, deleting revisions, and revisions with equal or higher numbers.
-func (c *ClusterExtensionRevisionReconciler) listPreviousRevisions(ctx context.Context, cer *ocv1.ClusterExtensionRevision) ([]*ocv1.ClusterExtensionRevision, error) {
+func (c *ObjectSetReconciler) listPreviousRevisions(ctx context.Context, cer *ocv1.ObjectSet) ([]*ocv1.ObjectSet, error) {
ownerLabel, ok := cer.Labels[labels.OwnerNameKey]
if !ok {
// No owner label means this revision isn't properly labeled - return empty list
return nil, nil
}
- revList := &ocv1.ClusterExtensionRevisionList{}
+ revList := &ocv1.ObjectSetList{}
if err := c.TrackingCache.List(ctx, revList, client.MatchingLabels{
labels.OwnerNameKey: ownerLabel,
}); err != nil {
return nil, fmt.Errorf("listing revisions: %w", err)
}
- previous := make([]*ocv1.ClusterExtensionRevision, 0, len(revList.Items))
+ previous := make([]*ocv1.ObjectSet, 0, len(revList.Items))
for i := range revList.Items {
r := &revList.Items[i]
if r.Name == cer.Name {
continue
}
// Skip archived or deleting revisions
- if r.Spec.LifecycleState == ocv1.ClusterExtensionRevisionLifecycleStateArchived ||
+ if r.Spec.LifecycleState == ocv1.ObjectSetLifecycleStateArchived ||
!r.DeletionTimestamp.IsZero() {
continue
}
@@ -460,7 +460,7 @@ func (c *ClusterExtensionRevisionReconciler) listPreviousRevisions(ctx context.C
return previous, nil
}
-func (c *ClusterExtensionRevisionReconciler) buildBoxcutterPhases(ctx context.Context, cer *ocv1.ClusterExtensionRevision) ([]boxcutter.Phase, []boxcutter.RevisionReconcileOption, error) {
+func (c *ObjectSetReconciler) buildBoxcutterPhases(ctx context.Context, cer *ocv1.ObjectSet) ([]boxcutter.Phase, []boxcutter.RevisionReconcileOption, error) {
previous, err := c.listPreviousRevisions(ctx, cer)
if err != nil {
return nil, nil, fmt.Errorf("listing previous revisions: %w", err)
@@ -654,16 +654,16 @@ var (
}
)
-func setRetryingConditions(cer *ocv1.ClusterExtensionRevision, message string) {
- markAsProgressing(cer, ocv1.ClusterExtensionRevisionReasonRetrying, message)
- if meta.FindStatusCondition(cer.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable) != nil {
- markAsAvailableUnknown(cer, ocv1.ClusterExtensionRevisionReasonReconciling, message)
+func setRetryingConditions(cer *ocv1.ObjectSet, message string) {
+ markAsProgressing(cer, ocv1.ObjectSetReasonRetrying, message)
+ if meta.FindStatusCondition(cer.Status.Conditions, ocv1.ObjectSetTypeAvailable) != nil {
+ markAsAvailableUnknown(cer, ocv1.ObjectSetReasonReconciling, message)
}
}
-func markAsProgressing(cer *ocv1.ClusterExtensionRevision, reason, message string) {
+func markAsProgressing(cer *ocv1.ObjectSet, reason, message string) {
meta.SetStatusCondition(&cer.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeProgressing,
+ Type: ocv1.ObjectSetTypeProgressing,
Status: metav1.ConditionTrue,
Reason: reason,
Message: message,
@@ -671,9 +671,9 @@ func markAsProgressing(cer *ocv1.ClusterExtensionRevision, reason, message strin
})
}
-func markAsNotProgressing(cer *ocv1.ClusterExtensionRevision, reason, message string) bool {
+func markAsNotProgressing(cer *ocv1.ObjectSet, reason, message string) bool {
return meta.SetStatusCondition(&cer.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeProgressing,
+ Type: ocv1.ObjectSetTypeProgressing,
Status: metav1.ConditionFalse,
Reason: reason,
Message: message,
@@ -681,9 +681,9 @@ func markAsNotProgressing(cer *ocv1.ClusterExtensionRevision, reason, message st
})
}
-func markAsAvailable(cer *ocv1.ClusterExtensionRevision, reason, message string) bool {
+func markAsAvailable(cer *ocv1.ObjectSet, reason, message string) bool {
return meta.SetStatusCondition(&cer.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeAvailable,
+ Type: ocv1.ObjectSetTypeAvailable,
Status: metav1.ConditionTrue,
Reason: reason,
Message: message,
@@ -691,9 +691,9 @@ func markAsAvailable(cer *ocv1.ClusterExtensionRevision, reason, message string)
})
}
-func markAsUnavailable(cer *ocv1.ClusterExtensionRevision, reason, message string) {
+func markAsUnavailable(cer *ocv1.ObjectSet, reason, message string) {
meta.SetStatusCondition(&cer.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeAvailable,
+ Type: ocv1.ObjectSetTypeAvailable,
Status: metav1.ConditionFalse,
Reason: reason,
Message: message,
@@ -701,9 +701,9 @@ func markAsUnavailable(cer *ocv1.ClusterExtensionRevision, reason, message strin
})
}
-func markAsAvailableUnknown(cer *ocv1.ClusterExtensionRevision, reason, message string) bool {
+func markAsAvailableUnknown(cer *ocv1.ObjectSet, reason, message string) bool {
return meta.SetStatusCondition(&cer.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeAvailable,
+ Type: ocv1.ObjectSetTypeAvailable,
Status: metav1.ConditionUnknown,
Reason: reason,
Message: message,
@@ -711,8 +711,8 @@ func markAsAvailableUnknown(cer *ocv1.ClusterExtensionRevision, reason, message
})
}
-func markAsArchived(cer *ocv1.ClusterExtensionRevision) bool {
+func markAsArchived(cer *ocv1.ObjectSet) bool {
const msg = "revision is archived"
- updated := markAsNotProgressing(cer, ocv1.ClusterExtensionRevisionReasonArchived, msg)
- return markAsAvailableUnknown(cer, ocv1.ClusterExtensionRevisionReasonArchived, msg) || updated
+ updated := markAsNotProgressing(cer, ocv1.ObjectSetReasonArchived, msg)
+ return markAsAvailableUnknown(cer, ocv1.ObjectSetReasonArchived, msg) || updated
}
diff --git a/internal/operator-controller/controllers/clusterextensionrevision_controller_internal_test.go b/internal/operator-controller/controllers/objectset_controller_internal_test.go
similarity index 82%
rename from internal/operator-controller/controllers/clusterextensionrevision_controller_internal_test.go
rename to internal/operator-controller/controllers/objectset_controller_internal_test.go
index af4445c6c6..81d11bbcf7 100644
--- a/internal/operator-controller/controllers/clusterextensionrevision_controller_internal_test.go
+++ b/internal/operator-controller/controllers/objectset_controller_internal_test.go
@@ -22,7 +22,7 @@ import (
"github.com/operator-framework/operator-controller/internal/operator-controller/labels"
)
-func Test_ClusterExtensionRevisionReconciler_listPreviousRevisions(t *testing.T) {
+func Test_ObjectSetReconciler_listPreviousRevisions(t *testing.T) {
testScheme := runtime.NewScheme()
require.NoError(t, ocv1.AddToScheme(testScheme))
@@ -41,9 +41,9 @@ func Test_ClusterExtensionRevisionReconciler_listPreviousRevisions(t *testing.T)
name: "should skip current revision when listing previous",
existingObjs: func() []client.Object {
ext := newTestClusterExtensionInternal()
- rev1 := newTestClusterExtensionRevisionInternal(t, "rev-1")
- rev2 := newTestClusterExtensionRevisionInternal(t, "rev-2")
- rev3 := newTestClusterExtensionRevisionInternal(t, "rev-3")
+ rev1 := newTestObjectSetInternal(t, "rev-1")
+ rev2 := newTestObjectSetInternal(t, "rev-2")
+ rev3 := newTestObjectSetInternal(t, "rev-3")
require.NoError(t, controllerutil.SetControllerReference(ext, rev1, testScheme))
require.NoError(t, controllerutil.SetControllerReference(ext, rev2, testScheme))
require.NoError(t, controllerutil.SetControllerReference(ext, rev3, testScheme))
@@ -60,10 +60,10 @@ func Test_ClusterExtensionRevisionReconciler_listPreviousRevisions(t *testing.T)
name: "should drop archived revisions when listing previous",
existingObjs: func() []client.Object {
ext := newTestClusterExtensionInternal()
- rev1 := newTestClusterExtensionRevisionInternal(t, "rev-1")
- rev2 := newTestClusterExtensionRevisionInternal(t, "rev-2")
- rev2.Spec.LifecycleState = ocv1.ClusterExtensionRevisionLifecycleStateArchived
- rev3 := newTestClusterExtensionRevisionInternal(t, "rev-3")
+ rev1 := newTestObjectSetInternal(t, "rev-1")
+ rev2 := newTestObjectSetInternal(t, "rev-2")
+ rev2.Spec.LifecycleState = ocv1.ObjectSetLifecycleStateArchived
+ rev3 := newTestObjectSetInternal(t, "rev-3")
require.NoError(t, controllerutil.SetControllerReference(ext, rev1, testScheme))
require.NoError(t, controllerutil.SetControllerReference(ext, rev2, testScheme))
require.NoError(t, controllerutil.SetControllerReference(ext, rev3, testScheme))
@@ -80,11 +80,11 @@ func Test_ClusterExtensionRevisionReconciler_listPreviousRevisions(t *testing.T)
name: "should drop deleting revisions when listing previous",
existingObjs: func() []client.Object {
ext := newTestClusterExtensionInternal()
- rev1 := newTestClusterExtensionRevisionInternal(t, "rev-1")
- rev2 := newTestClusterExtensionRevisionInternal(t, "rev-2")
+ rev1 := newTestObjectSetInternal(t, "rev-1")
+ rev2 := newTestObjectSetInternal(t, "rev-2")
rev2.Finalizers = []string{"test-finalizer"}
rev2.DeletionTimestamp = &metav1.Time{Time: time.Now()}
- rev3 := newTestClusterExtensionRevisionInternal(t, "rev-3")
+ rev3 := newTestObjectSetInternal(t, "rev-3")
require.NoError(t, controllerutil.SetControllerReference(ext, rev1, testScheme))
require.NoError(t, controllerutil.SetControllerReference(ext, rev2, testScheme))
require.NoError(t, controllerutil.SetControllerReference(ext, rev3, testScheme))
@@ -105,10 +105,10 @@ func Test_ClusterExtensionRevisionReconciler_listPreviousRevisions(t *testing.T)
ext2.Name = "test-ext-2"
ext2.UID = "test-ext-2"
- rev1 := newTestClusterExtensionRevisionInternal(t, "rev-1")
- rev2 := newTestClusterExtensionRevisionInternal(t, "rev-2")
+ rev1 := newTestObjectSetInternal(t, "rev-1")
+ rev2 := newTestObjectSetInternal(t, "rev-2")
rev2.Labels[labels.OwnerNameKey] = "test-ext-2"
- rev3 := newTestClusterExtensionRevisionInternal(t, "rev-3")
+ rev3 := newTestObjectSetInternal(t, "rev-3")
require.NoError(t, controllerutil.SetControllerReference(ext, rev1, testScheme))
require.NoError(t, controllerutil.SetControllerReference(ext2, rev2, testScheme))
require.NoError(t, controllerutil.SetControllerReference(ext, rev3, testScheme))
@@ -125,7 +125,7 @@ func Test_ClusterExtensionRevisionReconciler_listPreviousRevisions(t *testing.T)
name: "should return empty list when owner label missing",
existingObjs: func() []client.Object {
ext := newTestClusterExtensionInternal()
- rev1 := newTestClusterExtensionRevisionInternal(t, "rev-1")
+ rev1 := newTestObjectSetInternal(t, "rev-1")
delete(rev1.Labels, labels.OwnerNameKey)
require.NoError(t, controllerutil.SetControllerReference(ext, rev1, testScheme))
return []client.Object{ext, rev1}
@@ -140,12 +140,12 @@ func Test_ClusterExtensionRevisionReconciler_listPreviousRevisions(t *testing.T)
WithObjects(tc.existingObjs()...).
Build()
- reconciler := &ClusterExtensionRevisionReconciler{
+ reconciler := &ObjectSetReconciler{
Client: testClient,
TrackingCache: &mockTrackingCacheInternal{client: testClient},
}
- currentRev := &ocv1.ClusterExtensionRevision{}
+ currentRev := &ocv1.ObjectSet{}
err := testClient.Get(t.Context(), client.ObjectKey{Name: tc.currentRev}, currentRev)
require.NoError(t, err)
@@ -183,13 +183,13 @@ func newTestClusterExtensionInternal() *ocv1.ClusterExtension {
}
}
-func newTestClusterExtensionRevisionInternal(t *testing.T, name string) *ocv1.ClusterExtensionRevision {
+func newTestObjectSetInternal(t *testing.T, name string) *ocv1.ObjectSet {
t.Helper()
// Extract revision number from name (e.g., "rev-1" -> 1, "test-ext-10" -> 10)
revNum := ExtractRevisionNumber(t, name)
- rev := &ocv1.ClusterExtensionRevision{
+ rev := &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
UID: types.UID(name),
@@ -198,17 +198,17 @@ func newTestClusterExtensionRevisionInternal(t *testing.T, name string) *ocv1.Cl
labels.OwnerNameKey: "test-ext",
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
+ Spec: ocv1.ObjectSetSpec{
Revision: revNum,
- Phases: []ocv1.ClusterExtensionRevisionPhase{
+ Phases: []ocv1.ObjectSetPhase{
{
Name: "everything",
- Objects: []ocv1.ClusterExtensionRevisionObject{},
+ Objects: []ocv1.ObjectSetObject{},
},
},
},
}
- rev.SetGroupVersionKind(ocv1.GroupVersion.WithKind("ClusterExtensionRevision"))
+ rev.SetGroupVersionKind(ocv1.GroupVersion.WithKind("ObjectSet"))
return rev
}
diff --git a/internal/operator-controller/controllers/clusterextensionrevision_controller_test.go b/internal/operator-controller/controllers/objectset_controller_test.go
similarity index 81%
rename from internal/operator-controller/controllers/clusterextensionrevision_controller_test.go
rename to internal/operator-controller/controllers/objectset_controller_test.go
index 682c101743..7d14ea06ad 100644
--- a/internal/operator-controller/controllers/clusterextensionrevision_controller_test.go
+++ b/internal/operator-controller/controllers/objectset_controller_test.go
@@ -35,9 +35,9 @@ import (
"github.com/operator-framework/operator-controller/internal/operator-controller/labels"
)
-const clusterExtensionRevisionName = "test-ext-1"
+const objectSetName = "test-ext-1"
-func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t *testing.T) {
+func Test_ObjectSetReconciler_Reconcile_RevisionReconciliation(t *testing.T) {
testScheme := newScheme(t)
for _, tc := range []struct {
@@ -50,17 +50,17 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
}{
{
name: "sets teardown finalizer",
- reconcilingRevisionName: clusterExtensionRevisionName,
+ reconcilingRevisionName: objectSetName,
revisionResult: mockRevisionResult{},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
require.Contains(t, rev.Finalizers, "olm.operatorframework.io/teardown")
@@ -68,71 +68,71 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
},
{
name: "Available condition is not updated on error if its not already set",
- reconcilingRevisionName: clusterExtensionRevisionName,
+ reconcilingRevisionName: objectSetName,
revisionResult: mockRevisionResult{},
revisionReconcileErr: errors.New("some error"),
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeAvailable)
require.Nil(t, cond)
},
},
{
name: "Available condition is updated to Unknown on error if its been already set",
- reconcilingRevisionName: clusterExtensionRevisionName,
+ reconcilingRevisionName: objectSetName,
revisionResult: mockRevisionResult{},
revisionReconcileErr: errors.New("some error"),
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
meta.SetStatusCondition(&rev1.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeAvailable,
+ Type: ocv1.ObjectSetTypeAvailable,
Status: metav1.ConditionTrue,
- Reason: ocv1.ClusterExtensionRevisionReasonProbesSucceeded,
+ Reason: ocv1.ObjectSetReasonProbesSucceeded,
Message: "Revision 1.0.0 is rolled out.",
ObservedGeneration: 1,
})
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeAvailable)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionUnknown, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonReconciling, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonReconciling, cond.Reason)
require.Equal(t, "some error", cond.Message)
require.Equal(t, int64(1), cond.ObservedGeneration)
},
},
{
name: "set Available:False:RollingOut status condition during rollout when no probe failures are detected",
- reconcilingRevisionName: clusterExtensionRevisionName,
+ reconcilingRevisionName: objectSetName,
revisionResult: mockRevisionResult{},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeAvailable)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionFalse, cond.Status)
require.Equal(t, ocv1.ReasonRollingOut, cond.Reason)
@@ -142,7 +142,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
},
{
name: "set Available:False:ProbeFailure condition when probe failures are detected and revision is in transition",
- reconcilingRevisionName: clusterExtensionRevisionName,
+ reconcilingRevisionName: objectSetName,
revisionResult: mockRevisionResult{
inTransition: true,
isComplete: false,
@@ -214,26 +214,26 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeAvailable)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionFalse, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonProbeFailure, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonProbeFailure, cond.Reason)
require.Equal(t, "Object Service.v1 my-namespace/my-service: something bad happened and something worse happened\nObject ConfigMap.v1 my-namespace/my-configmap: we have a problem", cond.Message)
require.Equal(t, int64(1), cond.ObservedGeneration)
},
},
{
name: "set Available:False:ProbeFailure condition when probe failures are detected and revision is not in transition",
- reconcilingRevisionName: clusterExtensionRevisionName,
+ reconcilingRevisionName: objectSetName,
revisionResult: mockRevisionResult{
inTransition: false,
isComplete: false,
@@ -305,19 +305,19 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeAvailable)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionFalse, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonProbeFailure, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonProbeFailure, cond.Reason)
require.Equal(t, "Object Service.v1 my-namespace/my-service: something bad happened and something worse happened\nObject ConfigMap.v1 my-namespace/my-configmap: we have a problem", cond.Message)
require.Equal(t, int64(1), cond.ObservedGeneration)
},
@@ -325,22 +325,22 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
{
name: "set Progressing:True:Retrying when there's an error reconciling the revision",
revisionReconcileErr: errors.New("some error"),
- reconcilingRevisionName: clusterExtensionRevisionName,
+ reconcilingRevisionName: objectSetName,
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.TypeProgressing)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionTrue, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonRetrying, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonRetrying, cond.Reason)
require.Equal(t, "some error", cond.Message)
require.Equal(t, int64(1), cond.ObservedGeneration)
},
@@ -350,16 +350,16 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
revisionResult: mockRevisionResult{
inTransition: true,
},
- reconcilingRevisionName: clusterExtensionRevisionName,
+ reconcilingRevisionName: objectSetName,
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.TypeProgressing)
@@ -376,10 +376,10 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
inTransition: false,
isComplete: true,
},
- reconcilingRevisionName: clusterExtensionRevisionName,
+ reconcilingRevisionName: objectSetName,
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
meta.SetStatusCondition(&rev1.Status.Conditions, metav1.Condition{
Type: ocv1.TypeProgressing,
Status: metav1.ConditionTrue,
@@ -390,9 +390,9 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.TypeProgressing)
@@ -408,33 +408,33 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
revisionResult: mockRevisionResult{
isComplete: true,
},
- reconcilingRevisionName: clusterExtensionRevisionName,
+ reconcilingRevisionName: objectSetName,
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeAvailable)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionTrue, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonProbesSucceeded, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonProbesSucceeded, cond.Reason)
require.Equal(t, "Objects are available and pass all probes.", cond.Message)
require.Equal(t, int64(1), cond.ObservedGeneration)
- cond = meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing)
+ cond = meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeProgressing)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionTrue, cond.Status)
require.Equal(t, ocv1.ReasonSucceeded, cond.Reason)
require.Equal(t, "Revision 1.0.0 has rolled out.", cond.Message)
require.Equal(t, int64(1), cond.ObservedGeneration)
- cond = meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeSucceeded)
+ cond = meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeSucceeded)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionTrue, cond.Status)
require.Equal(t, ocv1.ReasonSucceeded, cond.Reason)
@@ -450,30 +450,30 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
reconcilingRevisionName: "test-ext-3",
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- prevRev1 := newTestClusterExtensionRevision(t, "test-ext-1", ext, testScheme)
- prevRev2 := newTestClusterExtensionRevision(t, "test-ext-2", ext, testScheme)
- rev := newTestClusterExtensionRevision(t, "test-ext-3", ext, testScheme)
+ prevRev1 := newTestObjectSet(t, "test-ext-1", ext, testScheme)
+ prevRev2 := newTestObjectSet(t, "test-ext-2", ext, testScheme)
+ rev := newTestObjectSet(t, "test-ext-3", ext, testScheme)
return []client.Object{ext, prevRev1, prevRev2, rev}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
Name: "test-ext-1",
}, rev)
require.NoError(t, err)
- require.Equal(t, ocv1.ClusterExtensionRevisionLifecycleStateArchived, rev.Spec.LifecycleState)
+ require.Equal(t, ocv1.ObjectSetLifecycleStateArchived, rev.Spec.LifecycleState)
err = c.Get(t.Context(), client.ObjectKey{
Name: "test-ext-2",
}, rev)
require.NoError(t, err)
- require.Equal(t, ocv1.ClusterExtensionRevisionLifecycleStateArchived, rev.Spec.LifecycleState)
+ require.Equal(t, ocv1.ObjectSetLifecycleStateArchived, rev.Spec.LifecycleState)
err = c.Get(t.Context(), client.ObjectKey{
Name: "test-ext-3",
}, rev)
require.NoError(t, err)
- require.Equal(t, ocv1.ClusterExtensionRevisionLifecycleStateActive, rev.Spec.LifecycleState)
+ require.Equal(t, ocv1.ObjectSetLifecycleStateActive, rev.Spec.LifecycleState)
},
},
} {
@@ -481,7 +481,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
// create extension and cluster extension
testClient := fake.NewClientBuilder().
WithScheme(testScheme).
- WithStatusSubresource(&ocv1.ClusterExtensionRevision{}).
+ WithStatusSubresource(&ocv1.ObjectSet{}).
WithObjects(tc.existingObjs()...).
Build()
@@ -491,7 +491,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
return tc.revisionResult, tc.revisionReconcileErr
},
}
- result, err := (&controllers.ClusterExtensionRevisionReconciler{
+ result, err := (&controllers.ObjectSetReconciler{
Client: testClient,
RevisionEngineFactory: &mockRevisionEngineFactory{engine: mockEngine},
TrackingCache: &mockTrackingCache{client: testClient},
@@ -515,10 +515,10 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_RevisionReconciliation(t
}
}
-func Test_ClusterExtensionRevisionReconciler_Reconcile_ValidationError_Retries(t *testing.T) {
+func Test_ObjectSetReconciler_Reconcile_ValidationError_Retries(t *testing.T) {
const (
- clusterExtensionName = "test-ext"
- clusterExtensionRevisionName = "test-ext-1"
+ clusterExtensionName = "test-ext"
+ objectSetName = "test-ext-1"
)
testScheme := newScheme(t)
@@ -596,12 +596,12 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ValidationError_Retries(t
} {
t.Run(tc.name, func(t *testing.T) {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
// create extension and cluster extension
testClient := fake.NewClientBuilder().
WithScheme(testScheme).
- WithStatusSubresource(&ocv1.ClusterExtensionRevision{}).
+ WithStatusSubresource(&ocv1.ObjectSet{}).
WithObjects(ext, rev1).
Build()
@@ -611,13 +611,13 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ValidationError_Retries(t
return tc.revisionResult, nil
},
}
- result, err := (&controllers.ClusterExtensionRevisionReconciler{
+ result, err := (&controllers.ObjectSetReconciler{
Client: testClient,
RevisionEngineFactory: &mockRevisionEngineFactory{engine: mockEngine},
TrackingCache: &mockTrackingCache{client: testClient},
}).Reconcile(t.Context(), ctrl.Request{
NamespacedName: types.NamespacedName{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
},
})
@@ -630,9 +630,9 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ValidationError_Retries(t
}
}
-func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *testing.T) {
+func Test_ObjectSetReconciler_Reconcile_ArchivalAndDeletion(t *testing.T) {
const (
- clusterExtensionRevisionName = "test-ext-1"
+ objectSetName = "test-ext-1"
)
testScheme := newScheme(t)
@@ -654,16 +654,16 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
revisionResult: mockRevisionResult{},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
rev1.Finalizers = []string{
"olm.operatorframework.io/teardown",
}
return []client.Object{ext, rev1}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
require.NotContains(t, "olm.operatorframework.io/teardown", rev.Finalizers)
@@ -677,7 +677,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
revisionResult: mockRevisionResult{},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
rev1.Finalizers = []string{
"olm.operatorframework.io/teardown",
}
@@ -689,15 +689,15 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
},
expectedErr: "error stopping informers",
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeAvailable)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionUnknown, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonReconciling, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonReconciling, cond.Reason)
require.Contains(t, cond.Message, "tracking cache free failed")
},
revisionEngineTeardownFn: func(t *testing.T) func(context.Context, machinerytypes.Revision, ...machinerytypes.RevisionTeardownOption) (machinery.RevisionTeardownResult, error) {
@@ -709,11 +709,11 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
revisionResult: mockRevisionResult{},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
rev1.Finalizers = []string{
"olm.operatorframework.io/teardown",
}
- rev1.Spec.LifecycleState = ocv1.ClusterExtensionRevisionLifecycleStateArchived
+ rev1.Spec.LifecycleState = ocv1.ObjectSetLifecycleStateArchived
return []client.Object{rev1, ext}
},
revisionEngineTeardownFn: func(t *testing.T) func(ctx context.Context, rev machinerytypes.Revision, opts ...machinerytypes.RevisionTeardownOption) (machinery.RevisionTeardownResult, error) {
@@ -724,22 +724,22 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeAvailable)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeAvailable)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionUnknown, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonArchived, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonArchived, cond.Reason)
require.Equal(t, "revision is archived", cond.Message)
require.Equal(t, int64(1), cond.ObservedGeneration)
- cond = meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing)
+ cond = meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeProgressing)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionFalse, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonArchived, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonArchived, cond.Reason)
require.Equal(t, "revision is archived", cond.Message)
require.Equal(t, int64(1), cond.ObservedGeneration)
},
@@ -749,11 +749,11 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
revisionResult: mockRevisionResult{},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
rev1.Finalizers = []string{
"olm.operatorframework.io/teardown",
}
- rev1.Spec.LifecycleState = ocv1.ClusterExtensionRevisionLifecycleStateArchived
+ rev1.Spec.LifecycleState = ocv1.ObjectSetLifecycleStateArchived
return []client.Object{rev1, ext}
},
revisionEngineTeardownFn: func(t *testing.T) func(ctx context.Context, rev machinerytypes.Revision, opts ...machinerytypes.RevisionTeardownOption) (machinery.RevisionTeardownResult, error) {
@@ -765,15 +765,15 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
},
expectedResult: ctrl.Result{RequeueAfter: 5 * time.Second},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeProgressing)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionTrue, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonRetrying, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonRetrying, cond.Reason)
require.Equal(t, "removing revision resources that are not owned by another revision", cond.Message)
// Finalizer should still be present
@@ -785,11 +785,11 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
revisionResult: mockRevisionResult{},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
rev1.Finalizers = []string{
"olm.operatorframework.io/teardown",
}
- rev1.Spec.LifecycleState = ocv1.ClusterExtensionRevisionLifecycleStateArchived
+ rev1.Spec.LifecycleState = ocv1.ObjectSetLifecycleStateArchived
return []client.Object{rev1, ext}
},
revisionEngineTeardownFn: func(t *testing.T) func(ctx context.Context, rev machinerytypes.Revision, opts ...machinerytypes.RevisionTeardownOption) (machinery.RevisionTeardownResult, error) {
@@ -799,15 +799,15 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
},
expectedErr: "error archiving revision",
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeProgressing)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionTrue, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonRetrying, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonRetrying, cond.Reason)
require.Contains(t, cond.Message, "teardown failed: connection refused")
// Finalizer should still be present
@@ -819,11 +819,11 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
revisionResult: mockRevisionResult{},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
rev1.Finalizers = []string{
"olm.operatorframework.io/teardown",
}
- rev1.Spec.LifecycleState = ocv1.ClusterExtensionRevisionLifecycleStateArchived
+ rev1.Spec.LifecycleState = ocv1.ObjectSetLifecycleStateArchived
return []client.Object{rev1, ext}
},
revisionEngineTeardownFn: func(t *testing.T) func(ctx context.Context, rev machinerytypes.Revision, opts ...machinerytypes.RevisionTeardownOption) (machinery.RevisionTeardownResult, error) {
@@ -832,15 +832,15 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
revisionEngineFactoryErr: fmt.Errorf("token getter failed"),
expectedErr: "failed to create revision engine",
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing)
+ cond := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeProgressing)
require.NotNil(t, cond)
require.Equal(t, metav1.ConditionTrue, cond.Status)
- require.Equal(t, ocv1.ClusterExtensionRevisionReasonRetrying, cond.Reason)
+ require.Equal(t, ocv1.ObjectSetReasonRetrying, cond.Reason)
require.Contains(t, cond.Message, "token getter failed")
// Finalizer should still be present
@@ -852,22 +852,22 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
revisionResult: mockRevisionResult{},
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
rev1.Finalizers = []string{
"olm.operatorframework.io/teardown",
}
- rev1.Spec.LifecycleState = ocv1.ClusterExtensionRevisionLifecycleStateArchived
+ rev1.Spec.LifecycleState = ocv1.ObjectSetLifecycleStateArchived
meta.SetStatusCondition(&rev1.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeAvailable,
+ Type: ocv1.ObjectSetTypeAvailable,
Status: metav1.ConditionUnknown,
- Reason: ocv1.ClusterExtensionRevisionReasonArchived,
+ Reason: ocv1.ObjectSetReasonArchived,
Message: "revision is archived",
ObservedGeneration: rev1.Generation,
})
meta.SetStatusCondition(&rev1.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeProgressing,
+ Type: ocv1.ObjectSetTypeProgressing,
Status: metav1.ConditionFalse,
- Reason: ocv1.ClusterExtensionRevisionReasonArchived,
+ Reason: ocv1.ObjectSetReasonArchived,
Message: "revision is archived",
ObservedGeneration: rev1.Generation,
})
@@ -881,9 +881,9 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
}
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
require.NotContains(t, rev.Finalizers, "olm.operatorframework.io/teardown")
@@ -894,7 +894,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
// create extension and cluster extension
testClient := fake.NewClientBuilder().
WithScheme(testScheme).
- WithStatusSubresource(&ocv1.ClusterExtensionRevision{}).
+ WithStatusSubresource(&ocv1.ObjectSet{}).
WithObjects(tc.existingObjs()...).
Build()
@@ -906,7 +906,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
teardown: tc.revisionEngineTeardownFn(t),
}
factory := &mockRevisionEngineFactory{engine: mockEngine, createErr: tc.revisionEngineFactoryErr}
- result, err := (&controllers.ClusterExtensionRevisionReconciler{
+ result, err := (&controllers.ObjectSetReconciler{
Client: testClient,
RevisionEngineFactory: factory,
TrackingCache: &mockTrackingCache{
@@ -915,7 +915,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
},
}).Reconcile(t.Context(), ctrl.Request{
NamespacedName: types.NamespacedName{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
},
})
@@ -933,9 +933,9 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ArchivalAndDeletion(t *te
}
}
-func Test_ClusterExtensionRevisionReconciler_Reconcile_ProgressDeadline(t *testing.T) {
+func Test_ObjectSetReconciler_Reconcile_ProgressDeadline(t *testing.T) {
const (
- clusterExtensionRevisionName = "test-ext-1"
+ objectSetName = "test-ext-1"
)
testScheme := newScheme(t)
@@ -954,7 +954,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ProgressDeadline(t *testi
name: "progressing set to false when progress deadline is exceeded",
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
rev1.Spec.ProgressDeadlineMinutes = 1
rev1.CreationTimestamp = metav1.NewTime(time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC))
return []client.Object{rev1, ext}
@@ -965,12 +965,12 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ProgressDeadline(t *testi
inTransition: true,
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cnd := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing)
+ cnd := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeProgressing)
require.Equal(t, metav1.ConditionFalse, cnd.Status)
require.Equal(t, ocv1.ReasonProgressDeadlineExceeded, cnd.Reason)
},
@@ -979,7 +979,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ProgressDeadline(t *testi
name: "requeue after progressDeadline time for final progression deadline check",
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
rev1.Spec.ProgressDeadlineMinutes = 1
rev1.CreationTimestamp = metav1.NewTime(time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC))
return []client.Object{rev1, ext}
@@ -990,12 +990,12 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ProgressDeadline(t *testi
},
reconcileResult: ctrl.Result{RequeueAfter: 62 * time.Second},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cnd := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing)
+ cnd := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeProgressing)
require.Equal(t, metav1.ConditionTrue, cnd.Status)
require.Equal(t, ocv1.ReasonRollingOut, cnd.Reason)
},
@@ -1004,17 +1004,17 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ProgressDeadline(t *testi
name: "no progression deadline checks on revision recovery",
existingObjs: func() []client.Object {
ext := newTestClusterExtension()
- rev1 := newTestClusterExtensionRevision(t, clusterExtensionRevisionName, ext, testScheme)
+ rev1 := newTestObjectSet(t, objectSetName, ext, testScheme)
rev1.Spec.ProgressDeadlineMinutes = 1
rev1.CreationTimestamp = metav1.NewTime(time.Now().Add(-2 * time.Minute))
meta.SetStatusCondition(&rev1.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeProgressing,
+ Type: ocv1.ObjectSetTypeProgressing,
Status: metav1.ConditionTrue,
Reason: ocv1.ReasonSucceeded,
ObservedGeneration: rev1.Generation,
})
meta.SetStatusCondition(&rev1.Status.Conditions, metav1.Condition{
- Type: ocv1.ClusterExtensionRevisionTypeSucceeded,
+ Type: ocv1.ObjectSetTypeSucceeded,
Status: metav1.ConditionTrue,
Reason: ocv1.ReasonSucceeded,
ObservedGeneration: rev1.Generation,
@@ -1025,12 +1025,12 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ProgressDeadline(t *testi
inTransition: true,
},
validate: func(t *testing.T, c client.Client) {
- rev := &ocv1.ClusterExtensionRevision{}
+ rev := &ocv1.ObjectSet{}
err := c.Get(t.Context(), client.ObjectKey{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
}, rev)
require.NoError(t, err)
- cnd := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ClusterExtensionRevisionTypeProgressing)
+ cnd := meta.FindStatusCondition(rev.Status.Conditions, ocv1.ObjectSetTypeProgressing)
require.Equal(t, metav1.ConditionTrue, cnd.Status)
require.Equal(t, ocv1.ReasonRollingOut, cnd.Reason)
},
@@ -1040,7 +1040,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ProgressDeadline(t *testi
// create extension and cluster extension
testClient := fake.NewClientBuilder().
WithScheme(testScheme).
- WithStatusSubresource(&ocv1.ClusterExtensionRevision{}).
+ WithStatusSubresource(&ocv1.ObjectSet{}).
WithObjects(tc.existingObjs()...).
Build()
@@ -1050,7 +1050,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ProgressDeadline(t *testi
return tc.revisionResult, nil
},
}
- result, err := (&controllers.ClusterExtensionRevisionReconciler{
+ result, err := (&controllers.ObjectSetReconciler{
Client: testClient,
RevisionEngineFactory: &mockRevisionEngineFactory{engine: mockEngine},
TrackingCache: &mockTrackingCache{
@@ -1059,7 +1059,7 @@ func Test_ClusterExtensionRevisionReconciler_Reconcile_ProgressDeadline(t *testi
Clock: tc.clock,
}).Reconcile(t.Context(), ctrl.Request{
NamespacedName: types.NamespacedName{
- Name: clusterExtensionRevisionName,
+ Name: objectSetName,
},
})
require.Equal(t, tc.reconcileResult, result)
@@ -1091,13 +1091,13 @@ func newTestClusterExtension() *ocv1.ClusterExtension {
}
}
-func newTestClusterExtensionRevision(t *testing.T, revisionName string, ext *ocv1.ClusterExtension, scheme *runtime.Scheme) *ocv1.ClusterExtensionRevision {
+func newTestObjectSet(t *testing.T, revisionName string, ext *ocv1.ClusterExtension, scheme *runtime.Scheme) *ocv1.ObjectSet {
t.Helper()
// Extract revision number from name (e.g., "rev-1" -> 1, "test-ext-10" -> 10)
revNum := controllers.ExtractRevisionNumber(t, revisionName)
- rev := &ocv1.ClusterExtensionRevision{
+ rev := &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: revisionName,
UID: types.UID(revisionName),
@@ -1114,13 +1114,13 @@ func newTestClusterExtensionRevision(t *testing.T, revisionName string, ext *ocv
labels.OwnerNameKey: "test-ext",
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateActive,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateActive,
Revision: revNum,
- Phases: []ocv1.ClusterExtensionRevisionPhase{
+ Phases: []ocv1.ObjectSetPhase{
{
Name: "everything",
- Objects: []ocv1.ClusterExtensionRevisionObject{
+ Objects: []ocv1.ObjectSetObject{
{
Object: unstructured.Unstructured{
Object: map[string]interface{}{
@@ -1160,7 +1160,7 @@ type mockRevisionEngineFactory struct {
createErr error
}
-func (f *mockRevisionEngineFactory) CreateRevisionEngine(ctx context.Context, rev *ocv1.ClusterExtensionRevision) (controllers.RevisionEngine, error) {
+func (f *mockRevisionEngineFactory) CreateRevisionEngine(ctx context.Context, rev *ocv1.ObjectSet) (controllers.RevisionEngine, error) {
if f.createErr != nil {
return nil, f.createErr
}
@@ -1398,11 +1398,11 @@ func Test_effectiveCollisionProtection(t *testing.T) {
}
}
-func Test_ClusterExtensionRevisionReconciler_getScopedClient_Errors(t *testing.T) {
+func Test_ObjectSetReconciler_getScopedClient_Errors(t *testing.T) {
testScheme := newScheme(t)
t.Run("works with serviceAccount annotation and without owner label", func(t *testing.T) {
- rev := &ocv1.ClusterExtensionRevision{
+ rev := &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-rev-1",
UID: types.UID("test-rev-1"),
@@ -1413,16 +1413,16 @@ func Test_ClusterExtensionRevisionReconciler_getScopedClient_Errors(t *testing.T
labels.BundleVersionKey: "1.0.0",
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateActive,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateActive,
Revision: 1,
- Phases: []ocv1.ClusterExtensionRevisionPhase{},
+ Phases: []ocv1.ObjectSetPhase{},
},
}
testClient := fake.NewClientBuilder().
WithScheme(testScheme).
- WithStatusSubresource(&ocv1.ClusterExtensionRevision{}).
+ WithStatusSubresource(&ocv1.ObjectSet{}).
WithObjects(rev).
Build()
@@ -1432,7 +1432,7 @@ func Test_ClusterExtensionRevisionReconciler_getScopedClient_Errors(t *testing.T
},
}
- reconciler := &controllers.ClusterExtensionRevisionReconciler{
+ reconciler := &controllers.ObjectSetReconciler{
Client: testClient,
RevisionEngineFactory: &mockRevisionEngineFactory{engine: mockEngine},
TrackingCache: &mockTrackingCache{client: testClient},
@@ -1446,17 +1446,17 @@ func Test_ClusterExtensionRevisionReconciler_getScopedClient_Errors(t *testing.T
})
t.Run("missing serviceAccount annotation", func(t *testing.T) {
- rev := &ocv1.ClusterExtensionRevision{
+ rev := &ocv1.ObjectSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-rev-1",
Annotations: map[string]string{
labels.BundleVersionKey: "1.0.0",
},
},
- Spec: ocv1.ClusterExtensionRevisionSpec{
- LifecycleState: ocv1.ClusterExtensionRevisionLifecycleStateActive,
+ Spec: ocv1.ObjectSetSpec{
+ LifecycleState: ocv1.ObjectSetLifecycleStateActive,
Revision: 1,
- Phases: []ocv1.ClusterExtensionRevisionPhase{},
+ Phases: []ocv1.ObjectSetPhase{},
},
}
@@ -1469,7 +1469,7 @@ func Test_ClusterExtensionRevisionReconciler_getScopedClient_Errors(t *testing.T
createErr: errors.New("missing serviceAccount name annotation"),
}
- reconciler := &controllers.ClusterExtensionRevisionReconciler{
+ reconciler := &controllers.ObjectSetReconciler{
Client: testClient,
RevisionEngineFactory: failingFactory,
TrackingCache: &mockTrackingCache{client: testClient},
@@ -1485,7 +1485,7 @@ func Test_ClusterExtensionRevisionReconciler_getScopedClient_Errors(t *testing.T
t.Run("factory fails to create engine", func(t *testing.T) {
ext := newTestClusterExtension()
- rev := newTestClusterExtensionRevision(t, "test-rev", ext, testScheme)
+ rev := newTestObjectSet(t, "test-rev", ext, testScheme)
testClient := fake.NewClientBuilder().
WithScheme(testScheme).
@@ -1496,7 +1496,7 @@ func Test_ClusterExtensionRevisionReconciler_getScopedClient_Errors(t *testing.T
createErr: errors.New("token getter failed"),
}
- reconciler := &controllers.ClusterExtensionRevisionReconciler{
+ reconciler := &controllers.ObjectSetReconciler{
Client: testClient,
RevisionEngineFactory: failingFactory,
TrackingCache: &mockTrackingCache{client: testClient},
diff --git a/internal/operator-controller/controllers/revision_engine_factory.go b/internal/operator-controller/controllers/revision_engine_factory.go
index f87d930b38..a0c2b248cc 100644
--- a/internal/operator-controller/controllers/revision_engine_factory.go
+++ b/internal/operator-controller/controllers/revision_engine_factory.go
@@ -1,6 +1,6 @@
//go:build !standard
-// This file is excluded from standard builds because ClusterExtensionRevision
+// This file is excluded from standard builds because ObjectSet
// is an experimental feature. Standard builds use Helm-based applier only.
// The experimental build includes BoxcutterRuntime which requires these factories
// for serviceAccount-scoped client creation and RevisionEngine instantiation.
@@ -35,9 +35,9 @@ type RevisionEngine interface {
Reconcile(ctx context.Context, rev machinerytypes.Revision, opts ...machinerytypes.RevisionReconcileOption) (machinery.RevisionResult, error)
}
-// RevisionEngineFactory creates a RevisionEngine for a ClusterExtensionRevision.
+// RevisionEngineFactory creates a RevisionEngine for a ObjectSet.
type RevisionEngineFactory interface {
- CreateRevisionEngine(ctx context.Context, rev *ocv1.ClusterExtensionRevision) (RevisionEngine, error)
+ CreateRevisionEngine(ctx context.Context, rev *ocv1.ObjectSet) (RevisionEngine, error)
}
// defaultRevisionEngineFactory creates boxcutter RevisionEngines with serviceAccount-scoped clients.
@@ -51,9 +51,9 @@ type defaultRevisionEngineFactory struct {
TokenGetter *authentication.TokenGetter
}
-// CreateRevisionEngine constructs a boxcutter RevisionEngine for the given ClusterExtensionRevision.
+// CreateRevisionEngine constructs a boxcutter RevisionEngine for the given ObjectSet.
// It reads the ServiceAccount from annotations and creates a scoped client.
-func (f *defaultRevisionEngineFactory) CreateRevisionEngine(_ context.Context, rev *ocv1.ClusterExtensionRevision) (RevisionEngine, error) {
+func (f *defaultRevisionEngineFactory) CreateRevisionEngine(_ context.Context, rev *ocv1.ObjectSet) (RevisionEngine, error) {
saNamespace, saName, err := f.getServiceAccount(rev)
if err != nil {
return nil, err
@@ -77,7 +77,7 @@ func (f *defaultRevisionEngineFactory) CreateRevisionEngine(_ context.Context, r
), nil
}
-func (f *defaultRevisionEngineFactory) getServiceAccount(rev *ocv1.ClusterExtensionRevision) (string, string, error) {
+func (f *defaultRevisionEngineFactory) getServiceAccount(rev *ocv1.ObjectSet) (string, string, error) {
annotations := rev.GetAnnotations()
if annotations == nil {
return "", "", fmt.Errorf("revision %q is missing required annotations", rev.Name)
diff --git a/internal/operator-controller/labels/labels.go b/internal/operator-controller/labels/labels.go
index 16f45ecbb3..513075b94f 100644
--- a/internal/operator-controller/labels/labels.go
+++ b/internal/operator-controller/labels/labels.go
@@ -2,45 +2,45 @@ package labels
const (
// OwnerKindKey is the label key used to record the kind of the owner
- // resource responsible for creating or managing a ClusterExtensionRevision.
+ // resource responsible for creating or managing an ObjectSet.
OwnerKindKey = "olm.operatorframework.io/owner-kind"
// OwnerNameKey is the label key used to record the name of the owner
- // resource responsible for creating or managing a ClusterExtensionRevision.
+ // resource responsible for creating or managing an ObjectSet.
OwnerNameKey = "olm.operatorframework.io/owner-name"
// PackageNameKey is the label key used to record the package name
- // associated with a ClusterExtensionRevision.
+ // associated with an ObjectSet.
PackageNameKey = "olm.operatorframework.io/package-name"
// BundleNameKey is the label key used to record the bundle name
- // associated with a ClusterExtensionRevision.
+ // associated with an ObjectSet.
BundleNameKey = "olm.operatorframework.io/bundle-name"
// BundleVersionKey is the label key used to record the bundle version
- // associated with a ClusterExtensionRevision.
+ // associated with an ObjectSet.
BundleVersionKey = "olm.operatorframework.io/bundle-version"
// BundleReferenceKey is the label key used to record an external reference
- // (such as an image or catalog reference) to the bundle for a
- // ClusterExtensionRevision.
+ // (such as an image or catalog reference) to the bundle for an
+ // ObjectSet.
BundleReferenceKey = "olm.operatorframework.io/bundle-reference"
// ServiceAccountNameKey is the annotation key used to record the name of
// the ServiceAccount configured on the owning ClusterExtension. It is
- // applied as an annotation on ClusterExtensionRevision resources to
+ // applied as an annotation on ObjectSet resources to
// capture which ServiceAccount was used for their lifecycle operations.
ServiceAccountNameKey = "olm.operatorframework.io/service-account-name"
// ServiceAccountNamespaceKey is the annotation key used to record the
// namespace of the ServiceAccount configured on the owning
// ClusterExtension. It is applied as an annotation on
- // ClusterExtensionRevision resources together with ServiceAccountNameKey
+ // ObjectSet resources together with ServiceAccountNameKey
// so that the effective ServiceAccount identity used for
- // ClusterExtensionRevision operations is preserved.
+ // ObjectSet operations is preserved.
ServiceAccountNamespaceKey = "olm.operatorframework.io/service-account-namespace"
- // MigratedFromHelmKey is the label key used to mark ClusterExtensionRevisions
+ // MigratedFromHelmKey is the label key used to mark ObjectSets
// that were created during migration from Helm releases. This label is used
// to distinguish migrated revisions from those created by normal Boxcutter operation.
MigratedFromHelmKey = "olm.operatorframework.io/migrated-from-helm"
diff --git a/internal/shared/util/test/artifacts.go b/internal/shared/util/test/artifacts.go
index dc10546923..0bd9c1f6c8 100644
--- a/internal/shared/util/test/artifacts.go
+++ b/internal/shared/util/test/artifacts.go
@@ -25,7 +25,7 @@ import (
// CollectTestArtifacts gets all the artifacts from the test run and saves them to the artifact path.
// Currently, it saves:
// - clusterextensions
-// - clusterextensionrevisions
+// - objectsets
// - pods logs
// - deployments
// - catalogsources
@@ -71,18 +71,18 @@ func CollectTestArtifacts(t *testing.T, artifactName string, c client.Client, cf
}
// get all cluster extension revisions save them to the artifact path.
- clusterExtensionRevisions := ocv1.ClusterExtensionRevisionList{}
- if err := c.List(context.Background(), &clusterExtensionRevisions); err != nil {
+ objectSets := ocv1.ObjectSetList{}
+ if err := c.List(context.Background(), &objectSets); err != nil {
fmt.Printf("Failed to list cluster extensions: %v", err)
}
- for _, cer := range clusterExtensionRevisions.Items {
+ for _, cer := range objectSets.Items {
// Save cluster extension to artifact path
clusterExtensionYaml, err := yaml.Marshal(cer)
if err != nil {
fmt.Printf("Failed to marshal cluster extension: %v", err)
continue
}
- if err := os.WriteFile(filepath.Join(artifactPath, cer.Name+"-clusterextensionrevision.yaml"), clusterExtensionYaml, 0600); err != nil {
+ if err := os.WriteFile(filepath.Join(artifactPath, cer.Name+"-objectset.yaml"), clusterExtensionYaml, 0600); err != nil {
fmt.Printf("Failed to write cluster extension to file: %v", err)
}
}
diff --git a/manifests/experimental-e2e.yaml b/manifests/experimental-e2e.yaml
index 55a4e157c5..d26bb6549c 100644
--- a/manifests/experimental-e2e.yaml
+++ b/manifests/experimental-e2e.yaml
@@ -610,26 +610,32 @@ spec:
subresources:
status: {}
---
-# Source: olmv1/templates/crds/customresourcedefinition-clusterextensionrevisions.olm.operatorframework.io.yml
+# Source: olmv1/templates/crds/customresourcedefinition-clusterextensions.olm.operatorframework.io.yml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.20.1
olm.operatorframework.io/generator: experimental
- name: clusterextensionrevisions.olm.operatorframework.io
+ name: clusterextensions.olm.operatorframework.io
spec:
group: olm.operatorframework.io
names:
- kind: ClusterExtensionRevision
- listKind: ClusterExtensionRevisionList
- plural: clusterextensionrevisions
- singular: clusterextensionrevision
+ kind: ClusterExtension
+ listKind: ClusterExtensionList
+ plural: clusterextensions
+ singular: clusterextension
scope: Cluster
versions:
- additionalPrinterColumns:
- - jsonPath: .status.conditions[?(@.type=='Available')].status
- name: Available
+ - jsonPath: .status.install.bundle.name
+ name: Installed Bundle
+ type: string
+ - jsonPath: .status.install.bundle.version
+ name: Version
+ type: string
+ - jsonPath: .status.conditions[?(@.type=='Installed')].status
+ name: Installed
type: string
- jsonPath: .status.conditions[?(@.type=='Progressing')].status
name: Progressing
@@ -640,13 +646,7 @@ spec:
name: v1
schema:
openAPIV3Schema:
- description: |-
- ClusterExtensionRevision represents an immutable snapshot of Kubernetes objects
- for a specific version of a ClusterExtension. Each revision contains objects
- organized into phases that roll out sequentially. The same object can only be managed by a single revision
- at a time. Ownership of objects is transitioned from one revision to the next as the extension is upgraded
- or reconfigured. Once the latest revision has rolled out successfully, previous active revisions are archived for
- posterity.
+ description: ClusterExtension is the Schema for the clusterextensions API
properties:
apiVersion:
description: |-
@@ -666,165 +666,117 @@ spec:
metadata:
type: object
spec:
- description: spec defines the desired state of the ClusterExtensionRevision.
+ description: spec is an optional field that defines the desired state
+ of the ClusterExtension.
properties:
- collisionProtection:
+ config:
description: |-
- collisionProtection specifies the default collision protection strategy for all objects
- in this revision. Individual phases or objects can override this value.
-
- When set, this value is used as the default for any phase or object that does not
- explicitly specify its own collisionProtection.
+ config is optional and specifies bundle-specific configuration.
+ Configuration is bundle-specific and a bundle may provide a configuration schema.
+ When not specified, the default configuration of the resolved bundle is used.
- The resolution order is: object > phase > spec
- enum:
- - Prevent
- - IfNoController
- - None
- type: string
- x-kubernetes-validations:
- - message: collisionProtection is immutable
- rule: self == oldSelf
- lifecycleState:
- description: |-
- lifecycleState specifies the lifecycle state of the ClusterExtensionRevision.
+ config is validated against a configuration schema provided by the resolved bundle. If the bundle does not provide
+ a configuration schema the bundle is deemed to not be configurable. More information on how
+ to configure bundles can be found in the OLM documentation associated with your current OLM version.
+ properties:
+ configType:
+ description: |-
+ configType is required and specifies the type of configuration source.
- When set to "Active", the revision is actively managed and reconciled.
- When set to "Archived", the revision is inactive and any resources not managed by a subsequent revision are deleted.
- The revision is removed from the owner list of all objects previously under management.
- All objects that did not transition to a succeeding revision are deleted.
+ The only allowed value is "Inline".
- Once a revision is set to "Archived", it cannot be un-archived.
+ When set to "Inline", the cluster extension configuration is defined inline within the ClusterExtension resource.
+ enum:
+ - Inline
+ type: string
+ inline:
+ description: |-
+ inline contains JSON or YAML values specified directly in the ClusterExtension.
- It is possible for more than one revision to be "Active" simultaneously. This will occur when
- moving from one revision to another. The old revision will not be set to "Archived" until the
- new revision has been completely rolled out.
- enum:
- - Active
- - Archived
- type: string
+ It is used to specify arbitrary configuration values for the ClusterExtension.
+ It must be set if configType is 'Inline' and must be a valid JSON/YAML object containing at least one property.
+ The configuration values are validated at runtime against a JSON schema provided by the bundle.
+ minProperties: 1
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configType
+ type: object
x-kubernetes-validations:
- - message: cannot un-archive
- rule: oldSelf == 'Active' || oldSelf == 'Archived' && oldSelf ==
- self
- phases:
+ - message: inline is required when configType is Inline, and forbidden
+ otherwise
+ rule: 'has(self.configType) && self.configType == ''Inline'' ?has(self.inline)
+ : !has(self.inline)'
+ install:
description: |-
- phases is an optional, immutable list of phases that group objects to be applied together.
-
- Objects are organized into phases based on their Group-Kind. Common phases include:
- - namespaces: Namespace objects
- - policies: ResourceQuota, LimitRange, NetworkPolicy objects
- - rbac: ServiceAccount, Role, RoleBinding, ClusterRole, ClusterRoleBinding objects
- - crds: CustomResourceDefinition objects
- - storage: PersistentVolume, PersistentVolumeClaim, StorageClass objects
- - deploy: Deployment, StatefulSet, DaemonSet, Service, ConfigMap, Secret objects
- - publish: Ingress, APIService, Route, Webhook objects
-
- All objects in a phase are applied in no particular order.
- The revision progresses to the next phase only after all objects in the current phase pass their readiness probes.
-
- Once set, even if empty, the phases field is immutable.
-
- Each phase in the list must have a unique name. The maximum number of phases is 20.
- items:
- description: |-
- ClusterExtensionRevisionPhase represents a group of objects that are applied together. The phase is considered
- complete only after all objects pass their status probes.
- properties:
- collisionProtection:
- description: |-
- collisionProtection specifies the default collision protection strategy for all objects
- in this phase. Individual objects can override this value.
-
- When set, this value is used as the default for any object in this phase that does not
- explicitly specify its own collisionProtection.
-
- When omitted, we use .spec.collistionProtection as the default for any object in this phase that does not
- explicitly specify its own collisionProtection.
- enum:
- - Prevent
- - IfNoController
- - None
- type: string
- name:
- description: |-
- name is a required identifier for this phase.
-
- phase names must follow the DNS label standard as defined in [RFC 1123].
- They must contain only lowercase alphanumeric characters or hyphens (-),
- start and end with an alphanumeric character, and be no longer than 63 characters.
-
- Common phase names include: namespaces, policies, rbac, crds, storage, deploy, publish.
-
- [RFC 1123]: https://tools.ietf.org/html/rfc1123
- maxLength: 63
- minLength: 1
- type: string
- x-kubernetes-validations:
- - message: the value must consist of only lowercase alphanumeric
- characters and hyphens, and must start with an alphabetic
- character and end with an alphanumeric character.
- rule: '!format.dns1123Label().validate(self).hasValue()'
- objects:
- description: |-
- objects is a required list of all Kubernetes objects that belong to this phase.
+ install is optional and configures installation options for the ClusterExtension,
+ such as the pre-flight check configuration.
+ properties:
+ preflight:
+ description: |-
+ preflight is optional and configures the checks that run before installation or upgrade
+ of the content for the package specified in the packageName field.
- All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50.
- items:
+ When specified, it replaces the default preflight configuration for install/upgrade actions.
+ When not specified, the default configuration is used.
+ properties:
+ crdUpgradeSafety:
description: |-
- ClusterExtensionRevisionObject represents a Kubernetes object to be applied as part
- of a phase, along with its collision protection settings.
+ crdUpgradeSafety configures the CRD Upgrade Safety pre-flight checks that run
+ before upgrades of installed content.
+
+ The CRD Upgrade Safety pre-flight check safeguards from unintended consequences of upgrading a CRD,
+ such as data loss.
properties:
- collisionProtection:
+ enforcement:
description: |-
- collisionProtection controls whether the operator can adopt and modify objects
- that already exist on the cluster.
-
- Allowed values are: "Prevent", "IfNoController", and "None".
-
- When set to "Prevent", the operator only manages objects it created itself.
- This prevents ownership collisions.
+ enforcement is required and configures the state of the CRD Upgrade Safety pre-flight check.
- When set to "IfNoController", the operator can adopt and modify pre-existing objects
- that are not owned by another controller.
- This is useful for taking over management of manually-created resources.
+ Allowed values are "None" or "Strict". The default value is "Strict".
- When set to "None", the operator can adopt and modify any pre-existing object, even if
- owned by another controller.
- Use this setting with extreme caution as it may cause multiple controllers to fight over
- the same resource, resulting in increased load on the API server and etcd.
+ When set to "None", the CRD Upgrade Safety pre-flight check is skipped during an upgrade operation.
+ Use this option with caution as unintended consequences such as data loss can occur.
- When omitted, the value is inherited from the phase, then spec.
+ When set to "Strict", the CRD Upgrade Safety pre-flight check runs during an upgrade operation.
enum:
- - Prevent
- - IfNoController
- None
+ - Strict
type: string
- object:
- description: |-
- object is a required embedded Kubernetes object to be applied.
-
- This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields.
- type: object
- x-kubernetes-embedded-resource: true
- x-kubernetes-preserve-unknown-fields: true
required:
- - object
+ - enforcement
type: object
- maxItems: 50
- type: array
- required:
- - name
- - objects
- type: object
- maxItems: 20
- type: array
- x-kubernetes-list-map-keys:
- - name
- x-kubernetes-list-type: map
+ required:
+ - crdUpgradeSafety
+ type: object
+ x-kubernetes-validations:
+ - message: at least one of [crdUpgradeSafety] are required when
+ preflight is specified
+ rule: has(self.crdUpgradeSafety)
+ type: object
x-kubernetes-validations:
- - message: phases is immutable
- rule: self == oldSelf || oldSelf.size() == 0
+ - message: at least one of [preflight] are required when install is
+ specified
+ rule: has(self.preflight)
+ namespace:
+ description: |-
+ namespace specifies a Kubernetes namespace.
+ This is the namespace where the provided ServiceAccount must exist.
+ It also designates the default namespace where namespace-scoped resources for the extension are applied to the cluster.
+ Some extensions may contain namespace-scoped resources to be applied in other namespaces.
+ This namespace must exist.
+
+ The namespace field is required, immutable, and follows the DNS label standard as defined in [RFC 1123].
+ It must contain only lowercase alphanumeric characters or hyphens (-), start and end with an alphanumeric character,
+ and be no longer than 63 characters.
+
+ [RFC 1123]: https://tools.ietf.org/html/rfc1123
+ maxLength: 63
+ type: string
+ x-kubernetes-validations:
+ - message: namespace is immutable
+ rule: self == oldSelf
+ - message: namespace must be a valid DNS1123 label
+ rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$")
progressDeadlineMinutes:
description: |-
progressDeadlineMinutes is an optional field that defines the maximum period
@@ -835,983 +787,1069 @@ spec:
maximum: 720
minimum: 10
type: integer
- progressionProbes:
+ serviceAccount:
description: |-
- progressionProbes is an optional field which provides the ability to define custom readiness probes
- for objects defined within spec.phases. As documented in that field, most kubernetes-native objects
- within the phases already have some kind of readiness check built-in, but this field allows for checks
- which are tailored to the objects being rolled out - particularly custom resources.
-
- Probes defined within the progressionProbes list will apply to every phase in the revision. However, the probes will only
- execute against phase objects which are a match for the provided selector type. For instance, a probe using a GroupKind selector
- for ConfigMaps will automatically be considered to have passed for any non-ConfigMap object, but will halt any phase containing
- a ConfigMap if that particular object does not pass the probe check.
+ serviceAccount specifies a ServiceAccount used to perform all interactions with the cluster
+ that are required to manage the extension.
+ The ServiceAccount must be configured with the necessary permissions to perform these interactions.
+ The ServiceAccount must exist in the namespace referenced in the spec.
+ The serviceAccount field is required.
+ properties:
+ name:
+ description: |-
+ name is a required, immutable reference to the name of the ServiceAccount used for installation
+ and management of the content for the package specified in the packageName field.
- The maximum number of probes is 20.
- items:
- description: ProgressionProbe provides a custom probe definition,
- consisting of an object selection method and assertions.
- properties:
- assertions:
- description: |-
- assertions is a required list of checks which will run against the objects selected by the selector. If
- one or more assertions fail then the phase within which the object lives will be not be considered
- 'Ready', blocking rollout of all subsequent phases.
- items:
- description: Assertion is a discriminated union which defines
- the probe type and definition used as an assertion.
- properties:
- conditionEqual:
- description: conditionEqual contains the expected condition
- type and status.
- properties:
- status:
- description: |-
- status sets the expected condition status.
+ This ServiceAccount must exist in the installNamespace.
- Allowed values are "True" and "False".
- enum:
- - "True"
- - "False"
- type: string
- type:
- description: type sets the expected condition type,
- i.e. "Ready".
- maxLength: 200
- minLength: 1
- type: string
- required:
- - status
- - type
- type: object
- fieldValue:
- description: fieldValue contains the expected field path
- and value found within.
- properties:
- fieldPath:
- description: |-
- fieldPath sets the field path for the field to check, i.e. "status.phase". The probe will fail
- if the path does not exist.
- maxLength: 200
- minLength: 1
- type: string
- x-kubernetes-validations:
- - message: must contain a valid field path. valid
- fields contain upper or lower-case alphanumeric
- characters separated by the "." character.
- rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
- value:
- description: value sets the expected value found at
- fieldPath, i.e. "Bound".
- maxLength: 200
- minLength: 1
- type: string
- required:
- - fieldPath
- - value
- type: object
- fieldsEqual:
- description: fieldsEqual contains the two field paths
- whose values are expected to match.
- properties:
- fieldA:
- description: |-
- fieldA sets the field path for the first field, i.e. "spec.replicas". The probe will fail
- if the path does not exist.
- maxLength: 200
- minLength: 1
- type: string
- x-kubernetes-validations:
- - message: must contain a valid field path. valid
- fields contain upper or lower-case alphanumeric
- characters separated by the "." character.
- rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
- fieldB:
- description: |-
- fieldB sets the field path for the second field, i.e. "status.readyReplicas". The probe will fail
- if the path does not exist.
- maxLength: 200
- minLength: 1
- type: string
- x-kubernetes-validations:
- - message: must contain a valid field path. valid
- fields contain upper or lower-case alphanumeric
- characters separated by the "." character.
- rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
- required:
- - fieldA
- - fieldB
- type: object
- type:
- description: |-
- type is a required field which specifies the type of probe to use.
+ The name field follows the DNS subdomain standard as defined in [RFC 1123].
+ It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
+ start and end with an alphanumeric character, and be no longer than 253 characters.
- The allowed probe types are "ConditionEqual", "FieldsEqual", and "FieldValue".
+ Some examples of valid values are:
+ - some-serviceaccount
+ - 123-serviceaccount
+ - 1-serviceaccount-2
+ - someserviceaccount
+ - some.serviceaccount
- When set to "ConditionEqual", the probe checks objects that have reached a condition of specified type and status.
- When set to "FieldsEqual", the probe checks that the values found at two provided field paths are matching.
- When set to "FieldValue", the probe checks that the value found at the provided field path matches what was specified.
- enum:
- - ConditionEqual
- - FieldsEqual
- - FieldValue
- type: string
- required:
- - type
- type: object
- x-kubernetes-validations:
- - message: conditionEqual is required when type is ConditionEqual,
- and forbidden otherwise
- rule: 'self.type == ''ConditionEqual'' ?has(self.conditionEqual)
- : !has(self.conditionEqual)'
- - message: fieldsEqual is required when type is FieldsEqual,
- and forbidden otherwise
- rule: 'self.type == ''FieldsEqual'' ?has(self.fieldsEqual)
- : !has(self.fieldsEqual)'
- - message: fieldValue is required when type is FieldValue,
- and forbidden otherwise
- rule: 'self.type == ''FieldValue'' ?has(self.fieldValue)
- : !has(self.fieldValue)'
- maxItems: 20
- minItems: 1
- type: array
- x-kubernetes-list-type: atomic
- selector:
- description: |-
- selector is a required field which defines the method by which we select objects to apply the below
- assertions to. Any object which matches the defined selector will have all the associated assertions
- applied against it.
+ Some examples of invalid values are:
+ - -some-serviceaccount
+ - some-serviceaccount-
- If no objects within a phase are selected by the provided selector, then all assertions defined here
- are considered to have succeeded.
- properties:
- groupKind:
- description: |-
- groupKind specifies the group and kind of objects to select.
+ [RFC 1123]: https://tools.ietf.org/html/rfc1123
+ maxLength: 253
+ type: string
+ x-kubernetes-validations:
+ - message: name is immutable
+ rule: self == oldSelf
+ - message: name must be a valid DNS1123 subdomain. It must contain
+ only lowercase alphanumeric characters, hyphens (-) or periods
+ (.), start and end with an alphanumeric character, and be
+ no longer than 253 characters
+ rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
+ required:
+ - name
+ type: object
+ source:
+ description: |-
+ source is required and selects the installation source of content for this ClusterExtension.
+ Set the sourceType field to perform the selection.
- Required when type is "GroupKind".
+ Catalog is currently the only implemented sourceType.
+ Setting sourceType to "Catalog" requires the catalog field to also be defined.
- Uses the Kubernetes format specified here:
- https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#GroupKind
- properties:
- group:
- type: string
- kind:
- type: string
- required:
- - group
- - kind
- type: object
- label:
- description: |-
- label is the label selector definition.
+ Below is a minimal example of a source definition (in yaml):
- Required when type is "Label".
+ source:
+ sourceType: Catalog
+ catalog:
+ packageName: example-package
+ properties:
+ catalog:
+ description: |-
+ catalog configures how information is sourced from a catalog.
+ It is required when sourceType is "Catalog", and forbidden otherwise.
+ properties:
+ channels:
+ description: |-
+ channels is optional and specifies a set of channels belonging to the package
+ specified in the packageName field.
- A probe using a Label selector will be executed against every object matching the labels or expressions; you must use care
- when using this type of selector. For example, if multiple Kind objects are selected via labels then the probe is
- likely to fail because the values of different Kind objects rarely share the same schema.
+ A channel is a package-author-defined stream of updates for an extension.
- The LabelSelector field uses the following Kubernetes format:
- https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#LabelSelector
- Requires exactly one of matchLabels or matchExpressions.
- properties:
- matchExpressions:
- description: matchExpressions is a list of label selector
- requirements. The requirements are ANDed.
- items:
- description: |-
- A label selector requirement is a selector that contains values, a key, and an operator that
- relates the key and values.
- properties:
- key:
- description: key is the label key that the selector
- applies to.
- type: string
- operator:
- description: |-
- operator represents a key's relationship to a set of values.
- Valid operators are In, NotIn, Exists and DoesNotExist.
- type: string
- values:
- description: |-
- values is an array of string values. If the operator is In or NotIn,
- the values array must be non-empty. If the operator is Exists or DoesNotExist,
- the values array must be empty. This array is replaced during a strategic
- merge patch.
- items:
- type: string
- type: array
- x-kubernetes-list-type: atomic
- required:
- - key
- - operator
- type: object
- type: array
- x-kubernetes-list-type: atomic
- matchLabels:
- additionalProperties:
- type: string
- description: |-
- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
- map is equivalent to an element of matchExpressions, whose key field is "key", the
- operator is "In", and the values array contains only "value". The requirements are ANDed.
- type: object
- type: object
- x-kubernetes-map-type: atomic
- x-kubernetes-validations:
- - message: exactly one of matchLabels or matchExpressions
- must be set
- rule: (has(self.matchExpressions) && !has(self.matchLabels))
- || (!has(self.matchExpressions) && has(self.matchLabels))
- type:
- description: |-
- type is a required field which specifies the type of selector to use.
-
- The allowed selector types are "GroupKind" and "Label".
-
- When set to "GroupKind", all objects which match the specified group and kind will be selected.
- When set to "Label", all objects which match the specified labels and/or expressions will be selected.
- enum:
- - GroupKind
- - Label
- type: string
- required:
- - type
- type: object
- x-kubernetes-validations:
- - message: groupKind is required when type is GroupKind, and
- forbidden otherwise
- rule: 'self.type == ''GroupKind'' ?has(self.groupKind) : !has(self.groupKind)'
- - message: label is required when type is Label, and forbidden
- otherwise
- rule: 'self.type == ''Label'' ?has(self.label) : !has(self.label)'
- required:
- - assertions
- - selector
- type: object
- maxItems: 20
- minItems: 1
- type: array
- x-kubernetes-list-type: atomic
- revision:
- description: |-
- revision is a required, immutable sequence number representing a specific revision
- of the parent ClusterExtension.
+ Each channel in the list must follow the DNS subdomain standard as defined in [RFC 1123].
+ It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
+ start and end with an alphanumeric character, and be no longer than 253 characters.
+ You can specify no more than 256 channels.
- The revision field must be a positive integer.
- Each ClusterExtensionRevision belonging to the same parent ClusterExtension must have a unique revision number.
- The revision number must always be the previous revision number plus one, or 1 for the first revision.
- format: int64
- minimum: 1
- type: integer
- x-kubernetes-validations:
- - message: revision is immutable
- rule: self == oldSelf
- required:
- - collisionProtection
- - lifecycleState
- - revision
- type: object
- status:
- description: status is optional and defines the observed state of the
- ClusterExtensionRevision.
- properties:
- conditions:
- description: |-
- conditions is an optional list of status conditions describing the state of the
- ClusterExtensionRevision.
+ When specified, it constrains the set of installable bundles and the automated upgrade path.
+ This constraint is an AND operation with the version field. For example:
+ - Given channel is set to "foo"
+ - Given version is set to ">=1.0.0, <1.5.0"
+ - Only bundles that exist in channel "foo" AND satisfy the version range comparison are considered installable
+ - Automatic upgrades are constrained to upgrade edges defined by the selected channel
- The Progressing condition represents whether the revision is actively rolling out:
- - When status is True and reason is RollingOut, the ClusterExtensionRevision rollout is actively making progress and is in transition.
- - When status is True and reason is Retrying, the ClusterExtensionRevision has encountered an error that could be resolved on subsequent reconciliation attempts.
- - When status is True and reason is Succeeded, the ClusterExtensionRevision has reached the desired state.
- - When status is False and reason is Blocked, the ClusterExtensionRevision has encountered an error that requires manual intervention for recovery.
- - When status is False and reason is Archived, the ClusterExtensionRevision is archived and not being actively reconciled.
+ When unspecified, upgrade edges across all channels are used to identify valid automatic upgrade paths.
- The Available condition represents whether the revision has been successfully rolled out and is available:
- - When status is True and reason is ProbesSucceeded, the ClusterExtensionRevision has been successfully rolled out and all objects pass their readiness probes.
- - When status is False and reason is ProbeFailure, one or more objects are failing their readiness probes during rollout.
- - When status is Unknown and reason is Reconciling, the ClusterExtensionRevision has encountered an error that prevented it from observing the probes.
- - When status is Unknown and reason is Archived, the ClusterExtensionRevision has been archived and its objects have been torn down.
- - When status is Unknown and reason is Migrated, the ClusterExtensionRevision was migrated from an existing release and object status probe results have not yet been observed.
+ Some examples of valid values are:
+ - 1.1.x
+ - alpha
+ - stable
+ - stable-v1
+ - v1-stable
+ - dev-preview
+ - preview
+ - community
- The Succeeded condition represents whether the revision has successfully completed its rollout:
- - When status is True and reason is Succeeded, the ClusterExtensionRevision has successfully completed its rollout. This condition is set once and persists even if the revision later becomes unavailable.
- 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
- type: object
- type: object
- served: true
- storage: true
- subresources:
- status: {}
----
-# Source: olmv1/templates/crds/customresourcedefinition-clusterextensions.olm.operatorframework.io.yml
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
-metadata:
- annotations:
- controller-gen.kubebuilder.io/version: v0.20.1
- olm.operatorframework.io/generator: experimental
- name: clusterextensions.olm.operatorframework.io
-spec:
- group: olm.operatorframework.io
- names:
- kind: ClusterExtension
- listKind: ClusterExtensionList
- plural: clusterextensions
- singular: clusterextension
- scope: Cluster
- versions:
- - additionalPrinterColumns:
- - jsonPath: .status.install.bundle.name
- name: Installed Bundle
- type: string
- - jsonPath: .status.install.bundle.version
- name: Version
- type: string
- - jsonPath: .status.conditions[?(@.type=='Installed')].status
- name: Installed
- type: string
- - jsonPath: .status.conditions[?(@.type=='Progressing')].status
- name: Progressing
- type: string
- - jsonPath: .metadata.creationTimestamp
- name: Age
- type: date
- name: v1
- schema:
- openAPIV3Schema:
- description: ClusterExtension is the Schema for the clusterextensions API
- properties:
- apiVersion:
- description: |-
- APIVersion defines the versioned schema of this representation of an object.
- Servers should convert recognized schemas to the latest internal value, and
- may reject unrecognized values.
- More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
- type: string
- kind:
- description: |-
- Kind is a string value representing the REST resource this object represents.
- Servers may infer this from the endpoint the client submits requests to.
- Cannot be updated.
- In CamelCase.
- More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
- type: string
- metadata:
- type: object
- spec:
- description: spec is an optional field that defines the desired state
- of the ClusterExtension.
- properties:
- config:
- description: |-
- config is optional and specifies bundle-specific configuration.
- Configuration is bundle-specific and a bundle may provide a configuration schema.
- When not specified, the default configuration of the resolved bundle is used.
+ Some examples of invalid values are:
+ - -some-channel
+ - some-channel-
+ - thisisareallylongchannelnamethatisgreaterthanthemaximumlength
+ - original_40
+ - --default-channel
- config is validated against a configuration schema provided by the resolved bundle. If the bundle does not provide
- a configuration schema the bundle is deemed to not be configurable. More information on how
- to configure bundles can be found in the OLM documentation associated with your current OLM version.
- properties:
- configType:
- description: |-
- configType is required and specifies the type of configuration source.
+ [RFC 1123]: https://tools.ietf.org/html/rfc1123
+ items:
+ maxLength: 253
+ type: string
+ x-kubernetes-validations:
+ - message: channels entries must be valid DNS1123 subdomains
+ rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
+ maxItems: 256
+ type: array
+ packageName:
+ description: |-
+ packageName specifies the name of the package to be installed and is used to filter
+ the content from catalogs.
- The only allowed value is "Inline".
+ It is required, immutable, and follows the DNS subdomain standard as defined in [RFC 1123].
+ It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
+ start and end with an alphanumeric character, and be no longer than 253 characters.
- When set to "Inline", the cluster extension configuration is defined inline within the ClusterExtension resource.
- enum:
- - Inline
- type: string
- inline:
- description: |-
- inline contains JSON or YAML values specified directly in the ClusterExtension.
+ Some examples of valid values are:
+ - some-package
+ - 123-package
+ - 1-package-2
+ - somepackage
- It is used to specify arbitrary configuration values for the ClusterExtension.
- It must be set if configType is 'Inline' and must be a valid JSON/YAML object containing at least one property.
- The configuration values are validated at runtime against a JSON schema provided by the bundle.
- minProperties: 1
- type: object
- x-kubernetes-preserve-unknown-fields: true
- required:
- - configType
- type: object
- x-kubernetes-validations:
- - message: inline is required when configType is Inline, and forbidden
- otherwise
- rule: 'has(self.configType) && self.configType == ''Inline'' ?has(self.inline)
- : !has(self.inline)'
- install:
- description: |-
- install is optional and configures installation options for the ClusterExtension,
- such as the pre-flight check configuration.
- properties:
- preflight:
- description: |-
- preflight is optional and configures the checks that run before installation or upgrade
- of the content for the package specified in the packageName field.
+ Some examples of invalid values are:
+ - -some-package
+ - some-package-
+ - thisisareallylongpackagenamethatisgreaterthanthemaximumlength
+ - some.package
- When specified, it replaces the default preflight configuration for install/upgrade actions.
- When not specified, the default configuration is used.
- properties:
- crdUpgradeSafety:
+ [RFC 1123]: https://tools.ietf.org/html/rfc1123
+ maxLength: 253
+ type: string
+ x-kubernetes-validations:
+ - message: packageName is immutable
+ rule: self == oldSelf
+ - message: packageName must be a valid DNS1123 subdomain.
+ It must contain only lowercase alphanumeric characters,
+ hyphens (-) or periods (.), start and end with an alphanumeric
+ character, and be no longer than 253 characters
+ rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
+ selector:
description: |-
- crdUpgradeSafety configures the CRD Upgrade Safety pre-flight checks that run
- before upgrades of installed content.
+ selector is optional and filters the set of ClusterCatalogs used in the bundle selection process.
- The CRD Upgrade Safety pre-flight check safeguards from unintended consequences of upgrading a CRD,
- such as data loss.
+ When unspecified, all ClusterCatalogs are used in the bundle selection process.
properties:
- enforcement:
+ matchExpressions:
+ description: matchExpressions is a list of label selector
+ requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
description: |-
- enforcement is required and configures the state of the CRD Upgrade Safety pre-flight check.
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ upgradeConstraintPolicy:
+ default: CatalogProvided
+ description: |-
+ upgradeConstraintPolicy is optional and controls whether the upgrade paths defined in the catalog
+ are enforced for the package referenced in the packageName field.
- Allowed values are "None" or "Strict". The default value is "Strict".
+ Allowed values are "CatalogProvided", "SelfCertified", or omitted.
- When set to "None", the CRD Upgrade Safety pre-flight check is skipped during an upgrade operation.
- Use this option with caution as unintended consequences such as data loss can occur.
+ When set to "CatalogProvided", automatic upgrades only occur when upgrade constraints specified by the package
+ author are met.
- When set to "Strict", the CRD Upgrade Safety pre-flight check runs during an upgrade operation.
- enum:
- - None
- - Strict
- type: string
- required:
- - enforcement
- type: object
- required:
- - crdUpgradeSafety
- type: object
- x-kubernetes-validations:
- - message: at least one of [crdUpgradeSafety] are required when
- preflight is specified
- rule: has(self.crdUpgradeSafety)
- type: object
- x-kubernetes-validations:
- - message: at least one of [preflight] are required when install is
- specified
- rule: has(self.preflight)
- namespace:
- description: |-
- namespace specifies a Kubernetes namespace.
- This is the namespace where the provided ServiceAccount must exist.
- It also designates the default namespace where namespace-scoped resources for the extension are applied to the cluster.
- Some extensions may contain namespace-scoped resources to be applied in other namespaces.
- This namespace must exist.
+ When set to "SelfCertified", the upgrade constraints specified by the package author are ignored.
+ This allows upgrades and downgrades to any version of the package.
+ This is considered a dangerous operation as it can lead to unknown and potentially disastrous outcomes,
+ such as data loss.
+ Use this option only if you have independently verified the changes.
- The namespace field is required, immutable, and follows the DNS label standard as defined in [RFC 1123].
- It must contain only lowercase alphanumeric characters or hyphens (-), start and end with an alphanumeric character,
- and be no longer than 63 characters.
+ When omitted, the default value is "CatalogProvided".
+ enum:
+ - CatalogProvided
+ - SelfCertified
+ type: string
+ version:
+ description: |-
+ version is an optional semver constraint (a specific version or range of versions).
+ When unspecified, the latest version available is installed.
- [RFC 1123]: https://tools.ietf.org/html/rfc1123
- maxLength: 63
- type: string
- x-kubernetes-validations:
- - message: namespace is immutable
- rule: self == oldSelf
- - message: namespace must be a valid DNS1123 label
- rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$")
- progressDeadlineMinutes:
- description: |-
- progressDeadlineMinutes is an optional field that defines the maximum period
- of time in minutes after which an installation should be considered failed and
- require manual intervention. This functionality is disabled when no value
- is provided. The minimum period is 10 minutes, and the maximum is 720 minutes (12 hours).
- format: int32
- maximum: 720
- minimum: 10
- type: integer
- serviceAccount:
- description: |-
- serviceAccount specifies a ServiceAccount used to perform all interactions with the cluster
- that are required to manage the extension.
- The ServiceAccount must be configured with the necessary permissions to perform these interactions.
- The ServiceAccount must exist in the namespace referenced in the spec.
- The serviceAccount field is required.
- properties:
- name:
- description: |-
- name is a required, immutable reference to the name of the ServiceAccount used for installation
- and management of the content for the package specified in the packageName field.
+ Acceptable version ranges are no longer than 64 characters.
+ Version ranges are composed of comma- or space-delimited values and one or more comparison operators,
+ known as comparison strings.
+ You can add additional comparison strings using the OR operator (||).
- This ServiceAccount must exist in the installNamespace.
+ # Range Comparisons
- The name field follows the DNS subdomain standard as defined in [RFC 1123].
- It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
- start and end with an alphanumeric character, and be no longer than 253 characters.
+ To specify a version range, you can use a comparison string like ">=3.0,
+ <3.6". When specifying a range, automatic updates will occur within that
+ range. The example comparison string means "install any version greater than
+ or equal to 3.0.0 but less than 3.6.0.". It also states intent that if any
+ upgrades are available within the version range after initial installation,
+ those upgrades should be automatically performed.
- Some examples of valid values are:
- - some-serviceaccount
- - 123-serviceaccount
- - 1-serviceaccount-2
- - someserviceaccount
- - some.serviceaccount
+ # Pinned Versions
- Some examples of invalid values are:
- - -some-serviceaccount
- - some-serviceaccount-
+ To specify an exact version to install you can use a version range that
+ "pins" to a specific version. When pinning to a specific version, no
+ automatic updates will occur. An example of a pinned version range is
+ "0.6.0", which means "only install version 0.6.0 and never
+ upgrade from this version".
- [RFC 1123]: https://tools.ietf.org/html/rfc1123
- maxLength: 253
- type: string
- x-kubernetes-validations:
- - message: name is immutable
- rule: self == oldSelf
- - message: name must be a valid DNS1123 subdomain. It must contain
- only lowercase alphanumeric characters, hyphens (-) or periods
- (.), start and end with an alphanumeric character, and be
- no longer than 253 characters
- rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
- required:
- - name
- type: object
- source:
- description: |-
- source is required and selects the installation source of content for this ClusterExtension.
- Set the sourceType field to perform the selection.
+ # Basic Comparison Operators
- Catalog is currently the only implemented sourceType.
- Setting sourceType to "Catalog" requires the catalog field to also be defined.
+ The basic comparison operators and their meanings are:
+ - "=", equal (not aliased to an operator)
+ - "!=", not equal
+ - "<", less than
+ - ">", greater than
+ - ">=", greater than OR equal to
+ - "<=", less than OR equal to
- Below is a minimal example of a source definition (in yaml):
+ # Wildcard Comparisons
- source:
- sourceType: Catalog
- catalog:
- packageName: example-package
- properties:
- catalog:
- description: |-
- catalog configures how information is sourced from a catalog.
- It is required when sourceType is "Catalog", and forbidden otherwise.
- properties:
- channels:
- description: |-
- channels is optional and specifies a set of channels belonging to the package
- specified in the packageName field.
+ You can use the "x", "X", and "*" characters as wildcard characters in all
+ comparison operations. Some examples of using the wildcard characters:
+ - "1.2.x", "1.2.X", and "1.2.*" is equivalent to ">=1.2.0, < 1.3.0"
+ - ">= 1.2.x", ">= 1.2.X", and ">= 1.2.*" is equivalent to ">= 1.2.0"
+ - "<= 2.x", "<= 2.X", and "<= 2.*" is equivalent to "< 3"
+ - "x", "X", and "*" is equivalent to ">= 0.0.0"
- A channel is a package-author-defined stream of updates for an extension.
+ # Patch Release Comparisons
- Each channel in the list must follow the DNS subdomain standard as defined in [RFC 1123].
- It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
- start and end with an alphanumeric character, and be no longer than 253 characters.
- You can specify no more than 256 channels.
+ When you want to specify a minor version up to the next major version you
+ can use the "~" character to perform patch comparisons. Some examples:
+ - "~1.2.3" is equivalent to ">=1.2.3, <1.3.0"
+ - "~1" and "~1.x" is equivalent to ">=1, <2"
+ - "~2.3" is equivalent to ">=2.3, <2.4"
+ - "~1.2.x" is equivalent to ">=1.2.0, <1.3.0"
+
+ # Major Release Comparisons
+
+ You can use the "^" character to make major release comparisons after a
+ stable 1.0.0 version is published. If there is no stable version published, // minor versions define the stability level. Some examples:
+ - "^1.2.3" is equivalent to ">=1.2.3, <2.0.0"
+ - "^1.2.x" is equivalent to ">=1.2.0, <2.0.0"
+ - "^2.3" is equivalent to ">=2.3, <3"
+ - "^2.x" is equivalent to ">=2.0.0, <3"
+ - "^0.2.3" is equivalent to ">=0.2.3, <0.3.0"
+ - "^0.2" is equivalent to ">=0.2.0, <0.3.0"
+ - "^0.0.3" is equvalent to ">=0.0.3, <0.0.4"
+ - "^0.0" is equivalent to ">=0.0.0, <0.1.0"
+ - "^0" is equivalent to ">=0.0.0, <1.0.0"
- When specified, it constrains the set of installable bundles and the automated upgrade path.
- This constraint is an AND operation with the version field. For example:
- - Given channel is set to "foo"
- - Given version is set to ">=1.0.0, <1.5.0"
- - Only bundles that exist in channel "foo" AND satisfy the version range comparison are considered installable
- - Automatic upgrades are constrained to upgrade edges defined by the selected channel
+ # OR Comparisons
+ You can use the "||" character to represent an OR operation in the version
+ range. Some examples:
+ - ">=1.2.3, <2.0.0 || >3.0.0"
+ - "^0 || ^3 || ^5"
- When unspecified, upgrade edges across all channels are used to identify valid automatic upgrade paths.
+ For more information on semver, please see https://semver.org/
+ maxLength: 64
+ type: string
+ x-kubernetes-validations:
+ - message: invalid version expression
+ rule: self.matches("^(\\s*(=||!=|>|<|>=|=>|<=|=<|~|~>|\\^)\\s*(v?(0|[1-9]\\d*|[x|X|\\*])(\\.(0|[1-9]\\d*|x|X|\\*]))?(\\.(0|[1-9]\\d*|x|X|\\*))?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?)\\s*)((?:\\s+|,\\s*|\\s*\\|\\|\\s*)(=||!=|>|<|>=|=>|<=|=<|~|~>|\\^)\\s*(v?(0|[1-9]\\d*|x|X|\\*])(\\.(0|[1-9]\\d*|x|X|\\*))?(\\.(0|[1-9]\\d*|x|X|\\*]))?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?)\\s*)*$")
+ required:
+ - packageName
+ type: object
+ sourceType:
+ description: |-
+ sourceType is required and specifies the type of install source.
- Some examples of valid values are:
- - 1.1.x
- - alpha
- - stable
- - stable-v1
- - v1-stable
- - dev-preview
- - preview
- - community
+ The only allowed value is "Catalog".
- Some examples of invalid values are:
- - -some-channel
- - some-channel-
- - thisisareallylongchannelnamethatisgreaterthanthemaximumlength
- - original_40
- - --default-channel
+ When set to "Catalog", information for determining the appropriate bundle of content to install
+ is fetched from ClusterCatalog resources on the cluster.
+ When using the Catalog sourceType, the catalog field must also be set.
+ enum:
+ - Catalog
+ type: string
+ required:
+ - sourceType
+ type: object
+ x-kubernetes-validations:
+ - message: catalog is required when sourceType is Catalog, and forbidden
+ otherwise
+ rule: 'has(self.sourceType) && self.sourceType == ''Catalog'' ?
+ has(self.catalog) : !has(self.catalog)'
+ required:
+ - namespace
+ - serviceAccount
+ - source
+ type: object
+ status:
+ 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) ObjectSets,
+ including both installed and rolling out revisions.
+ items:
+ description: RevisionStatus defines the observed state of a ObjectSet.
+ properties:
+ conditions:
+ description: |-
+ conditions optionally expose Progressing and Available condition of the revision,
+ in case when it is not yet marked as successfully installed (condition Succeeded is not set to True).
+ 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 ObjectSet 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.
- [RFC 1123]: https://tools.ietf.org/html/rfc1123
- items:
- maxLength: 253
- type: string
- x-kubernetes-validations:
- - message: channels entries must be valid DNS1123 subdomains
- rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
- maxItems: 256
- type: array
- packageName:
- description: |-
- packageName specifies the name of the package to be installed and is used to filter
- the content from catalogs.
+ The set of condition types which apply to all spec.source variations are Installed and Progressing.
- It is required, immutable, and follows the DNS subdomain standard as defined in [RFC 1123].
- It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
- start and end with an alphanumeric character, and be no longer than 253 characters.
+ 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.
- Some examples of valid values are:
- - some-package
- - 123-package
- - 1-package-2
- - somepackage
+ 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.
- Some examples of invalid values are:
- - -some-package
- - some-package-
- - thisisareallylongpackagenamethatisgreaterthanthemaximumlength
- - some.package
+ When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ObjectSets in active roll out.
- [RFC 1123]: https://tools.ietf.org/html/rfc1123
- maxLength: 253
+ 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.
+ 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
+ install:
+ description: install is a representation of the current installation
+ status for this ClusterExtension.
+ properties:
+ bundle:
+ description: |-
+ bundle is required and represents the identifying attributes of a bundle.
+
+ A "bundle" is a versioned set of content that represents the resources that need to be applied
+ to a cluster to install a package.
+ properties:
+ name:
+ description: |-
+ name is required and follows the DNS subdomain standard as defined in [RFC 1123].
+ It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
+ start and end with an alphanumeric character, and be no longer than 253 characters.
type: string
x-kubernetes-validations:
- - message: packageName is immutable
- rule: self == oldSelf
- message: packageName must be a valid DNS1123 subdomain.
It must contain only lowercase alphanumeric characters,
hyphens (-) or periods (.), start and end with an alphanumeric
character, and be no longer than 253 characters
rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
- selector:
- description: |-
- selector is optional and filters the set of ClusterCatalogs used in the bundle selection process.
-
- When unspecified, all ClusterCatalogs are used in the bundle selection process.
- properties:
- matchExpressions:
- description: matchExpressions is a list of label selector
- requirements. The requirements are ANDed.
- items:
- description: |-
- A label selector requirement is a selector that contains values, a key, and an operator that
- relates the key and values.
- properties:
- key:
- description: key is the label key that the selector
- applies to.
- type: string
- operator:
- description: |-
- operator represents a key's relationship to a set of values.
- Valid operators are In, NotIn, Exists and DoesNotExist.
- type: string
- values:
- description: |-
- values is an array of string values. If the operator is In or NotIn,
- the values array must be non-empty. If the operator is Exists or DoesNotExist,
- the values array must be empty. This array is replaced during a strategic
- merge patch.
- items:
- type: string
- type: array
- x-kubernetes-list-type: atomic
- required:
- - key
- - operator
- type: object
- type: array
- x-kubernetes-list-type: atomic
- matchLabels:
- additionalProperties:
- type: string
- description: |-
- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
- map is equivalent to an element of matchExpressions, whose key field is "key", the
- operator is "In", and the values array contains only "value". The requirements are ANDed.
- type: object
- type: object
- x-kubernetes-map-type: atomic
- upgradeConstraintPolicy:
- default: CatalogProvided
+ version:
description: |-
- upgradeConstraintPolicy is optional and controls whether the upgrade paths defined in the catalog
- are enforced for the package referenced in the packageName field.
+ version is required and references the version that this bundle represents.
+ It follows the semantic versioning standard as defined in https://semver.org/.
+ type: string
+ x-kubernetes-validations:
+ - message: version must be well-formed semver
+ rule: self.matches("^([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(-([-0-9A-Za-z]+(\\.[-0-9A-Za-z]+)*))?(\\+([-0-9A-Za-z]+(-\\.[-0-9A-Za-z]+)*))?")
+ required:
+ - name
+ - version
+ type: object
+ required:
+ - bundle
+ type: object
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+---
+# Source: olmv1/templates/crds/customresourcedefinition-objectsets.olm.operatorframework.io.yml
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.20.1
+ olm.operatorframework.io/generator: experimental
+ name: objectsets.olm.operatorframework.io
+spec:
+ group: olm.operatorframework.io
+ names:
+ kind: ObjectSet
+ listKind: ObjectSetList
+ plural: objectsets
+ singular: objectset
+ scope: Cluster
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .status.conditions[?(@.type=='Available')].status
+ name: Available
+ type: string
+ - jsonPath: .status.conditions[?(@.type=='Progressing')].status
+ name: Progressing
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1
+ schema:
+ openAPIV3Schema:
+ description: |-
+ ObjectSet represents an immutable snapshot of Kubernetes objects
+ for a specific version of a ClusterExtension. Each revision contains objects
+ organized into phases that roll out sequentially. The same object can only be managed by a single revision
+ at a time. Ownership of objects is transitioned from one revision to the next as the extension is upgraded
+ or reconfigured. Once the latest revision has rolled out successfully, previous active revisions are archived for
+ posterity.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: spec defines the desired state of the ObjectSet.
+ properties:
+ collisionProtection:
+ description: |-
+ collisionProtection specifies the default collision protection strategy for all objects
+ in this revision. Individual phases or objects can override this value.
- Allowed values are "CatalogProvided", "SelfCertified", or omitted.
+ When set, this value is used as the default for any phase or object that does not
+ explicitly specify its own collisionProtection.
- When set to "CatalogProvided", automatic upgrades only occur when upgrade constraints specified by the package
- author are met.
+ The resolution order is: object > phase > spec
+ enum:
+ - Prevent
+ - IfNoController
+ - None
+ type: string
+ x-kubernetes-validations:
+ - message: collisionProtection is immutable
+ rule: self == oldSelf
+ lifecycleState:
+ description: |-
+ lifecycleState specifies the lifecycle state of the ObjectSet.
- When set to "SelfCertified", the upgrade constraints specified by the package author are ignored.
- This allows upgrades and downgrades to any version of the package.
- This is considered a dangerous operation as it can lead to unknown and potentially disastrous outcomes,
- such as data loss.
- Use this option only if you have independently verified the changes.
+ When set to "Active", the revision is actively managed and reconciled.
+ When set to "Archived", the revision is inactive and any resources not managed by a subsequent revision are deleted.
+ The revision is removed from the owner list of all objects previously under management.
+ All objects that did not transition to a succeeding revision are deleted.
- When omitted, the default value is "CatalogProvided".
- enum:
- - CatalogProvided
- - SelfCertified
- type: string
- version:
- description: |-
- version is an optional semver constraint (a specific version or range of versions).
- When unspecified, the latest version available is installed.
+ Once a revision is set to "Archived", it cannot be un-archived.
- Acceptable version ranges are no longer than 64 characters.
- Version ranges are composed of comma- or space-delimited values and one or more comparison operators,
- known as comparison strings.
- You can add additional comparison strings using the OR operator (||).
+ It is possible for more than one revision to be "Active" simultaneously. This will occur when
+ moving from one revision to another. The old revision will not be set to "Archived" until the
+ new revision has been completely rolled out.
+ enum:
+ - Active
+ - Archived
+ type: string
+ x-kubernetes-validations:
+ - message: cannot un-archive
+ rule: oldSelf == 'Active' || oldSelf == 'Archived' && oldSelf ==
+ self
+ phases:
+ description: |-
+ phases is an optional, immutable list of phases that group objects to be applied together.
- # Range Comparisons
+ Objects are organized into phases based on their Group-Kind. Common phases include:
+ - namespaces: Namespace objects
+ - policies: ResourceQuota, LimitRange, NetworkPolicy objects
+ - rbac: ServiceAccount, Role, RoleBinding, ClusterRole, ClusterRoleBinding objects
+ - crds: CustomResourceDefinition objects
+ - storage: PersistentVolume, PersistentVolumeClaim, StorageClass objects
+ - deploy: Deployment, StatefulSet, DaemonSet, Service, ConfigMap, Secret objects
+ - publish: Ingress, APIService, Route, Webhook objects
- To specify a version range, you can use a comparison string like ">=3.0,
- <3.6". When specifying a range, automatic updates will occur within that
- range. The example comparison string means "install any version greater than
- or equal to 3.0.0 but less than 3.6.0.". It also states intent that if any
- upgrades are available within the version range after initial installation,
- those upgrades should be automatically performed.
+ All objects in a phase are applied in no particular order.
+ The revision progresses to the next phase only after all objects in the current phase pass their readiness probes.
- # Pinned Versions
+ Once set, even if empty, the phases field is immutable.
- To specify an exact version to install you can use a version range that
- "pins" to a specific version. When pinning to a specific version, no
- automatic updates will occur. An example of a pinned version range is
- "0.6.0", which means "only install version 0.6.0 and never
- upgrade from this version".
+ Each phase in the list must have a unique name. The maximum number of phases is 20.
+ items:
+ description: |-
+ ObjectSetPhase represents a group of objects that are applied together. The phase is considered
+ complete only after all objects pass their status probes.
+ properties:
+ collisionProtection:
+ description: |-
+ collisionProtection specifies the default collision protection strategy for all objects
+ in this phase. Individual objects can override this value.
- # Basic Comparison Operators
+ When set, this value is used as the default for any object in this phase that does not
+ explicitly specify its own collisionProtection.
- The basic comparison operators and their meanings are:
- - "=", equal (not aliased to an operator)
- - "!=", not equal
- - "<", less than
- - ">", greater than
- - ">=", greater than OR equal to
- - "<=", less than OR equal to
+ When omitted, we use .spec.collistionProtection as the default for any object in this phase that does not
+ explicitly specify its own collisionProtection.
+ enum:
+ - Prevent
+ - IfNoController
+ - None
+ type: string
+ name:
+ description: |-
+ name is a required identifier for this phase.
- # Wildcard Comparisons
+ phase names must follow the DNS label standard as defined in [RFC 1123].
+ They must contain only lowercase alphanumeric characters or hyphens (-),
+ start and end with an alphanumeric character, and be no longer than 63 characters.
- You can use the "x", "X", and "*" characters as wildcard characters in all
- comparison operations. Some examples of using the wildcard characters:
- - "1.2.x", "1.2.X", and "1.2.*" is equivalent to ">=1.2.0, < 1.3.0"
- - ">= 1.2.x", ">= 1.2.X", and ">= 1.2.*" is equivalent to ">= 1.2.0"
- - "<= 2.x", "<= 2.X", and "<= 2.*" is equivalent to "< 3"
- - "x", "X", and "*" is equivalent to ">= 0.0.0"
+ Common phase names include: namespaces, policies, rbac, crds, storage, deploy, publish.
- # Patch Release Comparisons
+ [RFC 1123]: https://tools.ietf.org/html/rfc1123
+ maxLength: 63
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: the value must consist of only lowercase alphanumeric
+ characters and hyphens, and must start with an alphabetic
+ character and end with an alphanumeric character.
+ rule: '!format.dns1123Label().validate(self).hasValue()'
+ objects:
+ description: |-
+ objects is a required list of all Kubernetes objects that belong to this phase.
- When you want to specify a minor version up to the next major version you
- can use the "~" character to perform patch comparisons. Some examples:
- - "~1.2.3" is equivalent to ">=1.2.3, <1.3.0"
- - "~1" and "~1.x" is equivalent to ">=1, <2"
- - "~2.3" is equivalent to ">=2.3, <2.4"
- - "~1.2.x" is equivalent to ">=1.2.0, <1.3.0"
+ All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50.
+ items:
+ description: |-
+ ObjectSetObject represents a Kubernetes object to be applied as part
+ of a phase, along with its collision protection settings.
+ properties:
+ collisionProtection:
+ description: |-
+ collisionProtection controls whether the operator can adopt and modify objects
+ that already exist on the cluster.
- # Major Release Comparisons
+ Allowed values are: "Prevent", "IfNoController", and "None".
- You can use the "^" character to make major release comparisons after a
- stable 1.0.0 version is published. If there is no stable version published, // minor versions define the stability level. Some examples:
- - "^1.2.3" is equivalent to ">=1.2.3, <2.0.0"
- - "^1.2.x" is equivalent to ">=1.2.0, <2.0.0"
- - "^2.3" is equivalent to ">=2.3, <3"
- - "^2.x" is equivalent to ">=2.0.0, <3"
- - "^0.2.3" is equivalent to ">=0.2.3, <0.3.0"
- - "^0.2" is equivalent to ">=0.2.0, <0.3.0"
- - "^0.0.3" is equvalent to ">=0.0.3, <0.0.4"
- - "^0.0" is equivalent to ">=0.0.0, <0.1.0"
- - "^0" is equivalent to ">=0.0.0, <1.0.0"
+ When set to "Prevent", the operator only manages objects it created itself.
+ This prevents ownership collisions.
- # OR Comparisons
- You can use the "||" character to represent an OR operation in the version
- range. Some examples:
- - ">=1.2.3, <2.0.0 || >3.0.0"
- - "^0 || ^3 || ^5"
+ When set to "IfNoController", the operator can adopt and modify pre-existing objects
+ that are not owned by another controller.
+ This is useful for taking over management of manually-created resources.
- For more information on semver, please see https://semver.org/
- maxLength: 64
- type: string
- x-kubernetes-validations:
- - message: invalid version expression
- rule: self.matches("^(\\s*(=||!=|>|<|>=|=>|<=|=<|~|~>|\\^)\\s*(v?(0|[1-9]\\d*|[x|X|\\*])(\\.(0|[1-9]\\d*|x|X|\\*]))?(\\.(0|[1-9]\\d*|x|X|\\*))?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?)\\s*)((?:\\s+|,\\s*|\\s*\\|\\|\\s*)(=||!=|>|<|>=|=>|<=|=<|~|~>|\\^)\\s*(v?(0|[1-9]\\d*|x|X|\\*])(\\.(0|[1-9]\\d*|x|X|\\*))?(\\.(0|[1-9]\\d*|x|X|\\*]))?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?)\\s*)*$")
- required:
- - packageName
- type: object
- sourceType:
- description: |-
- sourceType is required and specifies the type of install source.
+ When set to "None", the operator can adopt and modify any pre-existing object, even if
+ owned by another controller.
+ Use this setting with extreme caution as it may cause multiple controllers to fight over
+ the same resource, resulting in increased load on the API server and etcd.
- The only allowed value is "Catalog".
+ When omitted, the value is inherited from the phase, then spec.
+ enum:
+ - Prevent
+ - IfNoController
+ - None
+ type: string
+ object:
+ description: |-
+ object is a required embedded Kubernetes object to be applied.
- When set to "Catalog", information for determining the appropriate bundle of content to install
- is fetched from ClusterCatalog resources on the cluster.
- When using the Catalog sourceType, the catalog field must also be set.
- enum:
- - Catalog
- type: string
- required:
- - sourceType
- type: object
+ This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields.
+ type: object
+ x-kubernetes-embedded-resource: true
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - object
+ type: object
+ maxItems: 50
+ type: array
+ required:
+ - name
+ - objects
+ type: object
+ maxItems: 20
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
x-kubernetes-validations:
- - message: catalog is required when sourceType is Catalog, and forbidden
- otherwise
- rule: 'has(self.sourceType) && self.sourceType == ''Catalog'' ?
- has(self.catalog) : !has(self.catalog)'
- required:
- - namespace
- - serviceAccount
- - source
- type: object
- status:
- description: status is an optional field that defines the observed state
- of the ClusterExtension.
- properties:
- activeRevisions:
+ - message: phases is immutable
+ rule: self == oldSelf || oldSelf.size() == 0
+ progressDeadlineMinutes:
description: |-
- activeRevisions holds a list of currently active (non-archived) ClusterExtensionRevisions,
- including both installed and rolling out revisions.
+ progressDeadlineMinutes is an optional field that defines the maximum period
+ of time in minutes after which an installation should be considered failed and
+ require manual intervention. This functionality is disabled when no value
+ is provided. The minimum period is 10 minutes, and the maximum is 720 minutes (12 hours).
+ format: int32
+ maximum: 720
+ minimum: 10
+ type: integer
+ progressionProbes:
+ description: |-
+ progressionProbes is an optional field which provides the ability to define custom readiness probes
+ for objects defined within spec.phases. As documented in that field, most kubernetes-native objects
+ within the phases already have some kind of readiness check built-in, but this field allows for checks
+ which are tailored to the objects being rolled out - particularly custom resources.
+
+ Probes defined within the progressionProbes list will apply to every phase in the revision. However, the probes will only
+ execute against phase objects which are a match for the provided selector type. For instance, a probe using a GroupKind selector
+ for ConfigMaps will automatically be considered to have passed for any non-ConfigMap object, but will halt any phase containing
+ a ConfigMap if that particular object does not pass the probe check.
+
+ The maximum number of probes is 20.
items:
- description: RevisionStatus defines the observed state of a ClusterExtensionRevision.
+ description: ProgressionProbe provides a custom probe definition,
+ consisting of an object selection method and assertions.
properties:
- conditions:
+ assertions:
description: |-
- conditions optionally expose Progressing and Available condition of the revision,
- in case when it is not yet marked as successfully installed (condition Succeeded is not set to True).
- 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.
+ assertions is a required list of checks which will run against the objects selected by the selector. If
+ one or more assertions fail then the phase within which the object lives will be not be considered
+ 'Ready', blocking rollout of all subsequent phases.
items:
- description: Condition contains details for one aspect of
- the current state of this API Resource.
+ description: Assertion is a discriminated union which defines
+ the probe type and definition used as an assertion.
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:
+ conditionEqual:
+ description: conditionEqual contains the expected condition
+ type and status.
+ properties:
+ status:
+ description: |-
+ status sets the expected condition status.
+
+ Allowed values are "True" and "False".
+ enum:
+ - "True"
+ - "False"
+ type: string
+ type:
+ description: type sets the expected condition type,
+ i.e. "Ready".
+ maxLength: 200
+ minLength: 1
+ type: string
+ required:
+ - status
+ - type
+ type: object
+ fieldValue:
+ description: fieldValue contains the expected field path
+ and value found within.
+ properties:
+ fieldPath:
+ description: |-
+ fieldPath sets the field path for the field to check, i.e. "status.phase". The probe will fail
+ if the path does not exist.
+ maxLength: 200
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: must contain a valid field path. valid
+ fields contain upper or lower-case alphanumeric
+ characters separated by the "." character.
+ rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
+ value:
+ description: value sets the expected value found at
+ fieldPath, i.e. "Bound".
+ maxLength: 200
+ minLength: 1
+ type: string
+ required:
+ - fieldPath
+ - value
+ type: object
+ fieldsEqual:
+ description: fieldsEqual contains the two field paths
+ whose values are expected to match.
+ properties:
+ fieldA:
+ description: |-
+ fieldA sets the field path for the first field, i.e. "spec.replicas". The probe will fail
+ if the path does not exist.
+ maxLength: 200
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: must contain a valid field path. valid
+ fields contain upper or lower-case alphanumeric
+ characters separated by the "." character.
+ rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
+ fieldB:
+ description: |-
+ fieldB sets the field path for the second field, i.e. "status.readyReplicas". The probe will fail
+ if the path does not exist.
+ maxLength: 200
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: must contain a valid field path. valid
+ fields contain upper or lower-case alphanumeric
+ characters separated by the "." character.
+ rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
+ required:
+ - fieldA
+ - fieldB
+ type: object
+ type:
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.
+ type is a required field which specifies the type of probe to use.
+
+ The allowed probe types are "ConditionEqual", "FieldsEqual", and "FieldValue".
+
+ When set to "ConditionEqual", the probe checks objects that have reached a condition of specified type and status.
+ When set to "FieldsEqual", the probe checks that the values found at two provided field paths are matching.
+ When set to "FieldValue", the probe checks that the value found at the provided field path matches what was specified.
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])$
+ - ConditionEqual
+ - FieldsEqual
+ - FieldValue
type: string
required:
- - lastTransitionTime
- - message
- - reason
- - status
- type
type: object
+ x-kubernetes-validations:
+ - message: conditionEqual is required when type is ConditionEqual,
+ and forbidden otherwise
+ rule: 'self.type == ''ConditionEqual'' ?has(self.conditionEqual)
+ : !has(self.conditionEqual)'
+ - message: fieldsEqual is required when type is FieldsEqual,
+ and forbidden otherwise
+ rule: 'self.type == ''FieldsEqual'' ?has(self.fieldsEqual)
+ : !has(self.fieldsEqual)'
+ - message: fieldValue is required when type is FieldValue,
+ and forbidden otherwise
+ rule: 'self.type == ''FieldValue'' ?has(self.fieldValue)
+ : !has(self.fieldValue)'
+ maxItems: 20
+ minItems: 1
type: array
- x-kubernetes-list-map-keys:
+ x-kubernetes-list-type: atomic
+ selector:
+ description: |-
+ selector is a required field which defines the method by which we select objects to apply the below
+ assertions to. Any object which matches the defined selector will have all the associated assertions
+ applied against it.
+
+ If no objects within a phase are selected by the provided selector, then all assertions defined here
+ are considered to have succeeded.
+ properties:
+ groupKind:
+ description: |-
+ groupKind specifies the group and kind of objects to select.
+
+ Required when type is "GroupKind".
+
+ Uses the Kubernetes format specified here:
+ https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#GroupKind
+ properties:
+ group:
+ type: string
+ kind:
+ type: string
+ required:
+ - group
+ - kind
+ type: object
+ label:
+ description: |-
+ label is the label selector definition.
+
+ Required when type is "Label".
+
+ A probe using a Label selector will be executed against every object matching the labels or expressions; you must use care
+ when using this type of selector. For example, if multiple Kind objects are selected via labels then the probe is
+ likely to fail because the values of different Kind objects rarely share the same schema.
+
+ The LabelSelector field uses the following Kubernetes format:
+ https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#LabelSelector
+ Requires exactly one of matchLabels or matchExpressions.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector
+ requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ x-kubernetes-validations:
+ - message: exactly one of matchLabels or matchExpressions
+ must be set
+ rule: (has(self.matchExpressions) && !has(self.matchLabels))
+ || (!has(self.matchExpressions) && has(self.matchLabels))
+ type:
+ description: |-
+ type is a required field which specifies the type of selector to use.
+
+ The allowed selector types are "GroupKind" and "Label".
+
+ When set to "GroupKind", all objects which match the specified group and kind will be selected.
+ When set to "Label", all objects which match the specified labels and/or expressions will be selected.
+ enum:
+ - GroupKind
+ - Label
+ type: string
+ required:
- type
- x-kubernetes-list-type: map
- name:
- description: name of the ClusterExtensionRevision resource
- type: string
+ type: object
+ x-kubernetes-validations:
+ - message: groupKind is required when type is GroupKind, and
+ forbidden otherwise
+ rule: 'self.type == ''GroupKind'' ?has(self.groupKind) : !has(self.groupKind)'
+ - message: label is required when type is Label, and forbidden
+ otherwise
+ rule: 'self.type == ''Label'' ?has(self.label) : !has(self.label)'
required:
- - name
+ - assertions
+ - selector
type: object
+ maxItems: 20
+ minItems: 1
type: array
- x-kubernetes-list-map-keys:
- - name
- x-kubernetes-list-type: map
- conditions:
+ x-kubernetes-list-type: atomic
+ revision:
description: |-
- conditions represents the current state of the ClusterExtension.
-
- The set of condition types which apply to all spec.source variations are Installed and Progressing.
+ revision is a required, immutable sequence number representing a specific revision
+ of the parent ClusterExtension.
- 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 revision field must be a positive integer.
+ Each ObjectSet belonging to the same parent ClusterExtension must have a unique revision number.
+ The revision number must always be the previous revision number plus one, or 1 for the first revision.
+ format: int64
+ minimum: 1
+ type: integer
+ x-kubernetes-validations:
+ - message: revision is immutable
+ rule: self == oldSelf
+ required:
+ - collisionProtection
+ - lifecycleState
+ - revision
+ type: object
+ status:
+ description: status is optional and defines the observed state of the
+ ObjectSet.
+ properties:
+ conditions:
+ description: |-
+ conditions is an optional list of status conditions describing the state of the
+ ObjectSet.
- 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.
+ The Progressing condition represents whether the revision is actively rolling out:
+ - When status is True and reason is RollingOut, the ObjectSet rollout is actively making progress and is in transition.
+ - When status is True and reason is Retrying, the ObjectSet has encountered an error that could be resolved on subsequent reconciliation attempts.
+ - When status is True and reason is Succeeded, the ObjectSet has reached the desired state.
+ - When status is False and reason is Blocked, the ObjectSet has encountered an error that requires manual intervention for recovery.
+ - When status is False and reason is Archived, the ObjectSet is archived and not being actively reconciled.
- When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterExtensionRevisions in active roll out.
+ The Available condition represents whether the revision has been successfully rolled out and is available:
+ - When status is True and reason is ProbesSucceeded, the ObjectSet has been successfully rolled out and all objects pass their readiness probes.
+ - When status is False and reason is ProbeFailure, one or more objects are failing their readiness probes during rollout.
+ - When status is Unknown and reason is Reconciling, the ObjectSet has encountered an error that prevented it from observing the probes.
+ - When status is Unknown and reason is Archived, the ObjectSet has been archived and its objects have been torn down.
+ - When status is Unknown and reason is Migrated, the ObjectSet was migrated from an existing release and object status probe results have not yet been observed.
- 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.
+ The Succeeded condition represents whether the revision has successfully completed its rollout:
+ - When status is True and reason is Succeeded, the ObjectSet has successfully completed its rollout. This condition is set once and persists even if the revision later becomes unavailable.
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
@@ -1870,44 +1908,6 @@ spec:
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
- install:
- description: install is a representation of the current installation
- status for this ClusterExtension.
- properties:
- bundle:
- description: |-
- bundle is required and represents the identifying attributes of a bundle.
-
- A "bundle" is a versioned set of content that represents the resources that need to be applied
- to a cluster to install a package.
- properties:
- name:
- description: |-
- name is required and follows the DNS subdomain standard as defined in [RFC 1123].
- It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
- start and end with an alphanumeric character, and be no longer than 253 characters.
- type: string
- x-kubernetes-validations:
- - message: packageName must be a valid DNS1123 subdomain.
- It must contain only lowercase alphanumeric characters,
- hyphens (-) or periods (.), start and end with an alphanumeric
- character, and be no longer than 253 characters
- rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
- version:
- description: |-
- version is required and references the version that this bundle represents.
- It follows the semantic versioning standard as defined in https://semver.org/.
- type: string
- x-kubernetes-validations:
- - message: version must be well-formed semver
- rule: self.matches("^([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(-([-0-9A-Za-z]+(\\.[-0-9A-Za-z]+)*))?(\\+([-0-9A-Za-z]+(-\\.[-0-9A-Za-z]+)*))?")
- required:
- - name
- - version
- type: object
- required:
- - bundle
- type: object
type: object
type: object
served: true
@@ -2133,7 +2133,7 @@ rules:
- apiGroups:
- olm.operatorframework.io
resources:
- - clusterextensionrevisions
+ - objectsets
verbs:
- create
- delete
@@ -2145,14 +2145,14 @@ rules:
- apiGroups:
- olm.operatorframework.io
resources:
- - clusterextensionrevisions/status
+ - objectsets/status
verbs:
- patch
- update
- apiGroups:
- olm.operatorframework.io
resources:
- - clusterextensionrevisions/finalizers
+ - objectsets/finalizers
verbs:
- update
---
diff --git a/manifests/experimental.yaml b/manifests/experimental.yaml
index 8604a7db8d..3982202847 100644
--- a/manifests/experimental.yaml
+++ b/manifests/experimental.yaml
@@ -571,26 +571,32 @@ spec:
subresources:
status: {}
---
-# Source: olmv1/templates/crds/customresourcedefinition-clusterextensionrevisions.olm.operatorframework.io.yml
+# Source: olmv1/templates/crds/customresourcedefinition-clusterextensions.olm.operatorframework.io.yml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.20.1
olm.operatorframework.io/generator: experimental
- name: clusterextensionrevisions.olm.operatorframework.io
+ name: clusterextensions.olm.operatorframework.io
spec:
group: olm.operatorframework.io
names:
- kind: ClusterExtensionRevision
- listKind: ClusterExtensionRevisionList
- plural: clusterextensionrevisions
- singular: clusterextensionrevision
+ kind: ClusterExtension
+ listKind: ClusterExtensionList
+ plural: clusterextensions
+ singular: clusterextension
scope: Cluster
versions:
- additionalPrinterColumns:
- - jsonPath: .status.conditions[?(@.type=='Available')].status
- name: Available
+ - jsonPath: .status.install.bundle.name
+ name: Installed Bundle
+ type: string
+ - jsonPath: .status.install.bundle.version
+ name: Version
+ type: string
+ - jsonPath: .status.conditions[?(@.type=='Installed')].status
+ name: Installed
type: string
- jsonPath: .status.conditions[?(@.type=='Progressing')].status
name: Progressing
@@ -601,13 +607,7 @@ spec:
name: v1
schema:
openAPIV3Schema:
- description: |-
- ClusterExtensionRevision represents an immutable snapshot of Kubernetes objects
- for a specific version of a ClusterExtension. Each revision contains objects
- organized into phases that roll out sequentially. The same object can only be managed by a single revision
- at a time. Ownership of objects is transitioned from one revision to the next as the extension is upgraded
- or reconfigured. Once the latest revision has rolled out successfully, previous active revisions are archived for
- posterity.
+ description: ClusterExtension is the Schema for the clusterextensions API
properties:
apiVersion:
description: |-
@@ -627,165 +627,117 @@ spec:
metadata:
type: object
spec:
- description: spec defines the desired state of the ClusterExtensionRevision.
+ description: spec is an optional field that defines the desired state
+ of the ClusterExtension.
properties:
- collisionProtection:
+ config:
description: |-
- collisionProtection specifies the default collision protection strategy for all objects
- in this revision. Individual phases or objects can override this value.
-
- When set, this value is used as the default for any phase or object that does not
- explicitly specify its own collisionProtection.
+ config is optional and specifies bundle-specific configuration.
+ Configuration is bundle-specific and a bundle may provide a configuration schema.
+ When not specified, the default configuration of the resolved bundle is used.
- The resolution order is: object > phase > spec
- enum:
- - Prevent
- - IfNoController
- - None
- type: string
- x-kubernetes-validations:
- - message: collisionProtection is immutable
- rule: self == oldSelf
- lifecycleState:
- description: |-
- lifecycleState specifies the lifecycle state of the ClusterExtensionRevision.
+ config is validated against a configuration schema provided by the resolved bundle. If the bundle does not provide
+ a configuration schema the bundle is deemed to not be configurable. More information on how
+ to configure bundles can be found in the OLM documentation associated with your current OLM version.
+ properties:
+ configType:
+ description: |-
+ configType is required and specifies the type of configuration source.
- When set to "Active", the revision is actively managed and reconciled.
- When set to "Archived", the revision is inactive and any resources not managed by a subsequent revision are deleted.
- The revision is removed from the owner list of all objects previously under management.
- All objects that did not transition to a succeeding revision are deleted.
+ The only allowed value is "Inline".
- Once a revision is set to "Archived", it cannot be un-archived.
+ When set to "Inline", the cluster extension configuration is defined inline within the ClusterExtension resource.
+ enum:
+ - Inline
+ type: string
+ inline:
+ description: |-
+ inline contains JSON or YAML values specified directly in the ClusterExtension.
- It is possible for more than one revision to be "Active" simultaneously. This will occur when
- moving from one revision to another. The old revision will not be set to "Archived" until the
- new revision has been completely rolled out.
- enum:
- - Active
- - Archived
- type: string
+ It is used to specify arbitrary configuration values for the ClusterExtension.
+ It must be set if configType is 'Inline' and must be a valid JSON/YAML object containing at least one property.
+ The configuration values are validated at runtime against a JSON schema provided by the bundle.
+ minProperties: 1
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - configType
+ type: object
x-kubernetes-validations:
- - message: cannot un-archive
- rule: oldSelf == 'Active' || oldSelf == 'Archived' && oldSelf ==
- self
- phases:
+ - message: inline is required when configType is Inline, and forbidden
+ otherwise
+ rule: 'has(self.configType) && self.configType == ''Inline'' ?has(self.inline)
+ : !has(self.inline)'
+ install:
description: |-
- phases is an optional, immutable list of phases that group objects to be applied together.
-
- Objects are organized into phases based on their Group-Kind. Common phases include:
- - namespaces: Namespace objects
- - policies: ResourceQuota, LimitRange, NetworkPolicy objects
- - rbac: ServiceAccount, Role, RoleBinding, ClusterRole, ClusterRoleBinding objects
- - crds: CustomResourceDefinition objects
- - storage: PersistentVolume, PersistentVolumeClaim, StorageClass objects
- - deploy: Deployment, StatefulSet, DaemonSet, Service, ConfigMap, Secret objects
- - publish: Ingress, APIService, Route, Webhook objects
-
- All objects in a phase are applied in no particular order.
- The revision progresses to the next phase only after all objects in the current phase pass their readiness probes.
-
- Once set, even if empty, the phases field is immutable.
-
- Each phase in the list must have a unique name. The maximum number of phases is 20.
- items:
- description: |-
- ClusterExtensionRevisionPhase represents a group of objects that are applied together. The phase is considered
- complete only after all objects pass their status probes.
- properties:
- collisionProtection:
- description: |-
- collisionProtection specifies the default collision protection strategy for all objects
- in this phase. Individual objects can override this value.
-
- When set, this value is used as the default for any object in this phase that does not
- explicitly specify its own collisionProtection.
-
- When omitted, we use .spec.collistionProtection as the default for any object in this phase that does not
- explicitly specify its own collisionProtection.
- enum:
- - Prevent
- - IfNoController
- - None
- type: string
- name:
- description: |-
- name is a required identifier for this phase.
-
- phase names must follow the DNS label standard as defined in [RFC 1123].
- They must contain only lowercase alphanumeric characters or hyphens (-),
- start and end with an alphanumeric character, and be no longer than 63 characters.
-
- Common phase names include: namespaces, policies, rbac, crds, storage, deploy, publish.
-
- [RFC 1123]: https://tools.ietf.org/html/rfc1123
- maxLength: 63
- minLength: 1
- type: string
- x-kubernetes-validations:
- - message: the value must consist of only lowercase alphanumeric
- characters and hyphens, and must start with an alphabetic
- character and end with an alphanumeric character.
- rule: '!format.dns1123Label().validate(self).hasValue()'
- objects:
- description: |-
- objects is a required list of all Kubernetes objects that belong to this phase.
+ install is optional and configures installation options for the ClusterExtension,
+ such as the pre-flight check configuration.
+ properties:
+ preflight:
+ description: |-
+ preflight is optional and configures the checks that run before installation or upgrade
+ of the content for the package specified in the packageName field.
- All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50.
- items:
+ When specified, it replaces the default preflight configuration for install/upgrade actions.
+ When not specified, the default configuration is used.
+ properties:
+ crdUpgradeSafety:
description: |-
- ClusterExtensionRevisionObject represents a Kubernetes object to be applied as part
- of a phase, along with its collision protection settings.
+ crdUpgradeSafety configures the CRD Upgrade Safety pre-flight checks that run
+ before upgrades of installed content.
+
+ The CRD Upgrade Safety pre-flight check safeguards from unintended consequences of upgrading a CRD,
+ such as data loss.
properties:
- collisionProtection:
+ enforcement:
description: |-
- collisionProtection controls whether the operator can adopt and modify objects
- that already exist on the cluster.
-
- Allowed values are: "Prevent", "IfNoController", and "None".
-
- When set to "Prevent", the operator only manages objects it created itself.
- This prevents ownership collisions.
+ enforcement is required and configures the state of the CRD Upgrade Safety pre-flight check.
- When set to "IfNoController", the operator can adopt and modify pre-existing objects
- that are not owned by another controller.
- This is useful for taking over management of manually-created resources.
+ Allowed values are "None" or "Strict". The default value is "Strict".
- When set to "None", the operator can adopt and modify any pre-existing object, even if
- owned by another controller.
- Use this setting with extreme caution as it may cause multiple controllers to fight over
- the same resource, resulting in increased load on the API server and etcd.
+ When set to "None", the CRD Upgrade Safety pre-flight check is skipped during an upgrade operation.
+ Use this option with caution as unintended consequences such as data loss can occur.
- When omitted, the value is inherited from the phase, then spec.
+ When set to "Strict", the CRD Upgrade Safety pre-flight check runs during an upgrade operation.
enum:
- - Prevent
- - IfNoController
- None
+ - Strict
type: string
- object:
- description: |-
- object is a required embedded Kubernetes object to be applied.
-
- This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields.
- type: object
- x-kubernetes-embedded-resource: true
- x-kubernetes-preserve-unknown-fields: true
required:
- - object
+ - enforcement
type: object
- maxItems: 50
- type: array
- required:
- - name
- - objects
- type: object
- maxItems: 20
- type: array
- x-kubernetes-list-map-keys:
- - name
- x-kubernetes-list-type: map
+ required:
+ - crdUpgradeSafety
+ type: object
+ x-kubernetes-validations:
+ - message: at least one of [crdUpgradeSafety] are required when
+ preflight is specified
+ rule: has(self.crdUpgradeSafety)
+ type: object
x-kubernetes-validations:
- - message: phases is immutable
- rule: self == oldSelf || oldSelf.size() == 0
+ - message: at least one of [preflight] are required when install is
+ specified
+ rule: has(self.preflight)
+ namespace:
+ description: |-
+ namespace specifies a Kubernetes namespace.
+ This is the namespace where the provided ServiceAccount must exist.
+ It also designates the default namespace where namespace-scoped resources for the extension are applied to the cluster.
+ Some extensions may contain namespace-scoped resources to be applied in other namespaces.
+ This namespace must exist.
+
+ The namespace field is required, immutable, and follows the DNS label standard as defined in [RFC 1123].
+ It must contain only lowercase alphanumeric characters or hyphens (-), start and end with an alphanumeric character,
+ and be no longer than 63 characters.
+
+ [RFC 1123]: https://tools.ietf.org/html/rfc1123
+ maxLength: 63
+ type: string
+ x-kubernetes-validations:
+ - message: namespace is immutable
+ rule: self == oldSelf
+ - message: namespace must be a valid DNS1123 label
+ rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$")
progressDeadlineMinutes:
description: |-
progressDeadlineMinutes is an optional field that defines the maximum period
@@ -796,983 +748,1069 @@ spec:
maximum: 720
minimum: 10
type: integer
- progressionProbes:
+ serviceAccount:
description: |-
- progressionProbes is an optional field which provides the ability to define custom readiness probes
- for objects defined within spec.phases. As documented in that field, most kubernetes-native objects
- within the phases already have some kind of readiness check built-in, but this field allows for checks
- which are tailored to the objects being rolled out - particularly custom resources.
-
- Probes defined within the progressionProbes list will apply to every phase in the revision. However, the probes will only
- execute against phase objects which are a match for the provided selector type. For instance, a probe using a GroupKind selector
- for ConfigMaps will automatically be considered to have passed for any non-ConfigMap object, but will halt any phase containing
- a ConfigMap if that particular object does not pass the probe check.
+ serviceAccount specifies a ServiceAccount used to perform all interactions with the cluster
+ that are required to manage the extension.
+ The ServiceAccount must be configured with the necessary permissions to perform these interactions.
+ The ServiceAccount must exist in the namespace referenced in the spec.
+ The serviceAccount field is required.
+ properties:
+ name:
+ description: |-
+ name is a required, immutable reference to the name of the ServiceAccount used for installation
+ and management of the content for the package specified in the packageName field.
- The maximum number of probes is 20.
- items:
- description: ProgressionProbe provides a custom probe definition,
- consisting of an object selection method and assertions.
- properties:
- assertions:
- description: |-
- assertions is a required list of checks which will run against the objects selected by the selector. If
- one or more assertions fail then the phase within which the object lives will be not be considered
- 'Ready', blocking rollout of all subsequent phases.
- items:
- description: Assertion is a discriminated union which defines
- the probe type and definition used as an assertion.
- properties:
- conditionEqual:
- description: conditionEqual contains the expected condition
- type and status.
- properties:
- status:
- description: |-
- status sets the expected condition status.
+ This ServiceAccount must exist in the installNamespace.
- Allowed values are "True" and "False".
- enum:
- - "True"
- - "False"
- type: string
- type:
- description: type sets the expected condition type,
- i.e. "Ready".
- maxLength: 200
- minLength: 1
- type: string
- required:
- - status
- - type
- type: object
- fieldValue:
- description: fieldValue contains the expected field path
- and value found within.
- properties:
- fieldPath:
- description: |-
- fieldPath sets the field path for the field to check, i.e. "status.phase". The probe will fail
- if the path does not exist.
- maxLength: 200
- minLength: 1
- type: string
- x-kubernetes-validations:
- - message: must contain a valid field path. valid
- fields contain upper or lower-case alphanumeric
- characters separated by the "." character.
- rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
- value:
- description: value sets the expected value found at
- fieldPath, i.e. "Bound".
- maxLength: 200
- minLength: 1
- type: string
- required:
- - fieldPath
- - value
- type: object
- fieldsEqual:
- description: fieldsEqual contains the two field paths
- whose values are expected to match.
- properties:
- fieldA:
- description: |-
- fieldA sets the field path for the first field, i.e. "spec.replicas". The probe will fail
- if the path does not exist.
- maxLength: 200
- minLength: 1
- type: string
- x-kubernetes-validations:
- - message: must contain a valid field path. valid
- fields contain upper or lower-case alphanumeric
- characters separated by the "." character.
- rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
- fieldB:
- description: |-
- fieldB sets the field path for the second field, i.e. "status.readyReplicas". The probe will fail
- if the path does not exist.
- maxLength: 200
- minLength: 1
- type: string
- x-kubernetes-validations:
- - message: must contain a valid field path. valid
- fields contain upper or lower-case alphanumeric
- characters separated by the "." character.
- rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
- required:
- - fieldA
- - fieldB
- type: object
- type:
- description: |-
- type is a required field which specifies the type of probe to use.
+ The name field follows the DNS subdomain standard as defined in [RFC 1123].
+ It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
+ start and end with an alphanumeric character, and be no longer than 253 characters.
- The allowed probe types are "ConditionEqual", "FieldsEqual", and "FieldValue".
+ Some examples of valid values are:
+ - some-serviceaccount
+ - 123-serviceaccount
+ - 1-serviceaccount-2
+ - someserviceaccount
+ - some.serviceaccount
- When set to "ConditionEqual", the probe checks objects that have reached a condition of specified type and status.
- When set to "FieldsEqual", the probe checks that the values found at two provided field paths are matching.
- When set to "FieldValue", the probe checks that the value found at the provided field path matches what was specified.
- enum:
- - ConditionEqual
- - FieldsEqual
- - FieldValue
- type: string
- required:
- - type
- type: object
- x-kubernetes-validations:
- - message: conditionEqual is required when type is ConditionEqual,
- and forbidden otherwise
- rule: 'self.type == ''ConditionEqual'' ?has(self.conditionEqual)
- : !has(self.conditionEqual)'
- - message: fieldsEqual is required when type is FieldsEqual,
- and forbidden otherwise
- rule: 'self.type == ''FieldsEqual'' ?has(self.fieldsEqual)
- : !has(self.fieldsEqual)'
- - message: fieldValue is required when type is FieldValue,
- and forbidden otherwise
- rule: 'self.type == ''FieldValue'' ?has(self.fieldValue)
- : !has(self.fieldValue)'
- maxItems: 20
- minItems: 1
- type: array
- x-kubernetes-list-type: atomic
- selector:
- description: |-
- selector is a required field which defines the method by which we select objects to apply the below
- assertions to. Any object which matches the defined selector will have all the associated assertions
- applied against it.
+ Some examples of invalid values are:
+ - -some-serviceaccount
+ - some-serviceaccount-
- If no objects within a phase are selected by the provided selector, then all assertions defined here
- are considered to have succeeded.
- properties:
- groupKind:
- description: |-
- groupKind specifies the group and kind of objects to select.
+ [RFC 1123]: https://tools.ietf.org/html/rfc1123
+ maxLength: 253
+ type: string
+ x-kubernetes-validations:
+ - message: name is immutable
+ rule: self == oldSelf
+ - message: name must be a valid DNS1123 subdomain. It must contain
+ only lowercase alphanumeric characters, hyphens (-) or periods
+ (.), start and end with an alphanumeric character, and be
+ no longer than 253 characters
+ rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
+ required:
+ - name
+ type: object
+ source:
+ description: |-
+ source is required and selects the installation source of content for this ClusterExtension.
+ Set the sourceType field to perform the selection.
- Required when type is "GroupKind".
+ Catalog is currently the only implemented sourceType.
+ Setting sourceType to "Catalog" requires the catalog field to also be defined.
- Uses the Kubernetes format specified here:
- https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#GroupKind
- properties:
- group:
- type: string
- kind:
- type: string
- required:
- - group
- - kind
- type: object
- label:
- description: |-
- label is the label selector definition.
+ Below is a minimal example of a source definition (in yaml):
- Required when type is "Label".
+ source:
+ sourceType: Catalog
+ catalog:
+ packageName: example-package
+ properties:
+ catalog:
+ description: |-
+ catalog configures how information is sourced from a catalog.
+ It is required when sourceType is "Catalog", and forbidden otherwise.
+ properties:
+ channels:
+ description: |-
+ channels is optional and specifies a set of channels belonging to the package
+ specified in the packageName field.
- A probe using a Label selector will be executed against every object matching the labels or expressions; you must use care
- when using this type of selector. For example, if multiple Kind objects are selected via labels then the probe is
- likely to fail because the values of different Kind objects rarely share the same schema.
+ A channel is a package-author-defined stream of updates for an extension.
- The LabelSelector field uses the following Kubernetes format:
- https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#LabelSelector
- Requires exactly one of matchLabels or matchExpressions.
- properties:
- matchExpressions:
- description: matchExpressions is a list of label selector
- requirements. The requirements are ANDed.
- items:
- description: |-
- A label selector requirement is a selector that contains values, a key, and an operator that
- relates the key and values.
- properties:
- key:
- description: key is the label key that the selector
- applies to.
- type: string
- operator:
- description: |-
- operator represents a key's relationship to a set of values.
- Valid operators are In, NotIn, Exists and DoesNotExist.
- type: string
- values:
- description: |-
- values is an array of string values. If the operator is In or NotIn,
- the values array must be non-empty. If the operator is Exists or DoesNotExist,
- the values array must be empty. This array is replaced during a strategic
- merge patch.
- items:
- type: string
- type: array
- x-kubernetes-list-type: atomic
- required:
- - key
- - operator
- type: object
- type: array
- x-kubernetes-list-type: atomic
- matchLabels:
- additionalProperties:
- type: string
- description: |-
- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
- map is equivalent to an element of matchExpressions, whose key field is "key", the
- operator is "In", and the values array contains only "value". The requirements are ANDed.
- type: object
- type: object
- x-kubernetes-map-type: atomic
- x-kubernetes-validations:
- - message: exactly one of matchLabels or matchExpressions
- must be set
- rule: (has(self.matchExpressions) && !has(self.matchLabels))
- || (!has(self.matchExpressions) && has(self.matchLabels))
- type:
- description: |-
- type is a required field which specifies the type of selector to use.
-
- The allowed selector types are "GroupKind" and "Label".
-
- When set to "GroupKind", all objects which match the specified group and kind will be selected.
- When set to "Label", all objects which match the specified labels and/or expressions will be selected.
- enum:
- - GroupKind
- - Label
- type: string
- required:
- - type
- type: object
- x-kubernetes-validations:
- - message: groupKind is required when type is GroupKind, and
- forbidden otherwise
- rule: 'self.type == ''GroupKind'' ?has(self.groupKind) : !has(self.groupKind)'
- - message: label is required when type is Label, and forbidden
- otherwise
- rule: 'self.type == ''Label'' ?has(self.label) : !has(self.label)'
- required:
- - assertions
- - selector
- type: object
- maxItems: 20
- minItems: 1
- type: array
- x-kubernetes-list-type: atomic
- revision:
- description: |-
- revision is a required, immutable sequence number representing a specific revision
- of the parent ClusterExtension.
+ Each channel in the list must follow the DNS subdomain standard as defined in [RFC 1123].
+ It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
+ start and end with an alphanumeric character, and be no longer than 253 characters.
+ You can specify no more than 256 channels.
- The revision field must be a positive integer.
- Each ClusterExtensionRevision belonging to the same parent ClusterExtension must have a unique revision number.
- The revision number must always be the previous revision number plus one, or 1 for the first revision.
- format: int64
- minimum: 1
- type: integer
- x-kubernetes-validations:
- - message: revision is immutable
- rule: self == oldSelf
- required:
- - collisionProtection
- - lifecycleState
- - revision
- type: object
- status:
- description: status is optional and defines the observed state of the
- ClusterExtensionRevision.
- properties:
- conditions:
- description: |-
- conditions is an optional list of status conditions describing the state of the
- ClusterExtensionRevision.
+ When specified, it constrains the set of installable bundles and the automated upgrade path.
+ This constraint is an AND operation with the version field. For example:
+ - Given channel is set to "foo"
+ - Given version is set to ">=1.0.0, <1.5.0"
+ - Only bundles that exist in channel "foo" AND satisfy the version range comparison are considered installable
+ - Automatic upgrades are constrained to upgrade edges defined by the selected channel
- The Progressing condition represents whether the revision is actively rolling out:
- - When status is True and reason is RollingOut, the ClusterExtensionRevision rollout is actively making progress and is in transition.
- - When status is True and reason is Retrying, the ClusterExtensionRevision has encountered an error that could be resolved on subsequent reconciliation attempts.
- - When status is True and reason is Succeeded, the ClusterExtensionRevision has reached the desired state.
- - When status is False and reason is Blocked, the ClusterExtensionRevision has encountered an error that requires manual intervention for recovery.
- - When status is False and reason is Archived, the ClusterExtensionRevision is archived and not being actively reconciled.
+ When unspecified, upgrade edges across all channels are used to identify valid automatic upgrade paths.
- The Available condition represents whether the revision has been successfully rolled out and is available:
- - When status is True and reason is ProbesSucceeded, the ClusterExtensionRevision has been successfully rolled out and all objects pass their readiness probes.
- - When status is False and reason is ProbeFailure, one or more objects are failing their readiness probes during rollout.
- - When status is Unknown and reason is Reconciling, the ClusterExtensionRevision has encountered an error that prevented it from observing the probes.
- - When status is Unknown and reason is Archived, the ClusterExtensionRevision has been archived and its objects have been torn down.
- - When status is Unknown and reason is Migrated, the ClusterExtensionRevision was migrated from an existing release and object status probe results have not yet been observed.
+ Some examples of valid values are:
+ - 1.1.x
+ - alpha
+ - stable
+ - stable-v1
+ - v1-stable
+ - dev-preview
+ - preview
+ - community
- The Succeeded condition represents whether the revision has successfully completed its rollout:
- - When status is True and reason is Succeeded, the ClusterExtensionRevision has successfully completed its rollout. This condition is set once and persists even if the revision later becomes unavailable.
- 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
- type: object
- type: object
- served: true
- storage: true
- subresources:
- status: {}
----
-# Source: olmv1/templates/crds/customresourcedefinition-clusterextensions.olm.operatorframework.io.yml
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
-metadata:
- annotations:
- controller-gen.kubebuilder.io/version: v0.20.1
- olm.operatorframework.io/generator: experimental
- name: clusterextensions.olm.operatorframework.io
-spec:
- group: olm.operatorframework.io
- names:
- kind: ClusterExtension
- listKind: ClusterExtensionList
- plural: clusterextensions
- singular: clusterextension
- scope: Cluster
- versions:
- - additionalPrinterColumns:
- - jsonPath: .status.install.bundle.name
- name: Installed Bundle
- type: string
- - jsonPath: .status.install.bundle.version
- name: Version
- type: string
- - jsonPath: .status.conditions[?(@.type=='Installed')].status
- name: Installed
- type: string
- - jsonPath: .status.conditions[?(@.type=='Progressing')].status
- name: Progressing
- type: string
- - jsonPath: .metadata.creationTimestamp
- name: Age
- type: date
- name: v1
- schema:
- openAPIV3Schema:
- description: ClusterExtension is the Schema for the clusterextensions API
- properties:
- apiVersion:
- description: |-
- APIVersion defines the versioned schema of this representation of an object.
- Servers should convert recognized schemas to the latest internal value, and
- may reject unrecognized values.
- More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
- type: string
- kind:
- description: |-
- Kind is a string value representing the REST resource this object represents.
- Servers may infer this from the endpoint the client submits requests to.
- Cannot be updated.
- In CamelCase.
- More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
- type: string
- metadata:
- type: object
- spec:
- description: spec is an optional field that defines the desired state
- of the ClusterExtension.
- properties:
- config:
- description: |-
- config is optional and specifies bundle-specific configuration.
- Configuration is bundle-specific and a bundle may provide a configuration schema.
- When not specified, the default configuration of the resolved bundle is used.
+ Some examples of invalid values are:
+ - -some-channel
+ - some-channel-
+ - thisisareallylongchannelnamethatisgreaterthanthemaximumlength
+ - original_40
+ - --default-channel
- config is validated against a configuration schema provided by the resolved bundle. If the bundle does not provide
- a configuration schema the bundle is deemed to not be configurable. More information on how
- to configure bundles can be found in the OLM documentation associated with your current OLM version.
- properties:
- configType:
- description: |-
- configType is required and specifies the type of configuration source.
+ [RFC 1123]: https://tools.ietf.org/html/rfc1123
+ items:
+ maxLength: 253
+ type: string
+ x-kubernetes-validations:
+ - message: channels entries must be valid DNS1123 subdomains
+ rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
+ maxItems: 256
+ type: array
+ packageName:
+ description: |-
+ packageName specifies the name of the package to be installed and is used to filter
+ the content from catalogs.
- The only allowed value is "Inline".
+ It is required, immutable, and follows the DNS subdomain standard as defined in [RFC 1123].
+ It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
+ start and end with an alphanumeric character, and be no longer than 253 characters.
- When set to "Inline", the cluster extension configuration is defined inline within the ClusterExtension resource.
- enum:
- - Inline
- type: string
- inline:
- description: |-
- inline contains JSON or YAML values specified directly in the ClusterExtension.
+ Some examples of valid values are:
+ - some-package
+ - 123-package
+ - 1-package-2
+ - somepackage
- It is used to specify arbitrary configuration values for the ClusterExtension.
- It must be set if configType is 'Inline' and must be a valid JSON/YAML object containing at least one property.
- The configuration values are validated at runtime against a JSON schema provided by the bundle.
- minProperties: 1
- type: object
- x-kubernetes-preserve-unknown-fields: true
- required:
- - configType
- type: object
- x-kubernetes-validations:
- - message: inline is required when configType is Inline, and forbidden
- otherwise
- rule: 'has(self.configType) && self.configType == ''Inline'' ?has(self.inline)
- : !has(self.inline)'
- install:
- description: |-
- install is optional and configures installation options for the ClusterExtension,
- such as the pre-flight check configuration.
- properties:
- preflight:
- description: |-
- preflight is optional and configures the checks that run before installation or upgrade
- of the content for the package specified in the packageName field.
+ Some examples of invalid values are:
+ - -some-package
+ - some-package-
+ - thisisareallylongpackagenamethatisgreaterthanthemaximumlength
+ - some.package
- When specified, it replaces the default preflight configuration for install/upgrade actions.
- When not specified, the default configuration is used.
- properties:
- crdUpgradeSafety:
+ [RFC 1123]: https://tools.ietf.org/html/rfc1123
+ maxLength: 253
+ type: string
+ x-kubernetes-validations:
+ - message: packageName is immutable
+ rule: self == oldSelf
+ - message: packageName must be a valid DNS1123 subdomain.
+ It must contain only lowercase alphanumeric characters,
+ hyphens (-) or periods (.), start and end with an alphanumeric
+ character, and be no longer than 253 characters
+ rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
+ selector:
description: |-
- crdUpgradeSafety configures the CRD Upgrade Safety pre-flight checks that run
- before upgrades of installed content.
+ selector is optional and filters the set of ClusterCatalogs used in the bundle selection process.
- The CRD Upgrade Safety pre-flight check safeguards from unintended consequences of upgrading a CRD,
- such as data loss.
+ When unspecified, all ClusterCatalogs are used in the bundle selection process.
properties:
- enforcement:
+ matchExpressions:
+ description: matchExpressions is a list of label selector
+ requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
description: |-
- enforcement is required and configures the state of the CRD Upgrade Safety pre-flight check.
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ upgradeConstraintPolicy:
+ default: CatalogProvided
+ description: |-
+ upgradeConstraintPolicy is optional and controls whether the upgrade paths defined in the catalog
+ are enforced for the package referenced in the packageName field.
- Allowed values are "None" or "Strict". The default value is "Strict".
+ Allowed values are "CatalogProvided", "SelfCertified", or omitted.
- When set to "None", the CRD Upgrade Safety pre-flight check is skipped during an upgrade operation.
- Use this option with caution as unintended consequences such as data loss can occur.
+ When set to "CatalogProvided", automatic upgrades only occur when upgrade constraints specified by the package
+ author are met.
- When set to "Strict", the CRD Upgrade Safety pre-flight check runs during an upgrade operation.
- enum:
- - None
- - Strict
- type: string
- required:
- - enforcement
- type: object
- required:
- - crdUpgradeSafety
- type: object
- x-kubernetes-validations:
- - message: at least one of [crdUpgradeSafety] are required when
- preflight is specified
- rule: has(self.crdUpgradeSafety)
- type: object
- x-kubernetes-validations:
- - message: at least one of [preflight] are required when install is
- specified
- rule: has(self.preflight)
- namespace:
- description: |-
- namespace specifies a Kubernetes namespace.
- This is the namespace where the provided ServiceAccount must exist.
- It also designates the default namespace where namespace-scoped resources for the extension are applied to the cluster.
- Some extensions may contain namespace-scoped resources to be applied in other namespaces.
- This namespace must exist.
+ When set to "SelfCertified", the upgrade constraints specified by the package author are ignored.
+ This allows upgrades and downgrades to any version of the package.
+ This is considered a dangerous operation as it can lead to unknown and potentially disastrous outcomes,
+ such as data loss.
+ Use this option only if you have independently verified the changes.
- The namespace field is required, immutable, and follows the DNS label standard as defined in [RFC 1123].
- It must contain only lowercase alphanumeric characters or hyphens (-), start and end with an alphanumeric character,
- and be no longer than 63 characters.
+ When omitted, the default value is "CatalogProvided".
+ enum:
+ - CatalogProvided
+ - SelfCertified
+ type: string
+ version:
+ description: |-
+ version is an optional semver constraint (a specific version or range of versions).
+ When unspecified, the latest version available is installed.
- [RFC 1123]: https://tools.ietf.org/html/rfc1123
- maxLength: 63
- type: string
- x-kubernetes-validations:
- - message: namespace is immutable
- rule: self == oldSelf
- - message: namespace must be a valid DNS1123 label
- rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$")
- progressDeadlineMinutes:
- description: |-
- progressDeadlineMinutes is an optional field that defines the maximum period
- of time in minutes after which an installation should be considered failed and
- require manual intervention. This functionality is disabled when no value
- is provided. The minimum period is 10 minutes, and the maximum is 720 minutes (12 hours).
- format: int32
- maximum: 720
- minimum: 10
- type: integer
- serviceAccount:
- description: |-
- serviceAccount specifies a ServiceAccount used to perform all interactions with the cluster
- that are required to manage the extension.
- The ServiceAccount must be configured with the necessary permissions to perform these interactions.
- The ServiceAccount must exist in the namespace referenced in the spec.
- The serviceAccount field is required.
- properties:
- name:
- description: |-
- name is a required, immutable reference to the name of the ServiceAccount used for installation
- and management of the content for the package specified in the packageName field.
+ Acceptable version ranges are no longer than 64 characters.
+ Version ranges are composed of comma- or space-delimited values and one or more comparison operators,
+ known as comparison strings.
+ You can add additional comparison strings using the OR operator (||).
- This ServiceAccount must exist in the installNamespace.
+ # Range Comparisons
- The name field follows the DNS subdomain standard as defined in [RFC 1123].
- It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
- start and end with an alphanumeric character, and be no longer than 253 characters.
+ To specify a version range, you can use a comparison string like ">=3.0,
+ <3.6". When specifying a range, automatic updates will occur within that
+ range. The example comparison string means "install any version greater than
+ or equal to 3.0.0 but less than 3.6.0.". It also states intent that if any
+ upgrades are available within the version range after initial installation,
+ those upgrades should be automatically performed.
- Some examples of valid values are:
- - some-serviceaccount
- - 123-serviceaccount
- - 1-serviceaccount-2
- - someserviceaccount
- - some.serviceaccount
+ # Pinned Versions
- Some examples of invalid values are:
- - -some-serviceaccount
- - some-serviceaccount-
+ To specify an exact version to install you can use a version range that
+ "pins" to a specific version. When pinning to a specific version, no
+ automatic updates will occur. An example of a pinned version range is
+ "0.6.0", which means "only install version 0.6.0 and never
+ upgrade from this version".
- [RFC 1123]: https://tools.ietf.org/html/rfc1123
- maxLength: 253
- type: string
- x-kubernetes-validations:
- - message: name is immutable
- rule: self == oldSelf
- - message: name must be a valid DNS1123 subdomain. It must contain
- only lowercase alphanumeric characters, hyphens (-) or periods
- (.), start and end with an alphanumeric character, and be
- no longer than 253 characters
- rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
- required:
- - name
- type: object
- source:
- description: |-
- source is required and selects the installation source of content for this ClusterExtension.
- Set the sourceType field to perform the selection.
+ # Basic Comparison Operators
- Catalog is currently the only implemented sourceType.
- Setting sourceType to "Catalog" requires the catalog field to also be defined.
+ The basic comparison operators and their meanings are:
+ - "=", equal (not aliased to an operator)
+ - "!=", not equal
+ - "<", less than
+ - ">", greater than
+ - ">=", greater than OR equal to
+ - "<=", less than OR equal to
- Below is a minimal example of a source definition (in yaml):
+ # Wildcard Comparisons
- source:
- sourceType: Catalog
- catalog:
- packageName: example-package
- properties:
- catalog:
- description: |-
- catalog configures how information is sourced from a catalog.
- It is required when sourceType is "Catalog", and forbidden otherwise.
- properties:
- channels:
- description: |-
- channels is optional and specifies a set of channels belonging to the package
- specified in the packageName field.
+ You can use the "x", "X", and "*" characters as wildcard characters in all
+ comparison operations. Some examples of using the wildcard characters:
+ - "1.2.x", "1.2.X", and "1.2.*" is equivalent to ">=1.2.0, < 1.3.0"
+ - ">= 1.2.x", ">= 1.2.X", and ">= 1.2.*" is equivalent to ">= 1.2.0"
+ - "<= 2.x", "<= 2.X", and "<= 2.*" is equivalent to "< 3"
+ - "x", "X", and "*" is equivalent to ">= 0.0.0"
- A channel is a package-author-defined stream of updates for an extension.
+ # Patch Release Comparisons
- Each channel in the list must follow the DNS subdomain standard as defined in [RFC 1123].
- It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
- start and end with an alphanumeric character, and be no longer than 253 characters.
- You can specify no more than 256 channels.
+ When you want to specify a minor version up to the next major version you
+ can use the "~" character to perform patch comparisons. Some examples:
+ - "~1.2.3" is equivalent to ">=1.2.3, <1.3.0"
+ - "~1" and "~1.x" is equivalent to ">=1, <2"
+ - "~2.3" is equivalent to ">=2.3, <2.4"
+ - "~1.2.x" is equivalent to ">=1.2.0, <1.3.0"
+
+ # Major Release Comparisons
+
+ You can use the "^" character to make major release comparisons after a
+ stable 1.0.0 version is published. If there is no stable version published, // minor versions define the stability level. Some examples:
+ - "^1.2.3" is equivalent to ">=1.2.3, <2.0.0"
+ - "^1.2.x" is equivalent to ">=1.2.0, <2.0.0"
+ - "^2.3" is equivalent to ">=2.3, <3"
+ - "^2.x" is equivalent to ">=2.0.0, <3"
+ - "^0.2.3" is equivalent to ">=0.2.3, <0.3.0"
+ - "^0.2" is equivalent to ">=0.2.0, <0.3.0"
+ - "^0.0.3" is equvalent to ">=0.0.3, <0.0.4"
+ - "^0.0" is equivalent to ">=0.0.0, <0.1.0"
+ - "^0" is equivalent to ">=0.0.0, <1.0.0"
- When specified, it constrains the set of installable bundles and the automated upgrade path.
- This constraint is an AND operation with the version field. For example:
- - Given channel is set to "foo"
- - Given version is set to ">=1.0.0, <1.5.0"
- - Only bundles that exist in channel "foo" AND satisfy the version range comparison are considered installable
- - Automatic upgrades are constrained to upgrade edges defined by the selected channel
+ # OR Comparisons
+ You can use the "||" character to represent an OR operation in the version
+ range. Some examples:
+ - ">=1.2.3, <2.0.0 || >3.0.0"
+ - "^0 || ^3 || ^5"
- When unspecified, upgrade edges across all channels are used to identify valid automatic upgrade paths.
+ For more information on semver, please see https://semver.org/
+ maxLength: 64
+ type: string
+ x-kubernetes-validations:
+ - message: invalid version expression
+ rule: self.matches("^(\\s*(=||!=|>|<|>=|=>|<=|=<|~|~>|\\^)\\s*(v?(0|[1-9]\\d*|[x|X|\\*])(\\.(0|[1-9]\\d*|x|X|\\*]))?(\\.(0|[1-9]\\d*|x|X|\\*))?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?)\\s*)((?:\\s+|,\\s*|\\s*\\|\\|\\s*)(=||!=|>|<|>=|=>|<=|=<|~|~>|\\^)\\s*(v?(0|[1-9]\\d*|x|X|\\*])(\\.(0|[1-9]\\d*|x|X|\\*))?(\\.(0|[1-9]\\d*|x|X|\\*]))?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?)\\s*)*$")
+ required:
+ - packageName
+ type: object
+ sourceType:
+ description: |-
+ sourceType is required and specifies the type of install source.
- Some examples of valid values are:
- - 1.1.x
- - alpha
- - stable
- - stable-v1
- - v1-stable
- - dev-preview
- - preview
- - community
+ The only allowed value is "Catalog".
- Some examples of invalid values are:
- - -some-channel
- - some-channel-
- - thisisareallylongchannelnamethatisgreaterthanthemaximumlength
- - original_40
- - --default-channel
+ When set to "Catalog", information for determining the appropriate bundle of content to install
+ is fetched from ClusterCatalog resources on the cluster.
+ When using the Catalog sourceType, the catalog field must also be set.
+ enum:
+ - Catalog
+ type: string
+ required:
+ - sourceType
+ type: object
+ x-kubernetes-validations:
+ - message: catalog is required when sourceType is Catalog, and forbidden
+ otherwise
+ rule: 'has(self.sourceType) && self.sourceType == ''Catalog'' ?
+ has(self.catalog) : !has(self.catalog)'
+ required:
+ - namespace
+ - serviceAccount
+ - source
+ type: object
+ status:
+ 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) ObjectSets,
+ including both installed and rolling out revisions.
+ items:
+ description: RevisionStatus defines the observed state of a ObjectSet.
+ properties:
+ conditions:
+ description: |-
+ conditions optionally expose Progressing and Available condition of the revision,
+ in case when it is not yet marked as successfully installed (condition Succeeded is not set to True).
+ 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 ObjectSet 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.
- [RFC 1123]: https://tools.ietf.org/html/rfc1123
- items:
- maxLength: 253
- type: string
- x-kubernetes-validations:
- - message: channels entries must be valid DNS1123 subdomains
- rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
- maxItems: 256
- type: array
- packageName:
- description: |-
- packageName specifies the name of the package to be installed and is used to filter
- the content from catalogs.
+ The set of condition types which apply to all spec.source variations are Installed and Progressing.
- It is required, immutable, and follows the DNS subdomain standard as defined in [RFC 1123].
- It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
- start and end with an alphanumeric character, and be no longer than 253 characters.
+ 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.
- Some examples of valid values are:
- - some-package
- - 123-package
- - 1-package-2
- - somepackage
+ 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.
- Some examples of invalid values are:
- - -some-package
- - some-package-
- - thisisareallylongpackagenamethatisgreaterthanthemaximumlength
- - some.package
+ When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ObjectSets in active roll out.
- [RFC 1123]: https://tools.ietf.org/html/rfc1123
- maxLength: 253
+ 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.
+ 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
+ install:
+ description: install is a representation of the current installation
+ status for this ClusterExtension.
+ properties:
+ bundle:
+ description: |-
+ bundle is required and represents the identifying attributes of a bundle.
+
+ A "bundle" is a versioned set of content that represents the resources that need to be applied
+ to a cluster to install a package.
+ properties:
+ name:
+ description: |-
+ name is required and follows the DNS subdomain standard as defined in [RFC 1123].
+ It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
+ start and end with an alphanumeric character, and be no longer than 253 characters.
type: string
x-kubernetes-validations:
- - message: packageName is immutable
- rule: self == oldSelf
- message: packageName must be a valid DNS1123 subdomain.
It must contain only lowercase alphanumeric characters,
hyphens (-) or periods (.), start and end with an alphanumeric
character, and be no longer than 253 characters
rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
- selector:
- description: |-
- selector is optional and filters the set of ClusterCatalogs used in the bundle selection process.
-
- When unspecified, all ClusterCatalogs are used in the bundle selection process.
- properties:
- matchExpressions:
- description: matchExpressions is a list of label selector
- requirements. The requirements are ANDed.
- items:
- description: |-
- A label selector requirement is a selector that contains values, a key, and an operator that
- relates the key and values.
- properties:
- key:
- description: key is the label key that the selector
- applies to.
- type: string
- operator:
- description: |-
- operator represents a key's relationship to a set of values.
- Valid operators are In, NotIn, Exists and DoesNotExist.
- type: string
- values:
- description: |-
- values is an array of string values. If the operator is In or NotIn,
- the values array must be non-empty. If the operator is Exists or DoesNotExist,
- the values array must be empty. This array is replaced during a strategic
- merge patch.
- items:
- type: string
- type: array
- x-kubernetes-list-type: atomic
- required:
- - key
- - operator
- type: object
- type: array
- x-kubernetes-list-type: atomic
- matchLabels:
- additionalProperties:
- type: string
- description: |-
- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
- map is equivalent to an element of matchExpressions, whose key field is "key", the
- operator is "In", and the values array contains only "value". The requirements are ANDed.
- type: object
- type: object
- x-kubernetes-map-type: atomic
- upgradeConstraintPolicy:
- default: CatalogProvided
+ version:
description: |-
- upgradeConstraintPolicy is optional and controls whether the upgrade paths defined in the catalog
- are enforced for the package referenced in the packageName field.
+ version is required and references the version that this bundle represents.
+ It follows the semantic versioning standard as defined in https://semver.org/.
+ type: string
+ x-kubernetes-validations:
+ - message: version must be well-formed semver
+ rule: self.matches("^([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(-([-0-9A-Za-z]+(\\.[-0-9A-Za-z]+)*))?(\\+([-0-9A-Za-z]+(-\\.[-0-9A-Za-z]+)*))?")
+ required:
+ - name
+ - version
+ type: object
+ required:
+ - bundle
+ type: object
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+---
+# Source: olmv1/templates/crds/customresourcedefinition-objectsets.olm.operatorframework.io.yml
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.20.1
+ olm.operatorframework.io/generator: experimental
+ name: objectsets.olm.operatorframework.io
+spec:
+ group: olm.operatorframework.io
+ names:
+ kind: ObjectSet
+ listKind: ObjectSetList
+ plural: objectsets
+ singular: objectset
+ scope: Cluster
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .status.conditions[?(@.type=='Available')].status
+ name: Available
+ type: string
+ - jsonPath: .status.conditions[?(@.type=='Progressing')].status
+ name: Progressing
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1
+ schema:
+ openAPIV3Schema:
+ description: |-
+ ObjectSet represents an immutable snapshot of Kubernetes objects
+ for a specific version of a ClusterExtension. Each revision contains objects
+ organized into phases that roll out sequentially. The same object can only be managed by a single revision
+ at a time. Ownership of objects is transitioned from one revision to the next as the extension is upgraded
+ or reconfigured. Once the latest revision has rolled out successfully, previous active revisions are archived for
+ posterity.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: spec defines the desired state of the ObjectSet.
+ properties:
+ collisionProtection:
+ description: |-
+ collisionProtection specifies the default collision protection strategy for all objects
+ in this revision. Individual phases or objects can override this value.
- Allowed values are "CatalogProvided", "SelfCertified", or omitted.
+ When set, this value is used as the default for any phase or object that does not
+ explicitly specify its own collisionProtection.
- When set to "CatalogProvided", automatic upgrades only occur when upgrade constraints specified by the package
- author are met.
+ The resolution order is: object > phase > spec
+ enum:
+ - Prevent
+ - IfNoController
+ - None
+ type: string
+ x-kubernetes-validations:
+ - message: collisionProtection is immutable
+ rule: self == oldSelf
+ lifecycleState:
+ description: |-
+ lifecycleState specifies the lifecycle state of the ObjectSet.
- When set to "SelfCertified", the upgrade constraints specified by the package author are ignored.
- This allows upgrades and downgrades to any version of the package.
- This is considered a dangerous operation as it can lead to unknown and potentially disastrous outcomes,
- such as data loss.
- Use this option only if you have independently verified the changes.
+ When set to "Active", the revision is actively managed and reconciled.
+ When set to "Archived", the revision is inactive and any resources not managed by a subsequent revision are deleted.
+ The revision is removed from the owner list of all objects previously under management.
+ All objects that did not transition to a succeeding revision are deleted.
- When omitted, the default value is "CatalogProvided".
- enum:
- - CatalogProvided
- - SelfCertified
- type: string
- version:
- description: |-
- version is an optional semver constraint (a specific version or range of versions).
- When unspecified, the latest version available is installed.
+ Once a revision is set to "Archived", it cannot be un-archived.
- Acceptable version ranges are no longer than 64 characters.
- Version ranges are composed of comma- or space-delimited values and one or more comparison operators,
- known as comparison strings.
- You can add additional comparison strings using the OR operator (||).
+ It is possible for more than one revision to be "Active" simultaneously. This will occur when
+ moving from one revision to another. The old revision will not be set to "Archived" until the
+ new revision has been completely rolled out.
+ enum:
+ - Active
+ - Archived
+ type: string
+ x-kubernetes-validations:
+ - message: cannot un-archive
+ rule: oldSelf == 'Active' || oldSelf == 'Archived' && oldSelf ==
+ self
+ phases:
+ description: |-
+ phases is an optional, immutable list of phases that group objects to be applied together.
- # Range Comparisons
+ Objects are organized into phases based on their Group-Kind. Common phases include:
+ - namespaces: Namespace objects
+ - policies: ResourceQuota, LimitRange, NetworkPolicy objects
+ - rbac: ServiceAccount, Role, RoleBinding, ClusterRole, ClusterRoleBinding objects
+ - crds: CustomResourceDefinition objects
+ - storage: PersistentVolume, PersistentVolumeClaim, StorageClass objects
+ - deploy: Deployment, StatefulSet, DaemonSet, Service, ConfigMap, Secret objects
+ - publish: Ingress, APIService, Route, Webhook objects
- To specify a version range, you can use a comparison string like ">=3.0,
- <3.6". When specifying a range, automatic updates will occur within that
- range. The example comparison string means "install any version greater than
- or equal to 3.0.0 but less than 3.6.0.". It also states intent that if any
- upgrades are available within the version range after initial installation,
- those upgrades should be automatically performed.
+ All objects in a phase are applied in no particular order.
+ The revision progresses to the next phase only after all objects in the current phase pass their readiness probes.
- # Pinned Versions
+ Once set, even if empty, the phases field is immutable.
- To specify an exact version to install you can use a version range that
- "pins" to a specific version. When pinning to a specific version, no
- automatic updates will occur. An example of a pinned version range is
- "0.6.0", which means "only install version 0.6.0 and never
- upgrade from this version".
+ Each phase in the list must have a unique name. The maximum number of phases is 20.
+ items:
+ description: |-
+ ObjectSetPhase represents a group of objects that are applied together. The phase is considered
+ complete only after all objects pass their status probes.
+ properties:
+ collisionProtection:
+ description: |-
+ collisionProtection specifies the default collision protection strategy for all objects
+ in this phase. Individual objects can override this value.
- # Basic Comparison Operators
+ When set, this value is used as the default for any object in this phase that does not
+ explicitly specify its own collisionProtection.
- The basic comparison operators and their meanings are:
- - "=", equal (not aliased to an operator)
- - "!=", not equal
- - "<", less than
- - ">", greater than
- - ">=", greater than OR equal to
- - "<=", less than OR equal to
+ When omitted, we use .spec.collistionProtection as the default for any object in this phase that does not
+ explicitly specify its own collisionProtection.
+ enum:
+ - Prevent
+ - IfNoController
+ - None
+ type: string
+ name:
+ description: |-
+ name is a required identifier for this phase.
- # Wildcard Comparisons
+ phase names must follow the DNS label standard as defined in [RFC 1123].
+ They must contain only lowercase alphanumeric characters or hyphens (-),
+ start and end with an alphanumeric character, and be no longer than 63 characters.
- You can use the "x", "X", and "*" characters as wildcard characters in all
- comparison operations. Some examples of using the wildcard characters:
- - "1.2.x", "1.2.X", and "1.2.*" is equivalent to ">=1.2.0, < 1.3.0"
- - ">= 1.2.x", ">= 1.2.X", and ">= 1.2.*" is equivalent to ">= 1.2.0"
- - "<= 2.x", "<= 2.X", and "<= 2.*" is equivalent to "< 3"
- - "x", "X", and "*" is equivalent to ">= 0.0.0"
+ Common phase names include: namespaces, policies, rbac, crds, storage, deploy, publish.
- # Patch Release Comparisons
+ [RFC 1123]: https://tools.ietf.org/html/rfc1123
+ maxLength: 63
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: the value must consist of only lowercase alphanumeric
+ characters and hyphens, and must start with an alphabetic
+ character and end with an alphanumeric character.
+ rule: '!format.dns1123Label().validate(self).hasValue()'
+ objects:
+ description: |-
+ objects is a required list of all Kubernetes objects that belong to this phase.
- When you want to specify a minor version up to the next major version you
- can use the "~" character to perform patch comparisons. Some examples:
- - "~1.2.3" is equivalent to ">=1.2.3, <1.3.0"
- - "~1" and "~1.x" is equivalent to ">=1, <2"
- - "~2.3" is equivalent to ">=2.3, <2.4"
- - "~1.2.x" is equivalent to ">=1.2.0, <1.3.0"
+ All objects in this list are applied to the cluster in no particular order. The maximum number of objects per phase is 50.
+ items:
+ description: |-
+ ObjectSetObject represents a Kubernetes object to be applied as part
+ of a phase, along with its collision protection settings.
+ properties:
+ collisionProtection:
+ description: |-
+ collisionProtection controls whether the operator can adopt and modify objects
+ that already exist on the cluster.
- # Major Release Comparisons
+ Allowed values are: "Prevent", "IfNoController", and "None".
- You can use the "^" character to make major release comparisons after a
- stable 1.0.0 version is published. If there is no stable version published, // minor versions define the stability level. Some examples:
- - "^1.2.3" is equivalent to ">=1.2.3, <2.0.0"
- - "^1.2.x" is equivalent to ">=1.2.0, <2.0.0"
- - "^2.3" is equivalent to ">=2.3, <3"
- - "^2.x" is equivalent to ">=2.0.0, <3"
- - "^0.2.3" is equivalent to ">=0.2.3, <0.3.0"
- - "^0.2" is equivalent to ">=0.2.0, <0.3.0"
- - "^0.0.3" is equvalent to ">=0.0.3, <0.0.4"
- - "^0.0" is equivalent to ">=0.0.0, <0.1.0"
- - "^0" is equivalent to ">=0.0.0, <1.0.0"
+ When set to "Prevent", the operator only manages objects it created itself.
+ This prevents ownership collisions.
- # OR Comparisons
- You can use the "||" character to represent an OR operation in the version
- range. Some examples:
- - ">=1.2.3, <2.0.0 || >3.0.0"
- - "^0 || ^3 || ^5"
+ When set to "IfNoController", the operator can adopt and modify pre-existing objects
+ that are not owned by another controller.
+ This is useful for taking over management of manually-created resources.
- For more information on semver, please see https://semver.org/
- maxLength: 64
- type: string
- x-kubernetes-validations:
- - message: invalid version expression
- rule: self.matches("^(\\s*(=||!=|>|<|>=|=>|<=|=<|~|~>|\\^)\\s*(v?(0|[1-9]\\d*|[x|X|\\*])(\\.(0|[1-9]\\d*|x|X|\\*]))?(\\.(0|[1-9]\\d*|x|X|\\*))?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?)\\s*)((?:\\s+|,\\s*|\\s*\\|\\|\\s*)(=||!=|>|<|>=|=>|<=|=<|~|~>|\\^)\\s*(v?(0|[1-9]\\d*|x|X|\\*])(\\.(0|[1-9]\\d*|x|X|\\*))?(\\.(0|[1-9]\\d*|x|X|\\*]))?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?)\\s*)*$")
- required:
- - packageName
- type: object
- sourceType:
- description: |-
- sourceType is required and specifies the type of install source.
+ When set to "None", the operator can adopt and modify any pre-existing object, even if
+ owned by another controller.
+ Use this setting with extreme caution as it may cause multiple controllers to fight over
+ the same resource, resulting in increased load on the API server and etcd.
- The only allowed value is "Catalog".
+ When omitted, the value is inherited from the phase, then spec.
+ enum:
+ - Prevent
+ - IfNoController
+ - None
+ type: string
+ object:
+ description: |-
+ object is a required embedded Kubernetes object to be applied.
- When set to "Catalog", information for determining the appropriate bundle of content to install
- is fetched from ClusterCatalog resources on the cluster.
- When using the Catalog sourceType, the catalog field must also be set.
- enum:
- - Catalog
- type: string
- required:
- - sourceType
- type: object
+ This object must be a valid Kubernetes resource with apiVersion, kind, and metadata fields.
+ type: object
+ x-kubernetes-embedded-resource: true
+ x-kubernetes-preserve-unknown-fields: true
+ required:
+ - object
+ type: object
+ maxItems: 50
+ type: array
+ required:
+ - name
+ - objects
+ type: object
+ maxItems: 20
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
x-kubernetes-validations:
- - message: catalog is required when sourceType is Catalog, and forbidden
- otherwise
- rule: 'has(self.sourceType) && self.sourceType == ''Catalog'' ?
- has(self.catalog) : !has(self.catalog)'
- required:
- - namespace
- - serviceAccount
- - source
- type: object
- status:
- description: status is an optional field that defines the observed state
- of the ClusterExtension.
- properties:
- activeRevisions:
+ - message: phases is immutable
+ rule: self == oldSelf || oldSelf.size() == 0
+ progressDeadlineMinutes:
description: |-
- activeRevisions holds a list of currently active (non-archived) ClusterExtensionRevisions,
- including both installed and rolling out revisions.
+ progressDeadlineMinutes is an optional field that defines the maximum period
+ of time in minutes after which an installation should be considered failed and
+ require manual intervention. This functionality is disabled when no value
+ is provided. The minimum period is 10 minutes, and the maximum is 720 minutes (12 hours).
+ format: int32
+ maximum: 720
+ minimum: 10
+ type: integer
+ progressionProbes:
+ description: |-
+ progressionProbes is an optional field which provides the ability to define custom readiness probes
+ for objects defined within spec.phases. As documented in that field, most kubernetes-native objects
+ within the phases already have some kind of readiness check built-in, but this field allows for checks
+ which are tailored to the objects being rolled out - particularly custom resources.
+
+ Probes defined within the progressionProbes list will apply to every phase in the revision. However, the probes will only
+ execute against phase objects which are a match for the provided selector type. For instance, a probe using a GroupKind selector
+ for ConfigMaps will automatically be considered to have passed for any non-ConfigMap object, but will halt any phase containing
+ a ConfigMap if that particular object does not pass the probe check.
+
+ The maximum number of probes is 20.
items:
- description: RevisionStatus defines the observed state of a ClusterExtensionRevision.
+ description: ProgressionProbe provides a custom probe definition,
+ consisting of an object selection method and assertions.
properties:
- conditions:
+ assertions:
description: |-
- conditions optionally expose Progressing and Available condition of the revision,
- in case when it is not yet marked as successfully installed (condition Succeeded is not set to True).
- 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.
+ assertions is a required list of checks which will run against the objects selected by the selector. If
+ one or more assertions fail then the phase within which the object lives will be not be considered
+ 'Ready', blocking rollout of all subsequent phases.
items:
- description: Condition contains details for one aspect of
- the current state of this API Resource.
+ description: Assertion is a discriminated union which defines
+ the probe type and definition used as an assertion.
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:
+ conditionEqual:
+ description: conditionEqual contains the expected condition
+ type and status.
+ properties:
+ status:
+ description: |-
+ status sets the expected condition status.
+
+ Allowed values are "True" and "False".
+ enum:
+ - "True"
+ - "False"
+ type: string
+ type:
+ description: type sets the expected condition type,
+ i.e. "Ready".
+ maxLength: 200
+ minLength: 1
+ type: string
+ required:
+ - status
+ - type
+ type: object
+ fieldValue:
+ description: fieldValue contains the expected field path
+ and value found within.
+ properties:
+ fieldPath:
+ description: |-
+ fieldPath sets the field path for the field to check, i.e. "status.phase". The probe will fail
+ if the path does not exist.
+ maxLength: 200
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: must contain a valid field path. valid
+ fields contain upper or lower-case alphanumeric
+ characters separated by the "." character.
+ rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
+ value:
+ description: value sets the expected value found at
+ fieldPath, i.e. "Bound".
+ maxLength: 200
+ minLength: 1
+ type: string
+ required:
+ - fieldPath
+ - value
+ type: object
+ fieldsEqual:
+ description: fieldsEqual contains the two field paths
+ whose values are expected to match.
+ properties:
+ fieldA:
+ description: |-
+ fieldA sets the field path for the first field, i.e. "spec.replicas". The probe will fail
+ if the path does not exist.
+ maxLength: 200
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: must contain a valid field path. valid
+ fields contain upper or lower-case alphanumeric
+ characters separated by the "." character.
+ rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
+ fieldB:
+ description: |-
+ fieldB sets the field path for the second field, i.e. "status.readyReplicas". The probe will fail
+ if the path does not exist.
+ maxLength: 200
+ minLength: 1
+ type: string
+ x-kubernetes-validations:
+ - message: must contain a valid field path. valid
+ fields contain upper or lower-case alphanumeric
+ characters separated by the "." character.
+ rule: self.matches('^[a-zA-Z0-9]+(?:\\.[a-zA-Z0-9]+)*$')
+ required:
+ - fieldA
+ - fieldB
+ type: object
+ type:
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.
+ type is a required field which specifies the type of probe to use.
+
+ The allowed probe types are "ConditionEqual", "FieldsEqual", and "FieldValue".
+
+ When set to "ConditionEqual", the probe checks objects that have reached a condition of specified type and status.
+ When set to "FieldsEqual", the probe checks that the values found at two provided field paths are matching.
+ When set to "FieldValue", the probe checks that the value found at the provided field path matches what was specified.
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])$
+ - ConditionEqual
+ - FieldsEqual
+ - FieldValue
type: string
required:
- - lastTransitionTime
- - message
- - reason
- - status
- type
type: object
+ x-kubernetes-validations:
+ - message: conditionEqual is required when type is ConditionEqual,
+ and forbidden otherwise
+ rule: 'self.type == ''ConditionEqual'' ?has(self.conditionEqual)
+ : !has(self.conditionEqual)'
+ - message: fieldsEqual is required when type is FieldsEqual,
+ and forbidden otherwise
+ rule: 'self.type == ''FieldsEqual'' ?has(self.fieldsEqual)
+ : !has(self.fieldsEqual)'
+ - message: fieldValue is required when type is FieldValue,
+ and forbidden otherwise
+ rule: 'self.type == ''FieldValue'' ?has(self.fieldValue)
+ : !has(self.fieldValue)'
+ maxItems: 20
+ minItems: 1
type: array
- x-kubernetes-list-map-keys:
+ x-kubernetes-list-type: atomic
+ selector:
+ description: |-
+ selector is a required field which defines the method by which we select objects to apply the below
+ assertions to. Any object which matches the defined selector will have all the associated assertions
+ applied against it.
+
+ If no objects within a phase are selected by the provided selector, then all assertions defined here
+ are considered to have succeeded.
+ properties:
+ groupKind:
+ description: |-
+ groupKind specifies the group and kind of objects to select.
+
+ Required when type is "GroupKind".
+
+ Uses the Kubernetes format specified here:
+ https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#GroupKind
+ properties:
+ group:
+ type: string
+ kind:
+ type: string
+ required:
+ - group
+ - kind
+ type: object
+ label:
+ description: |-
+ label is the label selector definition.
+
+ Required when type is "Label".
+
+ A probe using a Label selector will be executed against every object matching the labels or expressions; you must use care
+ when using this type of selector. For example, if multiple Kind objects are selected via labels then the probe is
+ likely to fail because the values of different Kind objects rarely share the same schema.
+
+ The LabelSelector field uses the following Kubernetes format:
+ https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#LabelSelector
+ Requires exactly one of matchLabels or matchExpressions.
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label selector
+ requirements. The requirements are ANDed.
+ items:
+ description: |-
+ A label selector requirement is a selector that contains values, a key, and an operator that
+ relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the selector
+ applies to.
+ type: string
+ operator:
+ description: |-
+ operator represents a key's relationship to a set of values.
+ Valid operators are In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: |-
+ values is an array of string values. If the operator is In or NotIn,
+ the values array must be non-empty. If the operator is Exists or DoesNotExist,
+ the values array must be empty. This array is replaced during a strategic
+ merge patch.
+ items:
+ type: string
+ type: array
+ x-kubernetes-list-type: atomic
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ x-kubernetes-list-type: atomic
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: |-
+ matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions, whose key field is "key", the
+ operator is "In", and the values array contains only "value". The requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ x-kubernetes-validations:
+ - message: exactly one of matchLabels or matchExpressions
+ must be set
+ rule: (has(self.matchExpressions) && !has(self.matchLabels))
+ || (!has(self.matchExpressions) && has(self.matchLabels))
+ type:
+ description: |-
+ type is a required field which specifies the type of selector to use.
+
+ The allowed selector types are "GroupKind" and "Label".
+
+ When set to "GroupKind", all objects which match the specified group and kind will be selected.
+ When set to "Label", all objects which match the specified labels and/or expressions will be selected.
+ enum:
+ - GroupKind
+ - Label
+ type: string
+ required:
- type
- x-kubernetes-list-type: map
- name:
- description: name of the ClusterExtensionRevision resource
- type: string
+ type: object
+ x-kubernetes-validations:
+ - message: groupKind is required when type is GroupKind, and
+ forbidden otherwise
+ rule: 'self.type == ''GroupKind'' ?has(self.groupKind) : !has(self.groupKind)'
+ - message: label is required when type is Label, and forbidden
+ otherwise
+ rule: 'self.type == ''Label'' ?has(self.label) : !has(self.label)'
required:
- - name
+ - assertions
+ - selector
type: object
+ maxItems: 20
+ minItems: 1
type: array
- x-kubernetes-list-map-keys:
- - name
- x-kubernetes-list-type: map
- conditions:
+ x-kubernetes-list-type: atomic
+ revision:
description: |-
- conditions represents the current state of the ClusterExtension.
-
- The set of condition types which apply to all spec.source variations are Installed and Progressing.
+ revision is a required, immutable sequence number representing a specific revision
+ of the parent ClusterExtension.
- 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 revision field must be a positive integer.
+ Each ObjectSet belonging to the same parent ClusterExtension must have a unique revision number.
+ The revision number must always be the previous revision number plus one, or 1 for the first revision.
+ format: int64
+ minimum: 1
+ type: integer
+ x-kubernetes-validations:
+ - message: revision is immutable
+ rule: self == oldSelf
+ required:
+ - collisionProtection
+ - lifecycleState
+ - revision
+ type: object
+ status:
+ description: status is optional and defines the observed state of the
+ ObjectSet.
+ properties:
+ conditions:
+ description: |-
+ conditions is an optional list of status conditions describing the state of the
+ ObjectSet.
- 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.
+ The Progressing condition represents whether the revision is actively rolling out:
+ - When status is True and reason is RollingOut, the ObjectSet rollout is actively making progress and is in transition.
+ - When status is True and reason is Retrying, the ObjectSet has encountered an error that could be resolved on subsequent reconciliation attempts.
+ - When status is True and reason is Succeeded, the ObjectSet has reached the desired state.
+ - When status is False and reason is Blocked, the ObjectSet has encountered an error that requires manual intervention for recovery.
+ - When status is False and reason is Archived, the ObjectSet is archived and not being actively reconciled.
- When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterExtensionRevisions in active roll out.
+ The Available condition represents whether the revision has been successfully rolled out and is available:
+ - When status is True and reason is ProbesSucceeded, the ObjectSet has been successfully rolled out and all objects pass their readiness probes.
+ - When status is False and reason is ProbeFailure, one or more objects are failing their readiness probes during rollout.
+ - When status is Unknown and reason is Reconciling, the ObjectSet has encountered an error that prevented it from observing the probes.
+ - When status is Unknown and reason is Archived, the ObjectSet has been archived and its objects have been torn down.
+ - When status is Unknown and reason is Migrated, the ObjectSet was migrated from an existing release and object status probe results have not yet been observed.
- 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.
+ The Succeeded condition represents whether the revision has successfully completed its rollout:
+ - When status is True and reason is Succeeded, the ObjectSet has successfully completed its rollout. This condition is set once and persists even if the revision later becomes unavailable.
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
@@ -1831,44 +1869,6 @@ spec:
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
- install:
- description: install is a representation of the current installation
- status for this ClusterExtension.
- properties:
- bundle:
- description: |-
- bundle is required and represents the identifying attributes of a bundle.
-
- A "bundle" is a versioned set of content that represents the resources that need to be applied
- to a cluster to install a package.
- properties:
- name:
- description: |-
- name is required and follows the DNS subdomain standard as defined in [RFC 1123].
- It must contain only lowercase alphanumeric characters, hyphens (-) or periods (.),
- start and end with an alphanumeric character, and be no longer than 253 characters.
- type: string
- x-kubernetes-validations:
- - message: packageName must be a valid DNS1123 subdomain.
- It must contain only lowercase alphanumeric characters,
- hyphens (-) or periods (.), start and end with an alphanumeric
- character, and be no longer than 253 characters
- rule: self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$")
- version:
- description: |-
- version is required and references the version that this bundle represents.
- It follows the semantic versioning standard as defined in https://semver.org/.
- type: string
- x-kubernetes-validations:
- - message: version must be well-formed semver
- rule: self.matches("^([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(-([-0-9A-Za-z]+(\\.[-0-9A-Za-z]+)*))?(\\+([-0-9A-Za-z]+(-\\.[-0-9A-Za-z]+)*))?")
- required:
- - name
- - version
- type: object
- required:
- - bundle
- type: object
type: object
type: object
served: true
@@ -2094,7 +2094,7 @@ rules:
- apiGroups:
- olm.operatorframework.io
resources:
- - clusterextensionrevisions
+ - objectsets
verbs:
- create
- delete
@@ -2106,14 +2106,14 @@ rules:
- apiGroups:
- olm.operatorframework.io
resources:
- - clusterextensionrevisions/status
+ - objectsets/status
verbs:
- patch
- update
- apiGroups:
- olm.operatorframework.io
resources:
- - clusterextensionrevisions/finalizers
+ - objectsets/finalizers
verbs:
- update
---
diff --git a/test/e2e/README.md b/test/e2e/README.md
index 01dbca7026..687e38a2af 100644
--- a/test/e2e/README.md
+++ b/test/e2e/README.md
@@ -201,7 +201,7 @@ Leverage existing steps for common operations:
Use these variables in YAML templates:
- `${NAME}`: Scenario-specific ClusterExtension name (e.g., `ce-123`)
-- `${CER_NAME}`: Scenario-specific ClusterExtensionRevision name (e.g., `cer-123`; for applying CERs directly)
+- `${CER_NAME}`: Scenario-specific ObjectSet name (e.g., `cer-123`; for applying CERs directly)
- `${TEST_NAMESPACE}`: Scenario-specific namespace (e.g., `ns-123`)
- `${CATALOG_IMG}`: Catalog image reference (defaults to in-cluster registry, overridable via `CATALOG_IMG` env var)
diff --git a/test/e2e/features/install.feature b/test/e2e/features/install.feature
index ce3fb34302..00d89642d4 100644
--- a/test/e2e/features/install.feature
+++ b/test/e2e/features/install.feature
@@ -387,7 +387,7 @@ Feature: Install ClusterExtension
@ProgressDeadline
Scenario: Report ClusterExtension as not progressing if the rollout does not become available within given timeout
Given min value for ClusterExtension .spec.progressDeadlineMinutes is set to 1
- And min value for ClusterExtensionRevision .spec.progressDeadlineMinutes is set to 1
+ And min value for ObjectSet .spec.progressDeadlineMinutes is set to 1
When ClusterExtension is applied
"""
apiVersion: olm.operatorframework.io/v1
@@ -409,7 +409,7 @@ Feature: Install ClusterExtension
matchLabels:
"olm.operatorframework.io/metadata.name": test-catalog
"""
- Then ClusterExtensionRevision "${NAME}-1" reports Progressing as False with Reason ProgressDeadlineExceeded
+ Then ObjectSet "${NAME}-1" reports Progressing as False with Reason ProgressDeadlineExceeded
And ClusterExtension reports Progressing as False with Reason ProgressDeadlineExceeded and Message:
"""
Revision has not rolled out for 1 minute(s).
@@ -420,7 +420,7 @@ Feature: Install ClusterExtension
@ProgressDeadline
Scenario: Report ClusterExtension as not progressing if the rollout does not complete within given timeout
Given min value for ClusterExtension .spec.progressDeadlineMinutes is set to 1
- And min value for ClusterExtensionRevision .spec.progressDeadlineMinutes is set to 1
+ And min value for ObjectSet .spec.progressDeadlineMinutes is set to 1
When ClusterExtension is applied
"""
apiVersion: olm.operatorframework.io/v1
@@ -441,7 +441,7 @@ Feature: Install ClusterExtension
matchLabels:
"olm.operatorframework.io/metadata.name": test-catalog
"""
- Then ClusterExtensionRevision "${NAME}-1" reports Progressing as False with Reason ProgressDeadlineExceeded
+ Then ObjectSet "${NAME}-1" reports Progressing as False with Reason ProgressDeadlineExceeded
And ClusterExtension reports Progressing as False with Reason ProgressDeadlineExceeded and Message:
"""
Revision has not rolled out for 1 minute(s).
@@ -449,7 +449,7 @@ Feature: Install ClusterExtension
And ClusterExtension reports Progressing transition between 1 and 2 minutes since its creation
@BoxcutterRuntime
- Scenario: ClusterExtensionRevision is annotated with bundle properties
+ Scenario: ObjectSet is annotated with bundle properties
When ClusterExtension is applied
"""
apiVersion: olm.operatorframework.io/v1
@@ -470,13 +470,13 @@ Feature: Install ClusterExtension
"olm.operatorframework.io/metadata.name": test-catalog
"""
# The annotation key and value come from the bundle's metadata/properties.yaml file
- Then ClusterExtensionRevision "${NAME}-1" contains annotation "olm.properties" with value
+ Then ObjectSet "${NAME}-1" contains annotation "olm.properties" with value
"""
[{"type":"olm.test-property","value":"some-value"}]
"""
@BoxcutterRuntime
- Scenario: ClusterExtensionRevision is labeled with owner information
+ Scenario: ObjectSet is labeled with owner information
When ClusterExtension is applied
"""
apiVersion: olm.operatorframework.io/v1
@@ -498,8 +498,8 @@ Feature: Install ClusterExtension
"""
Then ClusterExtension is rolled out
And ClusterExtension is available
- And ClusterExtensionRevision "${NAME}-1" has label "olm.operatorframework.io/owner-kind" with value "ClusterExtension"
- And ClusterExtensionRevision "${NAME}-1" has label "olm.operatorframework.io/owner-name" with value "${NAME}"
+ And ObjectSet "${NAME}-1" has label "olm.operatorframework.io/owner-kind" with value "ClusterExtension"
+ And ObjectSet "${NAME}-1" has label "olm.operatorframework.io/owner-name" with value "${NAME}"
@DeploymentConfig
Scenario: deploymentConfig nodeSelector is applied to the operator deployment
diff --git a/test/e2e/features/revision.feature b/test/e2e/features/revision.feature
index 755762a8a9..c91b05909d 100644
--- a/test/e2e/features/revision.feature
+++ b/test/e2e/features/revision.feature
@@ -1,5 +1,5 @@
@BoxcutterRuntime
-Feature: Install ClusterExtensionRevision
+Feature: Install ObjectSet
As an OLM user I would like to install a cluster extension revision directly, without using the cluster extension API.
@@ -8,10 +8,10 @@ Feature: Install ClusterExtensionRevision
Scenario: Probe failure for PersistentVolumeClaim halts phase progression
Given ServiceAccount "pvc-probe-sa" with needed permissions is available in test namespace
- When ClusterExtensionRevision is applied
+ When ObjectSet is applied
"""
apiVersion: olm.operatorframework.io/v1
- kind: ClusterExtensionRevision
+ kind: ObjectSet
metadata:
annotations:
olm.operatorframework.io/service-account-name: pvc-probe-sa
@@ -52,7 +52,7 @@ Feature: Install ClusterExtensionRevision
"""
Then resource "persistentvolumeclaim/test-pvc" is installed
- And ClusterExtensionRevision "${CER_NAME}" reports Available as False with Reason ProbeFailure and Message:
+ And ObjectSet "${CER_NAME}" reports Available as False with Reason ProbeFailure and Message:
"""
Object PersistentVolumeClaim.v1 ${TEST_NAMESPACE}/test-pvc: value at key "status.phase" != "Bound"; expected: "Bound" got: "Pending"
"""
@@ -60,10 +60,10 @@ Feature: Install ClusterExtensionRevision
Scenario: Phases progress when PersistentVolumeClaim becomes "Bound"
Given ServiceAccount "pvc-probe-sa" with needed permissions is available in test namespace
- When ClusterExtensionRevision is applied
+ When ObjectSet is applied
"""
apiVersion: olm.operatorframework.io/v1
- kind: ClusterExtensionRevision
+ kind: ObjectSet
metadata:
annotations:
olm.operatorframework.io/service-account-name: pvc-probe-sa
@@ -131,18 +131,18 @@ Feature: Install ClusterExtensionRevision
revision: 1
"""
- Then ClusterExtensionRevision "${CER_NAME}" reports Progressing as True with Reason Succeeded
- And ClusterExtensionRevision "${CER_NAME}" reports Available as True with Reason ProbesSucceeded
+ Then ObjectSet "${CER_NAME}" reports Progressing as True with Reason Succeeded
+ And ObjectSet "${CER_NAME}" reports Available as True with Reason ProbesSucceeded
And resource "persistentvolume/test-pv" is installed
And resource "persistentvolumeclaim/test-pvc" is installed
And resource "configmap/test-configmap" is installed
Scenario: Phases does not progress when user-provided progressionProbes do not pass
Given ServiceAccount "pvc-probe-sa" with needed permissions is available in test namespace
- When ClusterExtensionRevision is applied
+ When ObjectSet is applied
"""
apiVersion: olm.operatorframework.io/v1
- kind: ClusterExtensionRevision
+ kind: ObjectSet
metadata:
annotations:
olm.operatorframework.io/service-account-name: pvc-probe-sa
@@ -192,7 +192,7 @@ Feature: Install ClusterExtensionRevision
"""
Then resource "configmap/test-configmap-1" is installed
- And ClusterExtensionRevision "${CER_NAME}" reports Available as False with Reason ProbeFailure and Message:
+ And ObjectSet "${CER_NAME}" reports Available as False with Reason ProbeFailure and Message:
"""
Object ConfigMap.v1 ${TEST_NAMESPACE}/test-configmap-1: value at key "data.foo" != "bar"; expected: "bar" got: "foo"
"""
@@ -200,10 +200,10 @@ Feature: Install ClusterExtensionRevision
Scenario: Phases progresses when user-provided progressionProbes pass
Given ServiceAccount "pvc-probe-sa" with needed permissions is available in test namespace
- When ClusterExtensionRevision is applied
+ When ObjectSet is applied
"""
apiVersion: olm.operatorframework.io/v1
- kind: ClusterExtensionRevision
+ kind: ObjectSet
metadata:
annotations:
olm.operatorframework.io/service-account-name: pvc-probe-sa
@@ -315,5 +315,5 @@ Feature: Install ClusterExtensionRevision
And resource "serviceaccount/test-serviceaccount" is installed
And resource "pod/test-pod" is installed
And resource "configmap/test-configmap-3" is installed
- And ClusterExtensionRevision "${CER_NAME}" reports Progressing as True with Reason Succeeded
- And ClusterExtensionRevision "${CER_NAME}" reports Available as True with Reason ProbesSucceeded
\ No newline at end of file
+ And ObjectSet "${CER_NAME}" reports Progressing as True with Reason Succeeded
+ And ObjectSet "${CER_NAME}" reports Available as True with Reason ProbesSucceeded
\ No newline at end of file
diff --git a/test/e2e/features/status.feature b/test/e2e/features/status.feature
index 5c8a3141d6..ff07e8d5ba 100644
--- a/test/e2e/features/status.feature
+++ b/test/e2e/features/status.feature
@@ -33,13 +33,13 @@ Feature: Report status of the managed ClusterExtension workload
Scenario: Report availability change when managed workload is not ready
When resource "deployment/test-operator" reports as not ready
Then ClusterExtension reports Available as False with Reason ProbeFailure
- And ClusterExtensionRevision "${NAME}-1" reports Available as False with Reason ProbeFailure
+ And ObjectSet "${NAME}-1" reports Available as False with Reason ProbeFailure
@BoxcutterRuntime
Scenario: Report availability change when managed workload restores its readiness
Given resource "deployment/test-operator" reports as not ready
And ClusterExtension reports Available as False with Reason ProbeFailure
- And ClusterExtensionRevision "${NAME}-1" reports Available as False with Reason ProbeFailure
+ And ObjectSet "${NAME}-1" reports Available as False with Reason ProbeFailure
When resource "deployment/test-operator" reports as ready
Then ClusterExtension is available
- And ClusterExtensionRevision "${NAME}-1" reports Available as True with Reason ProbesSucceeded
\ No newline at end of file
+ And ObjectSet "${NAME}-1" reports Available as True with Reason ProbesSucceeded
\ No newline at end of file
diff --git a/test/e2e/features/update.feature b/test/e2e/features/update.feature
index e1b4becca9..31787c8c1d 100644
--- a/test/e2e/features/update.feature
+++ b/test/e2e/features/update.feature
@@ -209,10 +209,10 @@ Feature: Update ClusterExtension
And ClusterExtension is rolled out
And ClusterExtension is available
And ClusterExtension reports "${NAME}-2" as active revision
- And ClusterExtensionRevision "${NAME}-2" reports Progressing as True with Reason Succeeded
- And ClusterExtensionRevision "${NAME}-2" reports Available as True with Reason ProbesSucceeded
- And ClusterExtensionRevision "${NAME}-1" is archived
- And ClusterExtensionRevision "${NAME}-1" phase objects are not found or not owned by the revision
+ And ObjectSet "${NAME}-2" reports Progressing as True with Reason Succeeded
+ And ObjectSet "${NAME}-2" reports Available as True with Reason ProbesSucceeded
+ And ObjectSet "${NAME}-1" is archived
+ And ObjectSet "${NAME}-1" phase objects are not found or not owned by the revision
@BoxcutterRuntime
Scenario: Report all active revisions on ClusterExtension
@@ -240,6 +240,6 @@ Feature: Update ClusterExtension
And ClusterExtension is available
When ClusterExtension is updated to version "1.0.2"
Then ClusterExtension reports "${NAME}-1, ${NAME}-2" as active revisions
- And ClusterExtensionRevision "${NAME}-2" reports Progressing as True with Reason RollingOut
- And ClusterExtensionRevision "${NAME}-2" reports Available as False with Reason ProbeFailure
+ And ObjectSet "${NAME}-2" reports Progressing as True with Reason RollingOut
+ And ObjectSet "${NAME}-2" reports Available as False with Reason ProbeFailure
diff --git a/test/e2e/steps/hooks.go b/test/e2e/steps/hooks.go
index f38559cb2f..8924f23b61 100644
--- a/test/e2e/steps/hooks.go
+++ b/test/e2e/steps/hooks.go
@@ -27,22 +27,22 @@ type resource struct {
}
type scenarioContext struct {
- id string
- namespace string
- clusterExtensionName string
- clusterExtensionRevisionName string
- clusterCatalogName string
- addedResources []resource
- removedResources []unstructured.Unstructured
- backGroundCmds []*exec.Cmd
- metricsResponse map[string]string
- leaderPods map[string]string // component name -> leader pod name
+ id string
+ namespace string
+ clusterExtensionName string
+ objectSetName string
+ clusterCatalogName string
+ addedResources []resource
+ removedResources []unstructured.Unstructured
+ backGroundCmds []*exec.Cmd
+ metricsResponse map[string]string
+ leaderPods map[string]string // component name -> leader pod name
extensionObjects []client.Object
}
// GatherClusterExtensionObjects collects all resources related to the ClusterExtension container in
-// either their Helm release Secret or ClusterExtensionRevision depending on the applier being used
+// either their Helm release Secret or ObjectSet depending on the applier being used
// and saves them into the context.
func (s *scenarioContext) GatherClusterExtensionObjects() error {
objs, err := listExtensionResources(s.clusterExtensionName)
@@ -153,11 +153,11 @@ func CheckFeatureTags(ctx context.Context, sc *godog.Scenario) (context.Context,
func CreateScenarioContext(ctx context.Context, sc *godog.Scenario) (context.Context, error) {
scCtx := &scenarioContext{
- id: sc.Id,
- namespace: fmt.Sprintf("ns-%s", sc.Id),
- clusterExtensionName: fmt.Sprintf("ce-%s", sc.Id),
- clusterExtensionRevisionName: fmt.Sprintf("cer-%s", sc.Id),
- leaderPods: make(map[string]string),
+ id: sc.Id,
+ namespace: fmt.Sprintf("ns-%s", sc.Id),
+ clusterExtensionName: fmt.Sprintf("ce-%s", sc.Id),
+ objectSetName: fmt.Sprintf("cer-%s", sc.Id),
+ leaderPods: make(map[string]string),
}
return context.WithValue(ctx, scenarioContextKey, scCtx), nil
}
@@ -189,8 +189,8 @@ func ScenarioCleanup(ctx context.Context, _ *godog.Scenario, err error) (context
if sc.clusterExtensionName != "" {
forDeletion = append(forDeletion, resource{name: sc.clusterExtensionName, kind: "clusterextension"})
}
- if sc.clusterExtensionRevisionName != "" {
- forDeletion = append(forDeletion, resource{name: sc.clusterExtensionRevisionName, kind: "clusterextensionrevision"})
+ if sc.objectSetName != "" {
+ forDeletion = append(forDeletion, resource{name: sc.objectSetName, kind: "objectset"})
}
forDeletion = append(forDeletion, resource{name: sc.namespace, kind: "namespace"})
for _, r := range forDeletion {
diff --git a/test/e2e/steps/steps.go b/test/e2e/steps/steps.go
index 57cfc864ed..469c057b67 100644
--- a/test/e2e/steps/steps.go
+++ b/test/e2e/steps/steps.go
@@ -87,14 +87,14 @@ func RegisterSteps(sc *godog.ScenarioContext) {
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)
sc.Step(`^(?i)ClusterExtension reports ([[:alnum:]]+) as ([[:alnum:]]+)$`, ClusterExtensionReportsConditionWithoutReason)
- sc.Step(`^(?i)ClusterExtensionRevision "([^"]+)" reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+)$`, ClusterExtensionRevisionReportsConditionWithoutMsg)
- sc.Step(`^(?i)ClusterExtensionRevision "([^"]+)" reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+) and Message:$`, ClusterExtensionRevisionReportsConditionWithMsg)
+ sc.Step(`^(?i)ObjectSet "([^"]+)" reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+)$`, ObjectSetReportsConditionWithoutMsg)
+ sc.Step(`^(?i)ObjectSet "([^"]+)" reports ([[:alnum:]]+) as ([[:alnum:]]+) with Reason ([[:alnum:]]+) and Message:$`, ObjectSetReportsConditionWithMsg)
sc.Step(`^(?i)ClusterExtension reports ([[:alnum:]]+) transition between (\d+) and (\d+) minutes since its creation$`, ClusterExtensionReportsConditionTransitionTime)
- sc.Step(`^(?i)ClusterExtensionRevision is applied(?:\s+.*)?$`, ResourceIsApplied)
- sc.Step(`^(?i)ClusterExtensionRevision "([^"]+)" is archived$`, ClusterExtensionRevisionIsArchived)
- sc.Step(`^(?i)ClusterExtensionRevision "([^"]+)" contains annotation "([^"]+)" with value$`, ClusterExtensionRevisionHasAnnotationWithValue)
- sc.Step(`^(?i)ClusterExtensionRevision "([^"]+)" has label "([^"]+)" with value "([^"]+)"$`, ClusterExtensionRevisionHasLabelWithValue)
- sc.Step(`^(?i)ClusterExtensionRevision "([^"]+)" phase objects are not found or not owned by the revision$`, ClusterExtensionRevisionObjectsNotFoundOrNotOwned)
+ sc.Step(`^(?i)ObjectSet is applied(?:\s+.*)?$`, ResourceIsApplied)
+ sc.Step(`^(?i)ObjectSet "([^"]+)" is archived$`, ObjectSetIsArchived)
+ sc.Step(`^(?i)ObjectSet "([^"]+)" contains annotation "([^"]+)" with value$`, ObjectSetHasAnnotationWithValue)
+ sc.Step(`^(?i)ObjectSet "([^"]+)" has label "([^"]+)" with value "([^"]+)"$`, ObjectSetHasLabelWithValue)
+ sc.Step(`^(?i)ObjectSet "([^"]+)" phase objects are not found or not owned by the revision$`, ObjectSetObjectsNotFoundOrNotOwned)
sc.Step(`^(?i)resource "([^"]+)" is installed$`, ResourceAvailable)
sc.Step(`^(?i)resource "([^"]+)" is available$`, ResourceAvailable)
@@ -136,7 +136,7 @@ func RegisterSteps(sc *godog.ScenarioContext) {
sc.Step(`^(?i)operator "([^"]+)" target namespace is "([^"]+)"$`, OperatorTargetNamespace)
sc.Step(`^(?i)Prometheus metrics are returned in the response$`, PrometheusMetricsAreReturned)
- sc.Step(`^(?i)min value for (ClusterExtension|ClusterExtensionRevision) ((?:\.[a-zA-Z]+)+) is set to (\d+)$`, SetCRDFieldMinValue)
+ sc.Step(`^(?i)min value for (ClusterExtension|ObjectSet) ((?:\.[a-zA-Z]+)+) is set to (\d+)$`, SetCRDFieldMinValue)
// Upgrade-specific steps
sc.Step(`^(?i)the latest stable OLM release is installed$`, LatestStableOLMReleaseIsInstalled)
@@ -223,7 +223,7 @@ func substituteScenarioVars(content string, sc *scenarioContext) string {
vars := map[string]string{
"TEST_NAMESPACE": sc.namespace,
"NAME": sc.clusterExtensionName,
- "CER_NAME": sc.clusterExtensionRevisionName,
+ "CER_NAME": sc.objectSetName,
"CATALOG_IMG": "docker-registry.operator-controller-e2e.svc.cluster.local:5000/e2e/test-catalog:v1",
}
if v, found := os.LookupEnv("CATALOG_IMG"); found {
@@ -273,7 +273,7 @@ func ClusterExtensionVersionUpdate(ctx context.Context, version string) error {
return err
}
-// ResourceIsApplied applies the provided YAML resource to the cluster and in case of ClusterExtension or ClusterExtensionRevision it captures
+// ResourceIsApplied applies the provided YAML resource to the cluster and in case of ClusterExtension or ObjectSet it captures
// its name in the test context so that it can be referred to in later steps with ${NAME} or ${CER_NAME}, respectively
func ResourceIsApplied(ctx context.Context, yamlTemplate *godog.DocString) error {
sc := scenarioCtx(ctx)
@@ -288,8 +288,8 @@ func ResourceIsApplied(ctx context.Context, yamlTemplate *godog.DocString) error
}
if res.GetKind() == "ClusterExtension" {
sc.clusterExtensionName = res.GetName()
- } else if res.GetKind() == "ClusterExtensionRevision" {
- sc.clusterExtensionRevisionName = res.GetName()
+ } else if res.GetKind() == "ObjectSet" {
+ sc.objectSetName = res.GetName()
}
return nil
}
@@ -550,27 +550,27 @@ func ClusterExtensionReportsActiveRevisions(ctx context.Context, rawRevisionName
return nil
}
-// ClusterExtensionRevisionReportsConditionWithoutMsg waits for the named ClusterExtensionRevision to have a condition
+// ObjectSetReportsConditionWithoutMsg waits for the named ObjectSet to have a condition
// matching type, status, and reason. Polls with timeout.
-func ClusterExtensionRevisionReportsConditionWithoutMsg(ctx context.Context, revisionName, conditionType, conditionStatus, conditionReason string) error {
- return waitForCondition(ctx, "clusterextensionrevision", substituteScenarioVars(revisionName, scenarioCtx(ctx)), conditionType, conditionStatus, &conditionReason, nil)
+func ObjectSetReportsConditionWithoutMsg(ctx context.Context, revisionName, conditionType, conditionStatus, conditionReason string) error {
+ return waitForCondition(ctx, "objectset", substituteScenarioVars(revisionName, scenarioCtx(ctx)), conditionType, conditionStatus, &conditionReason, nil)
}
-// ClusterExtensionRevisionReportsConditionWithMsg waits for the named ClusterExtensionRevision to have a condition
+// ObjectSetReportsConditionWithMsg waits for the named ObjectSet to have a condition
// matching type, status, reason, and message. Polls with timeout.
-func ClusterExtensionRevisionReportsConditionWithMsg(ctx context.Context, revisionName, conditionType, conditionStatus, conditionReason string, msg *godog.DocString) error {
- return waitForCondition(ctx, "clusterextensionrevision", substituteScenarioVars(revisionName, scenarioCtx(ctx)), conditionType, conditionStatus, &conditionReason, messageComparison(ctx, msg))
+func ObjectSetReportsConditionWithMsg(ctx context.Context, revisionName, conditionType, conditionStatus, conditionReason string, msg *godog.DocString) error {
+ return waitForCondition(ctx, "objectset", substituteScenarioVars(revisionName, scenarioCtx(ctx)), conditionType, conditionStatus, &conditionReason, messageComparison(ctx, msg))
}
-// ClusterExtensionRevisionIsArchived waits for the named ClusterExtensionRevision to have Progressing=False
+// ObjectSetIsArchived waits for the named ObjectSet to have Progressing=False
// with reason Archived. Polls with timeout.
-func ClusterExtensionRevisionIsArchived(ctx context.Context, revisionName string) error {
- return waitForCondition(ctx, "clusterextensionrevision", substituteScenarioVars(revisionName, scenarioCtx(ctx)), "Progressing", "False", ptr.To("Archived"), nil)
+func ObjectSetIsArchived(ctx context.Context, revisionName string) error {
+ return waitForCondition(ctx, "objectset", substituteScenarioVars(revisionName, scenarioCtx(ctx)), "Progressing", "False", ptr.To("Archived"), nil)
}
-// ClusterExtensionRevisionHasAnnotationWithValue waits for the named ClusterExtensionRevision to have the specified
+// ObjectSetHasAnnotationWithValue waits for the named ObjectSet to have the specified
// annotation with the expected value. Polls with timeout.
-func ClusterExtensionRevisionHasAnnotationWithValue(ctx context.Context, revisionName, annotationKey string, annotationValue *godog.DocString) error {
+func ObjectSetHasAnnotationWithValue(ctx context.Context, revisionName, annotationKey string, annotationValue *godog.DocString) error {
sc := scenarioCtx(ctx)
revisionName = substituteScenarioVars(strings.TrimSpace(revisionName), sc)
expectedValue := ""
@@ -578,9 +578,9 @@ func ClusterExtensionRevisionHasAnnotationWithValue(ctx context.Context, revisio
expectedValue = annotationValue.Content
}
waitFor(ctx, func() bool {
- obj, err := getResource("clusterextensionrevision", revisionName, "")
+ obj, err := getResource("objectset", revisionName, "")
if err != nil {
- logger.V(1).Error(err, "failed to get clusterextensionrevision", "name", revisionName)
+ logger.V(1).Error(err, "failed to get objectset", "name", revisionName)
return false
}
if obj.GetAnnotations() == nil {
@@ -591,16 +591,16 @@ func ClusterExtensionRevisionHasAnnotationWithValue(ctx context.Context, revisio
return nil
}
-// ClusterExtensionRevisionHasLabelWithValue waits for the named ClusterExtensionRevision to have the specified label
+// ObjectSetHasLabelWithValue waits for the named ObjectSet to have the specified label
// with the expected value. Polls with timeout.
-func ClusterExtensionRevisionHasLabelWithValue(ctx context.Context, revisionName, labelKey, labelValue string) error {
+func ObjectSetHasLabelWithValue(ctx context.Context, revisionName, labelKey, labelValue string) error {
sc := scenarioCtx(ctx)
revisionName = substituteScenarioVars(strings.TrimSpace(revisionName), sc)
labelValue = substituteScenarioVars(labelValue, sc)
waitFor(ctx, func() bool {
- obj, err := getResource("clusterextensionrevision", revisionName, "")
+ obj, err := getResource("objectset", revisionName, "")
if err != nil {
- logger.V(1).Error(err, "failed to get clusterextensionrevision", "name", revisionName)
+ logger.V(1).Error(err, "failed to get objectset", "name", revisionName)
return false
}
if obj.GetLabels() == nil {
@@ -611,17 +611,17 @@ func ClusterExtensionRevisionHasLabelWithValue(ctx context.Context, revisionName
return nil
}
-// ClusterExtensionRevisionObjectsNotFoundOrNotOwned waits for all objects described in the named
-// ClusterExtensionRevision's phases to either not exist on the cluster or not contain the revision
+// ObjectSetObjectsNotFoundOrNotOwned waits for all objects described in the named
+// ObjectSet's phases to either not exist on the cluster or not contain the revision
// in their ownerReferences. Polls with timeout.
-func ClusterExtensionRevisionObjectsNotFoundOrNotOwned(ctx context.Context, revisionName string) error {
+func ObjectSetObjectsNotFoundOrNotOwned(ctx context.Context, revisionName string) error {
sc := scenarioCtx(ctx)
revisionName = substituteScenarioVars(strings.TrimSpace(revisionName), sc)
// Get the CER to extract its phase objects
- var rev ocv1.ClusterExtensionRevision
+ var rev ocv1.ObjectSet
waitFor(ctx, func() bool {
- out, err := k8sClient("get", "clusterextensionrevision", revisionName, "-o", "json")
+ out, err := k8sClient("get", "objectset", revisionName, "-o", "json")
if err != nil {
return false
}
@@ -638,10 +638,10 @@ func ClusterExtensionRevisionObjectsNotFoundOrNotOwned(ctx context.Context, revi
namespace := obj.GetNamespace()
if kind == "" {
- return fmt.Errorf("clusterextensionrevision %q has a phase object with empty kind", revisionName)
+ return fmt.Errorf("objectset %q has a phase object with empty kind", revisionName)
}
if name == "" {
- return fmt.Errorf("clusterextensionrevision %q has a phase object with empty name (kind %q, namespace %q)", revisionName, kind, namespace)
+ return fmt.Errorf("objectset %q has a phase object with empty name (kind %q, namespace %q)", revisionName, kind, namespace)
}
waitFor(ctx, func() bool {
@@ -664,7 +664,7 @@ func ClusterExtensionRevisionObjectsNotFoundOrNotOwned(ctx context.Context, revi
// Check that no ownerReference points to this CER
for _, ref := range clusterObj.GetOwnerReferences() {
- if ref.Kind == ocv1.ClusterExtensionRevisionKind && ref.Name == revisionName && ref.UID == rev.UID {
+ if ref.Kind == ocv1.ObjectSetKind && ref.Name == revisionName && ref.UID == rev.UID {
logger.V(1).Info("object still owned by revision",
"kind", kind, "name", name, "namespace", namespace,
"revision", revisionName)
@@ -1153,8 +1153,8 @@ func SetCRDFieldMinValue(_ context.Context, resourceType, jsonPath string, minVa
switch resourceType {
case "ClusterExtension":
crdName = "clusterextensions.olm.operatorframework.io"
- case "ClusterExtensionRevision":
- crdName = "clusterextensionrevisions.olm.operatorframework.io"
+ case "ObjectSet":
+ crdName = "objectsets.olm.operatorframework.io"
default:
return fmt.Errorf("unsupported resource type: %s", resourceType)
}
@@ -1333,23 +1333,23 @@ func listExtensionRevisionResources(extName string) ([]client.Object, error) {
}
// latestActiveRevisionForExtension returns the latest active revision for the extension called extName
-func latestActiveRevisionForExtension(extName string) (*ocv1.ClusterExtensionRevision, error) {
- out, err := k8sClient("get", "clusterextensionrevisions", "-l", fmt.Sprintf("olm.operatorframework.io/owner-name=%s", extName), "-o", "json")
+func latestActiveRevisionForExtension(extName string) (*ocv1.ObjectSet, error) {
+ out, err := k8sClient("get", "objectsets", "-l", fmt.Sprintf("olm.operatorframework.io/owner-name=%s", extName), "-o", "json")
if err != nil {
return nil, fmt.Errorf("error listing revisions for extension '%s': %w", extName, err)
}
if strings.TrimSpace(out) == "" {
return nil, fmt.Errorf("no revisions found for extension '%s'", extName)
}
- var revisionList ocv1.ClusterExtensionRevisionList
+ var revisionList ocv1.ObjectSetList
if err := json.Unmarshal([]byte(out), &revisionList); err != nil {
return nil, fmt.Errorf("error unmarshalling revisions for extension '%s': %w", extName, err)
}
- var latest *ocv1.ClusterExtensionRevision
+ var latest *ocv1.ObjectSet
for i := range revisionList.Items {
rev := &revisionList.Items[i]
- if rev.Spec.LifecycleState != ocv1.ClusterExtensionRevisionLifecycleStateActive {
+ if rev.Spec.LifecycleState != ocv1.ObjectSetLifecycleStateActive {
continue
}
if latest == nil || rev.Spec.Revision > latest.Spec.Revision {
diff --git a/test/e2e/steps/testdata/olm-sa-boxcutter-rbac-template.yaml b/test/e2e/steps/testdata/olm-sa-boxcutter-rbac-template.yaml
index 7c35f997e5..3cbeb0250b 100644
--- a/test/e2e/steps/testdata/olm-sa-boxcutter-rbac-template.yaml
+++ b/test/e2e/steps/testdata/olm-sa-boxcutter-rbac-template.yaml
@@ -9,9 +9,9 @@ kind: ClusterRole
metadata:
name: ${TEST_NAMESPACE}-${SERVICEACCOUNT_NAME}-olm-admin-clusterrole
rules:
- # Allow management of ClusterExtensionRevision finalizers (e.g. by the Boxcutter applier)
+ # Allow management of ObjectSet finalizers (e.g. by the Boxcutter applier)
- apiGroups: [olm.operatorframework.io]
- resources: [clusterextensionrevisions/finalizers]
+ resources: [objectsets/finalizers]
verbs: [update, patch]
# OLMv0 compatibility requirement for AllNamespaces install
# https://github.com/operator-framework/operator-lifecycle-manager/blob/dfd0b2bea85038d3c0d65348bc812d297f16b8d2/pkg/controller/operators/olm/operatorgroup.go#L530
diff --git a/test/e2e/steps/testdata/pvc-probe-sa-boxcutter-rbac-template.yaml b/test/e2e/steps/testdata/pvc-probe-sa-boxcutter-rbac-template.yaml
index 526b9845a0..1496d46fdc 100644
--- a/test/e2e/steps/testdata/pvc-probe-sa-boxcutter-rbac-template.yaml
+++ b/test/e2e/steps/testdata/pvc-probe-sa-boxcutter-rbac-template.yaml
@@ -4,7 +4,7 @@ metadata:
name: ${TEST_NAMESPACE}-${SERVICEACCOUNT_NAME}-clusterrole
rules:
- apiGroups: [olm.operatorframework.io]
- resources: [clusterextensionrevisions/finalizers]
+ resources: [objectsets/finalizers]
verbs: [update]
- apiGroups: [""]
resources: [persistentvolumes]
diff --git a/test/e2e/steps/testdata/rbac-template-for-all-extensions.yaml b/test/e2e/steps/testdata/rbac-template-for-all-extensions.yaml
index fa27689828..7cca0a6b66 100644
--- a/test/e2e/steps/testdata/rbac-template-for-all-extensions.yaml
+++ b/test/e2e/steps/testdata/rbac-template-for-all-extensions.yaml
@@ -12,9 +12,9 @@ rules:
- apiGroups: [olm.operatorframework.io]
resources: [clusterextensions, clusterextensions/finalizers]
verbs: [update]
- # Allow ClusterExtensionRevisions to set blockOwnerDeletion ownerReferences
+ # Allow ObjectSets to set blockOwnerDeletion ownerReferences
- apiGroups: [olm.operatorframework.io]
- resources: [clusterextensionrevisions, clusterextensionrevisions/finalizers]
+ resources: [objectsets, objectsets/finalizers]
verbs: [update, create, list, watch, get, delete, patch]
- apiGroups: [apiextensions.k8s.io]
resources: [customresourcedefinitions]