Skip to content

Commit 7df3830

Browse files
(fix): unhandle changes for crd upgrade safety
- Keep unhandled spec changes as errors; message: "unhandled changes found" Assisted-by: Cursor
1 parent 33fdce2 commit 7df3830

File tree

4 files changed

+126
-4
lines changed

4 files changed

+126
-4
lines changed

internal/operator-controller/rukpak/preflights/crdupgradesafety/crdupgradesafety.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,9 @@ func (p *Preflight) runPreflight(ctx context.Context, relObjects []client.Object
9999
resultErrs := crdWideErrors(results)
100100
resultErrs = append(resultErrs, sameVersionErrors(results)...)
101101
resultErrs = append(resultErrs, servedVersionErrors(results)...)
102-
103-
validateErrors = append(validateErrors, fmt.Errorf("validating upgrade for CRD %q: %w", newCrd.Name, errors.Join(resultErrs...)))
102+
if len(resultErrs) > 0 {
103+
validateErrors = append(validateErrors, fmt.Errorf("validating upgrade for CRD %q: %w", newCrd.Name, errors.Join(resultErrs...)))
104+
}
104105
}
105106
}
106107

@@ -162,7 +163,11 @@ func sameVersionErrors(results *runner.Results) []error {
162163
for property, comparisonResults := range propertyResults {
163164
for _, result := range comparisonResults {
164165
for _, err := range result.Errors {
165-
errs = append(errs, fmt.Errorf("%s: %s: %s: %s", version, property, result.Name, err))
166+
msg := err
167+
if result.Name == "unhandled" {
168+
msg = "unhandled changes found"
169+
}
170+
errs = append(errs, fmt.Errorf("%s: %s: %s: %s", version, property, result.Name, msg))
166171
}
167172
}
168173
}
@@ -181,7 +186,11 @@ func servedVersionErrors(results *runner.Results) []error {
181186
for property, comparisonResults := range propertyResults {
182187
for _, result := range comparisonResults {
183188
for _, err := range result.Errors {
184-
errs = append(errs, fmt.Errorf("%s: %s: %s: %s", version, property, result.Name, err))
189+
msg := err
190+
if result.Name == "unhandled" {
191+
msg = "unhandled changes found"
192+
}
193+
errs = append(errs, fmt.Errorf("%s: %s: %s: %s", version, property, result.Name, msg))
185194
}
186195
}
187196
}

internal/operator-controller/rukpak/preflights/crdupgradesafety/crdupgradesafety_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1616
"k8s.io/apimachinery/pkg/runtime"
1717
"k8s.io/apimachinery/pkg/runtime/schema"
18+
crdifyconfig "sigs.k8s.io/crdify/pkg/config"
1819

1920
"github.com/operator-framework/operator-controller/internal/operator-controller/applier"
2021
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/preflights/crdupgradesafety"
@@ -386,3 +387,36 @@ func TestUpgrade(t *testing.T) {
386387
})
387388
}
388389
}
390+
391+
func TestUpgrade_UnhandledChanges_InSpec_DefaultPolicy(t *testing.T) {
392+
t.Run("unhandled spec changes cause error by default", func(t *testing.T) {
393+
preflight := newMockPreflight(getCrdFromManifestFile(t, "crd-unhandled-old.json"), nil)
394+
rel := &release.Release{
395+
Name: "test-release",
396+
Manifest: getManifestString(t, "crd-unhandled-new.json"),
397+
}
398+
err := preflight.Upgrade(context.Background(), rel)
399+
require.Error(t, err)
400+
require.ErrorContains(t, err, "unhandled changes found")
401+
require.NotContains(t, err.Error(), "v1.JSONSchemaProps", "error message should be concise without raw diff")
402+
})
403+
}
404+
405+
func TestUpgrade_UnhandledChanges_PolicyError(t *testing.T) {
406+
t.Run("unhandled changes error when policy is Error", func(t *testing.T) {
407+
oldCrd := getCrdFromManifestFile(t, "crd-unhandled-old.json")
408+
preflight := crdupgradesafety.NewPreflight(&MockCRDGetter{oldCrd: oldCrd}, crdupgradesafety.WithConfig(&crdifyconfig.Config{
409+
Conversion: crdifyconfig.ConversionPolicyIgnore,
410+
UnhandledEnforcement: crdifyconfig.EnforcementPolicyError,
411+
}))
412+
413+
rel := &release.Release{
414+
Name: "test-release",
415+
Manifest: getManifestString(t, "crd-unhandled-new.json"),
416+
}
417+
418+
err := preflight.Upgrade(context.Background(), rel)
419+
require.Error(t, err)
420+
require.ErrorContains(t, err, "unhandled changes found")
421+
})
422+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"apiVersion": "apiextensions.k8s.io/v1",
3+
"kind": "CustomResourceDefinition",
4+
"metadata": {
5+
"name": "widgets.example.com"
6+
},
7+
"spec": {
8+
"group": "example.com",
9+
"versions": [
10+
{
11+
"name": "v1alpha1",
12+
"served": true,
13+
"storage": true,
14+
"schema": {
15+
"openAPIV3Schema": {
16+
"type": "object",
17+
"properties": {
18+
"spec": {
19+
"type": "object",
20+
"properties": {
21+
"field": {
22+
"type": "string",
23+
"format": "email"
24+
}
25+
}
26+
}
27+
}
28+
}
29+
}
30+
}
31+
],
32+
"scope": "Namespaced",
33+
"names": {
34+
"plural": "widgets",
35+
"singular": "widget",
36+
"kind": "Widget"
37+
}
38+
}
39+
}
40+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"apiVersion": "apiextensions.k8s.io/v1",
3+
"kind": "CustomResourceDefinition",
4+
"metadata": {
5+
"name": "widgets.example.com"
6+
},
7+
"spec": {
8+
"group": "example.com",
9+
"versions": [
10+
{
11+
"name": "v1alpha1",
12+
"served": true,
13+
"storage": true,
14+
"schema": {
15+
"openAPIV3Schema": {
16+
"type": "object",
17+
"properties": {
18+
"spec": {
19+
"type": "object",
20+
"properties": {
21+
"field": {
22+
"type": "string"
23+
}
24+
}
25+
}
26+
}
27+
}
28+
}
29+
}
30+
],
31+
"scope": "Namespaced",
32+
"names": {
33+
"plural": "widgets",
34+
"singular": "widget",
35+
"kind": "Widget"
36+
}
37+
}
38+
}
39+

0 commit comments

Comments
 (0)