Skip to content

Commit dbc4af3

Browse files
Fix deprecation conditions (#2296)
This fixes three problems: 1. Install errors were leaking into deprecation conditions 2. Catalog unavailable showed "False" instead of "Unknown" 3. BundleDeprecated was checking the wrong bundle (resolved vs installed) 4. Ensure that we have Deprecated False when has no deprecation Also improved the code: - Simpler logic (clear all, then add only what's needed) - Better reason values - Comprehensive test coverage for all scenarios Assisted-by: Cursor
1 parent 4360747 commit dbc4af3

15 files changed

+1205
-203
lines changed

api/v1/clusterextension_types.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -500,12 +500,12 @@ type ClusterExtensionStatus struct {
500500
// When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterExtensionRevisions in active roll out.
501501
// </opcon:experimental:description>
502502
//
503-
// When the ClusterExtension is sourced from a catalog, it may also communicate a deprecation condition.
503+
// When the ClusterExtension is sourced from a catalog, it surfaces deprecation conditions based on catalog metadata.
504504
// These are indications from a package owner to guide users away from a particular package, channel, or bundle:
505-
// - BundleDeprecated is set if the requested bundle version is marked deprecated in the catalog.
506-
// - ChannelDeprecated is set if the requested channel is marked deprecated in the catalog.
507-
// - PackageDeprecated is set if the requested package is marked deprecated in the catalog.
508-
// - Deprecated is a rollup condition that is present when any of the deprecated conditions are present.
505+
// - 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.
506+
// - ChannelDeprecated is True if any requested channel is marked deprecated, False if not deprecated, or Unknown if catalog data is unavailable.
507+
// - PackageDeprecated is True if the requested package is marked deprecated, False if not deprecated, or Unknown if catalog data is unavailable.
508+
// - Deprecated is a rollup condition that is True when any deprecation exists, False when none exist, or Unknown when catalog data is unavailable.
509509
//
510510
// +listType=map
511511
// +listMapKey=type

api/v1/common_types.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ const (
2929
ReasonBlocked = "Blocked"
3030

3131
// Deprecation reasons
32-
ReasonDeprecated = "Deprecated"
32+
ReasonDeprecated = "Deprecated"
33+
ReasonNotDeprecated = "NotDeprecated"
34+
ReasonDeprecationStatusUnknown = "DeprecationStatusUnknown"
3335

3436
// Common reasons
3537
ReasonSucceeded = "Succeeded"

docs/api-reference/olmv1-api-reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ _Appears in:_
360360

361361
| Field | Description | Default | Validation |
362362
| --- | --- | --- | --- |
363-
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | conditions represents the current state of the ClusterExtension.<br />The set of condition types which apply to all spec.source variations are Installed and Progressing.<br />The Installed condition represents whether the bundle has been installed for this ClusterExtension:<br /> - When Installed is True and the Reason is Succeeded, the bundle has been successfully installed.<br /> - When Installed is False and the Reason is Failed, the bundle has failed to install.<br />The Progressing condition represents whether or not the ClusterExtension is advancing towards a new state.<br />When Progressing is True and the Reason is Succeeded, the ClusterExtension is making progress towards a new state.<br />When Progressing is True and the Reason is Retrying, the ClusterExtension has encountered an error that could be resolved on subsequent reconciliation attempts.<br />When Progressing is False and the Reason is Blocked, the ClusterExtension has encountered an error that requires manual intervention for recovery.<br /><opcon:experimental:description><br />When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterExtensionRevisions in active roll out.<br /></opcon:experimental:description><br />When the ClusterExtension is sourced from a catalog, it may also communicate a deprecation condition.<br />These are indications from a package owner to guide users away from a particular package, channel, or bundle:<br /> - BundleDeprecated is set if the requested bundle version is marked deprecated in the catalog.<br /> - ChannelDeprecated is set if the requested channel is marked deprecated in the catalog.<br /> - PackageDeprecated is set if the requested package is marked deprecated in the catalog.<br /> - Deprecated is a rollup condition that is present when any of the deprecated conditions are present. | | |
363+
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | conditions represents the current state of the ClusterExtension.<br />The set of condition types which apply to all spec.source variations are Installed and Progressing.<br />The Installed condition represents whether the bundle has been installed for this ClusterExtension:<br /> - When Installed is True and the Reason is Succeeded, the bundle has been successfully installed.<br /> - When Installed is False and the Reason is Failed, the bundle has failed to install.<br />The Progressing condition represents whether or not the ClusterExtension is advancing towards a new state.<br />When Progressing is True and the Reason is Succeeded, the ClusterExtension is making progress towards a new state.<br />When Progressing is True and the Reason is Retrying, the ClusterExtension has encountered an error that could be resolved on subsequent reconciliation attempts.<br />When Progressing is False and the Reason is Blocked, the ClusterExtension has encountered an error that requires manual intervention for recovery.<br /><opcon:experimental:description><br />When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterExtensionRevisions in active roll out.<br /></opcon:experimental:description><br />When the ClusterExtension is sourced from a catalog, it surfaces deprecation conditions based on catalog metadata.<br />These are indications from a package owner to guide users away from a particular package, channel, or bundle:<br /> - 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.<br /> - ChannelDeprecated is True if any requested channel is marked deprecated, False if not deprecated, or Unknown if catalog data is unavailable.<br /> - PackageDeprecated is True if the requested package is marked deprecated, False if not deprecated, or Unknown if catalog data is unavailable.<br /> - Deprecated is a rollup condition that is True when any deprecation exists, False when none exist, or Unknown when catalog data is unavailable. | | |
364364
| `install` _[ClusterExtensionInstallStatus](#clusterextensioninstallstatus)_ | install is a representation of the current installation status for this ClusterExtension. | | |
365365
| `activeRevisions` _[RevisionStatus](#revisionstatus) array_ | activeRevisions holds a list of currently active (non-archived) ClusterExtensionRevisions,<br />including both installed and rolling out revisions.<br /><opcon:experimental> | | |
366366

helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensions.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -601,12 +601,12 @@ spec:
601601
602602
When Progressing is True and Reason is RollingOut, the ClusterExtension has one or more ClusterExtensionRevisions in active roll out.
603603
604-
When the ClusterExtension is sourced from a catalog, it may also communicate a deprecation condition.
604+
When the ClusterExtension is sourced from a catalog, it surfaces deprecation conditions based on catalog metadata.
605605
These are indications from a package owner to guide users away from a particular package, channel, or bundle:
606-
- BundleDeprecated is set if the requested bundle version is marked deprecated in the catalog.
607-
- ChannelDeprecated is set if the requested channel is marked deprecated in the catalog.
608-
- PackageDeprecated is set if the requested package is marked deprecated in the catalog.
609-
- Deprecated is a rollup condition that is present when any of the deprecated conditions are present.
606+
- 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.
607+
- ChannelDeprecated is True if any requested channel is marked deprecated, False if not deprecated, or Unknown if catalog data is unavailable.
608+
- PackageDeprecated is True if the requested package is marked deprecated, False if not deprecated, or Unknown if catalog data is unavailable.
609+
- Deprecated is a rollup condition that is True when any deprecation exists, False when none exist, or Unknown when catalog data is unavailable.
610610
items:
611611
description: Condition contains details for one aspect of the current
612612
state of this API Resource.

helm/olmv1/base/operator-controller/crd/standard/olm.operatorframework.io_clusterextensions.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -507,12 +507,12 @@ spec:
507507
When Progressing is True and the Reason is Retrying, the ClusterExtension has encountered an error that could be resolved on subsequent reconciliation attempts.
508508
When Progressing is False and the Reason is Blocked, the ClusterExtension has encountered an error that requires manual intervention for recovery.
509509
510-
When the ClusterExtension is sourced from a catalog, it may also communicate a deprecation condition.
510+
When the ClusterExtension is sourced from a catalog, it surfaces deprecation conditions based on catalog metadata.
511511
These are indications from a package owner to guide users away from a particular package, channel, or bundle:
512-
- BundleDeprecated is set if the requested bundle version is marked deprecated in the catalog.
513-
- ChannelDeprecated is set if the requested channel is marked deprecated in the catalog.
514-
- PackageDeprecated is set if the requested package is marked deprecated in the catalog.
515-
- Deprecated is a rollup condition that is present when any of the deprecated conditions are present.
512+
- 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.
513+
- ChannelDeprecated is True if any requested channel is marked deprecated, False if not deprecated, or Unknown if catalog data is unavailable.
514+
- PackageDeprecated is True if the requested package is marked deprecated, False if not deprecated, or Unknown if catalog data is unavailable.
515+
- Deprecated is a rollup condition that is True when any deprecation exists, False when none exist, or Unknown when catalog data is unavailable.
516516
items:
517517
description: Condition contains details for one aspect of the current
518518
state of this API Resource.

internal/operator-controller/conditionsets/conditionsets.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ var ConditionTypes = []string{
3636
var ConditionReasons = []string{
3737
ocv1.ReasonSucceeded,
3838
ocv1.ReasonDeprecated,
39+
ocv1.ReasonNotDeprecated,
40+
ocv1.ReasonDeprecationStatusUnknown,
3941
ocv1.ReasonFailed,
4042
ocv1.ReasonBlocked,
4143
ocv1.ReasonRetrying,

internal/operator-controller/controllers/clusterextension_admission_test.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,20 @@ import (
1313
)
1414

1515
func TestClusterExtensionSourceConfig(t *testing.T) {
16-
// NOTE: Kubernetes validation error format for JSON null values varies across K8s versions.
17-
// We check for the common part "Invalid value:" which appears in all versions.
18-
sourceTypeEmptyError := "Invalid value:"
16+
sourceTypeEmptyErrors := []string{"Invalid value: \"null\"", "Invalid value: null"}
1917
sourceTypeMismatchError := "spec.source.sourceType: Unsupported value"
2018
sourceConfigInvalidError := "spec.source: Invalid value"
2119
// unionField represents the required Catalog or (future) Bundle field required by SourceConfig
2220
testCases := []struct {
2321
name string
2422
sourceType string
2523
unionField string
26-
errMsg string
24+
errMsgs []string
2725
}{
28-
{"sourceType is null", "", "Catalog", sourceTypeEmptyError},
29-
{"sourceType is invalid", "Invalid", "Catalog", sourceTypeMismatchError},
30-
{"catalog field does not exist", "Catalog", "", sourceConfigInvalidError},
31-
{"sourceConfig has required fields", "Catalog", "Catalog", ""},
26+
{"sourceType is null", "", "Catalog", sourceTypeEmptyErrors},
27+
{"sourceType is invalid", "Invalid", "Catalog", []string{sourceTypeMismatchError}},
28+
{"catalog field does not exist", "Catalog", "", []string{sourceConfigInvalidError}},
29+
{"sourceConfig has required fields", "Catalog", "Catalog", []string{}},
3230
}
3331

3432
t.Parallel()
@@ -64,12 +62,20 @@ func TestClusterExtensionSourceConfig(t *testing.T) {
6462
}))
6563
}
6664

67-
if tc.errMsg == "" {
65+
if len(tc.errMsgs) == 0 {
6866
require.NoError(t, err, "unexpected error for sourceType %q: %w", tc.sourceType, err)
69-
} else {
70-
require.Error(t, err)
71-
require.Contains(t, err.Error(), tc.errMsg)
67+
return
68+
}
69+
70+
require.Error(t, err)
71+
matched := false
72+
for _, msg := range tc.errMsgs {
73+
if strings.Contains(err.Error(), msg) {
74+
matched = true
75+
break
76+
}
7277
}
78+
require.True(t, matched, "expected one of %v in error %q", tc.errMsgs, err)
7379
})
7480
}
7581
}

0 commit comments

Comments
 (0)