Skip to content

Commit 3199880

Browse files
csv_validator: add check to ensure that the example is a valid JSON (#207)
1 parent ff6b5eb commit 3199880

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

Diff for: pkg/validation/internal/csv.go

+27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package internal
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"io"
67
"reflect"
@@ -97,6 +98,12 @@ func validateExamplesAnnotations(csv *v1alpha1.ClusterServiceVersion) (errs []er
9798
} else {
9899
examplesString = olmExamples
99100
}
101+
102+
if err := validateJSON(examplesString); err != nil {
103+
errs = append(errs, errors.ErrInvalidParse("invalid example", err))
104+
return errs
105+
}
106+
100107
us := []unstructured.Unstructured{}
101108
dec := yaml.NewYAMLOrJSONDecoder(strings.NewReader(examplesString), 8)
102109
if err := dec.Decode(&us); err != nil && err != io.EOF {
@@ -115,6 +122,26 @@ func validateExamplesAnnotations(csv *v1alpha1.ClusterServiceVersion) (errs []er
115122
return errs
116123
}
117124

125+
func validateJSON(value string) error {
126+
var js json.RawMessage
127+
byteValue := []byte(value)
128+
if err := json.Unmarshal(byteValue, &js); err != nil {
129+
switch t := err.(type) {
130+
case *json.SyntaxError:
131+
jsn := string(byteValue[0:t.Offset])
132+
jsn += "<--(see the invalid character)"
133+
return fmt.Errorf("invalid character at %v\n %s", t.Offset, jsn)
134+
case *json.UnmarshalTypeError:
135+
jsn := string(byteValue[0:t.Offset])
136+
jsn += "<--(see the invalid type)"
137+
return fmt.Errorf("invalid value at %v\n %s", t.Offset, jsn)
138+
default:
139+
return err
140+
}
141+
}
142+
return nil
143+
}
144+
118145
func getProvidedAPIs(csv *v1alpha1.ClusterServiceVersion) (provided map[schema.GroupVersionKind]struct{}, errs []errors.Error) {
119146
provided = map[schema.GroupVersionKind]struct{}{}
120147
for _, owned := range csv.Spec.CustomResourceDefinitions.Owned {

Diff for: pkg/validation/internal/csv_test.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import (
55
"path/filepath"
66
"testing"
77

8+
"github.com/ghodss/yaml"
89
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
910
"github.com/operator-framework/api/pkg/validation/errors"
10-
11-
"github.com/ghodss/yaml"
1211
)
1312

1413
func TestValidateCSV(t *testing.T) {
@@ -71,6 +70,16 @@ func TestValidateCSV(t *testing.T) {
7170
},
7271
filepath.Join("testdata", "badName.csv.yaml"),
7372
},
73+
{
74+
validatorFuncTest{
75+
description: "should fail when alm-examples is pretty format and is invalid",
76+
wantErr: true,
77+
errors: []errors.Error{
78+
errors.ErrInvalidParse("invalid example", "invalid character at 176\n [{\"apiVersion\":\"local.storage.openshift.io/v1\",\"kind\":\"LocalVolume\",\"metadata\":{\"name\":\"example\"},\"spec\":{\"storageClassDevices\":[{\"devicePaths\":[\"/dev/disk/by-id/ata-crucial\",]<--(see the invalid character)"),
79+
},
80+
},
81+
filepath.Join("testdata", "invalid.alm-examples.csv.yaml"),
82+
},
7483
}
7584
for _, c := range cases {
7685
b, err := ioutil.ReadFile(c.csvPath)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
apiVersion: operators.coreos.com/v1alpha1
2+
kind: ClusterServiceVersion
3+
metadata:
4+
annotations:
5+
alm-examples: '[{"apiVersion":"local.storage.openshift.io/v1","kind":"LocalVolume","metadata":{"name":"example"},"spec":{"storageClassDevices":[{"devicePaths":["/dev/disk/by-id/ata-crucial",],"fsType": "ext4", "storageClassName": "foobar", "volumeMode": "Filesystem" } ] } }, { "apiVersion": "local.storage.openshift.io/v1alpha1", "kind": "LocalVolumeSet", "metadata": { "name": "example-localvolumeset" }, "spec": { "deviceInclusionSpec": { "deviceMechanicalProperties": [ "Rotational", "NonRotational" ], "deviceTypes": [ "RawDisk" ], "maxSize": "100G", "minSize": "10G" }, "maxDeviceCount": 10, "nodeSelector": { "nodeSelectorTerms": [ { "matchExpressions": [ { "key": "kubernetes.io/hostname", "operator": "In", "values": [ "worker-0", "worker-1" ] } ] } ] }, "storageClassName": "example-storageclass", "volumeMode": "Block" } }, { "apiVersion": "local.storage.openshift.io/v1alpha1", "kind": "LocalVolumeDiscovery", "metadata": { "name": "auto-discover-devices" }, "spec": { "nodeSelector": { "nodeSelectorTerms": [ { "matchExpressions": [ { "key":"kubernetes.io/hostname","operator":"In","values":["worker-0","worker-1"]}]}]}}}]'
6+
capabilities: Basic Install
7+
name: test-operator.v0.0.1
8+
namespace: placeholder
9+
spec:
10+
displayName: test-operator
11+
install:
12+
strategy: deployment
13+
installModes:
14+
- supported: true
15+
type: OwnNamespace
16+
- supported: true
17+
type: SingleNamespace
18+
- supported: false
19+
type: MultiNamespace
20+
- supported: true
21+
type: AllNamespaces
22+
keywords:
23+
- test-operator
24+
links:
25+
- name: Test Operator
26+
url: https://test-operator.domain
27+
maintainers:
28+
29+
name: Maintainer Name
30+
maturity: alpha
31+
provider:
32+
name: Provider Name
33+
url: https://your.domain
34+
version: 0.0.1

0 commit comments

Comments
 (0)