11package internal
22
33import (
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
2624func 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}
0 commit comments