Skip to content

Commit c9e58f8

Browse files
Fix deprecation conditions and make YAML output cleaner
Deprecation conditions now only show what matters: - When deprecated: condition shows "True" with deprecation message - When not deprecated: condition is absent (no clutter!) - When we can't check: condition shows "Unknown" 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) Also improved the code: - Simpler logic (clear all, then add only what's needed) - Better reason values (Deprecated, DeprecationStatusUnknown, Absent) - Comprehensive test coverage for all scenarios Assisted-by: Cursor
1 parent 6e4f192 commit c9e58f8

15 files changed

Lines changed: 893 additions & 253 deletions

api/v1/clusterextension_types.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -500,12 +500,13 @@ 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.
504-
// 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.
503+
// When the ClusterExtension is sourced from a catalog, it may surface deprecation conditions based on catalog metadata.
504+
// These are indications from a package owner to guide users away from a particular package, channel, or bundle.
505+
// Deprecation conditions are only present when there's something to report - absence means "not deprecated".
506+
// - BundleDeprecated is set to True if the installed bundle is marked as deprecated in the catalog, or Unknown if no bundle is installed yet.
507+
// - ChannelDeprecated is set to True if any requested channel is marked as deprecated in the catalog, or Unknown if the channel is not found.
508+
// - PackageDeprecated is set to True if the requested package is marked as deprecated in the catalog, or Unknown if the package is not found.
509+
// - Deprecated is a rollup condition that is present only when at least one deprecation exists (True) or when catalog information is unavailable (Unknown).
509510
//
510511
// +listType=map
511512
// +listMapKey=type

api/v1/common_types.go

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

3131
// Deprecation reasons
32-
ReasonDeprecated = "Deprecated"
32+
ReasonDeprecated = "Deprecated"
33+
ReasonDeprecationStatusUnknown = "DeprecationStatusUnknown"
3334

3435
// Common reasons
3536
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 may surface 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 />Deprecation conditions are only present when there's something to report - absence means "not deprecated".<br /> - BundleDeprecated is set to True if the installed bundle is marked as deprecated in the catalog, or Unknown if no bundle is installed yet.<br /> - ChannelDeprecated is set to True if any requested channel is marked as deprecated in the catalog, or Unknown if the channel is not found.<br /> - PackageDeprecated is set to True if the requested package is marked as deprecated in the catalog, or Unknown if the package is not found.<br /> - Deprecated is a rollup condition that is present only when at least one deprecation exists (True) or when catalog information is unavailable (Unknown). | | |
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: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -601,12 +601,13 @@ 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.
605-
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.
604+
When the ClusterExtension is sourced from a catalog, it may surface deprecation conditions based on catalog metadata.
605+
These are indications from a package owner to guide users away from a particular package, channel, or bundle.
606+
Deprecation conditions are only present when there's something to report - absence means "not deprecated".
607+
- BundleDeprecated is set to True if the installed bundle is marked as deprecated in the catalog, or Unknown if no bundle is installed yet.
608+
- ChannelDeprecated is set to True if any requested channel is marked as deprecated in the catalog, or Unknown if the channel is not found.
609+
- PackageDeprecated is set to True if the requested package is marked as deprecated in the catalog, or Unknown if the package is not found.
610+
- Deprecated is a rollup condition that is present only when at least one deprecation exists (True) or when catalog information is unavailable (Unknown).
610611
items:
611612
description: Condition contains details for one aspect of the current
612613
state of this API Resource.

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -507,12 +507,13 @@ 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.
511-
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.
510+
When the ClusterExtension is sourced from a catalog, it may surface deprecation conditions based on catalog metadata.
511+
These are indications from a package owner to guide users away from a particular package, channel, or bundle.
512+
Deprecation conditions are only present when there's something to report - absence means "not deprecated".
513+
- BundleDeprecated is set to True if the installed bundle is marked as deprecated in the catalog, or Unknown if no bundle is installed yet.
514+
- ChannelDeprecated is set to True if any requested channel is marked as deprecated in the catalog, or Unknown if the channel is not found.
515+
- PackageDeprecated is set to True if the requested package is marked as deprecated in the catalog, or Unknown if the package is not found.
516+
- Deprecated is a rollup condition that is present only when at least one deprecation exists (True) or when catalog information is unavailable (Unknown).
516517
items:
517518
description: Condition contains details for one aspect of the current
518519
state of this API Resource.

internal/operator-controller/conditionsets/conditionsets.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var ConditionTypes = []string{
3636
var ConditionReasons = []string{
3737
ocv1.ReasonSucceeded,
3838
ocv1.ReasonDeprecated,
39+
ocv1.ReasonDeprecationStatusUnknown,
3940
ocv1.ReasonFailed,
4041
ocv1.ReasonBlocked,
4142
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", nil},
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)