@@ -31,10 +31,11 @@ type AddToRegistryRequest struct {
3131 Bundles []string
3232 Mode registry.Mode
3333 ContainerTool containertools.ContainerTool
34+ Overwrite bool
3435}
3536
3637func (r RegistryUpdater ) AddToRegistry (request AddToRegistryRequest ) error {
37- db , err := sql .Open ("sqlite3" , request .InputDatabase )
38+ db , err := sql .Open ("sqlite3" , "file:" + request .InputDatabase + "?_foreign_keys=on" )
3839 if err != nil {
3940 return err
4041 }
@@ -84,51 +85,115 @@ func (r RegistryUpdater) AddToRegistry(request AddToRegistryRequest) error {
8485 simpleRefs = append (simpleRefs , image .SimpleReference (ref ))
8586 }
8687
87- if err := populate (context .TODO (), dbLoader , graphLoader , dbQuerier , reg , simpleRefs , request .Mode ); err != nil {
88+ if err := populate (context .TODO (), dbLoader , graphLoader , dbQuerier , reg , simpleRefs , request .Mode , request . Overwrite ); err != nil {
8889 r .Logger .Debugf ("unable to populate database: %s" , err )
8990
9091 if ! request .Permissive {
9192 r .Logger .WithError (err ).Error ("permissive mode disabled" )
9293 return err
93- } else {
94- r .Logger .WithError (err ).Warn ("permissive mode enabled" )
9594 }
95+ r .Logger .WithError (err ).Warn ("permissive mode enabled" )
9696 }
9797
9898 return nil
9999}
100100
101- func populate (ctx context.Context , loader registry. Load , graphLoader registry. GraphLoader , querier registry. Query , reg image.Registry , refs [] image.Reference , mode registry. Mode ) error {
101+ func unpackImage (ctx context.Context , reg image.Registry , ref image.Reference ) (image. Reference , string , func (), error ) {
102102 var errs []error
103+ workingDir , err := ioutil .TempDir ("./" , "bundle_tmp" )
104+ if err != nil {
105+ errs = append (errs , err )
106+ }
103107
104- unpackedImageMap := make (map [image.Reference ]string , 0 )
105- for _ , ref := range refs {
106- workingDir , err := ioutil .TempDir ("./" , "bundle_tmp" )
107- if err != nil {
108- errs = append (errs , err )
109- continue
110- }
111- defer os .RemoveAll (workingDir )
108+ if err = reg .Pull (ctx , ref ); err != nil {
109+ errs = append (errs , err )
110+ }
112111
113- if err = reg .Pull (ctx , ref ); err != nil {
114- errs = append (errs , err )
115- continue
116- }
112+ if err = reg .Unpack (ctx , ref , workingDir ); err != nil {
113+ errs = append (errs , err )
114+ }
117115
118- if err = reg . Unpack ( ctx , ref , workingDir ); err != nil {
119- errs = append ( errs , err )
120- continue
116+ cleanup := func () {
117+ if err := os . RemoveAll ( workingDir ); err != nil {
118+ logrus . Error ( err )
121119 }
122-
123- unpackedImageMap [ref ] = workingDir
124120 }
125121
126122 if len (errs ) > 0 {
127- return utilerrors .NewAggregate (errs )
123+ return nil , "" , cleanup , utilerrors .NewAggregate (errs )
124+ }
125+ return ref , workingDir , cleanup , nil
126+ }
127+
128+ func populate (ctx context.Context , loader registry.Load , graphLoader registry.GraphLoader , querier registry.Query , reg image.Registry , refs []image.Reference , mode registry.Mode , overwrite bool ) error {
129+ unpackedImageMap := make (map [image.Reference ]string , 0 )
130+ for _ , ref := range refs {
131+ to , from , cleanup , err := unpackImage (ctx , reg , ref )
132+ if err != nil {
133+ return err
134+ }
135+ unpackedImageMap [to ] = from
136+ defer cleanup ()
128137 }
129138
130- populator := registry .NewDirectoryPopulator (loader , graphLoader , querier , unpackedImageMap )
139+ overwriteImageMap := make (map [string ]map [image.Reference ]string , 0 )
140+ if overwrite {
141+ // find all bundles that are attempting to overwrite
142+ for to , from := range unpackedImageMap {
143+ img , err := registry .NewImageInput (to , from )
144+ if err != nil {
145+ return err
146+ }
147+ overwritten , err := querier .GetBundlePathIfExists (ctx , img .Bundle .Name )
148+ if err != nil {
149+ if err == registry .ErrBundleImageNotInDatabase {
150+ continue
151+ }
152+ return err
153+ }
154+ if overwritten != "" {
155+ // get all bundle paths for that package - we will re-add these to regenerate the graph
156+ bundles , err := querier .GetBundlesForPackage (ctx , img .Bundle .Package )
157+ if err != nil {
158+ return err
159+ }
160+ cleanups := make (chan func (), 1 )
161+ errs := make (chan error , 1 )
162+ for bundle := range bundles {
163+ if _ , ok := overwriteImageMap [img .Bundle .Package ]; ! ok {
164+ overwriteImageMap [img .Bundle .Package ] = make (map [image.Reference ]string , 0 )
165+ }
166+ // parallelize image pulls
167+ go func (bundle registry.BundleKey , img * registry.ImageInput ) {
168+ if bundle .CsvName != img .Bundle .Name {
169+ to , from , cleanup , err := unpackImage (ctx , reg , image .SimpleReference (bundle .BundlePath ))
170+ if err != nil {
171+ errs <- err
172+ }
173+ cleanups <- cleanup
174+ overwriteImageMap [img .Bundle .Package ][to ] = from
175+ } else {
176+ overwriteImageMap [img .Bundle .Package ][to ] = from
177+ delete (unpackedImageMap , to )
178+ }
179+ }(bundle , img )
180+ }
181+ for i := 0 ; i < len (bundles )- 1 ; i ++ {
182+ select {
183+ case err := <- errs :
184+ return err
185+ default :
186+ cleanup := <- cleanups
187+ defer cleanup ()
188+ }
189+ }
190+ } else {
191+ return fmt .Errorf ("index add --overwrite-latest is only supported when using bundle images" )
192+ }
193+ }
194+ }
131195
196+ populator := registry .NewDirectoryPopulator (loader , graphLoader , querier , unpackedImageMap , overwriteImageMap , overwrite )
132197 return populator .Populate (mode )
133198}
134199
0 commit comments