@@ -3,13 +3,16 @@ package applier
33import (
44 "crypto/sha256"
55 "encoding/json"
6+ "errors"
67 "fmt"
78 "io/fs"
9+ "strings"
810
911 "helm.sh/helm/v3/pkg/chart"
1012 "k8s.io/apimachinery/pkg/util/sets"
1113 "k8s.io/apimachinery/pkg/util/validation"
1214 "sigs.k8s.io/controller-runtime/pkg/client"
15+ "sigs.k8s.io/yaml"
1316
1417 "github.com/operator-framework/api/pkg/operators/v1alpha1"
1518
@@ -32,6 +35,9 @@ type RegistryV1ManifestProvider struct {
3235 IsWebhookSupportEnabled bool
3336 IsSingleOwnNamespaceEnabled bool
3437}
38+ type registryV1Config struct {
39+ WatchNamespace string `json:"watchNamespace"`
40+ }
3541
3642func (r * RegistryV1ManifestProvider ) Get (bundleFS fs.FS , ext * ocv1.ClusterExtension ) ([]client.Object , error ) {
3743 rv1 , err := source .FromFS (bundleFS ).GetBundle ()
@@ -70,7 +76,7 @@ func (r *RegistryV1ManifestProvider) Get(bundleFS fs.FS, ext *ocv1.ClusterExtens
7076
7177 watchNamespace , err := r .getWatchNamespace (ext )
7278 if err != nil {
73- return nil , err
79+ return nil , fmt . Errorf ( "invalid bundle configuration: %w" , err )
7480 }
7581
7682 if watchNamespace != "" {
@@ -89,11 +95,12 @@ func (r *RegistryV1ManifestProvider) getWatchNamespace(ext *ocv1.ClusterExtensio
8995
9096 var watchNamespace string
9197 if ext .Spec .Config != nil && ext .Spec .Config .Inline != nil {
92- cfg := struct {
93- WatchNamespace string `json:"watchNamespace"`
94- }{}
95- if err := json .Unmarshal (ext .Spec .Config .Inline .Raw , & cfg ); err != nil {
96- return "" , fmt .Errorf ("invalid bundle configuration: %w" , err )
98+ cfg := & registryV1Config {}
99+ // Using k8s.io/yaml package as that is able to handle both json and yaml
100+ // In most cases, at this point we should have a valid JSON/YAML object in the byte slice and failures will
101+ // be related to object structure (e.g. additional fields).
102+ if err := yaml .UnmarshalStrict (ext .Spec .Config .Inline .Raw , cfg ); err != nil {
103+ return "" , fmt .Errorf ("error unmarshalling registry+v1 configuration: %w" , formatUnmarshallError (err ))
97104 }
98105 watchNamespace = cfg .WatchNamespace
99106 } else {
@@ -153,3 +160,27 @@ func (r *RegistryV1HelmChartProvider) Get(bundleFS fs.FS, ext *ocv1.ClusterExten
153160
154161 return chrt , nil
155162}
163+
164+ func formatUnmarshallError (err error ) error {
165+ var unmarshalErr * json.UnmarshalTypeError
166+ if errors .As (err , & unmarshalErr ) {
167+ if unmarshalErr .Field == "" {
168+ return errors .New ("input is not a valid JSON object" )
169+ } else {
170+ return fmt .Errorf ("invalid value type for field %q: expected %q but got %q" , unmarshalErr .Field , unmarshalErr .Type .String (), unmarshalErr .Value )
171+ }
172+ }
173+
174+ // unwrap error until the core and process it
175+ for {
176+ unwrapped := errors .Unwrap (err )
177+ if unwrapped == nil {
178+ // usually the errors present in the form json: <message> or yaml: <message>
179+ // we want to extract <message> if we can
180+ errMessageComponents := strings .Split (err .Error (), ":" )
181+ coreErrMessage := strings .TrimSpace (errMessageComponents [len (errMessageComponents )- 1 ])
182+ return errors .New (coreErrMessage )
183+ }
184+ err = unwrapped
185+ }
186+ }
0 commit comments