@@ -13,6 +13,7 @@ import (
13
13
14
14
"github.com/h2non/filetype"
15
15
"github.com/h2non/filetype/matchers"
16
+ "github.com/operator-framework/api/pkg/operators/v1alpha1"
16
17
"github.com/sirupsen/logrus"
17
18
"k8s.io/apimachinery/pkg/util/sets"
18
19
@@ -30,10 +31,12 @@ type RefType uint
30
31
31
32
const (
32
33
RefBundleImage RefType = 1 << iota
34
+ RefBundleDir
33
35
RefSqliteImage
34
36
RefSqliteFile
35
37
RefDCImage
36
38
RefDCDir
39
+ RefPackageManifestDir
37
40
38
41
RefAll = 0
39
42
)
@@ -100,25 +103,48 @@ func (r Render) createRegistry() (*containerdregistry.Registry, error) {
100
103
}
101
104
102
105
func (r Render ) renderReference (ctx context.Context , ref string ) (* declcfg.DeclarativeConfig , error ) {
103
- if stat , serr := os .Stat (ref ); serr == nil {
104
- if stat .IsDir () {
105
- if ! r .AllowedRefMask .Allowed (RefDCDir ) {
106
- return nil , fmt .Errorf ("cannot render declarative config directory: %w" , ErrNotAllowed )
106
+ stat , err := os .Stat (ref )
107
+ if err != nil {
108
+ return r .imageToDeclcfg (ctx , ref )
109
+ }
110
+ if stat .IsDir () {
111
+ dirEntries , err := os .ReadDir (ref )
112
+ if err != nil {
113
+ return nil , err
114
+ }
115
+ if isBundle (dirEntries ) {
116
+ // Looks like a bundle directory
117
+ if ! r .AllowedRefMask .Allowed (RefBundleDir ) {
118
+ return nil , fmt .Errorf ("cannot render bundle directory: %w" , ErrNotAllowed )
107
119
}
108
- return declcfg .LoadFS (os .DirFS (ref ))
109
- } else {
110
- // The only supported file type is an sqlite DB file,
111
- // since declarative configs will be in a directory.
112
- if err := checkDBFile (ref ); err != nil {
120
+ img , err := registry .NewImageInput (image .SimpleReference ("" ), ref )
121
+ if err != nil {
113
122
return nil , err
114
123
}
115
- if ! r .AllowedRefMask .Allowed (RefSqliteFile ) {
116
- return nil , fmt .Errorf ("cannot render sqlite file: %w" , ErrNotAllowed )
124
+ return bundleToDeclcfg (img .Bundle , true )
125
+ } else if isPackageManifest (dirEntries ) {
126
+ // Looks like a package manifest directory
127
+ if ! r .AllowedRefMask .Allowed (RefPackageManifestDir ) {
128
+ return nil , fmt .Errorf ("cannot render package manifest directory: %w" , ErrNotAllowed )
117
129
}
118
- return sqliteToDeclcfg (ctx , ref )
130
+ return renderPackageManifest (ctx , ref )
119
131
}
132
+
133
+ // Otherwise, assume it is a declarative config root directory.
134
+ if ! r .AllowedRefMask .Allowed (RefDCDir ) {
135
+ return nil , fmt .Errorf ("cannot render declarative config directory: %w" , ErrNotAllowed )
136
+ }
137
+ return declcfg .LoadFS (os .DirFS (ref ))
138
+ }
139
+ // The only supported file type is an sqlite DB file,
140
+ // since declarative configs will be in a directory.
141
+ if err := checkDBFile (ref ); err != nil {
142
+ return nil , err
143
+ }
144
+ if ! r .AllowedRefMask .Allowed (RefSqliteFile ) {
145
+ return nil , fmt .Errorf ("cannot render sqlite file: %w" , ErrNotAllowed )
120
146
}
121
- return r . imageToDeclcfg (ctx , ref )
147
+ return sqliteToDeclcfg (ctx , ref )
122
148
}
123
149
124
150
func (r Render ) imageToDeclcfg (ctx context.Context , imageRef string ) (* declcfg.DeclarativeConfig , error ) {
@@ -165,7 +191,7 @@ func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.D
165
191
return nil , err
166
192
}
167
193
168
- cfg , err = bundleToDeclcfg (img .Bundle )
194
+ cfg , err = bundleToDeclcfg (img .Bundle , false )
169
195
if err != nil {
170
196
return nil , err
171
197
}
@@ -273,7 +299,7 @@ func populateDBRelatedImages(ctx context.Context, cfg *declcfg.DeclarativeConfig
273
299
return nil
274
300
}
275
301
276
- func bundleToDeclcfg (bundle * registry.Bundle ) (* declcfg.DeclarativeConfig , error ) {
302
+ func bundleToDeclcfg (bundle * registry.Bundle , inlineManifests bool ) (* declcfg.DeclarativeConfig , error ) {
277
303
bundleProperties , err := registry .PropertiesFromBundle (bundle )
278
304
if err != nil {
279
305
return nil , fmt .Errorf ("get properties for bundle %q: %v" , bundle .Name , err )
@@ -283,13 +309,33 @@ func bundleToDeclcfg(bundle *registry.Bundle) (*declcfg.DeclarativeConfig, error
283
309
return nil , fmt .Errorf ("get related images for bundle %q: %v" , bundle .Name , err )
284
310
}
285
311
312
+ var (
313
+ objs []string
314
+ csvJSON string
315
+ )
316
+ if inlineManifests {
317
+ for _ , obj := range bundle .Objects {
318
+ objJSON , err := json .Marshal (obj )
319
+ if err != nil {
320
+ return nil , fmt .Errorf ("marshal bundle object %q (kind: %q)" , obj .GetName (), obj .GetKind ())
321
+ }
322
+ bundleProperties = append (bundleProperties , property .MustBuildBundleObjectData (objJSON ))
323
+ objs = append (objs , string (objJSON ))
324
+ if obj .GetKind () == v1alpha1 .ClusterServiceVersionKind && csvJSON == "" {
325
+ csvJSON = string (objJSON )
326
+ }
327
+ }
328
+ }
329
+
286
330
dBundle := declcfg.Bundle {
287
331
Schema : "olm.bundle" ,
288
332
Name : bundle .Name ,
289
333
Package : bundle .Package ,
290
334
Image : bundle .BundleImage ,
291
335
Properties : bundleProperties ,
292
336
RelatedImages : relatedImages ,
337
+ Objects : objs ,
338
+ CsvJSON : csvJSON ,
293
339
}
294
340
295
341
return & declcfg.DeclarativeConfig {Bundles : []declcfg.Bundle {dBundle }}, nil
@@ -343,3 +389,63 @@ func combineConfigs(cfgs []declcfg.DeclarativeConfig) *declcfg.DeclarativeConfig
343
389
}
344
390
return out
345
391
}
392
+
393
+ func isBundle (entries []os.DirEntry ) bool {
394
+ foundManifests := false
395
+ foundMetadata := false
396
+ for _ , e := range entries {
397
+ if e .IsDir () {
398
+ switch e .Name () {
399
+ case "manifests" :
400
+ foundManifests = true
401
+ case "metadata" :
402
+ foundMetadata = true
403
+ }
404
+ }
405
+ if foundMetadata && foundManifests {
406
+ return true
407
+ }
408
+ }
409
+ return false
410
+ }
411
+
412
+ func isPackageManifest (entries []os.DirEntry ) bool {
413
+ for _ , e := range entries {
414
+ if strings .HasSuffix (e .Name (), ".package.yaml" ) || strings .HasSuffix (e .Name (), ".package.yml" ) {
415
+ return true
416
+ }
417
+ }
418
+ return false
419
+ }
420
+
421
+ func renderPackageManifest (ctx context.Context , ref string ) (* declcfg.DeclarativeConfig , error ) {
422
+ tmpDB , err := os .CreateTemp ("" , "opm-render-pm-" )
423
+ if err != nil {
424
+ return nil , err
425
+ }
426
+ if err := tmpDB .Close (); err != nil {
427
+ return nil , err
428
+ }
429
+
430
+ db , err := sqlite .Open (tmpDB .Name ())
431
+ if err != nil {
432
+ return nil , err
433
+ }
434
+ defer db .Close ()
435
+ defer os .RemoveAll (tmpDB .Name ())
436
+
437
+ dbLoader , err := sqlite .NewSQLLiteLoader (db )
438
+ if err != nil {
439
+ return nil , err
440
+ }
441
+ if err := dbLoader .Migrate (context .TODO ()); err != nil {
442
+ return nil , err
443
+ }
444
+
445
+ loader := sqlite .NewSQLLoaderForDirectory (dbLoader , ref )
446
+ if err := loader .Populate (); err != nil {
447
+ return nil , fmt .Errorf ("error loading manifests from directory: %s" , err )
448
+ }
449
+
450
+ return sqliteToDeclcfg (ctx , tmpDB .Name ())
451
+ }
0 commit comments