Skip to content

Commit 8ac9e61

Browse files
(chore): Add JSONSchema validation for bundle configuration
Bundle configuration is now validated using JSONSchema. Configuration errors (typos, missing required fields, wrong types) are caught immediately with clear error messages instead of failing during installation. Assisted-by: Cursor
1 parent c95fc24 commit 8ac9e61

File tree

8 files changed

+964
-200
lines changed

8 files changed

+964
-200
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ require (
2323
github.com/operator-framework/operator-registry v1.61.0
2424
github.com/prometheus/client_golang v1.23.2
2525
github.com/prometheus/common v0.67.2
26+
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
2627
github.com/spf13/cobra v1.10.1
2728
github.com/spf13/pflag v1.0.10
2829
github.com/stretchr/testify v1.11.1
@@ -192,7 +193,6 @@ require (
192193
github.com/rivo/uniseg v0.4.7 // indirect
193194
github.com/rubenv/sql-migrate v1.8.0 // indirect
194195
github.com/russross/blackfriday/v2 v2.1.0 // indirect
195-
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
196196
github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect
197197
github.com/shopspring/decimal v1.4.0 // indirect
198198
github.com/sigstore/fulcio v1.7.1 // indirect

internal/operator-controller/applier/provider.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,19 @@ func (r *RegistryV1ManifestProvider) Get(bundleFS fs.FS, ext *ocv1.ClusterExtens
6969
}
7070

7171
if r.IsSingleOwnNamespaceEnabled {
72-
bundleConfigBytes := extensionConfigBytes(ext)
73-
// treat no config as empty to properly validate the configuration
74-
// e.g. ensure that validation catches missing required fields
75-
if bundleConfigBytes == nil {
76-
bundleConfigBytes = []byte(`{}`)
72+
schema, err := rv1.Get()
73+
if err != nil {
74+
return nil, fmt.Errorf("error getting configuration schema: %w", err)
7775
}
78-
bundleConfig, err := bundle.UnmarshalConfig(bundleConfigBytes, rv1, ext.Spec.Namespace)
76+
77+
bundleConfigBytes := extensionConfigBytes(ext)
78+
bundleConfig, err := bundle.UnmarshalConfig(bundleConfigBytes, schema, ext.Spec.Namespace)
7979
if err != nil {
80-
return nil, fmt.Errorf("invalid bundle configuration: %w", err)
80+
return nil, fmt.Errorf("invalid ClusterExtension configuration: %w", err)
8181
}
8282

83-
if bundleConfig != nil && bundleConfig.WatchNamespace != nil {
84-
opts = append(opts, render.WithTargetNamespaces(*bundleConfig.WatchNamespace))
83+
if watchNS := bundleConfig.GetWatchNamespace(); watchNS != nil {
84+
opts = append(opts, render.WithTargetNamespaces(*watchNS))
8585
}
8686
}
8787

internal/operator-controller/applier/provider_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func Test_RegistryV1ManifestProvider_Integration(t *testing.T) {
9797

9898
_, err := provider.Get(bundleFS, ext)
9999
require.Error(t, err)
100-
require.Contains(t, err.Error(), "invalid bundle configuration")
100+
require.Contains(t, err.Error(), "invalid ClusterExtension configuration")
101101
})
102102

103103
t.Run("returns rendered manifests", func(t *testing.T) {
@@ -392,7 +392,7 @@ func Test_RegistryV1ManifestProvider_SingleOwnNamespaceSupport(t *testing.T) {
392392
},
393393
})
394394
require.Error(t, err)
395-
require.Contains(t, err.Error(), "invalid 'watchNamespace' \"not-install-namespace\": must be install namespace (install-namespace)")
395+
require.Contains(t, err.Error(), "invalid ClusterExtension configuration: invalid configuration:")
396396
})
397397

398398
t.Run("rejects bundles without AllNamespaces, SingleNamespace, or OwnNamespace install mode support when Single/OwnNamespace install mode support is enabled", func(t *testing.T) {

0 commit comments

Comments
 (0)