Skip to content

Commit

Permalink
Add ExtendedBundle wrapper
Browse files Browse the repository at this point in the history
This wraps the cnab-go bundle and adds support for custom extensions
that porter supports. It will help us wean off of using the porter
manifest at runtime, which is a huge problem because then our support
for spec extensions only works when it was authored in Porter.

More work is needed to fix this, but this is just a refactoring to get
the data in the right place, i.e. when we do pass around a bundle, it's
a bundle that knows how to deal with extensions.

I am still saving a cnab bundle document so that if we change the
structure of the wrapper it doesn't impact the stored document.

Signed-off-by: Carolyn Van Slyck <[email protected]>
  • Loading branch information
carolynvs committed Aug 25, 2021
1 parent 9948dd3 commit 4c3ad07
Show file tree
Hide file tree
Showing 59 changed files with 490 additions and 381 deletions.
2 changes: 1 addition & 1 deletion pkg/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (c *Cache) StoreBundle(bundleRef cnab.BundleReference) (CachedBundle, error
// cacheManifest extracts the porter.yaml from the bundle, if present and caches it
// in the same cache directory as the rest of the bundle.
func (c *Cache) cacheManifest(cb *CachedBundle) error {
if configadapter.IsPorterBundle(cb.Definition) {
if cb.Definition.IsPorterBundle() {
stamp, err := configadapter.LoadStamp(cb.Definition)
if err != nil {
fmt.Fprintf(c.Err, "WARNING: Bundle %s was created by porter but could not load the Porter stamp. This may be because it was created by an older version of Porter.\n", cb.Reference)
Expand Down
25 changes: 11 additions & 14 deletions pkg/cache/cache_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cache

import (
"bytes"
"fmt"
"path"
"path/filepath"
Expand Down Expand Up @@ -89,8 +88,7 @@ func TestCacheWriteNoCacheDir(t *testing.T) {

cfg := config.NewTestConfig(t)
cfg.TestContext.AddTestFile("testdata/cnab/bundle.json", "/cnab/bundle.json")
b, err := cfg.FileSystem.ReadFile("/cnab/bundle.json")
bun, err := bundle.ParseReader(bytes.NewBuffer(b))
bun, err := cnab.LoadBundle(cfg.Context, "/cnab/bundle.json")
require.NoError(t, err, "bundle should have been valid")

c := New(cfg.Config)
Expand All @@ -116,8 +114,7 @@ func TestCacheWriteCacheDirExists(t *testing.T) {
cacheDir := filepath.Join(home, "cache")
cfg.TestContext.AddTestFile("testdata/cnab/bundle.json", "/cnab/bundle.json")
cfg.TestContext.AddTestDirectory("testdata", cacheDir)
b, err := cfg.FileSystem.ReadFile("/cnab/bundle.json")
bun, err := bundle.ParseReader(bytes.NewBuffer(b))
bun, err := cnab.LoadBundle(cfg.Context, "/cnab/bundle.json")
require.NoError(t, err, "bundle should have been valid")

c := New(cfg.Config)
Expand All @@ -137,13 +134,13 @@ func TestStoreRelocationMapping(t *testing.T) {
name string
relocationMapping relocation.ImageRelocationMap
tag cnab.OCIReference
bundle bundle.Bundle
bundle cnab.ExtendedBundle
wantedReloPath string
err error
}{
{
name: "relocation file gets a path",
bundle: bundle.Bundle{},
bundle: cnab.ExtendedBundle{},
tag: kahn1dot01,
relocationMapping: relocation.ImageRelocationMap{
"asd": "asdf",
Expand All @@ -153,7 +150,7 @@ func TestStoreRelocationMapping(t *testing.T) {
{
name: "no relocation file gets no path",
tag: kahnlatest,
bundle: bundle.Bundle{},
bundle: cnab.ExtendedBundle{},
wantedReloPath: "",
},
}
Expand All @@ -180,38 +177,38 @@ func TestStoreManifest(t *testing.T) {
tests := []struct {
name string
tag cnab.OCIReference
bundle bundle.Bundle
bundle cnab.ExtendedBundle
shouldCacheManifest bool
err error
}{
{
name: "embedded manifest",
bundle: bundle.Bundle{
bundle: cnab.ExtendedBundle{bundle.Bundle{
Custom: map[string]interface{}{
"sh.porter": map[string]interface{}{
"manifest": "bmFtZTogSEVMTE9fQ1VTVE9NCnZlcnNpb246IDAuMS4wCmRlc2NyaXB0aW9uOiAiQSBidW5kbGUgd2l0aCBhIGN1c3RvbSBhY3Rpb24iCnRhZzogZ2V0cG9ydGVyL3BvcnRlci1oZWxsbzp2MC4xLjAKaW52b2NhdGlvbkltYWdlOiBnZXRwb3J0ZXIvcG9ydGVyLWhlbGxvLWluc3RhbGxlcjowLjEuMAoKY3JlZGVudGlhbHM6CiAgLSBuYW1lOiBteS1maXJzdC1jcmVkCiAgICBlbnY6IE1ZX0ZJUlNUX0NSRUQKICAtIG5hbWU6IG15LXNlY29uZC1jcmVkCiAgICBkZXNjcmlwdGlvbjogIk15IHNlY29uZCBjcmVkIgogICAgcGF0aDogL3BhdGgvdG8vbXktc2Vjb25kLWNyZWQKCmltYWdlczogCiAgIHNvbWV0aGluZzoKICAgICAgZGVzY3JpcHRpb246ICJhbiBpbWFnZSIKICAgICAgaW1hZ2VUeXBlOiAiZG9ja2VyIgogICAgICByZXBvc2l0b3J5OiAiZ2V0cG9ydGVyL2JvbyIKCnBhcmFtZXRlcnM6CiAgLSBuYW1lOiBteS1maXJzdC1wYXJhbQogICAgdHlwZTogaW50ZWdlcgogICAgZGVmYXVsdDogOQogICAgZW52OiBNWV9GSVJTVF9QQVJBTQogICAgYXBwbHlUbzoKICAgICAgLSAiaW5zdGFsbCIKICAtIG5hbWU6IG15LXNlY29uZC1wYXJhbQogICAgZGVzY3JpcHRpb246ICJNeSBzZWNvbmQgcGFyYW1ldGVyIgogICAgdHlwZTogc3RyaW5nCiAgICBkZWZhdWx0OiBzcHJpbmctbXVzaWMtZGVtbwogICAgcGF0aDogL3BhdGgvdG8vbXktc2Vjb25kLXBhcmFtCiAgICBzZW5zaXRpdmU6IHRydWUKCm91dHB1dHM6CiAgLSBuYW1lOiBteS1maXJzdC1vdXRwdXQKICAgIHR5cGU6IHN0cmluZwogICAgYXBwbHlUbzoKICAgICAgLSAiaW5zdGFsbCIKICAgICAgLSAidXBncmFkZSIKICAgIHNlbnNpdGl2ZTogdHJ1ZQogIC0gbmFtZTogbXktc2Vjb25kLW91dHB1dAogICAgZGVzY3JpcHRpb246ICJNeSBzZWNvbmQgb3V0cHV0IgogICAgdHlwZTogYm9vbGVhbgogICAgc2Vuc2l0aXZlOiBmYWxzZQogIC0gbmFtZToga3ViZWNvbmZpZwogICAgdHlwZTogZmlsZQogICAgcGF0aDogL3Jvb3QvLmt1YmUvY29uZmlnCgptaXhpbnM6CiAgLSBleGVjCgppbnN0YWxsOgogIC0gZXhlYzoKICAgICAgZGVzY3JpcHRpb246ICJJbnN0YWxsIEhlbGxvIFdvcmxkIgogICAgICBjb21tYW5kOiBiYXNoCiAgICAgIGZsYWdzOgogICAgICAgIGM6IGVjaG8gSGVsbG8gV29ybGQKCnVwZ3JhZGU6CiAgLSBleGVjOgogICAgICBkZXNjcmlwdGlvbjogIldvcmxkIDIuMCIKICAgICAgY29tbWFuZDogYmFzaAogICAgICBmbGFnczoKICAgICAgICBjOiBlY2hvIFdvcmxkIDIuMAoKem9tYmllczoKICAtIGV4ZWM6CiAgICAgIGRlc2NyaXB0aW9uOiAiVHJpZ2dlciB6b21iaWUgYXBvY2FseXBzZSIKICAgICAgY29tbWFuZDogYmFzaAogICAgICBmbGFnczoKICAgICAgICBjOiBlY2hvIG9oIG5vZXMgbXkgYnJhaW5zCgp1bmluc3RhbGw6CiAgLSBleGVjOgogICAgICBkZXNjcmlwdGlvbjogIlVuaW5zdGFsbCBIZWxsbyBXb3JsZCIKICAgICAgY29tbWFuZDogYmFzaAogICAgICBmbGFnczoKICAgICAgICBjOiBlY2hvIEdvb2RieWUgV29ybGQK",
},
},
},
}},
tag: kahn1dot01,
shouldCacheManifest: true,
},
{
name: "porter stamp, no manifest",
bundle: bundle.Bundle{
bundle: cnab.ExtendedBundle{bundle.Bundle{
Custom: map[string]interface{}{
"sh.porter": map[string]interface{}{
"manifestDigest": "abc123",
},
},
},
}},
tag: kahn1dot01,
shouldCacheManifest: false,
},
{
name: "no embedded manifest",
tag: kahnlatest,
bundle: bundle.Bundle{},
bundle: cnab.ExtendedBundle{},
},
}

Expand Down
20 changes: 1 addition & 19 deletions pkg/cnab/bundle.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,13 @@
package cnab

import (
"get.porter.sh/porter/pkg/context"
"github.com/cnabio/cnab-go/bundle"
"github.com/cnabio/cnab-to-oci/relocation"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
)

type BundleReference struct {
Reference OCIReference
Digest digest.Digest
Definition bundle.Bundle
Definition ExtendedBundle
RelocationMap relocation.ImageRelocationMap
}

// LoadBundle from the specified filepath.
func LoadBundle(c *context.Context, bundleFile string) (bundle.Bundle, error) {
bunD, err := c.FileSystem.ReadFile(bundleFile)
if err != nil {
return bundle.Bundle{}, errors.Wrapf(err, "cannot read bundle at %s", bundleFile)
}

bun, err := bundle.Unmarshal(bunD)
if err != nil {
return bundle.Bundle{}, errors.Wrapf(err, "cannot load bundle from\n%s at %s", string(bunD), bundleFile)
}

return *bun, nil
}
6 changes: 3 additions & 3 deletions pkg/cnab/cnab-to-oci/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (r *Registry) PullBundle(ref cnab.OCIReference, insecureRegistry bool) (cna
bundleRef := cnab.BundleReference{
Reference: ref,
Digest: digest,
Definition: *bun,
Definition: cnab.ExtendedBundle{*bun},
RelocationMap: reloMap,
}

Expand All @@ -90,13 +90,13 @@ func (r *Registry) PushBundle(bundleRef cnab.BundleReference, insecureRegistry b

resolver := r.createResolver(insecureRegistries)

rm, err := remotes.FixupBundle(context.Background(), &bundleRef.Definition, bundleRef.Reference.Named, resolver, remotes.WithEventCallback(r.displayEvent), remotes.WithAutoBundleUpdate())
rm, err := remotes.FixupBundle(context.Background(), &bundleRef.Definition.Bundle, bundleRef.Reference.Named, resolver, remotes.WithEventCallback(r.displayEvent), remotes.WithAutoBundleUpdate())
if err != nil {
return cnab.BundleReference{}, errors.Wrap(err, "error preparing the bundle with cnab-to-oci before pushing")
}
bundleRef.RelocationMap = rm

d, err := remotes.Push(context.Background(), &bundleRef.Definition, rm, bundleRef.Reference.Named, resolver, true)
d, err := remotes.Push(context.Background(), &bundleRef.Definition.Bundle, rm, bundleRef.Reference.Named, resolver, true)
if err != nil {
return cnab.BundleReference{}, errors.Wrapf(err, "error pushing the bundle to %s", bundleRef.Reference)
}
Expand Down
70 changes: 35 additions & 35 deletions pkg/cnab/config-adapter/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"path"

"get.porter.sh/porter/pkg/cnab/extensions"
"get.porter.sh/porter/pkg/cnab"
"get.porter.sh/porter/pkg/config"
"get.porter.sh/porter/pkg/context"
"get.porter.sh/porter/pkg/manifest"
Expand Down Expand Up @@ -38,20 +38,20 @@ func NewManifestConverter(
}
}

func (c *ManifestConverter) ToBundle() (bundle.Bundle, error) {
func (c *ManifestConverter) ToBundle() (cnab.ExtendedBundle, error) {
stamp, err := c.GenerateStamp()
if err != nil {
return bundle.Bundle{}, err
return cnab.ExtendedBundle{}, err
}

b := bundle.Bundle{
b := cnab.ExtendedBundle{bundle.Bundle{
SchemaVersion: SchemaVersion,
Name: c.Manifest.Name,
Description: c.Manifest.Description,
Version: c.Manifest.Version,
Maintainers: c.generateBundleMaintainers(),
Custom: make(map[string]interface{}, 1),
}
}}
image := bundle.InvocationImage{
BaseImage: bundle.BaseImage{
Image: c.Manifest.Image,
Expand Down Expand Up @@ -336,24 +336,24 @@ func (c *ManifestConverter) generateBundleImages() map[string]bundle.Image {
return images
}

func (c *ManifestConverter) generateDependencies() *extensions.Dependencies {
func (c *ManifestConverter) generateDependencies() *cnab.Dependencies {

if len(c.Manifest.Dependencies.RequiredDependencies) == 0 {
return nil
}

deps := &extensions.Dependencies{
deps := &cnab.Dependencies{
Sequence: make([]string, 0, len(c.Manifest.Dependencies.RequiredDependencies)),
Requires: make(map[string]extensions.Dependency, len(c.Manifest.Dependencies.RequiredDependencies)),
Requires: make(map[string]cnab.Dependency, len(c.Manifest.Dependencies.RequiredDependencies)),
}

for _, dep := range c.Manifest.Dependencies.RequiredDependencies {
dependencyRef := extensions.Dependency{
dependencyRef := cnab.Dependency{
Name: dep.Name,
Bundle: dep.Reference,
}
if len(dep.Versions) > 0 || dep.AllowPrereleases {
dependencyRef.Version = &extensions.DependencyVersion{
dependencyRef.Version = &cnab.DependencyVersion{
AllowPrereleases: dep.AllowPrereleases,
}
if len(dep.Versions) > 0 {
Expand All @@ -368,8 +368,8 @@ func (c *ManifestConverter) generateDependencies() *extensions.Dependencies {
return deps
}

func (c *ManifestConverter) generateParameterSources(b *bundle.Bundle) extensions.ParameterSources {
ps := extensions.ParameterSources{}
func (c *ManifestConverter) generateParameterSources(b *cnab.ExtendedBundle) cnab.ParameterSources {
ps := cnab.ParameterSources{}

// Parameter sources come from two places, indirectly from our template wiring
// and directly when they use `source` on a parameter
Expand All @@ -381,7 +381,7 @@ func (c *ManifestConverter) generateParameterSources(b *bundle.Bundle) extension
continue
}

var pso extensions.ParameterSource
var pso cnab.ParameterSource
if p.Source.Dependency == "" {
pso = c.generateOutputParameterSource(p.Source.Output)
} else {
Expand Down Expand Up @@ -426,7 +426,7 @@ func (c *ManifestConverter) generateParameterSources(b *bundle.Bundle) extension
// generateOutputWiringParameter creates an internal parameter used only by porter, it won't be visible to the user.
// The parameter exists solely so that Porter can inject an output back into the bundle, using a parameter source.
// The parameter's definition is a copy of the output's definition, with the ID set so we know that it was generated by porter.
func (c *ManifestConverter) generateOutputWiringParameter(b bundle.Bundle, outputName string) (string, bundle.Parameter, definition.Schema) {
func (c *ManifestConverter) generateOutputWiringParameter(b cnab.ExtendedBundle, outputName string) (string, bundle.Parameter, definition.Schema) {
wiringName := manifest.GetParameterSourceForOutput(outputName)

paramDesc := fmt.Sprintf("Wires up the %s output for use as a parameter. Porter internal parameter that should not be set manually.", outputName)
Expand Down Expand Up @@ -474,23 +474,23 @@ func (g *ManifestConverter) generateWiringParameter(wiringName string, descripti
}

// generateOutputParameterSource builds a parameter source that connects a bundle output to a parameter.
func (c *ManifestConverter) generateOutputParameterSource(outputName string) extensions.ParameterSource {
return extensions.ParameterSource{
Priority: []string{extensions.ParameterSourceTypeOutput},
Sources: map[string]extensions.ParameterSourceDefinition{
extensions.ParameterSourceTypeOutput: extensions.OutputParameterSource{
func (c *ManifestConverter) generateOutputParameterSource(outputName string) cnab.ParameterSource {
return cnab.ParameterSource{
Priority: []string{cnab.ParameterSourceTypeOutput},
Sources: map[string]cnab.ParameterSourceDefinition{
cnab.ParameterSourceTypeOutput: cnab.OutputParameterSource{
OutputName: outputName,
},
},
}
}

// generateDependencyOutputParameterSource builds a parameter source that connects a dependency output to a parameter.
func (c *ManifestConverter) generateDependencyOutputParameterSource(ref manifest.DependencyOutputReference) extensions.ParameterSource {
return extensions.ParameterSource{
Priority: []string{extensions.ParameterSourceTypeDependencyOutput},
Sources: map[string]extensions.ParameterSourceDefinition{
extensions.ParameterSourceTypeDependencyOutput: extensions.DependencyOutputParameterSource{
func (c *ManifestConverter) generateDependencyOutputParameterSource(ref manifest.DependencyOutputReference) cnab.ParameterSource {
return cnab.ParameterSource{
Priority: []string{cnab.ParameterSourceTypeDependencyOutput},
Sources: map[string]cnab.ParameterSourceDefinition{
cnab.ParameterSourceTypeDependencyOutput: cnab.DependencyOutputParameterSource{
Dependency: ref.Dependency,
OutputName: ref.Output,
},
Expand All @@ -510,9 +510,9 @@ func toFloat(v float64) *float64 {
return &v
}

func (c *ManifestConverter) generateCustomExtensions(b *bundle.Bundle) map[string]interface{} {
func (c *ManifestConverter) generateCustomExtensions(b *cnab.ExtendedBundle) map[string]interface{} {
customExtensions := map[string]interface{}{
extensions.FileParameterExtensionKey: struct{}{},
cnab.FileParameterExtensionKey: struct{}{},
}

// Add custom metadata defined in the manifest
Expand All @@ -523,13 +523,13 @@ func (c *ManifestConverter) generateCustomExtensions(b *bundle.Bundle) map[strin
// Add the dependency extension
deps := c.generateDependencies()
if deps != nil && len(deps.Requires) > 0 {
customExtensions[extensions.DependenciesExtensionKey] = deps
customExtensions[cnab.DependenciesExtensionKey] = deps
}

// Add the parameter sources extension
ps := c.generateParameterSources(b)
if len(ps) > 0 {
customExtensions[extensions.ParameterSourcesExtensionKey] = ps
customExtensions[cnab.ParameterSourcesExtensionKey] = ps
}

// Add entries for user-specified required extensions, like docker
Expand All @@ -540,17 +540,17 @@ func (c *ManifestConverter) generateCustomExtensions(b *bundle.Bundle) map[strin
return customExtensions
}

func (c *ManifestConverter) generateRequiredExtensions(b bundle.Bundle) []string {
requiredExtensions := []string{extensions.FileParameterExtensionKey}
func (c *ManifestConverter) generateRequiredExtensions(b cnab.ExtendedBundle) []string {
requiredExtensions := []string{cnab.FileParameterExtensionKey}

// Add the appropriate dependencies key if applicable
if extensions.HasDependencies(b) {
requiredExtensions = append(requiredExtensions, extensions.DependenciesExtensionKey)
if b.HasDependencies() {
requiredExtensions = append(requiredExtensions, cnab.DependenciesExtensionKey)
}

// Add the appropriate parameter sources key if applicable
if extensions.HasParameterSources(b) {
requiredExtensions = append(requiredExtensions, extensions.ParameterSourcesExtensionKey)
if b.HasParameterSources() {
requiredExtensions = append(requiredExtensions, cnab.ParameterSourcesExtensionKey)
}

// Add all under required section of manifest
Expand All @@ -568,7 +568,7 @@ func lookupExtensionKey(name string) string {
key := name
// If an official supported extension, we grab the full key

supportedExt, err := extensions.GetSupportedExtension(name)
supportedExt, err := cnab.GetSupportedExtension(name)
if err != nil {
// TODO: Issue linter warning
} else {
Expand Down
Loading

0 comments on commit 4c3ad07

Please sign in to comment.