@@ -6,9 +6,12 @@ import (
66 "fmt"
77 "io"
88 "io/ioutil"
9+ "math/rand"
910 "os"
1011 "path"
1112 "path/filepath"
13+ "strconv"
14+ "sync"
1215
1316 "github.com/sirupsen/logrus"
1417 "gopkg.in/yaml.v2"
@@ -26,12 +29,13 @@ import (
2629)
2730
2831const (
29- defaultDockerfileName = "index.Dockerfile"
30- defaultImageTag = "operator-registry-index:latest"
31- defaultDatabaseFolder = "database"
32- defaultDatabaseFile = "index.db"
33- tmpDirPrefix = "index_tmp_"
34- tmpBuildDirPrefix = "index_build_tmp"
32+ defaultDockerfileName = "index.Dockerfile"
33+ defaultImageTag = "operator-registry-index:latest"
34+ defaultDatabaseFolder = "database"
35+ defaultDatabaseFile = "index.db"
36+ tmpDirPrefix = "index_tmp_"
37+ tmpBuildDirPrefix = "index_build_tmp"
38+ concurrencyLimitForExport = 10
3539)
3640
3741// ImageIndexer is a struct implementation of the Indexer interface
@@ -467,7 +471,7 @@ func write(dockerfileText, outDockerfile string, logger *logrus.Entry) error {
467471// ExportFromIndexRequest defines the parameters to send to the ExportFromIndex API
468472type ExportFromIndexRequest struct {
469473 Index string
470- Package string
474+ Packages [] string
471475 DownloadPath string
472476 ContainerTool containertools.ContainerTool
473477 CaFile string
@@ -497,14 +501,20 @@ func (i ImageIndexer) ExportFromIndex(request ExportFromIndexRequest) error {
497501 defer db .Close ()
498502
499503 dbQuerier := sqlite .NewSQLLiteQuerierFromDb (db )
500- if err != nil {
501- return err
504+
505+ // fetch all packages from the index image if packages is empty
506+ if len (request .Packages ) == 0 {
507+ request .Packages , err = dbQuerier .ListPackages (context .TODO ())
508+ if err != nil {
509+ return err
510+ }
502511 }
503512
504- bundles , err := getBundlesToExport (dbQuerier , request .Package )
513+ bundles , err := getBundlesToExport (dbQuerier , request .Packages )
505514 if err != nil {
506515 return err
507516 }
517+
508518 i .Logger .Infof ("Preparing to pull bundles %+q" , bundles )
509519
510520 // Creating downloadPath dir
@@ -513,40 +523,68 @@ func (i ImageIndexer) ExportFromIndex(request ExportFromIndexRequest) error {
513523 }
514524
515525 var errs []error
516- for _ , bundleImage := range bundles {
517- // try to name the folder
518- folderName , err := dbQuerier .GetBundleVersion (context .TODO (), bundleImage )
519- if err != nil {
520- return err
521- }
522- if folderName == "" {
523- // operator-registry does not care about the folder name
524- folderName = bundleImage
525- }
526- exporter := bundle .NewExporterForBundle (bundleImage , filepath .Join (request .DownloadPath , folderName ), request .ContainerTool )
527- if err := exporter .Export (); err != nil {
528- err = fmt .Errorf ("error exporting bundle from image: %s" , err )
529- errs = append (errs , err )
530- }
531- }
532- if err != nil {
533- errs = append (errs , err )
526+ var wg sync.WaitGroup
527+ wg .Add (len (bundles ))
528+ var mu = & sync.Mutex {}
529+
530+ sem := make (chan struct {}, concurrencyLimitForExport )
531+
532+ for bundleImage , bundleDir := range bundles {
533+ go func (bundleImage string , bundleDir bundleDirPrefix ) {
534+ defer wg .Done ()
535+
536+ sem <- struct {}{}
537+ defer func () {
538+ <- sem
539+ }()
540+
541+ // generate a random folder name if bundle version is empty
542+ if bundleDir .bundleVersion == "" {
543+ bundleDir .bundleVersion = strconv .Itoa (rand .Intn (10000 ))
544+ }
545+ exporter := bundle .NewExporterForBundle (bundleImage , filepath .Join (request .DownloadPath , bundleDir .pkgName , bundleDir .bundleVersion ), request .ContainerTool )
546+ if err := exporter .Export (); err != nil {
547+ err = fmt .Errorf ("exporting bundle image:%s failed with %s" , bundleImage , err )
548+ mu .Lock ()
549+ errs = append (errs , err )
550+ mu .Unlock ()
551+ }
552+ }(bundleImage , bundleDir )
553+ }
554+ // Wait for all the go routines to finish export
555+ wg .Wait ()
556+
557+ if errs != nil {
534558 return utilerrors .NewAggregate (errs )
535559 }
536560
537- err = generatePackageYaml (dbQuerier , request .Package , request .DownloadPath )
538- if err != nil {
539- errs = append (errs , err )
561+ for _ , packageName := range request .Packages {
562+ err := generatePackageYaml (dbQuerier , packageName , filepath .Join (request .DownloadPath , packageName ))
563+ if err != nil {
564+ errs = append (errs , err )
565+ }
540566 }
541567 return utilerrors .NewAggregate (errs )
542568}
543569
544- func getBundlesToExport (dbQuerier pregistry.Query , packageName string ) ([]string , error ) {
545- bundles , err := dbQuerier .GetBundlePathsForPackage (context .TODO (), packageName )
546- if err != nil {
547- return nil , err
570+ type bundleDirPrefix struct {
571+ pkgName , bundleVersion string
572+ }
573+
574+ func getBundlesToExport (dbQuerier pregistry.Query , packages []string ) (map [string ]bundleDirPrefix , error ) {
575+ bundleMap := make (map [string ]bundleDirPrefix )
576+
577+ for _ , packageName := range packages {
578+ bundlesForPackage , err := dbQuerier .GetBundlesForPackage (context .TODO (), packageName )
579+ if err != nil {
580+ return nil , err
581+ }
582+ for k , _ := range bundlesForPackage {
583+ bundleMap [k .BundlePath ] = bundleDirPrefix {pkgName : packageName , bundleVersion : k .Version }
584+ }
548585 }
549- return bundles , nil
586+
587+ return bundleMap , nil
550588}
551589
552590func generatePackageYaml (dbQuerier pregistry.Query , packageName , downloadPath string ) error {
0 commit comments