Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions internal/operator-controller/applier/boxcutter.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,24 @@ func (r *SimpleRevisionGenerator) GenerateRevisionFromHelmRelease(
if err := yaml.Unmarshal([]byte(doc), &obj); err != nil {
return nil, err
}
obj.SetLabels(mergeLabelMaps(obj.GetLabels(), objectLabels))
obj.SetLabels(mergeStringMaps(obj.GetLabels(), objectLabels))

// Memory optimization: strip large annotations
// Note: ApplyStripTransform never returns an error in practice
_ = cache.ApplyStripAnnotationsTransform(&obj)
sanitizedUnstructured(ctx, &obj)

annotationUpdates := map[string]string{}
if v := helmRelease.Labels[labels.BundleVersionKey]; v != "" {
annotationUpdates[labels.BundleVersionKey] = v
}
if v := helmRelease.Labels[labels.PackageNameKey]; v != "" {
annotationUpdates[labels.PackageNameKey] = v
}
if len(annotationUpdates) > 0 {
obj.SetAnnotations(mergeStringMaps(obj.GetAnnotations(), annotationUpdates))
}

objs = append(objs, *ocv1ac.ClusterExtensionRevisionObject().
WithObject(obj))
}
Expand Down Expand Up @@ -126,7 +137,7 @@ func (r *SimpleRevisionGenerator) GenerateRevision(
// objectLabels
objs := make([]ocv1ac.ClusterExtensionRevisionObjectApplyConfiguration, 0, len(plain))
for _, obj := range plain {
obj.SetLabels(mergeLabelMaps(obj.GetLabels(), objectLabels))
obj.SetLabels(mergeStringMaps(obj.GetLabels(), objectLabels))

gvk, err := apiutil.GVKForObject(obj, r.Scheme)
if err != nil {
Expand All @@ -146,6 +157,17 @@ func (r *SimpleRevisionGenerator) GenerateRevision(
}
sanitizedUnstructured(ctx, &unstr)

annotationUpdates := map[string]string{}
if v := revisionAnnotations[labels.BundleVersionKey]; v != "" {
annotationUpdates[labels.BundleVersionKey] = v
}
if v := revisionAnnotations[labels.PackageNameKey]; v != "" {
annotationUpdates[labels.PackageNameKey] = v
}
if len(annotationUpdates) > 0 {
unstr.SetAnnotations(mergeStringMaps(unstr.GetAnnotations(), annotationUpdates))
}

objs = append(objs, *ocv1ac.ClusterExtensionRevisionObject().
WithObject(unstr))
}
Expand Down Expand Up @@ -671,9 +693,9 @@ func revisionManagementPerms(rev *ocv1ac.ClusterExtensionRevisionApplyConfigurat
}
}

func mergeLabelMaps(m1, m2 map[string]string) map[string]string {
mergedLabels := make(map[string]string, len(m1)+len(m2))
maps.Copy(mergedLabels, m1)
maps.Copy(mergedLabels, m2)
return mergedLabels
func mergeStringMaps(m1, m2 map[string]string) map[string]string {
merged := make(map[string]string, len(m1)+len(m2))
maps.Copy(merged, m1)
maps.Copy(merged, m2)
return merged
}
19 changes: 18 additions & 1 deletion internal/operator-controller/applier/boxcutter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ func Test_SimpleRevisionGenerator_GenerateRevisionFromHelmRelease(t *testing.T)
"labels": map[string]interface{}{
"my-label": "my-value",
},
"annotations": map[string]interface{}{
"olm.operatorframework.io/bundle-version": "1.2.0",
"olm.operatorframework.io/package-name": "my-package",
},
},
},
}),
Expand All @@ -140,6 +144,10 @@ func Test_SimpleRevisionGenerator_GenerateRevisionFromHelmRelease(t *testing.T)
"labels": map[string]interface{}{
"my-label": "my-value",
},
"annotations": map[string]interface{}{
"olm.operatorframework.io/bundle-version": "1.2.0",
"olm.operatorframework.io/package-name": "my-package",
},
},
},
}),
Expand Down Expand Up @@ -199,7 +207,10 @@ func Test_SimpleRevisionGenerator_GenerateRevision(t *testing.T) {
},
}

