@@ -16,9 +16,11 @@ package catalog
16
16
17
17
import (
18
18
"fmt"
19
+ "io/ioutil"
19
20
"os"
20
21
"path/filepath"
21
22
"regexp"
23
+ "sort"
22
24
"strings"
23
25
"sync"
24
26
@@ -34,6 +36,8 @@ import (
34
36
"github.com/pkg/errors"
35
37
log "github.com/sirupsen/logrus"
36
38
"github.com/spf13/afero"
39
+ apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
40
+ "k8s.io/apimachinery/pkg/runtime/schema"
37
41
)
38
42
39
43
const (
@@ -121,7 +125,7 @@ func (s *CSV) CustomRender() ([]byte, error) {
121
125
if err = s .updateCSVVersions (csv ); err != nil {
122
126
return nil , err
123
127
}
124
- if err = s .updateCSVFromManifestFiles (cfg , csv ); err != nil {
128
+ if err = s .updateCSVFromManifests (cfg , csv ); err != nil {
125
129
return nil , err
126
130
}
127
131
s .setCSVDefaultFields (csv )
@@ -322,50 +326,90 @@ func (s *CSV) updateCSVVersions(csv *olmapiv1alpha1.ClusterServiceVersion) error
322
326
323
327
// updateCSVFromManifestFiles gathers relevant data from generated and
324
328
// user-defined manifests and updates csv.
325
- func (s * CSV ) updateCSVFromManifestFiles (cfg * CSVConfig , csv * olmapiv1alpha1.ClusterServiceVersion ) error {
326
- store := NewUpdaterStore ()
327
- otherSpecs := make (map [string ][][]byte )
329
+ func (g * CSV ) updateCSVFromManifests (cfg * CSVConfig , csv * olmapiv1alpha1.ClusterServiceVersion ) (err error ) {
328
330
paths := append (cfg .CRDCRPaths , cfg .OperatorPath )
329
331
paths = append (paths , cfg .RolePaths ... )
330
- for _ , f := range paths {
331
- yamlData , err := afero .ReadFile (s .getFS (), f )
332
+ manifestGVKMap := map [schema.GroupVersionKind ][][]byte {}
333
+ crGVKSet := map [schema.GroupVersionKind ]struct {}{}
334
+ for _ , path := range paths {
335
+ info , err := g .getFS ().Stat (path )
332
336
if err != nil {
333
337
return err
334
338
}
335
-
336
- scanner := yamlutil .NewYAMLScanner (yamlData )
339
+ if info .IsDir () {
340
+ continue
341
+ }
342
+ b , err := ioutil .ReadFile (path )
343
+ if err != nil {
344
+ return err
345
+ }
346
+ scanner := yamlutil .NewYAMLScanner (b )
337
347
for scanner .Scan () {
338
- yamlSpec := scanner .Bytes ()
339
- typeMeta , err := k8sutil .GetTypeMetaFromBytes (yamlSpec )
348
+ manifest := scanner .Bytes ()
349
+ typeMeta , err := k8sutil .GetTypeMetaFromBytes (manifest )
340
350
if err != nil {
341
- return errors .Wrapf (err , "error getting type metadata from manifest %s" , f )
351
+ log .Infof ("No TypeMeta in %s, skipping file" , path )
352
+ continue
342
353
}
343
- found , err := store .AddToUpdater (yamlSpec , typeMeta .Kind )
344
- if err != nil {
345
- return errors .Wrapf (err , "error adding manifest %s to CSV updaters" , f )
346
- }
347
- if ! found {
348
- id := gvkID (typeMeta .GroupVersionKind ())
349
- if _ , ok := otherSpecs [id ]; ! ok {
350
- otherSpecs [id ] = make ([][]byte , 0 )
354
+ gvk := typeMeta .GroupVersionKind ()
355
+ manifestGVKMap [gvk ] = append (manifestGVKMap [gvk ], manifest )
356
+ switch typeMeta .Kind {
357
+ case "CustomResourceDefinition" :
358
+ // Collect CRD kinds to filter them out from unsupported manifest types.
359
+ // The CRD type version doesn't matter as long as it has a group, kind,
360
+ // and versions in the expected fields.
361
+ crd := apiextv1beta1.CustomResourceDefinition {}
362
+ if err = yaml .Unmarshal (manifest , & crd ); err != nil {
363
+ return err
364
+ }
365
+ for _ , ver := range crd .Spec .Versions {
366
+ crGVK := schema.GroupVersionKind {
367
+ Group : crd .Spec .Group ,
368
+ Version : ver .Name ,
369
+ Kind : crd .Spec .Names .Kind ,
370
+ }
371
+ crGVKSet [crGVK ] = struct {}{}
351
372
}
352
- otherSpecs [id ] = append (otherSpecs [id ], yamlSpec )
353
373
}
354
374
}
355
375
if err = scanner .Err (); err != nil {
356
376
return err
357
377
}
358
378
}
359
379
360
- for id := range store .crds .crIDs {
361
- if crSpecs , ok := otherSpecs [id ]; ok {
362
- for _ , spec := range crSpecs {
363
- if err := store .AddCR (spec ); err != nil {
364
- return err
365
- }
380
+ crUpdaters := crs {}
381
+ for gvk , manifests := range manifestGVKMap {
382
+ // We don't necessarily care about sorting by a field value, more about
383
+ // consistent ordering.
384
+ sort .Slice (manifests , func (i int , j int ) bool {
385
+ return string (manifests [i ]) < string (manifests [j ])
386
+ })
387
+ switch gvk .Kind {
388
+ case "Role" :
389
+ err = roles (manifests ).apply (csv )
390
+ case "ClusterRole" :
391
+ err = clusterRoles (manifests ).apply (csv )
392
+ case "Deployment" :
393
+ err = deployments (manifests ).apply (csv )
394
+ case "CustomResourceDefinition" :
395
+ err = crds (manifests ).apply (csv )
396
+ default :
397
+ if _ , ok := crGVKSet [gvk ]; ok {
398
+ crUpdaters = append (crUpdaters , manifests ... )
399
+ } else {
400
+ log .Infof ("Skipping manifest %s" , gvk )
366
401
}
367
402
}
403
+ if err != nil {
404
+ return err
405
+ }
368
406
}
369
-
370
- return store .Apply (csv )
407
+ // Re-sort CR's since they are appended in random order.
408
+ sort .Slice (crUpdaters , func (i int , j int ) bool {
409
+ return string (crUpdaters [i ]) < string (crUpdaters [j ])
410
+ })
411
+ if err = crUpdaters .apply (csv ); err != nil {
412
+ return err
413
+ }
414
+ return nil
371
415
}
0 commit comments