Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
063ef86
Update boxcutter library to branch with latest k8s and controller-run…
Jul 15, 2025
d9fe32e
Update go.mod
Jul 23, 2025
f7cde06
Add ClusterExtensionRevisionAPI
Jul 23, 2025
7338e94
Add BoxcutterRuntime featuregate
Jul 23, 2025
5e3b6e6
Add Boxcutter applier
Jul 23, 2025
a86179e
Add ClusterExtensionRevision controller
Jul 23, 2025
6774ac5
Add Boxcutter runtime to main
Jul 23, 2025
fcafede
Remove ClusterExtensionRevision from crd-docs
Jul 23, 2025
0e9cb2a
Update hack/tools/update-crds.sh for ClusterExtensionRevision API
Jul 23, 2025
df72a78
Generate manifests
Jul 23, 2025
0add5f7
Remove access manager and dynamic cache
Jul 28, 2025
13dbfee
Update boxcutter to v0.3.0, add TrackingCache to Runnables
thetechnick Jul 31, 2025
abf3582
boxcutter webhook support
joelanford Jul 31, 2025
5ddd2f3
add BoxcutterRuntime feature gate to experimental release
joelanford Jul 31, 2025
f83d6d2
add boxcutter cluster-admin cluster role binding in boxcutter's featu…
joelanford Jul 31, 2025
2c83f11
Boxcutter Preflight
tmshort Jul 31, 2025
66c9531
Boxcutter Preflight mock cleanup
tmshort Aug 1, 2025
a5050c8
Use new TrackingCache Watch/Free.
thetechnick Aug 11, 2025
fe2caf3
add BoxcutterInstalledBundleGetter, plumb bundle metadata into revisi…
joelanford Jul 31, 2025
58e09b2
InstalledBundleGetter -> RevisionStatesGetter
joelanford Aug 1, 2025
58977ca
refactor Applier interface and improve status reporting
joelanford Aug 1, 2025
adeaac3
fixup tests for applier and installedbundlegetter changes
joelanford Aug 5, 2025
c2711f6
resolve linter issues
joelanford Aug 7, 2025
877ba2d
set status for other failure modes during ClusterExtensionRevision re…
joelanford Aug 8, 2025
decda1e
TODO: fail upgrade-e2e if revision storage is unmigrated
joelanford Aug 11, 2025
5462055
fixing broken tests after rebase
joelanford Aug 19, 2025
125ca53
Boxcutter Phases
dtfranz Aug 12, 2025
4d150cc
Const Cleanup
dtfranz Aug 28, 2025
87b4432
fix rebase issue
thetechnick Sep 5, 2025
46a09a8
Add migration from helm to boxcutter revision
thetechnick Aug 27, 2025
1a56e01
Run make manifests
thetechnick Sep 5, 2025
66d46b3
Run go mod tidy
thetechnick Sep 5, 2025
c175077
?
thetechnick Sep 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api/v1/clusterextension_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/operator-framework/operator-controller/internal/operator-controller/conditionsets"
)

// TODO Expand these tests to cover Types/Reasons/etc. from other APIs as well

