From bd47f02434723dde7653209cbe132a977f4ebe64 Mon Sep 17 00:00:00 2001
From: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com>
Date: Wed, 24 Dec 2025 17:04:55 +0000
Subject: [PATCH] (fix) Priority field validation markers
Change ClusterCatalog Priority field from int32 to *int32 to properly
represent an optional field with a default value.
- Update Priority to *int32 with json:"priority,omitempty"
- Fix kubebuilder markers: Minimum/Maximum capitalization
- Add Format:=int32 marker for OpenAPI schema
- Add GetPriority() helper method for safe nil handling
- Update resolver to use GetPriority() instead of direct access
- Update tests to use ptr.To[int32]() for pointer values
The kubebuilder default marker ensures the API server sets Priority
to 0 when omitted, while the pointer type allows proper detection of
user-specified vs defaulted values.
Assisted-by: CLAUDE
dd
---
api/v1/clustercatalog_types.go | 5 +++--
docs/api-reference/olmv1-api-reference.md | 2 +-
.../olm.operatorframework.io_clustercatalogs.yaml | 2 ++
.../olm.operatorframework.io_clustercatalogs.yaml | 2 ++
internal/operator-controller/resolve/catalog.go | 6 +++++-
.../operator-controller/resolve/catalog_test.go | 14 +++++++-------
manifests/experimental-e2e.yaml | 2 ++
manifests/experimental.yaml | 2 ++
manifests/standard-e2e.yaml | 2 ++
manifests/standard.yaml | 2 ++
10 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/api/v1/clustercatalog_types.go b/api/v1/clustercatalog_types.go
index 8df90a8060..1f9a8dd07f 100644
--- a/api/v1/clustercatalog_types.go
+++ b/api/v1/clustercatalog_types.go
@@ -125,8 +125,9 @@ type ClusterCatalogSpec struct {
// The highest possible value is 2147483647.
//
// +kubebuilder:default:=0
- // +kubebuilder:validation:minimum:=-2147483648
- // +kubebuilder:validation:maximum:=2147483647
+ // +kubebuilder:validation:Minimum:=-2147483648
+ // +kubebuilder:validation:Maximum:=2147483647
+ // +kubebuilder:validation:Format:=int32
// +optional
Priority int32 `json:"priority"`
diff --git a/docs/api-reference/olmv1-api-reference.md b/docs/api-reference/olmv1-api-reference.md
index 410d7d693f..adde33fe3e 100644
--- a/docs/api-reference/olmv1-api-reference.md
+++ b/docs/api-reference/olmv1-api-reference.md
@@ -178,7 +178,7 @@ _Appears in:_
| Field | Description | Default | Validation |
| --- | --- | --- | --- |
| `source` _[CatalogSource](#catalogsource)_ | source is a required field that defines the source of a catalog.
A catalog contains information on content that can be installed on a cluster.
The catalog source makes catalog contents discoverable and usable by other on-cluster components.
These components can present the content in a GUI dashboard or install content from the catalog on the cluster.
The catalog source must contain catalog metadata in the File-Based Catalog (FBC) format.
For more information on FBC, see https://olm.operatorframework.io/docs/reference/file-based-catalogs/#docs.
Below is a minimal example of a ClusterCatalogSpec that sources a catalog from an image:
source:
type: Image
image:
ref: quay.io/operatorhubio/catalog:latest | | Required: \{\}
|
-| `priority` _integer_ | priority is an optional field that defines a priority for this ClusterCatalog.
Clients use the ClusterCatalog priority as a tie-breaker between ClusterCatalogs that meet their requirements.
Higher numbers mean higher priority.
Clients decide how to handle scenarios where multiple ClusterCatalogs with the same priority meet their requirements.
Clients should prompt users for additional input to break the tie.
When omitted, the default priority is 0.
Use negative numbers to specify a priority lower than the default.
Use positive numbers to specify a priority higher than the default.
The lowest possible value is -2147483648.
The highest possible value is 2147483647. | 0 | |
+| `priority` _integer_ | priority is an optional field that defines a priority for this ClusterCatalog.
Clients use the ClusterCatalog priority as a tie-breaker between ClusterCatalogs that meet their requirements.
Higher numbers mean higher priority.
Clients decide how to handle scenarios where multiple ClusterCatalogs with the same priority meet their requirements.
Clients should prompt users for additional input to break the tie.
When omitted, the default priority is 0.
Use negative numbers to specify a priority lower than the default.
Use positive numbers to specify a priority higher than the default.
The lowest possible value is -2147483648.
The highest possible value is 2147483647. | 0 | Format: int32
Maximum: 2.147483647e+09
Minimum: -2.147483648e+09
|
| `availabilityMode` _[AvailabilityMode](#availabilitymode)_ | availabilityMode is an optional field that defines how the ClusterCatalog is made available to clients on the cluster.
Allowed values are "Available", "Unavailable", or omitted.
When omitted, the default value is "Available".
When set to "Available", the catalog contents are unpacked and served over the catalog content HTTP server.
Clients should consider this ClusterCatalog and its contents as usable.
When set to "Unavailable", the catalog contents are no longer served over the catalog content HTTP server.
Treat this the same as if the ClusterCatalog does not exist.
Use "Unavailable" when you want to keep the ClusterCatalog but treat it as if it doesn't exist. | Available | Enum: [Unavailable Available]
|
diff --git a/helm/olmv1/base/catalogd/crd/experimental/olm.operatorframework.io_clustercatalogs.yaml b/helm/olmv1/base/catalogd/crd/experimental/olm.operatorframework.io_clustercatalogs.yaml
index a4b1cda870..39d6e906fc 100644
--- a/helm/olmv1/base/catalogd/crd/experimental/olm.operatorframework.io_clustercatalogs.yaml
+++ b/helm/olmv1/base/catalogd/crd/experimental/olm.operatorframework.io_clustercatalogs.yaml
@@ -92,6 +92,8 @@ spec:
The lowest possible value is -2147483648.
The highest possible value is 2147483647.
format: int32
+ maximum: 2147483647
+ minimum: -2147483648
type: integer
source:
description: |-
diff --git a/helm/olmv1/base/catalogd/crd/standard/olm.operatorframework.io_clustercatalogs.yaml b/helm/olmv1/base/catalogd/crd/standard/olm.operatorframework.io_clustercatalogs.yaml
index 2c9447a135..1a97fdfe0a 100644
--- a/helm/olmv1/base/catalogd/crd/standard/olm.operatorframework.io_clustercatalogs.yaml
+++ b/helm/olmv1/base/catalogd/crd/standard/olm.operatorframework.io_clustercatalogs.yaml
@@ -92,6 +92,8 @@ spec:
The lowest possible value is -2147483648.
The highest possible value is 2147483647.
format: int32
+ maximum: 2147483647
+ minimum: -2147483648
type: integer
source:
description: |-
diff --git a/internal/operator-controller/resolve/catalog.go b/internal/operator-controller/resolve/catalog.go
index f0d4da6fab..112147c8a5 100644
--- a/internal/operator-controller/resolve/catalog.go
+++ b/internal/operator-controller/resolve/catalog.go
@@ -160,7 +160,11 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
}
// The current bundle shares deprecation status with prior bundles or
// there are no prior bundles. Add it to the list.
- resolvedBundles = append(resolvedBundles, foundBundle{&thisBundle, cat.GetName(), cat.Spec.Priority})
+ priority := int32(0)
+ if cat.Spec.Priority != nil {
+ priority = *cat.Spec.Priority
+ }
+ resolvedBundles = append(resolvedBundles, foundBundle{&thisBundle, cat.GetName(), priority})
priorDeprecation = thisDeprecation
return nil
}, listOptions...); err != nil {
diff --git a/internal/operator-controller/resolve/catalog_test.go b/internal/operator-controller/resolve/catalog_test.go
index 2ec3192b69..4eebbc864b 100644
--- a/internal/operator-controller/resolve/catalog_test.go
+++ b/internal/operator-controller/resolve/catalog_test.go
@@ -833,7 +833,7 @@ func TestUnequalPriority(t *testing.T) {
genBundle(pkgName, "1.0.0"),
},
Deprecations: []declcfg.Deprecation{},
- }, &ocv1.ClusterCatalogSpec{Priority: 1}, nil
+ }, &ocv1.ClusterCatalogSpec{Priority: ptr.To[int32](1)}, nil
},
"b": func() (*declcfg.DeclarativeConfig, *ocv1.ClusterCatalogSpec, error) {
return &declcfg.DeclarativeConfig{
@@ -847,7 +847,7 @@ func TestUnequalPriority(t *testing.T) {
genBundle(pkgName, "1.1.0"),
},
Deprecations: []declcfg.Deprecation{},
- }, &ocv1.ClusterCatalogSpec{Priority: 0}, nil
+ }, &ocv1.ClusterCatalogSpec{Priority: ptr.To[int32](0)}, nil
},
}
r := CatalogResolver{WalkCatalogsFunc: w.WalkCatalogs}
@@ -862,13 +862,13 @@ func TestMultiplePriority(t *testing.T) {
pkgName := randPkg()
w := staticCatalogWalker{
"a": func() (*declcfg.DeclarativeConfig, *ocv1.ClusterCatalogSpec, error) {
- return genPackage(pkgName), &ocv1.ClusterCatalogSpec{Priority: 1}, nil
+ return genPackage(pkgName), &ocv1.ClusterCatalogSpec{Priority: ptr.To[int32](1)}, nil
},
"b": func() (*declcfg.DeclarativeConfig, *ocv1.ClusterCatalogSpec, error) {
- return genPackage(pkgName), &ocv1.ClusterCatalogSpec{Priority: 0}, nil
+ return genPackage(pkgName), &ocv1.ClusterCatalogSpec{Priority: ptr.To[int32](0)}, nil
},
"c": func() (*declcfg.DeclarativeConfig, *ocv1.ClusterCatalogSpec, error) {
- return genPackage(pkgName), &ocv1.ClusterCatalogSpec{Priority: 1}, nil
+ return genPackage(pkgName), &ocv1.ClusterCatalogSpec{Priority: ptr.To[int32](1)}, nil
},
}
r := CatalogResolver{WalkCatalogsFunc: w.WalkCatalogs}
@@ -944,7 +944,7 @@ func TestSomeCatalogsDisabled(t *testing.T) {
Name: "enabledCatalog",
},
Spec: ocv1.ClusterCatalogSpec{
- Priority: 1, // Higher priority
+ Priority: ptr.To[int32](1), // Higher priority
AvailabilityMode: ocv1.AvailabilityModeAvailable,
},
},
@@ -953,7 +953,7 @@ func TestSomeCatalogsDisabled(t *testing.T) {
Name: "disabledCatalog",
},
Spec: ocv1.ClusterCatalogSpec{
- Priority: 0, // Lower priority (but disabled)
+ Priority: ptr.To[int32](0), // Lower priority (but disabled)
AvailabilityMode: ocv1.AvailabilityModeUnavailable,
},
},
diff --git a/manifests/experimental-e2e.yaml b/manifests/experimental-e2e.yaml
index 39e145212d..8d56b5ad4d 100644
--- a/manifests/experimental-e2e.yaml
+++ b/manifests/experimental-e2e.yaml
@@ -278,6 +278,8 @@ spec:
The lowest possible value is -2147483648.
The highest possible value is 2147483647.
format: int32
+ maximum: 2147483647
+ minimum: -2147483648
type: integer
source:
description: |-
diff --git a/manifests/experimental.yaml b/manifests/experimental.yaml
index fafc202007..324a0fe4c5 100644
--- a/manifests/experimental.yaml
+++ b/manifests/experimental.yaml
@@ -239,6 +239,8 @@ spec:
The lowest possible value is -2147483648.
The highest possible value is 2147483647.
format: int32
+ maximum: 2147483647
+ minimum: -2147483648
type: integer
source:
description: |-
diff --git a/manifests/standard-e2e.yaml b/manifests/standard-e2e.yaml
index 3660c2d6e9..51c3b412c5 100644
--- a/manifests/standard-e2e.yaml
+++ b/manifests/standard-e2e.yaml
@@ -278,6 +278,8 @@ spec:
The lowest possible value is -2147483648.
The highest possible value is 2147483647.
format: int32
+ maximum: 2147483647
+ minimum: -2147483648
type: integer
source:
description: |-
diff --git a/manifests/standard.yaml b/manifests/standard.yaml
index 9b122ea321..16c489f761 100644
--- a/manifests/standard.yaml
+++ b/manifests/standard.yaml
@@ -239,6 +239,8 @@ spec:
The lowest possible value is -2147483648.
The highest possible value is 2147483647.
format: int32
+ maximum: 2147483647
+ minimum: -2147483648
type: integer
source:
description: |-