Skip to content

Commit 5fafe40

Browse files
fix: Use labels for bundle metadata and unify owner labels
Fix bundle metadata storage to use labels instead of annotations, following Kubernetes best practices for queryable metadata. This enables kubectl queries like: kubectl get clusterextensionrevisions -l package-name=prometheus Also fixes inconsistent owner labels - now uses owner-name + owner-kind everywhere (previously ClusterExtensionRevision used just owner). Fixed issues: - Bundle metadata was in annotations (not queryable/indexed) - Owner labels were inconsistent across object types - Variable storeLbls was misleadingly named (actually annotations) Boxcutter runtime only - Helm unchanged except interface signature. Refs: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels Assisted-by: Cursor
1 parent 6ef62de commit 5fafe40

7 files changed

Lines changed: 151 additions & 105 deletions

File tree

internal/operator-controller/applier/boxcutter.go

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ const (
3535
)
3636

3737
type ClusterExtensionRevisionGenerator interface {
38-
GenerateRevision(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (*ocv1.ClusterExtensionRevision, error)
38+
GenerateRevision(ctx context.Context, bundleFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionLabels, revisionAnnotations map[string]string) (*ocv1.ClusterExtensionRevision, error)
3939
GenerateRevisionFromHelmRelease(
4040
ctx context.Context,
4141
helmRelease *release.Release, ext *ocv1.ClusterExtension,
42-
objectLabels map[string]string,
42+
objectLabels, revisionLabels map[string]string,
4343
) (*ocv1.ClusterExtensionRevision, error)
4444
}
4545

@@ -51,7 +51,7 @@ type SimpleRevisionGenerator struct {
5151
func (r *SimpleRevisionGenerator) GenerateRevisionFromHelmRelease(
5252
ctx context.Context,
5353
helmRelease *release.Release, ext *ocv1.ClusterExtension,
54-
objectLabels map[string]string,
54+
objectLabels, revisionLabels map[string]string,
5555
) (*ocv1.ClusterExtensionRevision, error) {
5656
docs := splitManifestDocuments(helmRelease.Manifest)
5757
objs := make([]ocv1.ClusterExtensionRevisionObject, 0, len(docs))
@@ -75,12 +75,19 @@ func (r *SimpleRevisionGenerator) GenerateRevisionFromHelmRelease(
7575
})
7676
}
7777

78-
rev := r.buildClusterExtensionRevision(objs, ext, map[string]string{
79-
labels.BundleNameKey: helmRelease.Labels[labels.BundleNameKey],
80-
labels.PackageNameKey: helmRelease.Labels[labels.PackageNameKey],
81-
labels.BundleVersionKey: helmRelease.Labels[labels.BundleVersionKey],
78+
// Merge provided revision labels with bundle metadata from Helm release
79+
allRevisionLabels := make(map[string]string, len(revisionLabels)+4)
80+
maps.Copy(allRevisionLabels, revisionLabels)
81+
allRevisionLabels[labels.BundleNameKey] = helmRelease.Labels[labels.BundleNameKey]
82+
allRevisionLabels[labels.PackageNameKey] = helmRelease.Labels[labels.PackageNameKey]
83+
allRevisionLabels[labels.BundleVersionKey] = helmRelease.Labels[labels.BundleVersionKey]
84+
85+
// Bundle reference goes to annotations (can be too long for labels)
86+
revisionAnnotations := map[string]string{
8287
labels.BundleReferenceKey: helmRelease.Labels[labels.BundleReferenceKey],
83-
})
88+
}
89+
90+
rev := r.buildClusterExtensionRevision(objs, ext, allRevisionLabels, revisionAnnotations)
8491
rev.Name = fmt.Sprintf("%s-1", ext.Name)
8592
rev.Spec.Revision = 1
8693
return rev, nil
@@ -89,15 +96,15 @@ func (r *SimpleRevisionGenerator) GenerateRevisionFromHelmRelease(
8996
func (r *SimpleRevisionGenerator) GenerateRevision(
9097
ctx context.Context,
9198
bundleFS fs.FS, ext *ocv1.ClusterExtension,
92-
objectLabels, revisionAnnotations map[string]string,
99+
objectLabels, revisionLabels, revisionAnnotations map[string]string,
93100
) (*ocv1.ClusterExtensionRevision, error) {
94101
// extract plain manifests
95102
plain, err := r.ManifestProvider.Get(bundleFS, ext)
96103
if err != nil {
97104
return nil, err
98105
}
99106

100-
// objectLabels
107+
// Apply objectLabels to each managed object
101108
objs := make([]ocv1.ClusterExtensionRevisionObject, 0, len(plain))
102109
for _, obj := range plain {
103110
existingLabels := obj.GetLabels()
@@ -125,11 +132,14 @@ func (r *SimpleRevisionGenerator) GenerateRevision(
125132
})
126133
}
127134

135+
if revisionLabels == nil {
136+
revisionLabels = map[string]string{}
137+
}
128138
if revisionAnnotations == nil {
129139
revisionAnnotations = map[string]string{}
130140
}
131141

132-
return r.buildClusterExtensionRevision(objs, ext, revisionAnnotations), nil
142+
return r.buildClusterExtensionRevision(objs, ext, revisionLabels, revisionAnnotations), nil
133143
}
134144

135145
// sanitizedUnstructured takes an unstructured obj, removes status if present, and returns a sanitized copy containing only the allowed metadata entries set below.
@@ -177,14 +187,20 @@ func sanitizedUnstructured(ctx context.Context, unstr *unstructured.Unstructured
177187
func (r *SimpleRevisionGenerator) buildClusterExtensionRevision(
178188
objects []ocv1.ClusterExtensionRevisionObject,
179189
ext *ocv1.ClusterExtension,
180-
annotations map[string]string,
190+
revisionLabels map[string]string,
191+
revisionAnnotations map[string]string,
181192
) *ocv1.ClusterExtensionRevision {
193+
// Build labels: owner labels + provided revision labels (package, bundle, version, etc.)
194+
// Use owner-name + owner-kind for consistency with managed objects
195+
allLabels := make(map[string]string, len(revisionLabels)+2)
196+
allLabels[labels.OwnerKindKey] = ocv1.ClusterExtensionKind
197+
allLabels[labels.OwnerNameKey] = ext.Name
198+
maps.Copy(allLabels, revisionLabels)
199+
182200
return &ocv1.ClusterExtensionRevision{
183201
ObjectMeta: metav1.ObjectMeta{
184-
Annotations: annotations,
185-
Labels: map[string]string{
186-
controllers.ClusterExtensionRevisionOwnerLabel: ext.Name,
187-
},
202+
Labels: allLabels,
203+
Annotations: revisionAnnotations,
188204
},
189205
Spec: ocv1.ClusterExtensionRevisionSpec{
190206
// Explicitly set LifecycleState to Active. While the CRD has a default,
@@ -240,7 +256,9 @@ func (m *BoxcutterStorageMigrator) Migrate(ctx context.Context, ext *ocv1.Cluste
240256
return err
241257
}
242258

243-
rev, err := m.RevisionGenerator.GenerateRevisionFromHelmRelease(ctx, helmRelease, ext, objectLabels)
259+
// revisionLabels will be merged with bundle metadata from Helm release
260+
revisionLabels := map[string]string{}
261+
rev, err := m.RevisionGenerator.GenerateRevisionFromHelmRelease(ctx, helmRelease, ext, objectLabels, revisionLabels)
244262
if err != nil {
245263
return err
246264
}
@@ -284,8 +302,8 @@ type Boxcutter struct {
284302
FieldOwner string
285303
}
286304

287-
func (bc *Boxcutter) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (bool, string, error) {
288-
return bc.apply(ctx, contentFS, ext, objectLabels, revisionAnnotations)
305+
func (bc *Boxcutter) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionLabels, revisionAnnotations map[string]string) (bool, string, error) {
306+
return bc.apply(ctx, contentFS, ext, objectLabels, revisionLabels, revisionAnnotations)
289307
}
290308

291309
func (bc *Boxcutter) getObjects(rev *ocv1.ClusterExtensionRevision) []client.Object {
@@ -309,9 +327,9 @@ func (bc *Boxcutter) createOrUpdate(ctx context.Context, obj client.Object) erro
309327
return bc.Client.Patch(ctx, obj, client.Apply, client.FieldOwner(bc.FieldOwner), client.ForceOwnership)
310328
}
311329

312-
func (bc *Boxcutter) apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionAnnotations map[string]string) (bool, string, error) {
330+
func (bc *Boxcutter) apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExtension, objectLabels, revisionLabels, revisionAnnotations map[string]string) (bool, string, error) {
313331
// Generate desired revision
314-
desiredRevision, err := bc.RevisionGenerator.GenerateRevision(ctx, contentFS, ext, objectLabels, revisionAnnotations)
332+
desiredRevision, err := bc.RevisionGenerator.GenerateRevision(ctx, contentFS, ext, objectLabels, revisionLabels, revisionAnnotations)
315333
if err != nil {
316334
return false, "", err
317335
}

0 commit comments

Comments
 (0)