func TestClusterExtensionTypeRegistration(t *testing.T) {
types, err := parseConstants("Type")
if err != nil {
Expand Down
181 changes: 181 additions & 0 deletions api/v1/clusterextensionrevision_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
Copyright 2024.

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.
*/

package v1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
)

const (
ClusterExtensionRevisionKind = "ClusterExtensionRevision"

// Condition Types
ClusterExtensionRevisionTypeAvailable = "Available"
ClusterExtensionRevisionTypeSucceeded = "Succeeded"

// Condition Reasons
ClusterExtensionRevisionReasonAvailable = "Available"
ClusterExtensionRevisionReasonReconcileFailure = "ReconcileFailure"
ClusterExtensionRevisionReasonRevisionValidationFailure = "RevisionValidationFailure"
ClusterExtensionRevisionReasonPhaseValidationError = "PhaseValidationError"
ClusterExtensionRevisionReasonObjectCollisions = "ObjectCollisions"
ClusterExtensionRevisionReasonRolloutSuccess = "RolloutSuccess"
ClusterExtensionRevisionReasonProbeFailure = "ProbeFailure"
ClusterExtensionRevisionReasonIncomplete = "Incomplete"
ClusterExtensionRevisionReasonProgressing = "Progressing"
)

// ClusterExtensionRevisionSpec defines the desired state of ClusterExtensionRevision.
type ClusterExtensionRevisionSpec struct {
// Specifies the lifecycle state of the ClusterExtensionRevision.
//
// +kubebuilder:default="Active"
// +kubebuilder:validation:Enum=Active;Paused;Archived
// +kubebuilder:validation:XValidation:rule="oldSelf == 'Active' || oldSelf == 'Paused' || oldSelf == 'Archived' && oldSelf == self", message="can not un-archive"
LifecycleState ClusterExtensionRevisionLifecycleState `json:"lifecycleState,omitempty"`
// Revision number orders changes over time, must always be previous revision +1.
//
// +kubebuilder:validation:Required
// +kubebuilder:validation:XValidation:rule="self == oldSelf", message="revision is immutable"
Revision int64 `json:"revision"`
// Phases are groups of objects that will be applied at the same time.
// All objects in the a phase will have to pass their probes in order to progress to the next phase.
//
// +kubebuilder:validation:Required
// +kubebuilder:validation:XValidation:rule="self == oldSelf || oldSelf.size() == 0", message="phases is immutable"
// +patchMergeKey=name
// +patchStrategy=merge
// +listType=map
// +listMapKey=name
Phases []ClusterExtensionRevisionPhase `json:"phases"`
// Previous references previous revisions that objects can be adopted from.
//
// +kubebuilder:validation:XValidation:rule="self == oldSelf", message="previous is immutable"
Previous []ClusterExtensionRevisionPrevious `json:"previous,omitempty"`
}

// ClusterExtensionRevisionLifecycleState specifies the lifecycle state of the ClusterExtensionRevision.
type ClusterExtensionRevisionLifecycleState string

const (
// ClusterExtensionRevisionLifecycleStateActive / "Active" is the default lifecycle state.
ClusterExtensionRevisionLifecycleStateActive ClusterExtensionRevisionLifecycleState = "Active"
// ClusterExtensionRevisionLifecycleStatePaused / "Paused" disables reconciliation of the ClusterExtensionRevision.
// Only Status updates will still propagated, but object changes will not be reconciled.
ClusterExtensionRevisionLifecycleStatePaused ClusterExtensionRevisionLifecycleState = "Paused"
// ClusterExtensionRevisionLifecycleStateArchived / "Archived" disables reconciliation while also "scaling to zero",
// which deletes all objects that are not excluded via the pausedFor property and
// removes itself from the owner list of all other objects previously under management.
ClusterExtensionRevisionLifecycleStateArchived ClusterExtensionRevisionLifecycleState = "Archived"
)

// ClusterExtensionRevisionPhase are groups of objects that will be applied at the same time.
// All objects in the a phase will have to pass their probes in order to progress to the next phase.
type ClusterExtensionRevisionPhase struct {
// Name identifies this phase.
//
// +kubebuilder:validation:MaxLength=63
// +kubebuilder:validation:Pattern=`^[a-z]([-a-z0-9]*[a-z0-9])?$`
Name string `json:"name"`
// Objects are a list of all the objects within this phase.
Objects []ClusterExtensionRevisionObject `json:"objects"`
}

// ClusterExtensionRevisionObject contains an object and settings for it.
type ClusterExtensionRevisionObject struct {
// +kubebuilder:validation:EmbeddedResource
// +kubebuilder:pruning:PreserveUnknownFields
Object unstructured.Unstructured `json:"object"`
// CollisionProtection controls whether OLM can adopt and modify objects
// already existing on the cluster or even owned by another controller.
//
// +kubebuilder:default="Prevent"
CollisionProtection CollisionProtection `json:"collisionProtection,omitempty"`
}

// CollisionProtection specifies if and how ownership collisions are prevented.
type CollisionProtection string

const (
// CollisionProtectionPrevent prevents owner collisions entirely
// by only allowing to work with objects itself has created.
CollisionProtectionPrevent CollisionProtection = "Prevent"
// CollisionProtectionIfNoController allows to patch and override
// objects already present if they are not owned by another controller.
CollisionProtectionIfNoController CollisionProtection = "IfNoController"
// CollisionProtectionNone allows to patch and override objects
// already present and owned by other controllers.
// Be careful! This setting may cause multiple controllers to fight over a resource,
// causing load on the API server and etcd.
CollisionProtectionNone CollisionProtection = "None"
)

type ClusterExtensionRevisionPrevious struct {
// +kubebuilder:validation:Required
Name string `json:"name"`
// +kubebuilder:validation:Required
UID types.UID `json:"uid"`
}

// ClusterExtensionRevisionStatus defines the observed state of a ClusterExtensionRevision.
type ClusterExtensionRevisionStatus struct {
// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
}

// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Cluster
// +kubebuilder:subresource:status

// ClusterExtensionRevision is the Schema for the clusterextensionrevisions API
type ClusterExtensionRevision struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// spec is an optional field that defines the desired state of the ClusterExtension.
// +optional
Spec ClusterExtensionRevisionSpec `json:"spec,omitempty"`

// status is an optional field that defines the observed state of the ClusterExtension.
// +optional
Status ClusterExtensionRevisionStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// ClusterExtensionRevisionList contains a list of ClusterExtensionRevision
type ClusterExtensionRevisionList struct {
metav1.TypeMeta `json:",inline"`

// +optional
metav1.ListMeta `json:"metadata,omitempty"`

// items is a required list of ClusterExtensionRevision objects.
//
// +kubebuilder:validation:Required
Items []ClusterExtensionRevision `json:"items"`
}

func init() {
SchemeBuilder.Register(&ClusterExtensionRevision{}, &ClusterExtensionRevisionList{})
}
16 changes: 11 additions & 5 deletions api/v1/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@ const (
TypeInstalled = "Installed"
TypeProgressing = "Progressing"

// Installed reasons
ReasonAbsent = "Absent"

// Progressing reasons
ReasonSucceeded = "Succeeded"
ReasonRetrying = "Retrying"
ReasonBlocked = "Blocked"
ReasonRolloutInProgress = "RolloutInProgress"
ReasonRetrying = "Retrying"
ReasonBlocked = "Blocked"

// Terminal reasons
// Deprecation reasons
ReasonDeprecated = "Deprecated"
ReasonFailed = "Failed"

// Common reasons
ReasonSucceeded = "Succeeded"
ReasonFailed = "Failed"
)
161 changes: 161 additions & 0 deletions api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading