@@ -12,6 +12,7 @@ import (
12
12
"sort"
13
13
"strings"
14
14
"sync"
15
+ "text/template"
15
16
16
17
"github.com/h2non/filetype"
17
18
"github.com/h2non/filetype/matchers"
@@ -39,6 +40,7 @@ const (
39
40
RefSqliteFile
40
41
RefDCImage
41
42
RefDCDir
43
+ RefBundleDir
42
44
43
45
RefAll = 0
44
46
)
@@ -50,10 +52,11 @@ func (r RefType) Allowed(refType RefType) bool {
50
52
var ErrNotAllowed = errors .New ("not allowed" )
51
53
52
54
type Render struct {
53
- Refs []string
54
- Registry image.Registry
55
- AllowedRefMask RefType
56
- Migrate bool
55
+ Refs []string
56
+ Registry image.Registry
57
+ AllowedRefMask RefType
58
+ Migrate bool
59
+ ImageRefTemplate * template.Template
57
60
58
61
skipSqliteDeprecationLog bool
59
62
}
@@ -125,25 +128,44 @@ func (r Render) createRegistry() (*containerdregistry.Registry, error) {
125
128
}
126
129
127
130
func (r Render ) renderReference (ctx context.Context , ref string ) (* declcfg.DeclarativeConfig , error ) {
128
- if stat , serr := os .Stat (ref ); serr == nil {
129
- if stat .IsDir () {
130
- if ! r .AllowedRefMask .Allowed (RefDCDir ) {
131
- return nil , fmt .Errorf ("cannot render declarative config directory: %w" , ErrNotAllowed )
132
- }
133
- return declcfg .LoadFS (ctx , os .DirFS (ref ))
134
- } else {
135
- // The only supported file type is an sqlite DB file,
136
- // since declarative configs will be in a directory.
137
- if err := checkDBFile (ref ); err != nil {
138
- return nil , err
139
- }
140
- if ! r .AllowedRefMask .Allowed (RefSqliteFile ) {
141
- return nil , fmt .Errorf ("cannot render sqlite file: %w" , ErrNotAllowed )
131
+ stat , err := os .Stat (ref )
132
+ if err != nil {
133
+ return r .imageToDeclcfg (ctx , ref )
134
+ }
135
+ if stat .IsDir () {
136
+ dirEntries , err := os .ReadDir (ref )
137
+ if err != nil {
138
+ return nil , err
139
+ }
140
+ if isBundle (dirEntries ) {
141
+ // Looks like a bundle directory
142
+ if ! r .AllowedRefMask .Allowed (RefBundleDir ) {
143
+ return nil , fmt .Errorf ("cannot render bundle directory %q: %w" , ref , ErrNotAllowed )
142
144
}
143
- return sqliteToDeclcfg ( ctx , ref )
145
+ return r . renderBundleDirectory ( ref )
144
146
}
147
+
148
+ // Otherwise, assume it is a declarative config root directory.
149
+ if ! r .AllowedRefMask .Allowed (RefDCDir ) {
150
+ return nil , fmt .Errorf ("cannot render declarative config directory: %w" , ErrNotAllowed )
151
+ }
152
+ return declcfg .LoadFS (ctx , os .DirFS (ref ))
153
+ }
154
+ // The only supported file type is an sqlite DB file,
155
+ // since declarative configs will be in a directory.
156
+ if err := checkDBFile (ref ); err != nil {
157
+ return nil , err
158
+ }
159
+ if ! r .AllowedRefMask .Allowed (RefSqliteFile ) {
160
+ return nil , fmt .Errorf ("cannot render sqlite file: %w" , ErrNotAllowed )
161
+ }
162
+
163
+ db , err := sqlite .Open (ref )
164
+ if err != nil {
165
+ return nil , err
145
166
}
146
- return r .imageToDeclcfg (ctx , ref )
167
+ defer db .Close ()
168
+ return sqliteToDeclcfg (ctx , db )
147
169
}
148
170
149
171
func (r Render ) imageToDeclcfg (ctx context.Context , imageRef string ) (* declcfg.DeclarativeConfig , error ) {
@@ -169,7 +191,12 @@ func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.D
169
191
if ! r .AllowedRefMask .Allowed (RefSqliteImage ) {
170
192
return nil , fmt .Errorf ("cannot render sqlite image: %w" , ErrNotAllowed )
171
193
}
172
- cfg , err = sqliteToDeclcfg (ctx , filepath .Join (tmpDir , dbFile ))
194
+ db , err := sqlite .Open (filepath .Join (tmpDir , dbFile ))
195
+ if err != nil {
196
+ return nil , err
197
+ }
198
+ defer db .Close ()
199
+ cfg , err = sqliteToDeclcfg (ctx , db )
173
200
if err != nil {
174
201
return nil , err
175
202
}
@@ -190,10 +217,11 @@ func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.D
190
217
return nil , err
191
218
}
192
219
193
- cfg , err = bundleToDeclcfg (img .Bundle )
220
+ bundle , err : = bundleToDeclcfg (img .Bundle )
194
221
if err != nil {
195
222
return nil , err
196
223
}
224
+ cfg = & declcfg.DeclarativeConfig {Bundles : []declcfg.Bundle {* bundle }}
197
225
} else {
198
226
labelKeys := sets .StringKeySet (labels )
199
227
labelVals := []string {}
@@ -221,17 +249,11 @@ func checkDBFile(ref string) error {
221
249
return nil
222
250
}
223
251
224
- func sqliteToDeclcfg (ctx context.Context , dbFile string ) (* declcfg.DeclarativeConfig , error ) {
252
+ func sqliteToDeclcfg (ctx context.Context , db * sql. DB ) (* declcfg.DeclarativeConfig , error ) {
225
253
logDeprecationMessage .Do (func () {
226
254
sqlite .LogSqliteDeprecation ()
227
255
})
228
256
229
- db , err := sqlite .Open (dbFile )
230
- if err != nil {
231
- return nil , err
232
- }
233
- defer db .Close ()
234
-
235
257
migrator , err := sqlite .NewSQLLiteMigrator (db )
236
258
if err != nil {
237
259
return nil , err
@@ -303,7 +325,7 @@ func populateDBRelatedImages(ctx context.Context, cfg *declcfg.DeclarativeConfig
303
325
return nil
304
326
}
305
327
306
- func bundleToDeclcfg (bundle * registry.Bundle ) (* declcfg.DeclarativeConfig , error ) {
328
+ func bundleToDeclcfg (bundle * registry.Bundle ) (* declcfg.Bundle , error ) {
307
329
objs , props , err := registry .ObjectsAndPropertiesFromBundle (bundle )
308
330
if err != nil {
309
331
return nil , fmt .Errorf ("get properties for bundle %q: %v" , bundle .Name , err )
@@ -323,7 +345,7 @@ func bundleToDeclcfg(bundle *registry.Bundle) (*declcfg.DeclarativeConfig, error
323
345
}
324
346
}
325
347
326
- dBundle := declcfg.Bundle {
348
+ return & declcfg.Bundle {
327
349
Schema : "olm.bundle" ,
328
350
Name : bundle .Name ,
329
351
Package : bundle .Package ,
@@ -332,9 +354,7 @@ func bundleToDeclcfg(bundle *registry.Bundle) (*declcfg.DeclarativeConfig, error
332
354
RelatedImages : relatedImages ,
333
355
Objects : objs ,
334
356
CsvJSON : string (csvJson ),
335
- }
336
-
337
- return & declcfg.DeclarativeConfig {Bundles : []declcfg.Bundle {dBundle }}, nil
357
+ }, nil
338
358
}
339
359
340
360
func getRelatedImages (b * registry.Bundle ) ([]declcfg.RelatedImage , error ) {
@@ -363,7 +383,7 @@ func getRelatedImages(b *registry.Bundle) ([]declcfg.RelatedImage, error) {
363
383
allImages = allImages .Insert (ri .Image )
364
384
}
365
385
366
- if ! allImages .Has (b .BundleImage ) {
386
+ if b . BundleImage != "" && ! allImages .Has (b .BundleImage ) {
367
387
relatedImages = append (relatedImages , declcfg.RelatedImage {
368
388
Image : b .BundleImage ,
369
389
})
@@ -454,3 +474,72 @@ func combineConfigs(cfgs []declcfg.DeclarativeConfig) *declcfg.DeclarativeConfig
454
474
}
455
475
return out
456
476
}
477
+
478
+ func isBundle (entries []os.DirEntry ) bool {
479
+ foundManifests := false
480
+ foundMetadata := false
481
+ for _ , e := range entries {
482
+ if e .IsDir () {
483
+ switch e .Name () {
484
+ case "manifests" :
485
+ foundManifests = true
486
+ case "metadata" :
487
+ foundMetadata = true
488
+ }
489
+ }
490
+ if foundMetadata && foundManifests {
491
+ return true
492
+ }
493
+ }
494
+ return false
495
+ }
496
+
497
+ type imageReferenceTemplateData struct {
498
+ Package string
499
+ Name string
500
+ Version string
501
+ }
502
+
503
+ func (r * Render ) renderBundleDirectory (ref string ) (* declcfg.DeclarativeConfig , error ) {
504
+ img , err := registry .NewImageInput (image .SimpleReference ("" ), ref )
505
+ if err != nil {
506
+ return nil , err
507
+ }
508
+ if err := r .templateBundleImageRef (img .Bundle ); err != nil {
509
+ return nil , fmt .Errorf ("failed templating image reference from bundle for %q: %v" , ref , err )
510
+ }
511
+ fbcBundle , err := bundleToDeclcfg (img .Bundle )
512
+ if err != nil {
513
+ return nil , err
514
+ }
515
+ return & declcfg.DeclarativeConfig {Bundles : []declcfg.Bundle {* fbcBundle }}, nil
516
+ }
517
+
518
+ func (r * Render ) templateBundleImageRef (bundle * registry.Bundle ) error {
519
+ if r .ImageRefTemplate == nil {
520
+ return nil
521
+ }
522
+
523
+ var pkgProp property.Package
524
+ for _ , p := range bundle .Properties {
525
+ if p .Type != property .TypePackage {
526
+ continue
527
+ }
528
+ if err := json .Unmarshal (p .Value , & pkgProp ); err != nil {
529
+ return err
530
+ }
531
+ break
532
+ }
533
+
534
+ var buf strings.Builder
535
+ tmplInput := imageReferenceTemplateData {
536
+ Package : bundle .Package ,
537
+ Name : bundle .Name ,
538
+ Version : pkgProp .Version ,
539
+ }
540
+ if err := r .ImageRefTemplate .Execute (& buf , tmplInput ); err != nil {
541
+ return err
542
+ }
543
+ bundle .BundleImage = buf .String ()
544
+ return nil
545
+ }
0 commit comments