Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
25e8c5e
:seedling: Bump certifi from 2025.11.12 to 2026.1.4 (#2449)
dependabot[bot] Jan 19, 2026
a9e5614
Support `ClusterExtension` progress deadline detection (#2447)
pedjak Jan 19, 2026
46e41b2
:seedling: Bump pathspec from 0.12.1 to 1.0.1 (#2450)
dependabot[bot] Jan 20, 2026
3c247ee
Add preflight checks to Boxcutter applier (#2443)
perdasilva Jan 20, 2026
0c36df6
Refactor Boxcutter controller to rely on kubernetes for resource clea…
perdasilva Jan 20, 2026
8167ff8
Remove unfinished uninstall e2e test (#2452)
perdasilva Jan 20, 2026
045ea8f
Merge branch 'main' into synchronize
Jan 21, 2026
8666729
UPSTREAM: <carry>: Add OpenShift specific files
dtfranz Oct 26, 2023
755e4c6
UPSTREAM: <carry>: Add new tests for single/own namespaces install modes
camilamacedo86 Oct 6, 2025
cba1e13
UPSTREAM: <carry>: Upgrade OCP image from 4.20 to 4.21
camilamacedo86 Oct 13, 2025
8b3b361
UPSTREAM: <carry>: [Default Catalog Tests] - Change logic to get ocp …
camilamacedo86 Oct 13, 2025
8a9cfd5
UPSTREAM: <carry>: Update OCP catalogs to v4.21
tmshort Oct 13, 2025
4aa73b7
UPSTREAM: <carry>: support singleown cases in disconnected
kuiwang02 Oct 16, 2025
375af73
UPSTREAM: <carry>: fix cases 81696 and 74618 for product code changes
kuiwang02 Oct 17, 2025
277ca8f
UPSTREAM: <carry>: Define Default timeouts and apply their usage accr…
camilamacedo86 Oct 22, 2025
a49836d
UPSTREAM: <carry>: Update to new feature-gate options in helm
tmshort Oct 22, 2025
6397e6c
UPSTREAM: <carry>: Fix flake for single/own ns tests by ensuring uniq…
camilamacedo86 Oct 22, 2025
ce4e7b0
UPSTREAM: <carry>: [OTE]: Enhance single/own ns based on review comme…
camilamacedo86 Oct 24, 2025
45613df
UPSTREAM: <carry>: Update OwnSingle template to use spec.config.inlin…
kuiwang02 Nov 3, 2025
a46c51a
UPSTREAM: <carry>: [OTE]: Add webhook cleanup validation on extension…
camilamacedo86 Nov 4, 2025
df3d3e0
UPSTREAM: <carry>: Add [OTP] to migrated cases
kuiwang02 Nov 7, 2025
e025d3e
UPSTREAM: <carry>: [OTE]: Upgrade dependencies used
camilamacedo86 Nov 5, 2025
61ed136
UPSTREAM: <carry>: fix(OTE): fix OpenShift Kubernetes replace version…
camilamacedo86 Nov 10, 2025
03c3151
UPSTREAM: <carry>: [Default Catalog Tests] Upgrade go 1.24.6 and depe…
camilamacedo86 Nov 11, 2025
d0c1978
UPSTREAM: <carry>: add disconnected environment support with custom p…
kuiwang02 Nov 12, 2025
81d762c
UPSTREAM: <carry>: migrate jiazha test cases to OTE
jianzhangbjz Nov 14, 2025
bc200a7
UPSTREAM: <carry>: migrate clustercatalog case to ote
Xia-Zhao-rh Oct 17, 2025
008dccb
UPSTREAM: <carry>: migrate olmv1 QE stress cases
kuiwang02 Nov 20, 2025
90457b1
UPSTREAM: <carry>: Use busybox/httpd to simulate probes
tmshort Nov 25, 2025
a3fb49b
UPSTREAM: <carry>: migrate olmv1 QE cases
Xia-Zhao-rh Nov 25, 2025
f00d756
UPSTREAM: <carry>: add agent for olmv1 qe cases
kuiwang02 Oct 21, 2025
78f83c8
UPSTREAM: <carry>: Disable upstream PodDisruptionBudget
tmshort Dec 3, 2025
2cbc4f7
UPSTREAM: <carry>: Add AGENTS.md for AI code contributions
rashmigottipati Dec 11, 2025
0ee68a7
UPSTREAM: <carry>: address review comments through addl prompts
rashmigottipati Dec 11, 2025
a22cae2
UPSTREAM: <carry>: addressing some more review comments
rashmigottipati Dec 11, 2025
bbf155e
UPSTREAM: <carry>: remove DCO line
rashmigottipati Dec 11, 2025
f542ca9
UPSTREAM: <carry>: migrate bandrade test cases to OTE
bandrade Nov 18, 2025
9a373e4
UPSTREAM: <carry>: update metadata
bandrade Dec 3, 2025
74fd3f5
UPSTREAM: <carry>: remove originalName
bandrade Dec 3, 2025
48f82c4
UPSTREAM: <carry>: update 80458's timeout to 180s
jianzhangbjz Dec 8, 2025
70209a3
UPSTREAM: <carry>: update 83026 to specify the clustercatalog
jianzhangbjz Dec 15, 2025
7d5719e
UPSTREAM: <carry>: Update to golang 1.25 and ocp 4.22
oceanc80 Dec 18, 2025
98e27e6
UPSTREAM: <carry>: Use oc client for running e2e tests
pedjak Jan 13, 2026
2885bcb
UPSTREAM: <carry>: Run upstream e2e tests tagged with `@catalogd-update`
pedjak Jan 14, 2026
6689860
UPSTREAM: <carry>: enhance case to make it more stable
kuiwang02 Jan 6, 2026
6f4997d
UPSTREAM: <carry>: add service account to curl job
ehearne-redhat Jan 7, 2026
e88d0a8
UPSTREAM: <carry>: move sa creation out of buildCurlJob()
ehearne-redhat Jan 8, 2026
ae753c3
UPSTREAM: <carry>: comment out delete service account
ehearne-redhat Jan 9, 2026
4a6348e
UPSTREAM: <carry>: move defercleanup for sa for LIFO
ehearne-redhat Jan 9, 2026
a74ad93
UPSTREAM: <carry>: add polling so job fully deleted before proceed
ehearne-redhat Jan 12, 2026
f0785ad
UPSTREAM: <carry>: Revert "Merge pull request #594 from ehearne-redha…
sosiouxme Jan 20, 2026
f837a23
UPSTREAM: <drop>: go mod vendor
Jan 21, 2026
1a7b1a4
UPSTREAM: <drop>: remove upstream GitHub configuration
Jan 21, 2026
f0ab2ca
UPSTREAM: <drop>: configure the commit-checker
Jan 21, 2026
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
11 changes: 11 additions & 0 deletions api/v1/clusterextension_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,17 @@ type ClusterExtensionSpec struct {
//
// +optional
Config *ClusterExtensionConfig `json:"config,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
// is provided. The minimum period is 10 minutes, and the maximum is 720 minutes (12 hours).
//
// +kubebuilder:validation:Minimum:=10
// +kubebuilder:validation:Maximum:=720
// +optional
// <opcon:experimental>
ProgressDeadlineMinutes int32 `json:"progressDeadlineMinutes,omitempty"`
}

const SourceTypeCatalog = "Catalog"
Expand Down
11 changes: 11 additions & 0 deletions api/v1/clusterextensionrevision_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ type ClusterExtensionRevisionSpec struct {
// +listMapKey=name
// +optional
Phases []ClusterExtensionRevisionPhase `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
// is provided. The minimum period is 10 minutes, and the maximum is 720 minutes (12 hours).
//
// +kubebuilder:validation:Minimum:=10
// +kubebuilder:validation:Maximum:=720
// +optional
// <opcon:experimental>
ProgressDeadlineMinutes int32 `json:"progressDeadlineMinutes,omitempty"`
}

// ClusterExtensionRevisionLifecycleState specifies the lifecycle state of the ClusterExtensionRevision.
Expand Down
5 changes: 3 additions & 2 deletions api/v1/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const (
ReasonDeprecated = "Deprecated"

// Common reasons
ReasonSucceeded = "Succeeded"
ReasonFailed = "Failed"
ReasonSucceeded = "Succeeded"
ReasonFailed = "Failed"
ReasonProgressDeadlineExceeded = "ProgressDeadlineExceeded"
)
176 changes: 176 additions & 0 deletions api/v1/validation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package v1

import (
"fmt"
"testing"

"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func TestValidate(t *testing.T) {
type args struct {
object any
skipDefaulting bool
}
type want struct {
valid bool
}
type testCase struct {
args args
want want
}
defaultExtensionSpec := func(s *ClusterExtensionSpec) *ClusterExtensionSpec {
s.Namespace = "ns"
s.ServiceAccount = ServiceAccountReference{
Name: "sa",
}
s.Source = SourceConfig{
SourceType: SourceTypeCatalog,
Catalog: &CatalogFilter{
PackageName: "test",
},
}
return s
}
defaultRevisionSpec := func(s *ClusterExtensionRevisionSpec) *ClusterExtensionRevisionSpec {
s.Revision = 1
return s
}
c := newClient(t)
i := 0

for name, tc := range map[string]testCase{
"ClusterExtension: invalid progress deadline < 10": {
args: args{
object: ClusterExtensionSpec{
ProgressDeadlineMinutes: 9,
},
},
want: want{valid: false},
},
"ClusterExtension: valid progress deadline = 10": {
args: args{
object: ClusterExtensionSpec{
ProgressDeadlineMinutes: 10,
},
},
want: want{valid: true},
},
"ClusterExtension: valid progress deadline = 360": {
args: args{
object: ClusterExtensionSpec{
ProgressDeadlineMinutes: 360,
},
},
want: want{valid: true},
},
"ClusterExtension: valid progress deadline = 720": {
args: args{
object: ClusterExtensionSpec{
ProgressDeadlineMinutes: 720,
},
},
want: want{valid: true},
},
"ClusterExtension: invalid progress deadline > 720": {
args: args{
object: ClusterExtensionSpec{
ProgressDeadlineMinutes: 721,
},
},
want: want{valid: false},
},
"ClusterExtension: no progress deadline set": {
args: args{
object: ClusterExtensionSpec{},
},
want: want{valid: true},
},
"ClusterExtensionRevision: invalid progress deadline < 10": {
args: args{
object: ClusterExtensionRevisionSpec{
ProgressDeadlineMinutes: 9,
},
},
want: want{valid: false},
},
"ClusterExtensionRevision: valid progress deadline = 10": {
args: args{
object: ClusterExtensionRevisionSpec{
ProgressDeadlineMinutes: 10,
},
},
want: want{valid: true},
},
"ClusterExtensionRevision: valid progress deadline = 360": {
args: args{
object: ClusterExtensionRevisionSpec{
ProgressDeadlineMinutes: 360,
},
},
want: want{valid: true},
},
"ClusterExtensionRevision: valid progress deadline = 720": {
args: args{
object: ClusterExtensionRevisionSpec{
ProgressDeadlineMinutes: 720,
},
},
want: want{valid: true},
},
"ClusterExtensionRevision: invalid progress deadline > 720": {
args: args{
object: ClusterExtensionRevisionSpec{
ProgressDeadlineMinutes: 721,
},
},
want: want{valid: false},
},
"ClusterExtensionRevision: no progress deadline set": {
args: args{
object: ClusterExtensionRevisionSpec{},
},
want: want{valid: true},
},
} {
t.Run(name, func(t *testing.T) {
var obj client.Object
switch s := tc.args.object.(type) {
case ClusterExtensionSpec:
ce := &ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("ce-%d", i),
},
Spec: s,
}
if !tc.args.skipDefaulting {
defaultExtensionSpec(&ce.Spec)
}
obj = ce
case ClusterExtensionRevisionSpec:
cer := &ClusterExtensionRevision{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("cer-%d", i),
},
Spec: s,
}
if !tc.args.skipDefaulting {
defaultRevisionSpec(&cer.Spec)
}
obj = cer
default:
t.Fatalf("unknown type %T", s)
}
i++
err := c.Create(t.Context(), obj)
if tc.want.valid && err != nil {
t.Fatal("expected create to succeed, but got:", err)
}
if !tc.want.valid && !errors.IsInvalid(err) {
t.Fatal("expected create to fail due to invalid payload, but got:", err)
}
})
}
}
8 changes: 7 additions & 1 deletion cmd/operator-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,12 @@ func (c *boxcutterReconcilerConfigurator) Configure(ceReconciler *controllers.Cl
return err
}

// TODO: add support for preflight checks
// determine if PreAuthorizer should be enabled based on feature gate
var preAuth authorization.PreAuthorizer
if features.OperatorControllerFeatureGate.Enabled(features.PreflightPermissions) {
preAuth = authorization.NewRBACPreAuthorizer(c.mgr.GetClient())
}

// TODO: better scheme handling - which types do we want to support?
_ = apiextensionsv1.AddToScheme(c.mgr.GetScheme())
rg := &applier.SimpleRevisionGenerator{
Expand All @@ -610,6 +615,7 @@ func (c *boxcutterReconcilerConfigurator) Configure(ceReconciler *controllers.Cl
Scheme: c.mgr.GetScheme(),
RevisionGenerator: rg,
Preflights: c.preflights,
PreAuthorizer: preAuth,
FieldOwner: fmt.Sprintf("%s/clusterextension-controller", fieldOwnerPrefix),
}
revisionStatesGetter := &controllers.BoxcutterRevisionStatesGetter{Reader: c.mgr.GetClient()}
Expand Down
2 changes: 1 addition & 1 deletion commitchecker.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
expectedMergeBase: b08a054acc3892fb5b1977299c8a92cbddd90819
expectedMergeBase: 8167ff8fd3ab3880459f9d1e5626c6e3073e3428
upstreamBranch: main
upstreamOrg: operator-framework
upstreamRepo: operator-controller
1 change: 1 addition & 0 deletions docs/api-reference/olmv1-api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ _Appears in:_
| `source` _[SourceConfig](#sourceconfig)_ | source is required and selects the installation source of content for this ClusterExtension.<br />Set the sourceType field to perform the selection.<br />Catalog is currently the only implemented sourceType.<br />Setting sourceType to "Catalog" requires the catalog field to also be defined.<br />Below is a minimal example of a source definition (in yaml):<br />source:<br /> sourceType: Catalog<br /> catalog:<br /> packageName: example-package | | Required: \{\} <br /> |
| `install` _[ClusterExtensionInstallConfig](#clusterextensioninstallconfig)_ | install is optional and configures installation options for the ClusterExtension,<br />such as the pre-flight check configuration. | | |
| `config` _[ClusterExtensionConfig](#clusterextensionconfig)_ | config is optional and specifies bundle-specific configuration.<br />Configuration is bundle-specific and a bundle may provide a configuration schema.<br />When not specified, the default configuration of the resolved bundle is used.<br />config is validated against a configuration schema provided by the resolved bundle. If the bundle does not provide<br />a configuration schema the bundle is deemed to not be configurable. More information on how<br />to configure bundles can be found in the OLM documentation associated with your current OLM version. | | |
| `progressDeadlineMinutes` _integer_ | progressDeadlineMinutes is an optional field that defines the maximum period<br />of time in minutes after which an installation should be considered failed and<br />require manual intervention. This functionality is disabled when no value<br />is provided. The minimum period is 10 minutes, and the maximum is 720 minutes (12 hours).<br /><opcon:experimental> | | Maximum: 720 <br />Minimum: 10 <br /> |


#### ClusterExtensionStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,16 @@ spec:
x-kubernetes-validations:
- message: phases is immutable
rule: self == oldSelf || oldSelf.size() == 0
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
revision:
description: |-
revision is a required, immutable sequence number representing a specific revision
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,16 @@ spec:
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
Expand Down
Loading