Skip to content

Commit fb54461

Browse files
committed
Add major version manifest filtering
1 parent 57706c4 commit fb54461

29 files changed

Lines changed: 1052 additions & 1127 deletions

go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ require (
1111
github.com/onsi/ginkgo/v2 v2.21.0
1212
github.com/onsi/gomega v1.35.1
1313
github.com/openshift-eng/openshift-tests-extension v0.0.0-20250220212757-b9c4d98a0c45
14-
github.com/openshift/api v0.0.0-20260116192047-6fb7fdae95fd
14+
github.com/openshift/api v0.0.0-20260126183958-606bd613f9f7
1515
github.com/openshift/client-go v0.0.0-20260108185524-48f4ccfc4e13
1616
github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04
1717
github.com/operator-framework/api v0.17.1
@@ -34,6 +34,8 @@ require (
3434
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
3535
)
3636

37+
replace github.com/openshift/library-go => github.com/JoelSpeed/library-go v0.0.0-20260130121715-6e5ccfd0da42
38+
3739
require (
3840
cel.dev/expr v0.24.0 // indirect
3941
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
22
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
3+
github.com/JoelSpeed/library-go v0.0.0-20260130121715-6e5ccfd0da42 h1:uIrR1qWklQm8U7WgtSZnyxj8bxCRtzvQ9JDKWvihOCg=
4+
github.com/JoelSpeed/library-go v0.0.0-20260130121715-6e5ccfd0da42/go.mod h1:DCRz1EgdayEmr9b6KXKDL+DWBN0rGHu/VYADeHzPoOk=
35
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
46
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
57
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -86,12 +88,10 @@ github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
8688
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
8789
github.com/openshift-eng/openshift-tests-extension v0.0.0-20250220212757-b9c4d98a0c45 h1:hXpbYtP3iTh8oy/RKwKkcMziwchY3fIk95ciczf7cOA=
8890
github.com/openshift-eng/openshift-tests-extension v0.0.0-20250220212757-b9c4d98a0c45/go.mod h1:6gkP5f2HL0meusT0Aim8icAspcD1cG055xxBZ9yC68M=
89-
github.com/openshift/api v0.0.0-20260116192047-6fb7fdae95fd h1:Hpjq/55Qb0Gy65RewTSWWlyxpSovaRF86EPjYQkdlRU=
90-
github.com/openshift/api v0.0.0-20260116192047-6fb7fdae95fd/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
91+
github.com/openshift/api v0.0.0-20260126183958-606bd613f9f7 h1:96rhgJpWlWzKEslMd6aYFMixV9vQVY32M71JcO4Gzn0=
92+
github.com/openshift/api v0.0.0-20260126183958-606bd613f9f7/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
9193
github.com/openshift/client-go v0.0.0-20260108185524-48f4ccfc4e13 h1:6rd4zSo2UaWQcAPZfHK9yzKVqH0BnMv1hqMzqXZyTds=
9294
github.com/openshift/client-go v0.0.0-20260108185524-48f4ccfc4e13/go.mod h1:YvOmPmV7wcJxpfhTDuFqqs2Xpb3M3ovsM6Qs/i2ptq4=
93-
github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04 h1:Fm9C8pT4l6VjpdqdhI1cBX9Y3D3S+rFxptVhCPBbMAI=
94-
github.com/openshift/library-go v0.0.0-20260121132910-dc3a1c884c04/go.mod h1:nIzWQQE49XbiKizVnVOip9CEB7HJ0hoJwNi3g3YKnKc=
9595
github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 h1:AKx/w1qpS8We43bsRgf8Nll3CGlDHpr/WAXvuedTNZI=
9696
github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
9797
github.com/operator-framework/api v0.17.1 h1:J/6+Xj4IEV8C7hcirqUFwOiZAU3PbnJhWvB0/bB51c4=

lib/manifest/manifest.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ type InclusionConfiguration struct {
3636

3737
// EnabledFeatureGates excludes manifests with a feature gate requirement when the condition is not met.
3838
EnabledFeatureGates sets.Set[string]
39+
40+
// MajorVersion, if non-nil, excludes manifests unless they match the major version.
41+
MajorVersion *uint64
3942
}
4043

4144
// GetImplicitlyEnabledCapabilities returns a set of capabilities that are implicitly enabled after a cluster update.
@@ -61,6 +64,7 @@ func GetImplicitlyEnabledCapabilities(
6164
manifestInclusionConfiguration.Capabilities,
6265
manifestInclusionConfiguration.Overrides,
6366
manifestInclusionConfiguration.EnabledFeatureGates,
67+
manifestInclusionConfiguration.MajorVersion,
6468
true,
6569
)
6670
// update manifest is enabled, no need to check
@@ -79,6 +83,7 @@ func GetImplicitlyEnabledCapabilities(
7983
manifestInclusionConfiguration.Capabilities,
8084
manifestInclusionConfiguration.Overrides,
8185
manifestInclusionConfiguration.EnabledFeatureGates,
86+
manifestInclusionConfiguration.MajorVersion,
8287
true,
8388
); err != nil {
8489
continue

pkg/cvo/featuregate_integration_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func TestFeatureGateManifestFiltering(t *testing.T) {
101101
}
102102

103103
// Test the manifest inclusion logic
104-
err := manifest.Include(nil, nil, nil, nil, nil, tt.enabledGates)
104+
err := manifest.Include(nil, nil, nil, nil, nil, tt.enabledGates, nil)
105105

106106
if tt.shouldInclude {
107107
if err != nil {
@@ -144,7 +144,7 @@ func TestSyncWorkIntegration(t *testing.T) {
144144
Obj: testObj,
145145
}
146146

147-
err := manifest.Include(nil, nil, nil, nil, nil, work.EnabledFeatureGates)
147+
err := manifest.Include(nil, nil, nil, nil, nil, work.EnabledFeatureGates, nil)
148148
if err != nil {
149149
t.Errorf("Expected manifest to be included with TestGate1 enabled, got error: %v", err)
150150
}
@@ -154,7 +154,7 @@ func TestSyncWorkIntegration(t *testing.T) {
154154
"release.openshift.io/feature-gate": "DisabledGate",
155155
})
156156

157-
err = manifest.Include(nil, nil, nil, nil, nil, work.EnabledFeatureGates)
157+
err = manifest.Include(nil, nil, nil, nil, nil, work.EnabledFeatureGates, nil)
158158
if err == nil {
159159
t.Error("Expected manifest to be excluded with DisabledGate not enabled, but no error occurred")
160160
}
@@ -263,7 +263,7 @@ func TestManifestFilteringExamples(t *testing.T) {
263263
Obj: obj,
264264
}
265265

266-
err := manifest.Include(nil, nil, nil, nil, nil, example.enabledGates)
266+
err := manifest.Include(nil, nil, nil, nil, nil, example.enabledGates, nil)
267267

268268
if example.shouldInclude {
269269
if err != nil {

pkg/cvo/sync_worker.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"k8s.io/apimachinery/pkg/util/wait"
2424
"k8s.io/client-go/tools/record"
2525
"k8s.io/klog/v2"
26+
"k8s.io/utils/ptr"
2627

2728
configv1 "github.com/openshift/api/config/v1"
2829

@@ -448,7 +449,7 @@ func (w *SyncWorker) syncPayload(ctx context.Context, work *SyncWork) ([]configv
448449

449450
if w.payload != nil {
450451
implicitlyEnabledCaps = capability.SortedList(payload.GetImplicitlyEnabledCapabilities(payloadUpdate.Manifests, w.payload.Manifests,
451-
work.Capabilities, work.EnabledFeatureGates))
452+
work.Capabilities, work.EnabledFeatureGates, ptr.To(w.payload.ParsedVersion.Major)))
452453
}
453454

454455
w.payload = payloadUpdate
@@ -1067,7 +1068,7 @@ func (w *SyncWorker) apply(ctx context.Context, work *SyncWork, maxWorkers int,
10671068
if task.Manifest.GVK != configv1.GroupVersion.WithKind("ClusterOperator") {
10681069
continue
10691070
}
1070-
if err := task.Manifest.Include(nil, nil, nil, &capabilities, work.Overrides, work.EnabledFeatureGates); err != nil {
1071+
if err := task.Manifest.Include(nil, nil, nil, &capabilities, work.Overrides, work.EnabledFeatureGates, ptr.To(payloadUpdate.ParsedVersion.Major)); err != nil {
10711072
klog.V(manifestVerbosity).Infof("Skipping precreation of %s: %s", task, err)
10721073
continue
10731074
}
@@ -1087,7 +1088,7 @@ func (w *SyncWorker) apply(ctx context.Context, work *SyncWork, maxWorkers int,
10871088

10881089
klog.V(manifestVerbosity).Infof("Running sync for %s", task)
10891090

1090-
if err := task.Manifest.Include(nil, nil, nil, &capabilities, work.Overrides, work.EnabledFeatureGates); err != nil {
1091+
if err := task.Manifest.Include(nil, nil, nil, &capabilities, work.Overrides, work.EnabledFeatureGates, ptr.To(payloadUpdate.ParsedVersion.Major)); err != nil {
10911092
klog.V(manifestVerbosity).Infof("Skipping %s: %s", task, err)
10921093
continue
10931094
}

pkg/payload/payload.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
utilerrors "k8s.io/apimachinery/pkg/util/errors"
1818
"k8s.io/apimachinery/pkg/util/sets"
1919
"k8s.io/klog/v2"
20+
"k8s.io/utils/ptr"
2021

2122
configv1 "github.com/openshift/api/config/v1"
2223
imagev1 "github.com/openshift/api/image/v1"
@@ -109,7 +110,8 @@ type Update struct {
109110

110111
ImageRef *imagev1.ImageStream
111112

112-
Architecture string
113+
Architecture string
114+
ParsedVersion semver.Version
113115

114116
// manifestHash is a hash of the manifests included in this payload
115117
ManifestHash string
@@ -211,7 +213,7 @@ func LoadUpdate(dir, releaseImage, excludeIdentifier string, requiredFeatureSet
211213
filteredMs := []manifest.Manifest{}
212214

213215
for _, manifest := range ms {
214-
if err := manifest.Include(&excludeIdentifier, &requiredFeatureSet, &profile, onlyKnownCaps, nil, enabledFeatureGates); err != nil {
216+
if err := manifest.Include(&excludeIdentifier, &requiredFeatureSet, &profile, onlyKnownCaps, nil, enabledFeatureGates, ptr.To(payload.ParsedVersion.Major)); err != nil {
215217
klog.V(2).Infof("excluding %s: %v\n", manifest.String(), err)
216218
continue
217219
}
@@ -243,12 +245,12 @@ func LoadUpdate(dir, releaseImage, excludeIdentifier string, requiredFeatureSet
243245
// the current payload the updated manifest's capabilities are checked to see if any must be implicitly enabled.
244246
// All capabilities requiring implicit enablement are returned.
245247
func GetImplicitlyEnabledCapabilities(updatePayloadManifests []manifest.Manifest, currentPayloadManifests []manifest.Manifest,
246-
capabilities capability.ClusterCapabilities, enabledFeatureGates sets.Set[string]) sets.Set[configv1.ClusterVersionCapability] {
248+
capabilities capability.ClusterCapabilities, enabledFeatureGates sets.Set[string], majorVersion *uint64) sets.Set[configv1.ClusterVersionCapability] {
247249
clusterCaps := capability.GetCapabilitiesStatus(capabilities)
248250
return localmanifest.GetImplicitlyEnabledCapabilities(
249251
updatePayloadManifests,
250252
currentPayloadManifests,
251-
localmanifest.InclusionConfiguration{Capabilities: &clusterCaps, EnabledFeatureGates: enabledFeatureGates},
253+
localmanifest.InclusionConfiguration{Capabilities: &clusterCaps, EnabledFeatureGates: enabledFeatureGates, MajorVersion: majorVersion},
252254
capabilities.ImplicitlyEnabled,
253255
)
254256
}
@@ -284,6 +286,11 @@ func loadPayloadMetadata(releaseDir, releaseImage string) (*Update, error) {
284286
klog.V(2).Infof("Architecture from %s (%s) retrieved from runtime: %q", cincinnatiJSONFile, release.Version, arch)
285287
}
286288

289+
parsedVersion, err := semver.Parse(release.Version)
290+
if err != nil {
291+
return nil, fmt.Errorf("failed to parse release version %s: %w", release.Version, err)
292+
}
293+
287294
release.Image = releaseImage
288295

289296
imageRef, err := loadImageReferences(releaseDir)
@@ -296,9 +303,10 @@ func loadPayloadMetadata(releaseDir, releaseImage string) (*Update, error) {
296303
}
297304

298305
return &Update{
299-
Release: release,
300-
ImageRef: imageRef,
301-
Architecture: arch,
306+
Release: release,
307+
ImageRef: imageRef,
308+
Architecture: arch,
309+
ParsedVersion: parsedVersion,
302310
}, nil
303311
}
304312

pkg/payload/payload_test.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"runtime"
99
"testing"
1010

11+
"github.com/blang/semver/v4"
1112
"github.com/google/go-cmp/cmp"
1213
"github.com/google/go-cmp/cmp/cmpopts"
1314

@@ -67,6 +68,12 @@ func TestLoadUpdate(t *testing.T) {
6768
},
6869
},
6970
Architecture: architecture,
71+
ParsedVersion: semver.Version{
72+
Major: 1,
73+
Minor: 0,
74+
Patch: 0,
75+
Pre: []semver.PRVersion{{VersionStr: "abc"}},
76+
},
7077
ManifestHash: "DL-FFQ2Uem8=",
7178
Manifests: []manifest.Manifest{
7279
{
@@ -178,6 +185,12 @@ func TestLoadUpdateArchitecture(t *testing.T) {
178185
},
179186
},
180187
Architecture: "Multi",
188+
ParsedVersion: semver.Version{
189+
Major: 1,
190+
Minor: 0,
191+
Patch: 0,
192+
Pre: []semver.PRVersion{{VersionStr: "abc"}},
193+
},
181194
ManifestHash: "fvnVhLw92pE=",
182195
Manifests: []manifest.Manifest{
183196
{
@@ -366,7 +379,7 @@ func TestGetImplicitlyEnabledCapabilities(t *testing.T) {
366379
if tt.pathExt == "test10" {
367380
updateMans = append(updateMans, updateMans[0])
368381
}
369-
caps := GetImplicitlyEnabledCapabilities(updateMans, currentMans, tt.capabilities, sets.Set[string]{})
382+
caps := GetImplicitlyEnabledCapabilities(updateMans, currentMans, tt.capabilities, sets.Set[string]{}, nil)
370383
if diff := cmp.Diff(tt.wantImplicit, caps); diff != "" {
371384
t.Errorf("%s: wantImplicit differs from expected:\n%s", tt.name, diff)
372385
}

pkg/payload/render.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99
"text/template"
1010

11+
"github.com/blang/semver/v4"
1112
"github.com/pkg/errors"
1213

1314
"k8s.io/apimachinery/pkg/runtime"
@@ -47,6 +48,11 @@ func Render(outputDir, releaseImage, clusterVersionManifestPath, featureGateMani
4748
return fmt.Errorf("error parsing feature gate manifest: %w", err)
4849
}
4950

51+
payloadVersion, err := loadReleaseVersion(releaseManifestsDir)
52+
if err != nil {
53+
return fmt.Errorf("error loading release version: %w", err)
54+
}
55+
5056
tasks := []struct {
5157
idir string
5258
odir string
@@ -77,7 +83,7 @@ func Render(outputDir, releaseImage, clusterVersionManifestPath, featureGateMani
7783
}}
7884
var errs []error
7985
for _, task := range tasks {
80-
if err := renderDir(renderConfig, task.idir, task.odir, overrides, requiredFeatureSet, enabledFeatureGates, &clusterProfile, task.processTemplate, task.skipFiles, task.filterGroupKind); err != nil {
86+
if err := renderDir(renderConfig, task.idir, task.odir, overrides, requiredFeatureSet, enabledFeatureGates, &clusterProfile, ptr.To(payloadVersion.Major), task.processTemplate, task.skipFiles, task.filterGroupKind); err != nil {
8187
errs = append(errs, err)
8288
}
8389
}
@@ -89,8 +95,8 @@ func Render(outputDir, releaseImage, clusterVersionManifestPath, featureGateMani
8995
return nil
9096
}
9197

92-
func renderDir(renderConfig manifestRenderConfig, idir, odir string, overrides []configv1.ComponentOverride, requiredFeatureSet *string, enabledFeatureGates sets.Set[string], clusterProfile *string, processTemplate bool, skipFiles sets.Set[string], filterGroupKind sets.Set[schema.GroupKind]) error {
93-
klog.Infof("Filtering manifests in %s for feature set %v, cluster profile %v and enabled feature gates %v", idir, *requiredFeatureSet, *clusterProfile, enabledFeatureGates.UnsortedList())
98+
func renderDir(renderConfig manifestRenderConfig, idir, odir string, overrides []configv1.ComponentOverride, requiredFeatureSet *string, enabledFeatureGates sets.Set[string], clusterProfile *string, majorVersion *uint64, processTemplate bool, skipFiles sets.Set[string], filterGroupKind sets.Set[schema.GroupKind]) error {
99+
klog.Infof("Filtering manifests in %s for feature set %v, cluster profile %v, enabled feature gates %v, and major version %v", idir, *requiredFeatureSet, *clusterProfile, enabledFeatureGates.UnsortedList(), ptr.Deref(majorVersion, 0))
94100

95101
if err := os.MkdirAll(odir, 0666); err != nil {
96102
return err
@@ -140,7 +146,7 @@ func renderDir(renderConfig manifestRenderConfig, idir, odir string, overrides [
140146
for _, manifest := range manifests {
141147
if len(filterGroupKind) > 0 && !filterGroupKind.Has(manifest.GVK.GroupKind()) {
142148
klog.Infof("excluding %s because we do not render that group/kind", manifest.String())
143-
} else if err := manifest.Include(nil, requiredFeatureSet, clusterProfile, nil, overrides, enabledFeatureGates); err != nil {
149+
} else if err := manifest.Include(nil, requiredFeatureSet, clusterProfile, nil, overrides, enabledFeatureGates, majorVersion); err != nil {
144150
klog.Infof("excluding %s: %v", manifest.String(), err)
145151
} else {
146152
filteredManifests = append(filteredManifests, string(manifest.Raw))
@@ -274,3 +280,17 @@ func parseFeatureGateManifest(featureGateManifestPath string) (*string, sets.Set
274280

275281
return requiredFeatureSet, enabledFeatureGates, nil
276282
}
283+
284+
func loadReleaseVersion(releaseDir string) (semver.Version, error) {
285+
release, err := loadReleaseMetadata(releaseDir)
286+
if err != nil {
287+
return semver.Version{}, err
288+
}
289+
290+
parsedVersion, err := semver.Parse(release.Version)
291+
if err != nil {
292+
return semver.Version{}, fmt.Errorf("cincinnati metadata version %q is not a valid semantic version: %v", release.Version, err)
293+
}
294+
295+
return parsedVersion, nil
296+
}

0 commit comments

Comments
 (0)