@@ -17,19 +17,20 @@ package catalog
17
17
import (
18
18
"bytes"
19
19
"encoding/json"
20
- "fmt"
21
20
"strings"
22
21
23
22
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
24
23
25
24
"github.com/ghodss/yaml"
26
25
olmapiv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
27
26
olminstall "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
27
+ "github.com/pkg/errors"
28
28
log "github.com/sirupsen/logrus"
29
29
appsv1 "k8s.io/api/apps/v1"
30
30
corev1 "k8s.io/api/core/v1"
31
31
rbacv1 "k8s.io/api/rbac/v1"
32
32
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
33
+ "k8s.io/apimachinery/pkg/runtime/schema"
33
34
)
34
35
35
36
// CSVUpdater is an interface for any data that can be in a CSV, which will be
@@ -207,7 +208,7 @@ func (u *InstallStrategyUpdate) Apply(csv *olmapiv1alpha1.ClusterServiceVersion)
207
208
u .updateClusterPermissions (s )
208
209
u .updateDeploymentSpecs (s )
209
210
default :
210
- return fmt .Errorf ("install strategy (%v) of unknown type" , strat )
211
+ return errors .Errorf ("install strategy (%v) of unknown type" , strat )
211
212
}
212
213
213
214
// Re-serialize permissions into csv strategy.
@@ -240,40 +241,82 @@ func (u *InstallStrategyUpdate) updateDeploymentSpecs(strat *olminstall.Strategy
240
241
241
242
type CustomResourceDefinitionsUpdate struct {
242
243
* olmapiv1alpha1.CustomResourceDefinitions
243
- crKinds map [string ]struct {}
244
+ crIDs map [string ]struct {}
244
245
}
245
246
246
247
func (store * updaterStore ) AddOwnedCRD (yamlDoc []byte ) error {
247
248
crd := & apiextv1beta1.CustomResourceDefinition {}
248
249
if err := yaml .Unmarshal (yamlDoc , crd ); err != nil {
249
250
return err
250
251
}
251
- store .crds .Owned = append (store .crds .Owned , olmapiv1alpha1.CRDDescription {
252
- Name : crd .ObjectMeta .Name ,
253
- Version : crd .Spec .Version ,
254
- Kind : crd .Spec .Names .Kind ,
255
- })
256
- store .crds .crKinds [crd .Spec .Names .Kind ] = struct {}{}
252
+ versions , err := getCRDVersions (crd )
253
+ if err != nil {
254
+ return errors .Wrapf (err , "failed to get owned CRD %s versions" , crd .GetName ())
255
+ }
256
+ for _ , ver := range versions {
257
+ kind := crd .Spec .Names .Kind
258
+ crdDesc := olmapiv1alpha1.CRDDescription {
259
+ Name : crd .ObjectMeta .Name ,
260
+ Version : ver ,
261
+ Kind : kind ,
262
+ }
263
+ store .crds .crIDs [crdDescID (crdDesc )] = struct {}{}
264
+ store .crds .Owned = append (store .crds .Owned , crdDesc )
265
+ }
257
266
return nil
258
267
}
259
268
269
+ func getCRDVersions (crd * apiextv1beta1.CustomResourceDefinition ) (versions []string , err error ) {
270
+ if len (crd .Spec .Versions ) != 0 {
271
+ for _ , ver := range crd .Spec .Versions {
272
+ // Only versions served by the API server are relevant to a CSV.
273
+ if ver .Served {
274
+ versions = append (versions , ver .Name )
275
+ }
276
+ }
277
+ } else if crd .Spec .Version != "" {
278
+ versions = append (versions , crd .Spec .Version )
279
+ }
280
+ if len (versions ) == 0 {
281
+ return nil , errors .Errorf ("no versions in CRD %s" , crd .GetName ())
282
+ }
283
+ return versions , nil
284
+ }
285
+
286
+ // crdDescID produces an opaque, unique string identifying a CRDDescription.
287
+ func crdDescID (desc olmapiv1alpha1.CRDDescription ) string {
288
+ // Name should always be <lower kind>.<group>, so this is effectively a GVK.
289
+ splitName := strings .Split (desc .Name , "." )
290
+ return getGVKID (strings .Join (splitName [1 :], "." ), desc .Version , desc .Kind )
291
+ }
292
+
293
+ // gvkID produces an opaque, unique string identifying a GVK.
294
+ func gvkID (gvk schema.GroupVersionKind ) string {
295
+ return getGVKID (gvk .Group , gvk .Version , gvk .Kind )
296
+ }
297
+
298
+ func getGVKID (g , v , k string ) string {
299
+ return g + v + k
300
+ }
301
+
260
302
// Apply updates csv's "owned" CRDDescriptions. "required" CRDDescriptions are
261
303
// left as-is, since they are user-defined values.
304
+ // Apply will only make a new spec.customresourcedefinitions.owned element if
305
+ // the CRD key is not in spec.customresourcedefinitions.owned already.
262
306
func (u * CustomResourceDefinitionsUpdate ) Apply (csv * olmapiv1alpha1.ClusterServiceVersion ) error {
263
307
set := make (map [string ]olmapiv1alpha1.CRDDescription )
264
- for _ , csvDesc := range csv . Spec . CustomResourceDefinitions .Owned {
265
- set [csvDesc . Name ] = csvDesc
308
+ for _ , uDesc := range u .Owned {
309
+ set [crdDescID ( uDesc ) ] = uDesc
266
310
}
267
- du := u .DeepCopy ()
268
- for i , uDesc := range u .Owned {
269
- if csvDesc , ok := set [uDesc .Name ]; ok {
270
- csvDesc .Name = uDesc .Name
271
- csvDesc .Version = uDesc .Version
272
- csvDesc .Kind = uDesc .Kind
273
- du .Owned [i ] = csvDesc
311
+ newDescs := []olmapiv1alpha1.CRDDescription {}
312
+ for _ , csvDesc := range csv .Spec .CustomResourceDefinitions .Owned {
313
+ if uDesc , ok := set [crdDescID (csvDesc )]; ! ok {
314
+ newDescs = append (newDescs , uDesc )
315
+ } else {
316
+ newDescs = append (newDescs , csvDesc )
274
317
}
275
318
}
276
- csv .Spec .CustomResourceDefinitions .Owned = du . Owned
319
+ csv .Spec .CustomResourceDefinitions .Owned = newDescs
277
320
return nil
278
321
}
279
322
0 commit comments