rev, err := b.GenerateRevision(t.Context(), dummyBundle, ext, map[string]string{}, map[string]string{})
rev, err := b.GenerateRevision(t.Context(), dummyBundle, ext, map[string]string{}, map[string]string{
labels.BundleVersionKey: "1.0.0",
labels.PackageNameKey: "test-package",
})
require.NoError(t, err)

t.Log("by checking the olm.operatorframework.io/owner-name and owner-kind labels are set")
Expand All @@ -223,6 +234,10 @@ func Test_SimpleRevisionGenerator_GenerateRevision(t *testing.T) {
"kind": "Service",
"metadata": map[string]interface{}{
"name": "test-service",
"annotations": map[string]interface{}{
"olm.operatorframework.io/bundle-version": "1.0.0",
"olm.operatorframework.io/package-name": "test-package",
},
},
"spec": map[string]interface{}{},
},
Expand All @@ -244,6 +259,8 @@ func Test_SimpleRevisionGenerator_GenerateRevision(t *testing.T) {
},
"annotations": map[string]interface{}{
"my-annotation": "my-annotation-value",
"olm.operatorframework.io/bundle-version": "1.0.0",
"olm.operatorframework.io/package-name": "test-package",
},
},
"spec": map[string]interface{}{
Expand Down
30 changes: 30 additions & 0 deletions test/e2e/features/update.feature
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,36 @@ Feature: Update ClusterExtension
When ClusterCatalog "test" image version "v2" is also tagged as "latest"
Then bundle "test-operator.1.3.0" is installed in version "1.3.0"

@BoxcutterRuntime
Scenario: Update to a version with identical bundle content creates a new revision
Given ClusterExtension is applied
"""
apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
name: ${NAME}
spec:
namespace: ${TEST_NAMESPACE}
serviceAccount:
name: olm-sa
source:
sourceType: Catalog
catalog:
packageName: test
selector:
matchLabels:
"olm.operatorframework.io/metadata.name": test-catalog
version: 1.0.0
upgradeConstraintPolicy: SelfCertified
"""
And ClusterExtension is rolled out
And ClusterExtension is available
And bundle "test-operator.1.0.0" is installed in version "1.0.0"
When ClusterExtension is updated to version "1.0.4"
Then ClusterExtension is rolled out
And ClusterExtension is available
And bundle "test-operator.1.0.4" is installed in version "1.0.4"

@BoxcutterRuntime
Scenario: Each update creates a new revision and resources not present in the new revision are removed from the cluster
Given ClusterExtension is applied
Expand Down
14 changes: 14 additions & 0 deletions testdata/images/catalogs/test-catalog/v1/configs/catalog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ entries:
- name: test-operator.1.0.0
- name: test-operator.1.0.1
replaces: test-operator.1.0.0
- name: test-operator.1.0.4
- name: test-operator.1.2.0
replaces: test-operator.1.0.1
---
Expand All @@ -40,6 +41,19 @@ properties:
packageName: test
version: 1.0.1
---
# Bundle with identical rendered content as v1.0.0 (same image).
# Used to test that upgrading between versions with identical manifests
# correctly updates the installed version status (OCPBUGS-78311).
schema: olm.bundle
name: test-operator.1.0.4
package: test
image: docker-registry.operator-controller-e2e.svc.cluster.local:5000/bundles/registry-v1/test-operator:v1.0.0
properties:
- type: olm.package
value:
packageName: test
version: 1.0.4
---
# Bundle with a wrong image ref causing image pull failure
schema: olm.bundle
name: test-operator.1.0.2
Expand Down
Loading