Skip to content

Commit

Permalink
render: support rendering DC from packagemanifest and bundle directories
Browse files Browse the repository at this point in the history
Signed-off-by: Joe Lanford <joe.lanford@gmail.com>
  • Loading branch information
joelanford committed Nov 1, 2021
1 parent 7c8187a commit 2f2e8c4
Show file tree
Hide file tree
Showing 7 changed files with 369 additions and 27 deletions.
125 changes: 103 additions & 22 deletions alpha/action/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ type RefType uint

const (
RefBundleImage RefType = 1 << iota
RefBundleDir
RefSqliteImage
RefSqliteFile
RefDCImage
RefDCDir
RefPackageManifestDir

RefAll = 0
)
Expand Down Expand Up @@ -117,25 +119,54 @@ func (r Render) createRegistry() (*containerdregistry.Registry, error) {
}

func (r Render) renderReference(ctx context.Context, ref string) (*declcfg.DeclarativeConfig, error) {
if stat, serr := os.Stat(ref); serr == nil {
if stat.IsDir() {
if !r.AllowedRefMask.Allowed(RefDCDir) {
return nil, fmt.Errorf("cannot render declarative config directory: %w", ErrNotAllowed)
stat, err := os.Stat(ref)
if err != nil {
return r.imageToDeclcfg(ctx, ref)
}
if stat.IsDir() {
dirEntries, err := os.ReadDir(ref)
if err != nil {
return nil, err
}
if isBundle(dirEntries) {
// Looks like a bundle directory
if !r.AllowedRefMask.Allowed(RefBundleDir) {
return nil, fmt.Errorf("cannot render bundle directory: %w", ErrNotAllowed)
}
return declcfg.LoadFS(os.DirFS(ref))
} else {
// The only supported file type is an sqlite DB file,
// since declarative configs will be in a directory.
if err := checkDBFile(ref); err != nil {
img, err := registry.NewImageInput(image.SimpleReference(""), ref)
if err != nil {
return nil, err
}
if !r.AllowedRefMask.Allowed(RefSqliteFile) {
return nil, fmt.Errorf("cannot render sqlite file: %w", ErrNotAllowed)
return bundleToDeclcfg(img.Bundle)
} else if isPackageManifest(dirEntries) {
// Looks like a package manifest directory
if !r.AllowedRefMask.Allowed(RefPackageManifestDir) {
return nil, fmt.Errorf("cannot render package manifest directory: %w", ErrNotAllowed)
}
return sqliteToDeclcfg(ctx, ref)
return renderPackageManifest(ctx, ref)
}

// Otherwise, assume it is a declarative config root directory.
if !r.AllowedRefMask.Allowed(RefDCDir) {
return nil, fmt.Errorf("cannot render declarative config directory: %w", ErrNotAllowed)
}
return declcfg.LoadFS(os.DirFS(ref))
}
// The only supported file type is an sqlite DB file,
// since declarative configs will be in a directory.
if err := checkDBFile(ref); err != nil {
return nil, err
}
if !r.AllowedRefMask.Allowed(RefSqliteFile) {
return nil, fmt.Errorf("cannot render sqlite file: %w", ErrNotAllowed)
}
return r.imageToDeclcfg(ctx, ref)

db, err := sqlite.Open(ref)
if err != nil {
return nil, err
}
defer db.Close()
return sqliteToDeclcfg(ctx, db)
}

func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.DeclarativeConfig, error) {
Expand All @@ -161,7 +192,12 @@ func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.D
if !r.AllowedRefMask.Allowed(RefSqliteImage) {
return nil, fmt.Errorf("cannot render sqlite image: %w", ErrNotAllowed)
}
cfg, err = sqliteToDeclcfg(ctx, filepath.Join(tmpDir, dbFile))
db, err := sqlite.Open(filepath.Join(tmpDir, dbFile))
if err != nil {
return nil, err
}
defer db.Close()
cfg, err = sqliteToDeclcfg(ctx, db)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -213,17 +249,11 @@ func checkDBFile(ref string) error {
return nil
}

func sqliteToDeclcfg(ctx context.Context, dbFile string) (*declcfg.DeclarativeConfig, error) {
func sqliteToDeclcfg(ctx context.Context, db *sql.DB) (*declcfg.DeclarativeConfig, error) {
logDeprecationMessage.Do(func() {
sqlite.LogSqliteDeprecation()
})

db, err := sqlite.Open(dbFile)
if err != nil {
return nil, err
}
defer db.Close()

migrator, err := sqlite.NewSQLLiteMigrator(db)
if err != nil {
return nil, err
Expand Down Expand Up @@ -354,7 +384,7 @@ func getRelatedImages(b *registry.Bundle) ([]declcfg.RelatedImage, error) {
allImages = allImages.Insert(ri.Image)
}

if !allImages.Has(b.BundleImage) {
if b.BundleImage != "" && !allImages.Has(b.BundleImage) {
relatedImages = append(relatedImages, declcfg.RelatedImage{
Image: b.BundleImage,
})
Expand Down Expand Up @@ -402,3 +432,54 @@ func combineConfigs(cfgs []declcfg.DeclarativeConfig) *declcfg.DeclarativeConfig
}
return out
}

func isBundle(entries []os.DirEntry) bool {
foundManifests := false
foundMetadata := false
for _, e := range entries {
if e.IsDir() {
switch e.Name() {
case "manifests":
foundManifests = true
case "metadata":
foundMetadata = true
}
}
if foundMetadata && foundManifests {
return true
}
}
return false
}

func isPackageManifest(entries []os.DirEntry) bool {
for _, e := range entries {
if strings.HasSuffix(e.Name(), ".package.yaml") || strings.HasSuffix(e.Name(), ".package.yml") {
return true
}
}
return false
}

func renderPackageManifest(ctx context.Context, ref string) (*declcfg.DeclarativeConfig, error) {
db, err := sql.Open("sqlite3", fmt.Sprintf("file:%s?mode=memory&cache=shared&_foreign_keys=on", ref))
if err != nil {
return nil, err
}
defer db.Close()

dbLoader, err := sqlite.NewSQLLiteLoader(db)
if err != nil {
return nil, err
}
if err := dbLoader.Migrate(ctx); err != nil {
return nil, err
}

loader := sqlite.NewSQLLoaderForDirectory(dbLoader, ref)
if err := loader.Populate(); err != nil {
return nil, fmt.Errorf("error loading manifests from directory: %s", err)
}

return sqliteToDeclcfg(ctx, db)
}
Loading

0 comments on commit 2f2e8c4

Please sign in to comment.