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
  • Loading branch information
joelanford committed Aug 13, 2021
1 parent a4fd56c commit 1ab84df
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 20 deletions.
136 changes: 121 additions & 15 deletions internal/action/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/h2non/filetype"
"github.com/h2non/filetype/matchers"
"github.com/operator-framework/api/pkg/operators/v1alpha1"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/sets"

Expand All @@ -30,10 +31,12 @@ type RefType uint

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

RefAll = 0
)
Expand Down Expand Up @@ -100,25 +103,48 @@ 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, true)
} 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)
return sqliteToDeclcfg(ctx, ref)
}

func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.DeclarativeConfig, error) {
Expand Down Expand Up @@ -165,7 +191,7 @@ func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.D
return nil, err
}

cfg, err = bundleToDeclcfg(img.Bundle)
cfg, err = bundleToDeclcfg(img.Bundle, false)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -273,7 +299,7 @@ func populateDBRelatedImages(ctx context.Context, cfg *declcfg.DeclarativeConfig
return nil
}

func bundleToDeclcfg(bundle *registry.Bundle) (*declcfg.DeclarativeConfig, error) {
func bundleToDeclcfg(bundle *registry.Bundle, inlineManifests bool) (*declcfg.DeclarativeConfig, error) {
bundleProperties, err := registry.PropertiesFromBundle(bundle)
if err != nil {
return nil, fmt.Errorf("get properties for bundle %q: %v", bundle.Name, err)
Expand All @@ -283,13 +309,33 @@ func bundleToDeclcfg(bundle *registry.Bundle) (*declcfg.DeclarativeConfig, error
return nil, fmt.Errorf("get related images for bundle %q: %v", bundle.Name, err)
}

var (
objs []string
csvJSON string
)
if inlineManifests {
for _, obj := range bundle.Objects {
objJSON, err := json.Marshal(obj)
if err != nil {
return nil, fmt.Errorf("marshal bundle object %q (kind: %q)", obj.GetName(), obj.GetKind())
}
bundleProperties = append(bundleProperties, property.MustBuildBundleObjectData(objJSON))
objs = append(objs, string(objJSON))
if obj.GetKind() == v1alpha1.ClusterServiceVersionKind && csvJSON == "" {
csvJSON = string(objJSON)
}
}
}

dBundle := declcfg.Bundle{
Schema: "olm.bundle",
Name: bundle.Name,
Package: bundle.Package,
Image: bundle.BundleImage,
Properties: bundleProperties,
RelatedImages: relatedImages,
Objects: objs,
CsvJSON: csvJSON,
}

return &declcfg.DeclarativeConfig{Bundles: []declcfg.Bundle{dBundle}}, nil
Expand Down Expand Up @@ -343,3 +389,63 @@ 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) {
tmpDB, err := os.CreateTemp("", "opm-render-pm-")
if err != nil {
return nil, err
}
if err := tmpDB.Close(); err != nil {
return nil, err
}

db, err := sqlite.Open(tmpDB.Name())
if err != nil {
return nil, err
}
defer db.Close()
defer os.RemoveAll(tmpDB.Name())

dbLoader, err := sqlite.NewSQLLiteLoader(db)
if err != nil {
return nil, err
}
if err := dbLoader.Migrate(context.TODO()); 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, tmpDB.Name())
}
Loading

0 comments on commit 1ab84df

Please sign in to comment.