Skip to content

Commit 5ad863a

Browse files
authoredMay 5, 2020
Merge pull request openshift#32 from estroz/bugfix/crd-cmp-by-key
validation: bundle CRDs are compared by definition key instead of name
2 parents 5b1f691 + b8285b9 commit 5ad863a

File tree

3 files changed

+68
-46
lines changed

3 files changed

+68
-46
lines changed
 

‎pkg/validation/internal/bundle.go

+50-41
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package internal
22

33
import (
4-
"encoding/json"
54
"fmt"
65

76
"github.com/operator-framework/api/pkg/validation/errors"
87
interfaces "github.com/operator-framework/api/pkg/validation/interfaces"
98

10-
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
119
"github.com/operator-framework/operator-registry/pkg/registry"
1210
)
1311

@@ -24,71 +22,82 @@ func validateBundles(objs ...interface{}) (results []errors.ManifestResult) {
2422
}
2523

2624
func validateBundle(bundle *registry.Bundle) (result errors.ManifestResult) {
27-
bcsv, err := bundle.ClusterServiceVersion()
25+
csv, err := bundle.ClusterServiceVersion()
2826
if err != nil {
2927
result.Add(errors.ErrInvalidParse("error getting bundle CSV", err))
3028
return result
3129
}
32-
csv, rerr := bundleCSVToCSV(bcsv)
33-
if rerr != (errors.Error{}) {
34-
result.Add(rerr)
30+
31+
result = validateOwnedCRDs(bundle, csv)
32+
33+
if result.Name, err = csv.GetVersion(); err != nil {
34+
result.Add(errors.ErrInvalidParse("error getting bundle CSV version", err))
3535
return result
3636
}
37-
result = validateOwnedCRDs(bundle, csv)
38-
result.Name = csv.Spec.Version.String()
3937
return result
4038
}
4139

42-
func bundleCSVToCSV(bcsv *registry.ClusterServiceVersion) (*operatorsv1alpha1.ClusterServiceVersion, errors.Error) {
43-
spec := operatorsv1alpha1.ClusterServiceVersionSpec{}
44-
if err := json.Unmarshal(bcsv.Spec, &spec); err != nil {
45-
return nil, errors.ErrInvalidParse(fmt.Sprintf("converting bundle CSV %q", bcsv.GetName()), err)
40+
func validateOwnedCRDs(bundle *registry.Bundle, csv *registry.ClusterServiceVersion) (result errors.ManifestResult) {
41+
ownedKeys, _, err := csv.GetCustomResourceDefintions()
42+
if err != nil {
43+
result.Add(errors.ErrInvalidParse("error getting CSV CRDs", err))
44+
return result
4645
}
47-
return &operatorsv1alpha1.ClusterServiceVersion{
48-
TypeMeta: bcsv.TypeMeta,
49-
ObjectMeta: bcsv.ObjectMeta,
50-
Spec: spec,
51-
}, errors.Error{}
52-
}
5346

54-
func validateOwnedCRDs(bundle *registry.Bundle, csv *operatorsv1alpha1.ClusterServiceVersion) (result errors.ManifestResult) {
55-
ownedCrdNames := getOwnedCustomResourceDefintionNames(csv)
56-
crdNames, err := getBundleCRDNames(bundle)
57-
if err != (errors.Error{}) {
58-
result.Add(err)
47+
keySet, rerr := getBundleCRDKeys(bundle)
48+
if rerr != (errors.Error{}) {
49+
result.Add(rerr)
5950
return result
6051
}
6152

62-
// validating names
63-
for _, crdName := range ownedCrdNames {
64-
if _, ok := crdNames[crdName]; !ok {
65-
result.Add(errors.ErrInvalidBundle(fmt.Sprintf("owned CRD %q not found in bundle %q", crdName, bundle.Name), crdName))
53+
// Validate all owned keys, and remove them from the set if seen.
54+
for _, ownedKey := range ownedKeys {
55+
if _, ok := keySet[*ownedKey]; !ok {
56+
result.Add(errors.ErrInvalidBundle(fmt.Sprintf("owned CRD %s not found in bundle %q", keyToString(*ownedKey), bundle.Name), *ownedKey))
6657
} else {
67-
delete(crdNames, crdName)
58+
delete(keySet, *ownedKey)
6859
}
6960
}
7061
// CRDs not defined in the CSV present in the bundle
71-
for crdName := range crdNames {
72-
result.Add(errors.WarnInvalidBundle(fmt.Sprintf("owned CRD %q is present in bundle %q but not defined in CSV", crdName, bundle.Name), crdName))
62+
for key := range keySet {
63+
result.Add(errors.WarnInvalidBundle(fmt.Sprintf("CRD %s is present in bundle %q but not defined in CSV", keyToString(key), bundle.Name), key))
7364
}
7465
return result
7566
}
7667

77-
func getOwnedCustomResourceDefintionNames(csv *operatorsv1alpha1.ClusterServiceVersion) (names []string) {
78-
for _, ownedCrd := range csv.Spec.CustomResourceDefinitions.Owned {
79-
names = append(names, ownedCrd.Name)
80-
}
81-
return names
82-
}
83-
84-
func getBundleCRDNames(bundle *registry.Bundle) (map[string]struct{}, errors.Error) {
68+
func getBundleCRDKeys(bundle *registry.Bundle) (map[registry.DefinitionKey]struct{}, errors.Error) {
8569
crds, err := bundle.CustomResourceDefinitions()
8670
if err != nil {
8771
return nil, errors.ErrInvalidParse("error getting bundle CRDs", err)
8872
}
89-
crdNames := map[string]struct{}{}
73+
keySet := map[registry.DefinitionKey]struct{}{}
9074
for _, crd := range crds {
91-
crdNames[crd.GetName()] = struct{}{}
75+
if len(crd.Spec.Versions) == 0 {
76+
// Skip group, which CSVs do not support.
77+
key := registry.DefinitionKey{
78+
Name: crd.GetName(),
79+
Version: crd.Spec.Version,
80+
Kind: crd.Spec.Names.Kind,
81+
}
82+
keySet[key] = struct{}{}
83+
} else {
84+
for _, version := range crd.Spec.Versions {
85+
// Skip group, which CSVs do not support.
86+
key := registry.DefinitionKey{
87+
Name: crd.GetName(),
88+
Version: version.Name,
89+
Kind: crd.Spec.Names.Kind,
90+
}
91+
keySet[key] = struct{}{}
92+
}
93+
}
94+
}
95+
return keySet, errors.Error{}
96+
}
97+
98+
func keyToString(key registry.DefinitionKey) string {
99+
if key.Name == "" {
100+
return fmt.Sprintf("%s/%s %s", key.Group, key.Version, key.Kind)
92101
}
93-
return crdNames, errors.Error{}
102+
return fmt.Sprintf("%s/%s", key.Name, key.Version)
94103
}

‎pkg/validation/internal/bundle_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ func TestValidateBundle(t *testing.T) {
2626
hasError: false,
2727
},
2828
{
29-
description: "registryv1 bundle/valid bundle",
29+
description: "registryv1 bundle/invalid bundle",
3030
directory: "./testdata/invalid_bundle",
3131
hasError: true,
32-
errString: `owned CRD "etcdclusters.etcd.database.coreos.com" not found in bundle`,
32+
errString: "owned CRD etcdclusters.etcd.database.coreos.com/v1beta2 not found in bundle",
3333
},
3434
{
35-
description: "registryv1 bundle/valid bundle",
35+
description: "registryv1 bundle/invalid bundle 2",
3636
directory: "./testdata/invalid_bundle_2",
3737
hasError: true,
38-
errString: `owned CRD "etcdclusters.etcd.database.coreos.com" is present in bundle "test" but not defined in CSV`,
38+
errString: `CRD etcdclusters.etcd.database.coreos.com/v1beta2 is present in bundle "test" but not defined in CSV`,
3939
},
4040
}
4141

@@ -64,7 +64,7 @@ func TestValidateBundle(t *testing.T) {
6464
results := BundleValidator.Validate(bundle)
6565

6666
if len(results) > 0 {
67-
require.Equal(t, results[0].HasError(), tt.hasError)
67+
require.Equal(t, tt.hasError, results[0].HasError(), "%s: %s", tt.description, results[0])
6868
if results[0].HasError() {
6969
require.Contains(t, results[0].Errors[0].Error(), tt.errString)
7070
}

‎pkg/validation/internal/csv.go

+13
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"
@@ -186,3 +187,15 @@ func validateInstallModes(csv *v1alpha1.ClusterServiceVersion) (errs []errors.Er
186187
}
187188
return errs
188189
}
190+
191+
func bundleCSVToCSV(bcsv *registry.ClusterServiceVersion) (*v1alpha1.ClusterServiceVersion, errors.Error) {
192+
spec := v1alpha1.ClusterServiceVersionSpec{}
193+
if err := json.Unmarshal(bcsv.Spec, &spec); err != nil {
194+
return nil, errors.ErrInvalidParse(fmt.Sprintf("converting bundle CSV %q", bcsv.GetName()), err)
195+
}
196+
return &v1alpha1.ClusterServiceVersion{
197+
TypeMeta: bcsv.TypeMeta,
198+
ObjectMeta: bcsv.ObjectMeta,
199+
Spec: spec,
200+
}, errors.Error{}
201+
}

0 commit comments

Comments
 (0)
Please sign in to comment.