From 4c3ad07a9b14b558e282c1928dab2e5033a42a29 Mon Sep 17 00:00:00 2001 From: Carolyn Van Slyck Date: Tue, 17 Aug 2021 10:37:46 -0500 Subject: [PATCH] Add ExtendedBundle wrapper 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 --- pkg/cache/cache.go | 2 +- pkg/cache/cache_test.go | 25 +++--- pkg/cnab/bundle.go | 20 +---- pkg/cnab/cnab-to-oci/registry.go | 6 +- pkg/cnab/config-adapter/adapter.go | 70 ++++++++-------- pkg/cnab/config-adapter/adapter_test.go | 30 +++---- pkg/cnab/config-adapter/stamp.go | 4 +- pkg/cnab/config-adapter/stamp_test.go | 13 +-- pkg/cnab/constants.go | 1 - pkg/cnab/{extensions => }/dependencies.go | 34 ++++++-- .../{extensions => }/dependencies_test.go | 38 +++++---- pkg/cnab/{extensions => }/docker.go | 14 +++- pkg/cnab/{extensions => }/docker_test.go | 2 +- pkg/cnab/extended_bundle.go | 83 +++++++++++++++++++ ...bundle_test.go => extended_bundle_test.go} | 26 +++--- pkg/cnab/{extensions => }/extensions.go | 13 ++- pkg/cnab/extensions/bundle.go | 35 -------- pkg/cnab/extensions/doc.go | 1 - pkg/cnab/{extensions => }/extensions_test.go | 10 +-- pkg/cnab/{extensions => }/file_parameter.go | 21 +++-- .../{extensions => }/file_parameter_test.go | 12 +-- pkg/cnab/helpers.go | 4 +- .../{extensions => }/parameter_sources.go | 34 ++++++-- .../{extensions => }/paramter_sources_test.go | 31 +++---- pkg/cnab/provider/action.go | 2 +- pkg/cnab/provider/bundle.go | 9 +- pkg/cnab/provider/driver.go | 6 +- pkg/cnab/provider/driver_test.go | 6 +- pkg/cnab/provider/helpers.go | 5 +- pkg/cnab/provider/parameters.go | 20 ++--- pkg/cnab/provider/parameters_test.go | 35 ++++---- pkg/cnab/provider/provider.go | 4 +- pkg/cnab/provider/runtime.go | 11 ++- pkg/cnab/{extensions => }/required.go | 16 +++- pkg/cnab/{extensions => }/required_test.go | 15 ++-- .../schema/io-cnab-docker.schema.json | 0 pkg/cnab/{extensions => }/solver.go | 21 +++-- pkg/cnab/{extensions => }/solver_test.go | 6 +- .../bundle-supported-unprocessable.json | 0 .../testdata/bundle-unsupported-required.json | 0 .../{extensions => }/testdata/bundle.json | 0 pkg/generator/parameters.go | 6 +- pkg/generator/parameters_test.go | 11 +-- pkg/porter/archive.go | 5 +- pkg/porter/build.go | 4 +- pkg/porter/build_test.go | 8 +- pkg/porter/credentials.go | 3 + pkg/porter/dependencies.go | 22 +++-- pkg/porter/explain.go | 11 ++- pkg/porter/explain_test.go | 44 +++++----- pkg/porter/lifecycle.go | 2 +- pkg/porter/outputs.go | 4 +- pkg/porter/parameters.go | 9 +- pkg/porter/publish.go | 25 +++--- pkg/porter/publish_test.go | 8 +- pkg/porter/stamp.go | 1 + pkg/runtime/runtime-manifest.go | 11 ++- pkg/runtime/runtime-manifest_test.go | 11 ++- tests/smoke/main_test.go | 1 + 59 files changed, 490 insertions(+), 381 deletions(-) delete mode 100644 pkg/cnab/constants.go rename pkg/cnab/{extensions => }/dependencies.go (79%) rename pkg/cnab/{extensions => }/dependencies_test.go (86%) rename pkg/cnab/{extensions => }/docker.go (83%) rename pkg/cnab/{extensions => }/docker_test.go (98%) create mode 100644 pkg/cnab/extended_bundle.go rename pkg/cnab/{extensions/bundle_test.go => extended_bundle_test.go} (60%) rename pkg/cnab/{extensions => }/extensions.go (57%) delete mode 100644 pkg/cnab/extensions/bundle.go delete mode 100644 pkg/cnab/extensions/doc.go rename pkg/cnab/{extensions => }/extensions_test.go (51%) rename pkg/cnab/{extensions => }/file_parameter.go (68%) rename pkg/cnab/{extensions => }/file_parameter_test.go (82%) rename pkg/cnab/{extensions => }/parameter_sources.go (85%) rename pkg/cnab/{extensions => }/paramter_sources_test.go (86%) rename pkg/cnab/{extensions => }/required.go (77%) rename pkg/cnab/{extensions => }/required_test.go (85%) rename pkg/cnab/{extensions => }/schema/io-cnab-docker.schema.json (100%) rename pkg/cnab/{extensions => }/solver.go (79%) rename pkg/cnab/{extensions => }/solver_test.go (98%) rename pkg/cnab/{extensions => }/testdata/bundle-supported-unprocessable.json (100%) rename pkg/cnab/{extensions => }/testdata/bundle-unsupported-required.json (100%) rename pkg/cnab/{extensions => }/testdata/bundle.json (100%) diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index 60e1def6d5..249bdc15cf 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -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) diff --git a/pkg/cache/cache_test.go b/pkg/cache/cache_test.go index a6c79f4740..b9856a5599 100644 --- a/pkg/cache/cache_test.go +++ b/pkg/cache/cache_test.go @@ -1,7 +1,6 @@ package cache import ( - "bytes" "fmt" "path" "path/filepath" @@ -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) @@ -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) @@ -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", @@ -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: "", }, } @@ -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{}, }, } diff --git a/pkg/cnab/bundle.go b/pkg/cnab/bundle.go index ee149b237e..b9c8ab97d1 100644 --- a/pkg/cnab/bundle.go +++ b/pkg/cnab/bundle.go @@ -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 -} diff --git a/pkg/cnab/cnab-to-oci/registry.go b/pkg/cnab/cnab-to-oci/registry.go index 28f61b90b2..dd702eb28c 100644 --- a/pkg/cnab/cnab-to-oci/registry.go +++ b/pkg/cnab/cnab-to-oci/registry.go @@ -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, } @@ -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) } diff --git a/pkg/cnab/config-adapter/adapter.go b/pkg/cnab/config-adapter/adapter.go index 34cac5c829..4084f2148e 100644 --- a/pkg/cnab/config-adapter/adapter.go +++ b/pkg/cnab/config-adapter/adapter.go @@ -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" @@ -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, @@ -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 { @@ -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 @@ -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 { @@ -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) @@ -474,11 +474,11 @@ 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, }, }, @@ -486,11 +486,11 @@ func (c *ManifestConverter) generateOutputParameterSource(outputName string) ext } // 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, }, @@ -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 @@ -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 @@ -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 @@ -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 { diff --git a/pkg/cnab/config-adapter/adapter_test.go b/pkg/cnab/config-adapter/adapter_test.go index 8131170a7a..bc44cbbff6 100644 --- a/pkg/cnab/config-adapter/adapter_test.go +++ b/pkg/cnab/config-adapter/adapter_test.go @@ -6,7 +6,7 @@ import ( "os" "testing" - "get.porter.sh/porter/pkg/cnab/extensions" + "get.porter.sh/porter/pkg/cnab" "get.porter.sh/porter/pkg/config" "get.porter.sh/porter/pkg/manifest" "get.porter.sh/porter/pkg/parameters" @@ -46,7 +46,7 @@ func TestManifestConverter_ToBundle(t *testing.T) { assert.Contains(t, bun.Parameters, "porter-debug", "porter-debug parameter was not defined") assert.Contains(t, bun.Definitions, "porter-debug-parameter", "porter-debug definition was not defined") - assert.True(t, extensions.HasDependencies(bun), "Dependencies was not populated") + assert.True(t, bun.HasDependencies(), "Dependencies was not populated") assert.Nil(t, bun.Outputs, "expected outputs section not to exist in generated bundle") } @@ -481,30 +481,30 @@ func TestManifestConverter_generateDependencies(t *testing.T) { testcases := []struct { name string - wantDep extensions.Dependency + wantDep cnab.Dependency }{ - {"no-version", extensions.Dependency{ + {"no-version", cnab.Dependency{ Name: "mysql", Bundle: "getporter/azure-mysql:5.7", }}, - {"no-ranges", extensions.Dependency{ + {"no-ranges", cnab.Dependency{ Name: "ad", Bundle: "getporter/azure-active-directory", - Version: &extensions.DependencyVersion{ + Version: &cnab.DependencyVersion{ AllowPrereleases: true, }, }}, - {"with-ranges", extensions.Dependency{ + {"with-ranges", cnab.Dependency{ Name: "storage", Bundle: "getporter/azure-blob-storage", - Version: &extensions.DependencyVersion{ + Version: &cnab.DependencyVersion{ Ranges: []string{ "1.x - 2", "2.1 - 3.x", }, }, }}, - {"with-tag", extensions.Dependency{ + {"with-tag", cnab.Dependency{ Name: "dep-with-tag", Bundle: "getporter/dep-bun:v0.1.0", }}, @@ -527,7 +527,7 @@ func TestManifestConverter_generateDependencies(t *testing.T) { require.Len(t, deps.Requires, 4, "incorrect number of dependencies were generated") require.Equal(t, []string{"mysql", "ad", "storage", "dep-with-tag"}, deps.Sequence, "incorrect sequence was generated") - var dep *extensions.Dependency + var dep *cnab.Dependency for _, d := range deps.Requires { if d.Bundle == tc.wantDep.Bundle { dep = &d @@ -570,10 +570,10 @@ func TestManifestConverter_generateParameterSources(t *testing.T) { b, err := a.ToBundle() require.NoError(t, err, "ToBundle failed") - sources, err := extensions.ReadParameterSources(b) + sources, err := b.ReadParameterSources() require.NoError(t, err, "ReadParameterSources failed") - want := extensions.ParameterSources{} + want := cnab.ParameterSources{} want.SetParameterFromOutput("porter-msg-output", "msg") want.SetParameterFromOutput("tfstate", "tfstate") want.SetParameterFromDependencyOutput("porter-mysql-mysql-password-dep-output", "mysql", "mysql-password") @@ -596,7 +596,7 @@ func TestNewManifestConverter_generateOutputWiringParameter(t *testing.T) { outputDef := definition.Schema{ Type: "string", } - b := bundle.Bundle{ + b := cnab.ExtendedBundle{bundle.Bundle{ Outputs: map[string]bundle.Output{ "msg": { Definition: "stringDef", @@ -608,7 +608,7 @@ func TestNewManifestConverter_generateOutputWiringParameter(t *testing.T) { Definitions: map[string]*definition.Schema{ "stringDef": &outputDef, }, - } + }} t.Run("generate parameter", func(t *testing.T) { t.Parallel() @@ -708,7 +708,7 @@ func TestManifestConverter_generateCustomExtensions_withRequired(t *testing.T) { bun, err := a.ToBundle() require.NoError(t, err, "ToBundle failed") - assert.Contains(t, bun.Custom, extensions.FileParameterExtensionKey) + assert.Contains(t, bun.Custom, cnab.FileParameterExtensionKey) assert.Contains(t, bun.Custom, "requiredExtension1") assert.Contains(t, bun.Custom, "requiredExtension2") assert.Equal(t, map[string]interface{}{"config": true}, bun.Custom["requiredExtension2"]) diff --git a/pkg/cnab/config-adapter/stamp.go b/pkg/cnab/config-adapter/stamp.go index df96afc5d5..6b666b7194 100644 --- a/pkg/cnab/config-adapter/stamp.go +++ b/pkg/cnab/config-adapter/stamp.go @@ -8,6 +8,7 @@ import ( "fmt" "get.porter.sh/porter/pkg" + "get.porter.sh/porter/pkg/cnab" "get.porter.sh/porter/pkg/config" "get.porter.sh/porter/pkg/context" "get.porter.sh/porter/pkg/manifest" @@ -122,7 +123,8 @@ func IsPorterBundle(bun bundle.Bundle) bool { return ok } -func LoadStamp(bun bundle.Bundle) (Stamp, error) { +func LoadStamp(bun cnab.ExtendedBundle) (Stamp, error) { + // TODO(carolynvs): can we simplify some of this by using the extended bundle? data, ok := bun.Custom[config.CustomPorterKey] if !ok { return Stamp{}, errors.Errorf("porter stamp (custom.%s) was not present on the bundle", config.CustomPorterKey) diff --git a/pkg/cnab/config-adapter/stamp_test.go b/pkg/cnab/config-adapter/stamp_test.go index 23bd9725ef..8d6e6db34a 100644 --- a/pkg/cnab/config-adapter/stamp_test.go +++ b/pkg/cnab/config-adapter/stamp_test.go @@ -4,6 +4,7 @@ import ( "testing" "get.porter.sh/porter/pkg" + "get.porter.sh/porter/pkg/cnab" "get.porter.sh/porter/pkg/config" "get.porter.sh/porter/pkg/manifest" "github.com/cnabio/cnab-go/bundle" @@ -41,7 +42,7 @@ func TestConfig_GenerateStamp(t *testing.T) { func TestConfig_LoadStamp(t *testing.T) { t.Parallel() - bun := &bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ Custom: map[string]interface{}{ config.CustomPorterKey: map[string]interface{}{ "manifestDigest": simpleManifestDigest, @@ -51,9 +52,9 @@ func TestConfig_LoadStamp(t *testing.T) { }, }, }, - } + }} - stamp, err := LoadStamp(*bun) + stamp, err := LoadStamp(bun) require.NoError(t, err) assert.Equal(t, simpleManifestDigest, stamp.ManifestDigest) assert.Equal(t, map[string]MixinRecord{"exec": {}}, stamp.Mixins, "Stamp.Mixins was not populated properly") @@ -63,15 +64,15 @@ func TestConfig_LoadStamp(t *testing.T) { func TestConfig_LoadStamp_Invalid(t *testing.T) { t.Parallel() - bun := &bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ Custom: map[string]interface{}{ config.CustomPorterKey: []string{ simpleManifestDigest, }, }, - } + }} - stamp, err := LoadStamp(*bun) + stamp, err := LoadStamp(bun) require.Error(t, err) assert.Contains(t, err.Error(), "could not unmarshal the porter stamp") assert.Equal(t, Stamp{}, stamp) diff --git a/pkg/cnab/constants.go b/pkg/cnab/constants.go deleted file mode 100644 index 6b699e8350..0000000000 --- a/pkg/cnab/constants.go +++ /dev/null @@ -1 +0,0 @@ -package cnab diff --git a/pkg/cnab/extensions/dependencies.go b/pkg/cnab/dependencies.go similarity index 79% rename from pkg/cnab/extensions/dependencies.go rename to pkg/cnab/dependencies.go index df94d7702a..c8d25d1448 100644 --- a/pkg/cnab/extensions/dependencies.go +++ b/pkg/cnab/dependencies.go @@ -1,4 +1,4 @@ -package extensions +package cnab import ( "encoding/json" @@ -62,7 +62,14 @@ type DependencyVersion struct { // Dependencies reference after reading from the applicable section from // the provided bundle func ReadDependencies(bun bundle.Bundle) (Dependencies, error) { - raw, err := DependencyReader(bun) + return ExtendedBundle{bun}.ReadDependencies() +} + +// ReadDependencies is a convenience method for returning a bonafide +// Dependencies reference after reading from the applicable section from +// the provided bundle +func (b ExtendedBundle) ReadDependencies() (Dependencies, error) { + raw, err := b.DependencyReader() if err != nil { return Dependencies{}, err } @@ -79,8 +86,15 @@ func ReadDependencies(bun bundle.Bundle) (Dependencies, error) { // DependencyReader is a Reader for the DependenciesExtension, which reads // from the applicable section in the provided bundle and returns a the raw // data in the form of an interface -func DependencyReader(bun bundle.Bundle) (interface{}, error) { - data, ok := bun.Custom[DependenciesExtensionKey] +func DependencyReader(bun ExtendedBundle) (interface{}, error) { + return bun.DependencyReader() +} + +// DependencyReader is a Reader for the DependenciesExtension, which reads +// from the applicable section in the provided bundle and returns a the raw +// data in the form of an interface +func (b ExtendedBundle) DependencyReader() (interface{}, error) { + data, ok := b.Custom[DependenciesExtensionKey] if !ok { return nil, errors.Errorf("attempted to read dependencies from bundle but none are defined") } @@ -101,11 +115,21 @@ func DependencyReader(bun bundle.Bundle) (interface{}, error) { // SupportsDependencies checks if the bundle supports dependencies func SupportsDependencies(b bundle.Bundle) bool { - return SupportsExtension(b, DependenciesExtensionKey) + return ExtendedBundle{b}.SupportsDependencies() +} + +// SupportsDependencies checks if the bundle supports dependencies +func (b ExtendedBundle) SupportsDependencies() bool { + return b.SupportsExtension(DependenciesExtensionKey) } // HasParameterSources returns whether or not the bundle has parameter sources defined. func HasDependencies(b bundle.Bundle) bool { + return ExtendedBundle{b}.HasDependencies() +} + +// HasParameterSources returns whether or not the bundle has parameter sources defined. +func (b ExtendedBundle) HasDependencies() bool { _, ok := b.Custom[DependenciesExtensionKey] return ok } diff --git a/pkg/cnab/extensions/dependencies_test.go b/pkg/cnab/dependencies_test.go similarity index 86% rename from pkg/cnab/extensions/dependencies_test.go rename to pkg/cnab/dependencies_test.go index b4016698f5..3271163083 100644 --- a/pkg/cnab/extensions/dependencies_test.go +++ b/pkg/cnab/dependencies_test.go @@ -1,4 +1,4 @@ -package extensions +package cnab import ( "io/ioutil" @@ -15,11 +15,13 @@ func TestReadDependencyProperties(t *testing.T) { data, err := ioutil.ReadFile("testdata/bundle.json") require.NoError(t, err, "cannot read bundle file") - bun, err := bundle.Unmarshal(data) + b, err := bundle.Unmarshal(data) require.NoError(t, err, "could not unmarshal the bundle") - assert.True(t, HasDependencies(*bun)) - deps, err := ReadDependencies(*bun) + bun := ExtendedBundle{*b} + assert.True(t, bun.HasDependencies()) + + deps, err := bun.ReadDependencies() assert.NotNil(t, deps, "Dependencies was not populated") assert.Len(t, deps.Requires, 2, "Dependencies.Requires is the wrong length") @@ -42,7 +44,7 @@ func TestDependencies_ListBySequence(t *testing.T) { sequenceMock := []string{"nginx", "storage", "mysql"} - bun := bundle.Bundle{ + bun := ExtendedBundle{bundle.Bundle{ Custom: map[string]interface{}{ DependenciesExtensionKey: Dependencies{ Sequence: sequenceMock, @@ -66,9 +68,9 @@ func TestDependencies_ListBySequence(t *testing.T) { }, }, }, - } + }} - rawDeps, err := ReadDependencies(bun) + rawDeps, err := bun.ReadDependencies() orderedDeps := rawDeps.ListBySequence() require.NoError(t, err, "unable to read dependencies extension data") @@ -90,16 +92,16 @@ func TestSupportsDependencies(t *testing.T) { t.Parallel() t.Run("supported", func(t *testing.T) { - b := bundle.Bundle{ + b := ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{DependenciesExtensionKey}, - } + }} - assert.True(t, SupportsDependencies(b)) + assert.True(t, b.SupportsDependencies()) }) t.Run("unsupported", func(t *testing.T) { - b := bundle.Bundle{} + b := ExtendedBundle{} - assert.False(t, SupportsDependencies(b)) + assert.False(t, b.SupportsDependencies()) }) } @@ -107,20 +109,20 @@ func TestHasDependencies(t *testing.T) { t.Parallel() t.Run("has dependencies", func(t *testing.T) { - b := bundle.Bundle{ + b := ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{DependenciesExtensionKey}, Custom: map[string]interface{}{ DependenciesExtensionKey: struct{}{}, }, - } + }} - assert.True(t, HasDependencies(b)) + assert.True(t, b.HasDependencies()) }) t.Run("no dependencies", func(t *testing.T) { - b := bundle.Bundle{ + b := ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{DependenciesExtensionKey}, - } + }} - assert.False(t, HasDependencies(b)) + assert.False(t, b.HasDependencies()) }) } diff --git a/pkg/cnab/extensions/docker.go b/pkg/cnab/docker.go similarity index 83% rename from pkg/cnab/extensions/docker.go rename to pkg/cnab/docker.go index 5630fc304b..5fbccb23ab 100644 --- a/pkg/cnab/extensions/docker.go +++ b/pkg/cnab/docker.go @@ -1,9 +1,8 @@ -package extensions +package cnab import ( "encoding/json" - "github.com/cnabio/cnab-go/bundle" "github.com/pkg/errors" ) @@ -35,8 +34,15 @@ type Docker struct { // DockerExtensionReader is a Reader for the DockerExtension, // which reads from the applicable section in the provided bundle and // returns a the raw data in the form of an interface -func DockerExtensionReader(bun bundle.Bundle) (interface{}, error) { - data, ok := bun.Custom[DockerExtensionKey] +func DockerExtensionReader(bun ExtendedBundle) (interface{}, error) { + return bun.DockerExtensionReader() +} + +// DockerExtensionReader is a Reader for the DockerExtension, +// which reads from the applicable section in the provided bundle and +// returns a the raw data in the form of an interface +func (b ExtendedBundle) DockerExtensionReader() (interface{}, error) { + data, ok := b.Custom[DockerExtensionKey] if !ok { return nil, errors.New("no custom extension configuration found") } diff --git a/pkg/cnab/extensions/docker_test.go b/pkg/cnab/docker_test.go similarity index 98% rename from pkg/cnab/extensions/docker_test.go rename to pkg/cnab/docker_test.go index e9f42b07ee..e34b1b3a8b 100644 --- a/pkg/cnab/extensions/docker_test.go +++ b/pkg/cnab/docker_test.go @@ -1,4 +1,4 @@ -package extensions +package cnab import ( "testing" diff --git a/pkg/cnab/extended_bundle.go b/pkg/cnab/extended_bundle.go new file mode 100644 index 0000000000..3debf449e2 --- /dev/null +++ b/pkg/cnab/extended_bundle.go @@ -0,0 +1,83 @@ +package cnab + +import ( + "fmt" + + "get.porter.sh/porter/pkg/context" + "get.porter.sh/porter/pkg/parameters" + "github.com/cnabio/cnab-go/bundle" + "github.com/cnabio/cnab-go/bundle/definition" + "github.com/cnabio/cnab-go/claim" + "github.com/pkg/errors" +) + +// ExtendedBundle is a bundle that has typed access to extensions declared in the bundle, +// allowing quick type-safe access to custom extensions from the CNAB spec. +type ExtendedBundle struct { + bundle.Bundle +} + +// LoadBundle from the specified filepath. +func LoadBundle(c *context.Context, bundleFile string) (ExtendedBundle, error) { + bunD, err := c.FileSystem.ReadFile(bundleFile) + if err != nil { + return ExtendedBundle{}, errors.Wrapf(err, "cannot read bundle at %s", bundleFile) + } + + bun, err := bundle.Unmarshal(bunD) + if err != nil { + return ExtendedBundle{}, errors.Wrapf(err, "cannot load bundle from\n%s at %s", string(bunD), bundleFile) + } + + return ExtendedBundle{*bun}, nil +} + +// IsPorterBundle determines if the bundle was created by Porter. +func (b ExtendedBundle) IsPorterBundle() bool { + _, madeByPorter := b.Custom[PorterExtension] + return madeByPorter +} + +// IsInternal determines if the provided param is an internal parameter +// to Porter after analyzing the provided bundle +func (b ExtendedBundle) IsInternal(param string) bool { + if param, exists := b.Parameters[param]; exists { + if def, exists := b.Definitions[param.Definition]; exists { + return def.Comment == parameters.PorterInternal + } + } + return false +} + +// GetParameterType determines the type of parameter accounting for +// Porter-specific parameter types like file. +func GetParameterType(b bundle.Bundle, def *definition.Schema) string { + eb := ExtendedBundle{b} + return eb.GetParameterType(def) +} + +// GetParameterType determines the type of parameter accounting for +// Porter-specific parameter types like file. +func (b ExtendedBundle) GetParameterType(def *definition.Schema) string { + if b.IsFileType(def) { + return "file" + } + + if def.ID == claim.OutputInvocationImageLogs { + return "string" + } + + return fmt.Sprintf("%v", def.Type) +} + +// IsFileType determines if the parameter/credential is of type "file". +func IsFileType(b bundle.Bundle, def *definition.Schema) bool { + eb := ExtendedBundle{b} + return eb.IsFileType(def) +} + +// IsFileType determines if the parameter/credential is of type "file". +func (b ExtendedBundle) IsFileType(def *definition.Schema) bool { + return b.SupportsFileParameters() && + def.Type == "string" && def.ContentEncoding == "base64" +} diff --git a/pkg/cnab/extensions/bundle_test.go b/pkg/cnab/extended_bundle_test.go similarity index 60% rename from pkg/cnab/extensions/bundle_test.go rename to pkg/cnab/extended_bundle_test.go index 0924044e86..55e6d9918b 100644 --- a/pkg/cnab/extensions/bundle_test.go +++ b/pkg/cnab/extended_bundle_test.go @@ -1,4 +1,4 @@ -package extensions +package cnab import ( "testing" @@ -8,21 +8,21 @@ import ( "github.com/stretchr/testify/assert" ) -func TestIsPorterBundle(t *testing.T) { +func TestExtendedBundle_IsPorterBundle(t *testing.T) { t.Run("made by porter", func(t *testing.T) { - b := bundle.Bundle{ + b := ExtendedBundle{bundle.Bundle{ Custom: map[string]interface{}{ "sh.porter": struct{}{}, }, - } + }} - assert.True(t, IsPorterBundle(b)) + assert.True(t, b.IsPorterBundle()) }) t.Run("third party bundle", func(t *testing.T) { - b := bundle.Bundle{} + b := ExtendedBundle{} - assert.False(t, IsPorterBundle(b)) + assert.False(t, b.IsPorterBundle()) }) } @@ -34,7 +34,7 @@ func TestIsFileType(t *testing.T) { Type: "string", ContentEncoding: "base64", } - bun := bundle.Bundle{ + bun := ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{ FileParameterExtensionKey, }, @@ -51,19 +51,19 @@ func TestIsFileType(t *testing.T) { Definition: "file", }, }, - } + }} - assert.False(t, IsFileType(bun, stringDef), "strings should not be flagged as files") - assert.True(t, IsFileType(bun, fileDef), "strings+base64 with the file-parameters extension should be categorized as files") + assert.False(t, bun.IsFileType(stringDef), "strings should not be flagged as files") + assert.True(t, bun.IsFileType(fileDef), "strings+base64 with the file-parameters extension should be categorized as files") // Ensure we honor the custom extension bun.RequiredExtensions = nil - assert.False(t, IsFileType(bun, fileDef), "don't categorize as file type when the extension is missing") + assert.False(t, bun.IsFileType(fileDef), "don't categorize as file type when the extension is missing") // Ensure we work with old bundles before the extension was created bun.Custom = map[string]interface{}{ "sh.porter": struct{}{}, } - assert.True(t, IsFileType(bun, fileDef), "categorize string+base64 in old porter bundles should be categorized as files") + assert.True(t, bun.IsFileType(fileDef), "categorize string+base64 in old porter bundles should be categorized as files") } diff --git a/pkg/cnab/extensions/extensions.go b/pkg/cnab/extensions.go similarity index 57% rename from pkg/cnab/extensions/extensions.go rename to pkg/cnab/extensions.go index b63a951ad6..3755eaf8b2 100644 --- a/pkg/cnab/extensions/extensions.go +++ b/pkg/cnab/extensions.go @@ -1,12 +1,15 @@ -package extensions +package cnab import ( "github.com/cnabio/cnab-go/bundle" ) const ( + // PorterExtension is the key for all Porter configuration stored the the custom section of bundles. + PorterExtension = "sh.porter" + // PorterExtensionsPrefix is the prefix applied to any custom CNAB extensions developed by Porter. - PorterExtensionsPrefix = "sh.porter." + PorterExtensionsPrefix = PorterExtension + "." // OfficialExtensionsPrefix is the prefix applied to extensions defined in the CNAB spec. OfficialExtensionsPrefix = "io.cnab." @@ -14,6 +17,12 @@ const ( // SupportsExtension checks if the bundle supports the specified CNAB extension. func SupportsExtension(b bundle.Bundle, key string) bool { + eb := ExtendedBundle{b} + return eb.SupportsExtension(key) +} + +// SupportsExtension checks if the bundle supports the specified CNAB extension. +func (b ExtendedBundle) SupportsExtension(key string) bool { for _, ext := range b.RequiredExtensions { if key == ext { return true diff --git a/pkg/cnab/extensions/bundle.go b/pkg/cnab/extensions/bundle.go deleted file mode 100644 index 67cb6bcfbb..0000000000 --- a/pkg/cnab/extensions/bundle.go +++ /dev/null @@ -1,35 +0,0 @@ -package extensions - -import ( - "fmt" - - claim "get.porter.sh/porter/pkg/cnab" - "github.com/cnabio/cnab-go/bundle" - "github.com/cnabio/cnab-go/bundle/definition" -) - -// IsPorterBundle determines if the bundle was created by Porter. -func IsPorterBundle(b bundle.Bundle) bool { - _, madeByPorter := b.Custom["sh.porter"] - return madeByPorter -} - -// GetParameterType determines the type of parameter accounting for -// Porter-specific parameter types like file. -func GetParameterType(b bundle.Bundle, def *definition.Schema) string { - if IsFileType(b, def) { - return "file" - } - - if def.ID == claim.OutputInvocationImageLogs { - return "string" - } - - return fmt.Sprintf("%v", def.Type) -} - -// IsFileType determines if the parameter/credential is of type "file". -func IsFileType(b bundle.Bundle, def *definition.Schema) bool { - return SupportsFileParameters(b) && - def.Type == "string" && def.ContentEncoding == "base64" -} diff --git a/pkg/cnab/extensions/doc.go b/pkg/cnab/extensions/doc.go deleted file mode 100644 index aeec0fa756..0000000000 --- a/pkg/cnab/extensions/doc.go +++ /dev/null @@ -1 +0,0 @@ -package extensions diff --git a/pkg/cnab/extensions/extensions_test.go b/pkg/cnab/extensions_test.go similarity index 51% rename from pkg/cnab/extensions/extensions_test.go rename to pkg/cnab/extensions_test.go index ca99820595..8fc99b132b 100644 --- a/pkg/cnab/extensions/extensions_test.go +++ b/pkg/cnab/extensions_test.go @@ -1,4 +1,4 @@ -package extensions +package cnab import ( "testing" @@ -9,13 +9,13 @@ import ( func TestSupportsExtension(t *testing.T) { t.Run("key present", func(t *testing.T) { - b := bundle.Bundle{RequiredExtensions: []string{"io.test.thing"}} - assert.True(t, SupportsExtension(b, "io.test.thing")) + b := ExtendedBundle{bundle.Bundle{RequiredExtensions: []string{"io.test.thing"}}} + assert.True(t, b.SupportsExtension("io.test.thing")) }) t.Run("key missing", func(t *testing.T) { // We need to match against the full key, not just shorthand - b := bundle.Bundle{RequiredExtensions: []string{"thing"}} - assert.False(t, SupportsExtension(b, "io.test.thing")) + b := ExtendedBundle{bundle.Bundle{RequiredExtensions: []string{"thing"}}} + assert.False(t, b.SupportsExtension("io.test.thing")) }) } diff --git a/pkg/cnab/extensions/file_parameter.go b/pkg/cnab/file_parameter.go similarity index 68% rename from pkg/cnab/extensions/file_parameter.go rename to pkg/cnab/file_parameter.go index ab45379163..a84f69bb2c 100644 --- a/pkg/cnab/extensions/file_parameter.go +++ b/pkg/cnab/file_parameter.go @@ -1,8 +1,7 @@ -package extensions +package cnab import ( "github.com/cnabio/cnab-go/bundle" - cnabbundle "github.com/cnabio/cnab-go/bundle" ) const ( @@ -24,19 +23,31 @@ var FileParameterExtension = RequiredExtension{ // FileParameterReader is a Reader for the FileParameterExtension. // The extension does not have any data, it's presence indicates that // parameters of type "file" should be supported by the tooling. -func FileParameterReader(_ cnabbundle.Bundle) (interface{}, error) { +func FileParameterReader(b ExtendedBundle) (interface{}, error) { + return b.FileParameterReader() +} + +// FileParameterReader is a Reader for the FileParameterExtension. +// The extension does not have any data, it's presence indicates that +// parameters of type "file" should be supported by the tooling. +func (b ExtendedBundle) FileParameterReader() (interface{}, error) { return nil, nil } // SupportsFileParameters checks if the bundle supports file parameters. func SupportsFileParameters(b bundle.Bundle) bool { - if SupportsExtension(b, FileParameterExtensionKey) { + return ExtendedBundle{b}.SupportsFileParameters() +} + +// SupportsFileParameters checks if the bundle supports file parameters. +func (b ExtendedBundle) SupportsFileParameters() bool { + if b.SupportsExtension(FileParameterExtensionKey) { return true } // Porter has always supported this but didn't have the extension declared // TODO(v1): Remove this logic in v1.0? - return IsPorterBundle(b) + return b.IsPorterBundle() } // FileParameterSupport checks if the file parameter extension diff --git a/pkg/cnab/extensions/file_parameter_test.go b/pkg/cnab/file_parameter_test.go similarity index 82% rename from pkg/cnab/extensions/file_parameter_test.go rename to pkg/cnab/file_parameter_test.go index 7b4a8a556d..8b8565d9e8 100644 --- a/pkg/cnab/extensions/file_parameter_test.go +++ b/pkg/cnab/file_parameter_test.go @@ -1,4 +1,4 @@ -package extensions +package cnab import ( "testing" @@ -35,15 +35,15 @@ func TestSupportsFileParameters(t *testing.T) { t.Parallel() t.Run("supported", func(t *testing.T) { - b := bundle.Bundle{ + b := ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{FileParameterExtensionKey}, - } + }} - assert.True(t, SupportsFileParameters(b)) + assert.True(t, b.SupportsFileParameters()) }) t.Run("unsupported", func(t *testing.T) { - b := bundle.Bundle{} + b := ExtendedBundle{bundle.Bundle{}} - assert.False(t, SupportsFileParameters(b)) + assert.False(t, b.SupportsFileParameters()) }) } diff --git a/pkg/cnab/helpers.go b/pkg/cnab/helpers.go index 856df3b3f5..020cdbd505 100644 --- a/pkg/cnab/helpers.go +++ b/pkg/cnab/helpers.go @@ -8,12 +8,12 @@ import ( "github.com/stretchr/testify/require" ) -func ReadTestBundle(t *testing.T, path string) bundle.Bundle { +func ReadTestBundle(t *testing.T, path string) ExtendedBundle { bunD, err := ioutil.ReadFile(path) require.NoError(t, err, "ReadFile failed for %s", path) bun, err := bundle.Unmarshal(bunD) require.NoError(t, err, "Unmarshal failed for bundle at %s", path) - return *bun + return ExtendedBundle{*bun} } diff --git a/pkg/cnab/extensions/parameter_sources.go b/pkg/cnab/parameter_sources.go similarity index 85% rename from pkg/cnab/extensions/parameter_sources.go rename to pkg/cnab/parameter_sources.go index ef23bf3c28..a17636cd68 100644 --- a/pkg/cnab/extensions/parameter_sources.go +++ b/pkg/cnab/parameter_sources.go @@ -1,4 +1,4 @@ -package extensions +package cnab import ( "encoding/json" @@ -157,7 +157,14 @@ type DependencyOutputParameterSource struct { // ParameterSources reference after reading from the applicable section from // the provided bundle func ReadParameterSources(bun bundle.Bundle) (ParameterSources, error) { - raw, err := ParameterSourcesReader(bun) + return ExtendedBundle{bun}.ReadParameterSources() +} + +// ReadParameterSources is a convenience method for returning a bonafide +// ParameterSources reference after reading from the applicable section from +// the provided bundle +func (b ExtendedBundle) ReadParameterSources() (ParameterSources, error) { + raw, err := b.ParameterSourcesReader() if err != nil { return nil, err } @@ -173,8 +180,15 @@ func ReadParameterSources(bun bundle.Bundle) (ParameterSources, error) { // ParameterSourcesReader is a Reader for the ParameterSourcesExtension, // which reads from the applicable section in the provided bundle and // returns a the raw data in the form of an interface -func ParameterSourcesReader(bun bundle.Bundle) (interface{}, error) { - data, ok := bun.Custom[ParameterSourcesExtensionKey] +func ParameterSourcesReader(bun ExtendedBundle) (interface{}, error) { + return bun.ParameterSourcesReader() +} + +// ParameterSourcesReader is a Reader for the ParameterSourcesExtension, +// which reads from the applicable section in the provided bundle and +// returns a the raw data in the form of an interface +func (b ExtendedBundle) ParameterSourcesReader() (interface{}, error) { + data, ok := b.Custom[ParameterSourcesExtensionKey] if !ok { return nil, errors.Errorf("attempted to read parameter sources from bundle but none are defined") } @@ -197,7 +211,12 @@ func ParameterSourcesReader(bun bundle.Bundle) (interface{}, error) { // SupportsParameterSources checks if the bundle supports parameter sources. func SupportsParameterSources(b bundle.Bundle) bool { - return SupportsExtension(b, ParameterSourcesExtensionKey) + return ExtendedBundle{b}.SupportsParameterSources() +} + +// SupportsParameterSources checks if the bundle supports parameter sources. +func (b ExtendedBundle) SupportsParameterSources() bool { + return b.SupportsExtension(ParameterSourcesExtensionKey) } // GetParameterSources checks if the parameter sources extension is present and returns its @@ -216,6 +235,11 @@ func (e ProcessedExtensions) GetParameterSources() (ParameterSources, bool, erro // HasParameterSources returns whether or not the bundle has parameter sources defined. func HasParameterSources(b bundle.Bundle) bool { + return ExtendedBundle{b}.HasParameterSources() +} + +// HasParameterSources returns whether or not the bundle has parameter sources defined. +func (b ExtendedBundle) HasParameterSources() bool { _, ok := b.Custom[ParameterSourcesExtensionKey] return ok } diff --git a/pkg/cnab/extensions/paramter_sources_test.go b/pkg/cnab/paramter_sources_test.go similarity index 86% rename from pkg/cnab/extensions/paramter_sources_test.go rename to pkg/cnab/paramter_sources_test.go index 515ad785a5..6ee613fe5a 100644 --- a/pkg/cnab/extensions/paramter_sources_test.go +++ b/pkg/cnab/paramter_sources_test.go @@ -1,4 +1,4 @@ -package extensions +package cnab import ( "io/ioutil" @@ -58,11 +58,12 @@ func TestReadParameterSourcesProperties(t *testing.T) { data, err := ioutil.ReadFile("testdata/bundle.json") require.NoError(t, err, "cannot read bundle file") - bun, err := bundle.Unmarshal(data) + b, err := bundle.Unmarshal(data) require.NoError(t, err, "could not unmarshal the bundle") - assert.True(t, HasParameterSources(*bun)) + bun := ExtendedBundle{*b} + assert.True(t, bun.HasParameterSources()) - ps, err := ReadParameterSources(*bun) + ps, err := bun.ReadParameterSources() require.NoError(t, err, "could not read parameter sources") want := ParameterSources{} @@ -87,16 +88,16 @@ func TestSupportsParameterSources(t *testing.T) { t.Parallel() t.Run("supported", func(t *testing.T) { - b := bundle.Bundle{ + b := ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{ParameterSourcesExtensionKey}, - } + }} - assert.True(t, SupportsParameterSources(b)) + assert.True(t, b.SupportsParameterSources()) }) t.Run("unsupported", func(t *testing.T) { - b := bundle.Bundle{} + b := ExtendedBundle{} - assert.False(t, SupportsParameterSources(b)) + assert.False(t, b.SupportsParameterSources()) }) } @@ -104,20 +105,20 @@ func TestHasParameterSources(t *testing.T) { t.Parallel() t.Run("has parameter sources", func(t *testing.T) { - b := bundle.Bundle{ + b := ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{ParameterSourcesExtensionKey}, Custom: map[string]interface{}{ ParameterSourcesExtensionKey: struct{}{}, }, - } + }} - assert.True(t, HasParameterSources(b)) + assert.True(t, b.HasParameterSources()) }) t.Run("no parameter sources", func(t *testing.T) { - b := bundle.Bundle{ + b := ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{ParameterSourcesExtensionKey}, - } + }} - assert.False(t, HasParameterSources(b)) + assert.False(t, b.HasParameterSources()) }) } diff --git a/pkg/cnab/provider/action.go b/pkg/cnab/provider/action.go index 6e7dde9191..3a3c051c6a 100644 --- a/pkg/cnab/provider/action.go +++ b/pkg/cnab/provider/action.go @@ -126,7 +126,7 @@ func (r *Runtime) Execute(args ActionArguments) error { // Create a record for the run we are about to execute var currentRun = args.Installation.NewRun(args.Action) - currentRun.Bundle = b + currentRun.Bundle = b.Bundle if args.BundleReference.Reference != (cnab.OCIReference{}) { currentRun.BundleReference = args.BundleReference.Reference.String() } diff --git a/pkg/cnab/provider/bundle.go b/pkg/cnab/provider/bundle.go index 500336f0ef..a89db023b0 100644 --- a/pkg/cnab/provider/bundle.go +++ b/pkg/cnab/provider/bundle.go @@ -2,24 +2,23 @@ package cnabprovider import ( "get.porter.sh/porter/pkg/cnab" - "github.com/cnabio/cnab-go/bundle" "github.com/pkg/errors" ) -func (r *Runtime) LoadBundle(bundleFile string) (bundle.Bundle, error) { +func (r *Runtime) LoadBundle(bundleFile string) (cnab.ExtendedBundle, error) { return cnab.LoadBundle(r.Context, bundleFile) } -func (r *Runtime) ProcessBundleFromFile(bundleFile string) (bundle.Bundle, error) { +func (r *Runtime) ProcessBundleFromFile(bundleFile string) (cnab.ExtendedBundle, error) { b, err := r.LoadBundle(bundleFile) if err != nil { - return bundle.Bundle{}, err + return cnab.ExtendedBundle{}, err } return r.ProcessBundle(b) } -func (r *Runtime) ProcessBundle(b bundle.Bundle) (bundle.Bundle, error) { +func (r *Runtime) ProcessBundle(b cnab.ExtendedBundle) (cnab.ExtendedBundle, error) { err := b.Validate() if err != nil { return b, errors.Wrap(err, "invalid bundle") diff --git a/pkg/cnab/provider/driver.go b/pkg/cnab/provider/driver.go index 19fc0b29c8..d8cd12ebf1 100644 --- a/pkg/cnab/provider/driver.go +++ b/pkg/cnab/provider/driver.go @@ -1,8 +1,8 @@ package cnabprovider import ( + "get.porter.sh/porter/pkg/cnab" "get.porter.sh/porter/pkg/cnab/drivers" - "get.porter.sh/porter/pkg/cnab/extensions" "github.com/cnabio/cnab-go/driver" "github.com/cnabio/cnab-go/driver/docker" "github.com/docker/docker/api/types/container" @@ -37,7 +37,7 @@ func (r *Runtime) newDriver(driverName string, args ActionArguments) (driver.Dri } else { if dockerRequired { return nil, errors.Errorf("extension %q is required but allow-docker-host-access was not enabled", - extensions.DockerExtensionKey) + cnab.DockerExtensionKey) } driverImpl, err = drivers.LookupDriver(r.Context, driverName) } @@ -60,7 +60,7 @@ func (r *Runtime) newDriver(driverName string, args ActionArguments) (driver.Dri return driverImpl, nil } -func (r *Runtime) dockerDriverWithHostAccess(config extensions.Docker) (driver.Driver, error) { +func (r *Runtime) dockerDriverWithHostAccess(config cnab.Docker) (driver.Driver, error) { const dockerSock = "/var/run/docker.sock" if exists, _ := r.FileSystem.Exists(dockerSock); !exists { diff --git a/pkg/cnab/provider/driver_test.go b/pkg/cnab/provider/driver_test.go index 6edc1bacb1..b88fde823d 100644 --- a/pkg/cnab/provider/driver_test.go +++ b/pkg/cnab/provider/driver_test.go @@ -3,7 +3,7 @@ package cnabprovider import ( "testing" - "get.porter.sh/porter/pkg/cnab/extensions" + "get.porter.sh/porter/pkg/cnab" "github.com/stretchr/testify/assert" "github.com/cnabio/cnab-go/driver/docker" @@ -79,7 +79,7 @@ func TestNewDriver_Docker(t *testing.T) { // Currently, toggling Privileged is the only config exposed to users // Here we supply no override, so expect Privileged to be false - r.Extensions[extensions.DockerExtensionKey] = extensions.Docker{} + r.Extensions[cnab.DockerExtensionKey] = cnab.Docker{} r.FileSystem.Create("/var/run/docker.sock") args := ActionArguments{ AllowDockerHostAccess: true, @@ -108,7 +108,7 @@ func TestNewDriver_Docker(t *testing.T) { // Currently, toggling Privileged is the only config exposed to users // Here we supply an override, so expect Privileged to be set to the override - r.Extensions[extensions.DockerExtensionKey] = extensions.Docker{ + r.Extensions[cnab.DockerExtensionKey] = cnab.Docker{ Privileged: true, } r.FileSystem.Create("/var/run/docker.sock") diff --git a/pkg/cnab/provider/helpers.go b/pkg/cnab/provider/helpers.go index 8f2e054ecd..7792754317 100644 --- a/pkg/cnab/provider/helpers.go +++ b/pkg/cnab/provider/helpers.go @@ -10,7 +10,6 @@ import ( "get.porter.sh/porter/pkg/credentials" "get.porter.sh/porter/pkg/parameters" "get.porter.sh/porter/pkg/storage" - "github.com/cnabio/cnab-go/bundle" "github.com/stretchr/testify/require" ) @@ -54,11 +53,11 @@ func (t *TestRuntime) Teardown() error { return nil } -func (t *TestRuntime) LoadBundle(bundleFile string) (bundle.Bundle, error) { +func (t *TestRuntime) LoadBundle(bundleFile string) (cnab.ExtendedBundle, error) { return t.Runtime.LoadBundle(bundleFile) } -func (t *TestRuntime) LoadTestBundle(bundleFile string) bundle.Bundle { +func (t *TestRuntime) LoadTestBundle(bundleFile string) cnab.ExtendedBundle { bun, err := cnab.LoadBundle(context.New(), bundleFile) require.NoError(t.TestConfig.TestContext.T, err) return bun diff --git a/pkg/cnab/provider/parameters.go b/pkg/cnab/provider/parameters.go index ebfa772c1c..d3175aae0b 100644 --- a/pkg/cnab/provider/parameters.go +++ b/pkg/cnab/provider/parameters.go @@ -4,10 +4,10 @@ import ( "encoding/base64" "fmt" + "get.porter.sh/porter/pkg/cnab" "get.porter.sh/porter/pkg/secrets" "get.porter.sh/porter/pkg/storage" - "get.porter.sh/porter/pkg/cnab/extensions" "github.com/cnabio/cnab-go/bundle" "github.com/cnabio/cnab-go/bundle/definition" "github.com/pkg/errors" @@ -16,7 +16,7 @@ import ( // loadParameters accepts a set of parameter overrides as well as parameter set // files and combines both with the default parameters to create a full set // of parameters. -func (r *Runtime) loadParameters(bun bundle.Bundle, args ActionArguments) (map[string]interface{}, error) { +func (r *Runtime) loadParameters(bun cnab.ExtendedBundle, args ActionArguments) (map[string]interface{}, error) { mergedParams := make(secrets.Set, len(args.Params)) paramSources, err := r.resolveParameterSources(bun, args) if err != nil { @@ -75,12 +75,12 @@ func (r *Runtime) loadParameters(bun bundle.Bundle, args ActionArguments) (map[s } - return bundle.ValuesOrDefaults(typedParams, &bun, args.Action) + return bundle.ValuesOrDefaults(typedParams, &bun.Bundle, args.Action) } -func (r *Runtime) getUnconvertedValueFromRaw(b bundle.Bundle, def *definition.Schema, key, rawValue string) (string, error) { +func (r *Runtime) getUnconvertedValueFromRaw(b cnab.ExtendedBundle, def *definition.Schema, key, rawValue string) (string, error) { // the parameter value (via rawValue) may represent a file on the local filesystem - if extensions.IsFileType(b, def) { + if b.IsFileType(def) { if _, err := r.FileSystem.Stat(rawValue); err == nil { bytes, err := r.FileSystem.ReadFile(rawValue) if err != nil { @@ -92,7 +92,7 @@ func (r *Runtime) getUnconvertedValueFromRaw(b bundle.Bundle, def *definition.Sc return rawValue, nil } -func (r *Runtime) resolveParameterSources(bun bundle.Bundle, args ActionArguments) (secrets.Set, error) { +func (r *Runtime) resolveParameterSources(bun cnab.ExtendedBundle, args ActionArguments) (secrets.Set, error) { if r.Debug { fmt.Fprintln(r.Err, "Resolving parameter sources...") } @@ -117,12 +117,12 @@ func (r *Runtime) resolveParameterSources(bun bundle.Bundle, args ActionArgument var installation string var outputName string switch source := rawSource.(type) { - case extensions.OutputParameterSource: + case cnab.OutputParameterSource: installation = args.Installation.Name outputName = source.OutputName - case extensions.DependencyOutputParameterSource: + case cnab.DependencyOutputParameterSource: // TODO(carolynvs): does this need to take namespace into account - installation = extensions.BuildPrerequisiteInstallationName(args.Installation.Name, source.Dependency) + installation = cnab.BuildPrerequisiteInstallationName(args.Installation.Name, source.Dependency) outputName = source.OutputName } @@ -149,7 +149,7 @@ func (r *Runtime) resolveParameterSources(bun bundle.Bundle, args ActionArgument return nil, fmt.Errorf("definition %s not defined in bundle", param.Definition) } - if extensions.IsFileType(bun, def) { + if bun.IsFileType(def) { values[parameterName] = base64.StdEncoding.EncodeToString(output.Value) } else { values[parameterName] = string(output.Value) diff --git a/pkg/cnab/provider/parameters_test.go b/pkg/cnab/provider/parameters_test.go index 359dc260ac..3f35863d19 100644 --- a/pkg/cnab/provider/parameters_test.go +++ b/pkg/cnab/provider/parameters_test.go @@ -5,7 +5,6 @@ import ( "get.porter.sh/porter/pkg/claims" "get.porter.sh/porter/pkg/cnab" - "get.porter.sh/porter/pkg/cnab/extensions" "get.porter.sh/porter/pkg/secrets" "github.com/cnabio/cnab-go/bundle" "github.com/cnabio/cnab-go/bundle/definition" @@ -19,9 +18,9 @@ func Test_loadParameters_paramNotDefined(t *testing.T) { r := NewTestRuntime(t) defer r.Teardown() - b := bundle.Bundle{ + b := cnab.ExtendedBundle{bundle.Bundle{ Parameters: map[string]bundle.Parameter{}, - } + }} overrides := map[string]string{ "foo": "bar", @@ -41,13 +40,13 @@ func Test_loadParameters_definitionNotDefined(t *testing.T) { r := NewTestRuntime(t) defer r.Teardown() - b := bundle.Bundle{ + b := cnab.ExtendedBundle{bundle.Bundle{ Parameters: map[string]bundle.Parameter{ "foo": { Definition: "foo", }, }, - } + }} overrides := map[string]string{ "foo": "bar", @@ -69,7 +68,7 @@ func Test_loadParameters_applyTo(t *testing.T) { // Here we set default values, but expect nil/empty // values for parameters that do not apply to a given action - b := bundle.Bundle{ + b := cnab.ExtendedBundle{bundle.Bundle{ Definitions: definition.Definitions{ "foo": &definition.Schema{ Type: "string", @@ -101,7 +100,7 @@ func Test_loadParameters_applyTo(t *testing.T) { }, }, }, - } + }} overrides := map[string]string{ "foo": "FOO", @@ -127,7 +126,7 @@ func Test_loadParameters_applyToBundleDefaults(t *testing.T) { r := NewTestRuntime(t) defer r.Teardown() - b := bundle.Bundle{ + b := cnab.ExtendedBundle{bundle.Bundle{ Definitions: definition.Definitions{ "foo": &definition.Schema{ Type: "string", @@ -142,7 +141,7 @@ func Test_loadParameters_applyToBundleDefaults(t *testing.T) { }, }, }, - } + }} args := ActionArguments{Action: "action"} params, err := r.loadParameters(b, args) @@ -157,7 +156,7 @@ func Test_loadParameters_requiredButDoesNotApply(t *testing.T) { r := NewTestRuntime(t) defer r.Teardown() - b := bundle.Bundle{ + b := cnab.ExtendedBundle{bundle.Bundle{ Definitions: definition.Definitions{ "foo": &definition.Schema{ Type: "string", @@ -172,7 +171,7 @@ func Test_loadParameters_requiredButDoesNotApply(t *testing.T) { Required: true, }, }, - } + }} args := ActionArguments{Action: "action"} params, err := r.loadParameters(b, args) @@ -189,9 +188,9 @@ func Test_loadParameters_fileParameter(t *testing.T) { r.TestConfig.TestContext.AddTestFile("testdata/file-param", "/path/to/file") - b := bundle.Bundle{ + b := cnab.ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{ - extensions.FileParameterExtensionKey, + cnab.FileParameterExtensionKey, }, Definitions: definition.Definitions{ "foo": &definition.Schema{ @@ -208,7 +207,7 @@ func Test_loadParameters_fileParameter(t *testing.T) { }, }, }, - } + }} overrides := map[string]string{ "foo": "/path/to/file", @@ -292,7 +291,7 @@ func Test_loadParameters_ParameterSourcePrecedence(t *testing.T) { require.NoError(t, err, "ProcessBundle failed") i := r.TestClaims.CreateInstallation(claims.NewInstallation("", "mybun")) - c := r.TestClaims.CreateRun(i.NewRun(cnab.ActionInstall), func(r *claims.Run) { r.Bundle = b }) + c := r.TestClaims.CreateRun(i.NewRun(cnab.ActionInstall), func(r *claims.Run) { r.Bundle = b.Bundle }) cr := r.TestClaims.CreateResult(c.NewResult(cnab.StatusSucceeded)) r.TestClaims.CreateOutput(cr.NewOutput("foo", []byte("foo_source"))) @@ -501,7 +500,7 @@ func Test_Paramapalooza(t *testing.T) { r := NewTestRuntime(t) defer r.Teardown() - bun := bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ Name: "mybuns", Version: "1.0.0", SchemaVersion: "v1.0.0", @@ -532,7 +531,7 @@ func Test_Paramapalooza(t *testing.T) { }, }, }, - } + }} if tc.DefaultExists { bun.Definitions["my-param"].Default = "my-param-default" @@ -609,7 +608,7 @@ func TestRuntime_ResolveParameterSources(t *testing.T) { r.TestClaims.CreateOutput(cr.NewOutput("connstr", []byte("connstr value"))) i = r.TestClaims.CreateInstallation(claims.NewInstallation("", "mybun")) - c = r.TestClaims.CreateRun(i.NewRun(cnab.ActionInstall), func(r *claims.Run) { r.Bundle = bun }) + c = r.TestClaims.CreateRun(i.NewRun(cnab.ActionInstall), func(r *claims.Run) { r.Bundle = bun.Bundle }) cr = r.TestClaims.CreateResult(c.NewResult(cnab.StatusSucceeded)) r.TestClaims.CreateOutput(cr.NewOutput("bar", []byte("bar value"))) diff --git a/pkg/cnab/provider/provider.go b/pkg/cnab/provider/provider.go index 7b825c469d..5ea56202ef 100644 --- a/pkg/cnab/provider/provider.go +++ b/pkg/cnab/provider/provider.go @@ -1,11 +1,11 @@ package cnabprovider import ( - "github.com/cnabio/cnab-go/bundle" + "get.porter.sh/porter/pkg/cnab" ) // CNABProvider is the interface Porter uses to communicate with the CNAB runtime type CNABProvider interface { - LoadBundle(bundleFile string) (bundle.Bundle, error) + LoadBundle(bundleFile string) (cnab.ExtendedBundle, error) Execute(arguments ActionArguments) error } diff --git a/pkg/cnab/provider/runtime.go b/pkg/cnab/provider/runtime.go index 51cde390f9..d3a85b376a 100644 --- a/pkg/cnab/provider/runtime.go +++ b/pkg/cnab/provider/runtime.go @@ -2,11 +2,10 @@ package cnabprovider import ( "get.porter.sh/porter/pkg/claims" - "get.porter.sh/porter/pkg/cnab/extensions" + "get.porter.sh/porter/pkg/cnab" "get.porter.sh/porter/pkg/config" "get.porter.sh/porter/pkg/credentials" "get.porter.sh/porter/pkg/parameters" - "github.com/cnabio/cnab-go/bundle" "github.com/pkg/errors" ) @@ -17,7 +16,7 @@ type Runtime struct { credentials credentials.Provider parameters parameters.Provider claims claims.Provider - Extensions extensions.ProcessedExtensions + Extensions cnab.ProcessedExtensions } func NewRuntime(c *config.Config, claims claims.Provider, credentials credentials.Provider) *Runtime { @@ -25,12 +24,12 @@ func NewRuntime(c *config.Config, claims claims.Provider, credentials credential Config: c, claims: claims, credentials: credentials, - Extensions: extensions.ProcessedExtensions{}, + Extensions: cnab.ProcessedExtensions{}, } } -func (r *Runtime) ProcessRequiredExtensions(b bundle.Bundle) error { - exts, err := extensions.ProcessRequiredExtensions(b) +func (r *Runtime) ProcessRequiredExtensions(b cnab.ExtendedBundle) error { + exts, err := b.ProcessRequiredExtensions() if err != nil { return errors.Wrap(err, "unable to process required extensions") } diff --git a/pkg/cnab/extensions/required.go b/pkg/cnab/required.go similarity index 77% rename from pkg/cnab/extensions/required.go rename to pkg/cnab/required.go index bac5a1de4a..5779def4cf 100644 --- a/pkg/cnab/extensions/required.go +++ b/pkg/cnab/required.go @@ -1,4 +1,4 @@ -package extensions +package cnab import ( "github.com/cnabio/cnab-go/bundle" @@ -10,7 +10,7 @@ type RequiredExtension struct { Shorthand string Key string Schema string - Reader func(b bundle.Bundle) (interface{}, error) + Reader func(b ExtendedBundle) (interface{}, error) } // SupportedExtensions represent a listing of the current required extensions @@ -35,6 +35,18 @@ type ProcessedExtensions map[string]interface{} // is read and returned in the form of a map of the extension name to // the extension configuration func ProcessRequiredExtensions(b bundle.Bundle) (ProcessedExtensions, error) { + return ExtendedBundle{b}.ProcessRequiredExtensions() +} + +// ProcessRequiredExtensions checks all required extensions in the provided +// bundle and makes sure Porter supports them. +// +// If an unsupported required extension is found, an error is returned. +// +// For each supported required extension, the configuration for that extension +// is read and returned in the form of a map of the extension name to +// the extension configuration +func (b ExtendedBundle) ProcessRequiredExtensions() (ProcessedExtensions, error) { processed := ProcessedExtensions{} for _, reqExt := range b.RequiredExtensions { supportedExtension, err := GetSupportedExtension(reqExt) diff --git a/pkg/cnab/extensions/required_test.go b/pkg/cnab/required_test.go similarity index 85% rename from pkg/cnab/extensions/required_test.go rename to pkg/cnab/required_test.go index e339750c08..7602ee6266 100644 --- a/pkg/cnab/extensions/required_test.go +++ b/pkg/cnab/required_test.go @@ -1,10 +1,9 @@ -package extensions +package cnab import ( "fmt" "testing" - "get.porter.sh/porter/pkg/cnab" "github.com/stretchr/testify/require" ) @@ -14,8 +13,8 @@ func TestProcessRequiredExtensions(t *testing.T) { t.Run("supported", func(t *testing.T) { t.Parallel() - bun := cnab.ReadTestBundle(t, "testdata/bundle.json") - exts, err := ProcessRequiredExtensions(bun) + bun := ReadTestBundle(t, "testdata/bundle.json") + exts, err := bun.ProcessRequiredExtensions() require.NoError(t, err, "could not process required extensions") expected := ProcessedExtensions{ @@ -58,16 +57,16 @@ func TestProcessRequiredExtensions(t *testing.T) { t.Run("supported unprocessable", func(t *testing.T) { t.Parallel() - bun := cnab.ReadTestBundle(t, "testdata/bundle-supported-unprocessable.json") - _, err := ProcessRequiredExtensions(bun) + bun := ReadTestBundle(t, "testdata/bundle-supported-unprocessable.json") + _, err := bun.ProcessRequiredExtensions() require.EqualError(t, err, "unable to process extension: io.cnab.docker: no custom extension configuration found") }) t.Run("unsupported", func(t *testing.T) { t.Parallel() - bun := cnab.ReadTestBundle(t, "testdata/bundle-unsupported-required.json") - _, err := ProcessRequiredExtensions(bun) + bun := ReadTestBundle(t, "testdata/bundle-unsupported-required.json") + _, err := bun.ProcessRequiredExtensions() require.EqualError(t, err, "unsupported required extension: donuts") }) } diff --git a/pkg/cnab/extensions/schema/io-cnab-docker.schema.json b/pkg/cnab/schema/io-cnab-docker.schema.json similarity index 100% rename from pkg/cnab/extensions/schema/io-cnab-docker.schema.json rename to pkg/cnab/schema/io-cnab-docker.schema.json diff --git a/pkg/cnab/extensions/solver.go b/pkg/cnab/solver.go similarity index 79% rename from pkg/cnab/extensions/solver.go rename to pkg/cnab/solver.go index 75013c6217..4ef78775e8 100644 --- a/pkg/cnab/extensions/solver.go +++ b/pkg/cnab/solver.go @@ -1,11 +1,9 @@ -package extensions +package cnab import ( "sort" - "get.porter.sh/porter/pkg/cnab" "github.com/Masterminds/semver/v3" - "github.com/cnabio/cnab-go/bundle" "github.com/google/go-containerregistry/pkg/crane" "github.com/pkg/errors" ) @@ -15,15 +13,16 @@ type DependencyLock struct { Reference string } +// TODO: move this logic onto the new ExtendedBundle struct type DependencySolver struct { } -func (s *DependencySolver) ResolveDependencies(bun bundle.Bundle) ([]DependencyLock, error) { - if !HasDependencies(bun) { +func (s *DependencySolver) ResolveDependencies(bun ExtendedBundle) ([]DependencyLock, error) { + if !bun.HasDependencies() { return nil, nil } - rawDeps, err := ReadDependencies(bun) + rawDeps, err := bun.ReadDependencies() // We need make sure the Dependencies are ordered by the desired sequence orderedDeps := rawDeps.ListBySequence() @@ -49,10 +48,10 @@ func (s *DependencySolver) ResolveDependencies(bun bundle.Bundle) ([]DependencyL } // ResolveVersion returns the bundle name, its version and any error. -func (s *DependencySolver) ResolveVersion(name string, dep Dependency) (cnab.OCIReference, error) { - ref, err := cnab.ParseOCIReference(dep.Bundle) +func (s *DependencySolver) ResolveVersion(name string, dep Dependency) (OCIReference, error) { + ref, err := ParseOCIReference(dep.Bundle) if err != nil { - return cnab.OCIReference{}, errors.Wrapf(err, "error parsing dependency (%s) bundle %q as OCI reference", name, dep.Bundle) + return OCIReference{}, errors.Wrapf(err, "error parsing dependency (%s) bundle %q as OCI reference", name, dep.Bundle) } // Here is where we could split out this logic into multiple strategy funcs / structs if necessary @@ -64,13 +63,13 @@ func (s *DependencySolver) ResolveVersion(name string, dep Dependency) (cnab.OCI tag, err := s.determineDefaultTag(dep) if err != nil { - return cnab.OCIReference{}, err + return OCIReference{}, err } return ref.WithTag(tag) } - return cnab.OCIReference{}, errors.Errorf("not implemented: dependency version range specified for %s", name) + return OCIReference{}, errors.Errorf("not implemented: dependency version range specified for %s", name) } func (s *DependencySolver) determineDefaultTag(dep Dependency) (string, error) { diff --git a/pkg/cnab/extensions/solver_test.go b/pkg/cnab/solver_test.go similarity index 98% rename from pkg/cnab/extensions/solver_test.go rename to pkg/cnab/solver_test.go index 492e85bbb0..fdd2c08982 100644 --- a/pkg/cnab/extensions/solver_test.go +++ b/pkg/cnab/solver_test.go @@ -1,4 +1,4 @@ -package extensions +package cnab import ( "testing" @@ -12,7 +12,7 @@ import ( func TestDependencySolver_ResolveDependencies(t *testing.T) { t.Parallel() - bun := bundle.Bundle{ + bun := ExtendedBundle{bundle.Bundle{ Custom: map[string]interface{}{ DependenciesExtensionKey: Dependencies{ Requires: map[string]Dependency{ @@ -25,7 +25,7 @@ func TestDependencySolver_ResolveDependencies(t *testing.T) { }, }, }, - } + }} s := DependencySolver{} locks, err := s.ResolveDependencies(bun) diff --git a/pkg/cnab/extensions/testdata/bundle-supported-unprocessable.json b/pkg/cnab/testdata/bundle-supported-unprocessable.json similarity index 100% rename from pkg/cnab/extensions/testdata/bundle-supported-unprocessable.json rename to pkg/cnab/testdata/bundle-supported-unprocessable.json diff --git a/pkg/cnab/extensions/testdata/bundle-unsupported-required.json b/pkg/cnab/testdata/bundle-unsupported-required.json similarity index 100% rename from pkg/cnab/extensions/testdata/bundle-unsupported-required.json rename to pkg/cnab/testdata/bundle-unsupported-required.json diff --git a/pkg/cnab/extensions/testdata/bundle.json b/pkg/cnab/testdata/bundle.json similarity index 100% rename from pkg/cnab/extensions/testdata/bundle.json rename to pkg/cnab/testdata/bundle.json diff --git a/pkg/generator/parameters.go b/pkg/generator/parameters.go index 0fdfaf698f..45a75f47bc 100644 --- a/pkg/generator/parameters.go +++ b/pkg/generator/parameters.go @@ -6,8 +6,8 @@ import ( "sort" "strings" + "get.porter.sh/porter/pkg/cnab" "get.porter.sh/porter/pkg/parameters" - "github.com/cnabio/cnab-go/bundle" ) // GenerateParametersOptions are the options to generate a Parameter Set @@ -15,7 +15,7 @@ type GenerateParametersOptions struct { GenerateOptions // Bundle to generate parameters from - Bundle bundle.Bundle + Bundle cnab.ExtendedBundle } // GenerateParameters will generate a parameter set based on the given options @@ -51,7 +51,7 @@ func (opts *GenerateParametersOptions) genParameterSet(fn generator) (parameters sort.Strings(parameterNames) for _, name := range parameterNames { - if parameters.IsInternal(name, opts.Bundle) { + if opts.Bundle.IsInternal(name) { continue } c, err := fn(name, surveyParameters) diff --git a/pkg/generator/parameters_test.go b/pkg/generator/parameters_test.go index 1b8d283947..56abfb9754 100644 --- a/pkg/generator/parameters_test.go +++ b/pkg/generator/parameters_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "get.porter.sh/porter/pkg/cnab" "get.porter.sh/porter/pkg/parameters" "github.com/cnabio/cnab-go/bundle" "github.com/cnabio/cnab-go/bundle/definition" @@ -33,7 +34,7 @@ func TestGoodParametersName(t *testing.T) { Name: name, Silent: true, }, - Bundle: bundle.Bundle{ + Bundle: cnab.ExtendedBundle{bundle.Bundle{ Parameters: map[string]bundle.Parameter{ "one": { Definition: "one", @@ -46,7 +47,7 @@ func TestGoodParametersName(t *testing.T) { }, }, }, - } + }} pset, err := opts.GenerateParameters() require.NoError(t, err, "name should NOT have resulted in an error") @@ -73,7 +74,7 @@ func TestEmptyParameters(t *testing.T) { Name: name, Silent: true, }, - Bundle: bundle.Bundle{}, + Bundle: cnab.ExtendedBundle{}, } pset, err := opts.GenerateParameters() require.NoError(t, err, "empty parameters should have generated an empty parameter set") @@ -98,7 +99,7 @@ func TestSkipParameters(t *testing.T) { Name: name, Silent: true, }, - Bundle: bundle.Bundle{ + Bundle: cnab.ExtendedBundle{bundle.Bundle{ Definitions: definition.Definitions{ "porter-debug": &definition.Schema{ Comment: parameters.PorterInternal, @@ -110,7 +111,7 @@ func TestSkipParameters(t *testing.T) { }, }, }, - } + }} pset, err := opts.GenerateParameters() require.NoError(t, err, "parameters generation should not have resulted in an error") diff --git a/pkg/porter/archive.go b/pkg/porter/archive.go index c75e7e54c3..55d2d0c344 100644 --- a/pkg/porter/archive.go +++ b/pkg/porter/archive.go @@ -7,6 +7,7 @@ import ( "path/filepath" "time" + "get.porter.sh/porter/pkg/cnab" "github.com/carolynvs/aferox" "github.com/cnabio/cnab-go/bundle" "github.com/cnabio/cnab-go/imagestore" @@ -78,7 +79,7 @@ type exporter struct { fs aferox.Aferox out io.Writer logs io.Writer - bundle bundle.Bundle + bundle cnab.ExtendedBundle destination io.Writer imageStoreConstructor imagestore.Constructor imageStore imagestore.Store @@ -158,7 +159,7 @@ func (ex *exporter) chtimes(path string) error { // prepareArtifacts pulls all images, verifies their digests and // saves them to a directory called artifacts/ in the bundle directory -func (ex *exporter) prepareArtifacts(bun bundle.Bundle) error { +func (ex *exporter) prepareArtifacts(bun cnab.ExtendedBundle) error { for _, image := range bun.Images { if err := ex.addImage(image.BaseImage); err != nil { return err diff --git a/pkg/porter/build.go b/pkg/porter/build.go index 33024a44cb..fc6168e050 100644 --- a/pkg/porter/build.go +++ b/pkg/porter/build.go @@ -5,12 +5,12 @@ import ( "os" "get.porter.sh/porter/pkg/build" + "get.porter.sh/porter/pkg/cnab" configadapter "get.porter.sh/porter/pkg/cnab/config-adapter" "get.porter.sh/porter/pkg/config" "get.porter.sh/porter/pkg/mixin" "get.porter.sh/porter/pkg/printer" "github.com/Masterminds/semver/v3" - "github.com/cnabio/cnab-go/bundle" "github.com/opencontainers/go-digest" "github.com/pkg/errors" ) @@ -185,7 +185,7 @@ func (p *Porter) buildBundle(invocationImage string, digest digest.Digest) error return p.writeBundle(bun) } -func (p Porter) writeBundle(b bundle.Bundle) error { +func (p Porter) writeBundle(b cnab.ExtendedBundle) error { f, err := p.Config.FileSystem.OpenFile(build.LOCAL_BUNDLE, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) defer f.Close() if err != nil { diff --git a/pkg/porter/build_test.go b/pkg/porter/build_test.go index 8c2d6b3a79..bb07e8ba33 100644 --- a/pkg/porter/build_test.go +++ b/pkg/porter/build_test.go @@ -50,18 +50,14 @@ func TestPorter_Build(t *testing.T) { junkExists, _ = p.FileSystem.DirExists(junkDir) assert.False(t, junkExists, "junk files were not cleaned up before building") - bundleBytes, err := p.FileSystem.ReadFile(build.LOCAL_BUNDLE) - require.NoError(t, err) - - bun := &bundle.Bundle{} - err = json.Unmarshal(bundleBytes, bun) + bun, err := p.CNAB.LoadBundle(build.LOCAL_BUNDLE) require.NoError(t, err) assert.Equal(t, bun.Name, "porter-hello") assert.Equal(t, bun.Version, "0.1.0") assert.Equal(t, bun.Description, "An example Porter configuration") - stamp, err := configadapter.LoadStamp(*bun) + stamp, err := configadapter.LoadStamp(bun) require.NoError(t, err) assert.Equal(t, "d421a6249dfbdba79e26e866da7533d59590565708dfdb32423cf989f588d0ea", stamp.ManifestDigest) diff --git a/pkg/porter/credentials.go b/pkg/porter/credentials.go index c0966c7d1a..aec233cc82 100644 --- a/pkg/porter/credentials.go +++ b/pkg/porter/credentials.go @@ -303,6 +303,9 @@ func validateCredentialName(args []string) error { func (p *Porter) CredentialsApply(o ApplyOptions) error { namespace, err := p.getNamespaceFromFile(o) + if err != nil { + return err + } var creds credentials.CredentialSet err = encoding.UnmarshalFile(p.FileSystem, o.File, &creds) diff --git a/pkg/porter/dependencies.go b/pkg/porter/dependencies.go index d9950efe90..22a3617c03 100644 --- a/pkg/porter/dependencies.go +++ b/pkg/porter/dependencies.go @@ -6,12 +6,10 @@ import ( "get.porter.sh/porter/pkg/claims" "get.porter.sh/porter/pkg/cnab" - "get.porter.sh/porter/pkg/cnab/extensions" cnabprovider "get.porter.sh/porter/pkg/cnab/provider" "get.porter.sh/porter/pkg/context" "get.porter.sh/porter/pkg/manifest" "get.porter.sh/porter/pkg/runtime" - "github.com/cnabio/cnab-go/bundle" "github.com/hashicorp/go-multierror" "github.com/pkg/errors" ) @@ -50,7 +48,7 @@ func newDependencyExecutioner(p *Porter, action string) *dependencyExecutioner { } type queuedDependency struct { - extensions.DependencyLock + cnab.DependencyLock BundleReference cnab.BundleReference Parameters map[string]string @@ -124,7 +122,7 @@ func (e *dependencyExecutioner) PrepareRootActionArguments(args *cnabprovider.Ac func (e *dependencyExecutioner) identifyDependencies() error { // Load parent CNAB bundle definition - var bun bundle.Bundle + var bun cnab.ExtendedBundle if e.parentOpts.CNABFile != "" { bundle, err := e.CNAB.LoadBundle(e.parentOpts.CNABFile) if err != nil { @@ -144,13 +142,13 @@ func (e *dependencyExecutioner) identifyDependencies() error { return err } - bun = c.Bundle + bun = cnab.ExtendedBundle{c.Bundle} } else { // If we hit here, there is a bug somewhere return errors.New("identifyDependencies failed to load the bundle because no bundle was specified. Please report this bug to https://github.com/getporter/porter/issues/new/choose") } - solver := &extensions.DependencySolver{} + solver := &cnab.DependencySolver{} locks, err := solver.ResolveDependencies(bun) if err != nil { return err @@ -250,15 +248,15 @@ func (e *dependencyExecutioner) prepareDependency(dep *queuedDependency) error { func (e *dependencyExecutioner) executeDependency(dep *queuedDependency) error { depInstallation := claims.NewInstallation(e.parentOpts.Namespace, - extensions.BuildPrerequisiteInstallationName(e.parentOpts.Name, dep.Alias)) + cnab.BuildPrerequisiteInstallationName(e.parentOpts.Name, dep.Alias)) depArgs := cnabprovider.ActionArguments{ - BundleReference: dep.BundleReference, - Action: e.parentArgs.Action, - Installation: depInstallation, - Driver: e.parentArgs.Driver, + BundleReference: dep.BundleReference, + Action: e.parentArgs.Action, + Installation: depInstallation, + Driver: e.parentArgs.Driver, AllowDockerHostAccess: e.parentOpts.AllowAccessToDockerHost, - Params: dep.Parameters, + Params: dep.Parameters, // For now, assume it's okay to give the dependency the same credentials as the parent CredentialIdentifiers: e.parentArgs.CredentialIdentifiers, } diff --git a/pkg/porter/explain.go b/pkg/porter/explain.go index 36c3705936..5c9dd21b1f 100644 --- a/pkg/porter/explain.go +++ b/pkg/porter/explain.go @@ -5,10 +5,9 @@ import ( "sort" "strings" + "get.porter.sh/porter/pkg/cnab" configadapter "get.porter.sh/porter/pkg/cnab/config-adapter" - "get.porter.sh/porter/pkg/cnab/extensions" "get.porter.sh/porter/pkg/context" - "get.porter.sh/porter/pkg/parameters" "get.porter.sh/porter/pkg/printer" "github.com/cnabio/cnab-go/bundle" "github.com/pkg/errors" @@ -177,7 +176,7 @@ func (p *Porter) printBundleExplain(o ExplainOpts, pb *PrintableBundle) error { } } -func generatePrintable(bun bundle.Bundle, action string) (*PrintableBundle, error) { +func generatePrintable(bun cnab.ExtendedBundle, action string) (*PrintableBundle, error) { var stamp configadapter.Stamp stamp, err := configadapter.LoadStamp(bun) @@ -219,7 +218,7 @@ func generatePrintable(bun bundle.Bundle, action string) (*PrintableBundle, erro params := make([]PrintableParameter, 0, len(bun.Parameters)) for p, v := range bun.Parameters { - if parameters.IsInternal(p, bun) { + if bun.IsInternal(p) { continue } def, ok := bun.Definitions[v.Definition] @@ -231,7 +230,7 @@ func generatePrintable(bun bundle.Bundle, action string) (*PrintableBundle, erro } pp := PrintableParameter{} pp.Name = p - pp.Type = extensions.GetParameterType(bun, def) + pp.Type = bun.GetParameterType(def) pp.Default = def.Default pp.ApplyTo = generateApplyToString(v.ApplyTo) pp.Required = v.Required @@ -264,7 +263,7 @@ func generatePrintable(bun bundle.Bundle, action string) (*PrintableBundle, erro } sort.Sort(SortPrintableOutput(outputs)) - solver := &extensions.DependencySolver{} + solver := &cnab.DependencySolver{} deps, err := solver.ResolveDependencies(bun) if err != nil { return nil, errors.Wrapf(err, "error executing dependencies") diff --git a/pkg/porter/explain_test.go b/pkg/porter/explain_test.go index 167be65b18..ff2a10db7b 100644 --- a/pkg/porter/explain_test.go +++ b/pkg/porter/explain_test.go @@ -5,7 +5,7 @@ import ( "io/ioutil" "testing" - "get.porter.sh/porter/pkg/cnab/extensions" + "get.porter.sh/porter/pkg/cnab" "github.com/cnabio/cnab-go/bundle" "github.com/cnabio/cnab-go/bundle/definition" "github.com/stretchr/testify/assert" @@ -199,9 +199,9 @@ func TestExplain_generateYAML(t *testing.T) { } func TestExplain_generatePrintableBundleParams(t *testing.T) { - bun := bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{ - extensions.FileParameterExtensionKey, + cnab.FileParameterExtensionKey, }, Definitions: definition.Definitions{ "string": &definition.Schema{ @@ -229,7 +229,7 @@ func TestExplain_generatePrintableBundleParams(t *testing.T) { "commit": "3b7c85ba", }, }, - } + }} pb, err := generatePrintable(bun, "") require.NoError(t, err) @@ -249,9 +249,9 @@ func TestExplain_generatePrintableBundleParams(t *testing.T) { } func TestExplain_generatePrintableBundleParamsWithAction(t *testing.T) { - bun := bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ RequiredExtensions: []string{ - extensions.FileParameterExtensionKey, + cnab.FileParameterExtensionKey, }, Definitions: definition.Definitions{ "string": &definition.Schema{ @@ -280,7 +280,7 @@ func TestExplain_generatePrintableBundleParamsWithAction(t *testing.T) { "commit": "3b7c85ba", }, }, - } + }} t.Run("action applies", func(t *testing.T) { pb, err := generatePrintable(bun, "install") @@ -322,7 +322,7 @@ func TestExplain_generatePrintableBundleParamsWithAction(t *testing.T) { } func TestExplain_generatePrintableBundleOutputs(t *testing.T) { - bun := bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ Definitions: definition.Definitions{ "string": &definition.Schema{ Type: "string", @@ -345,7 +345,7 @@ func TestExplain_generatePrintableBundleOutputs(t *testing.T) { "commit": "3b7c85ba", }, }, - } + }} pb, err := generatePrintable(bun, "") require.NoError(t, err) @@ -377,7 +377,7 @@ func TestExplain_generatePrintableBundleOutputs(t *testing.T) { } func TestExplain_generatePrintableBundleCreds(t *testing.T) { - bun := bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ Credentials: map[string]bundle.Credential{ "kubeconfig": { Required: true, @@ -395,7 +395,7 @@ func TestExplain_generatePrintableBundleCreds(t *testing.T) { "commit": "3b7c85ba", }, }, - } + }} t.Run("action applies", func(t *testing.T) { pb, err := generatePrintable(bun, "install") @@ -437,7 +437,7 @@ func TestExplain_generatePrintableBundleCreds(t *testing.T) { } func TestExplain_generatePrintableBundlePorterVersion(t *testing.T) { - bun := bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ Definitions: definition.Definitions{ "string": &definition.Schema{ Type: "string", @@ -451,7 +451,7 @@ func TestExplain_generatePrintableBundlePorterVersion(t *testing.T) { "commit": "3b7c85ba", }, }, - } + }} pb, err := generatePrintable(bun, "") assert.NoError(t, err) @@ -460,14 +460,14 @@ func TestExplain_generatePrintableBundlePorterVersion(t *testing.T) { } func TestExplain_generatePrintableBundlePorterVersionNonPorterBundle(t *testing.T) { - bun := bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ Definitions: definition.Definitions{ "string": &definition.Schema{ Type: "string", Default: "clippy", }, }, - } + }} pb, err := generatePrintable(bun, "") assert.NoError(t, err) @@ -478,20 +478,20 @@ func TestExplain_generatePrintableBundlePorterVersionNonPorterBundle(t *testing. func TestExplain_generatePrintableBundleDependencies(t *testing.T) { sequenceMock := []string{"nginx", "storage", "mysql"} - bun := bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ Custom: map[string]interface{}{ - extensions.DependenciesExtensionKey: extensions.Dependencies{ + cnab.DependenciesExtensionKey: cnab.Dependencies{ Sequence: sequenceMock, - Requires: map[string]extensions.Dependency{ - "mysql": extensions.Dependency{ + Requires: map[string]cnab.Dependency{ + "mysql": cnab.Dependency{ Name: "mysql", Bundle: "somecloud/mysql:0.1.0", }, - "storage": extensions.Dependency{ + "storage": cnab.Dependency{ Name: "storage", Bundle: "localhost:5000/blob-storage:0.1.0", }, - "nginx": extensions.Dependency{ + "nginx": cnab.Dependency{ Name: "nginx", Bundle: "localhost:5000/nginx:1.19", }, @@ -503,7 +503,7 @@ func TestExplain_generatePrintableBundleDependencies(t *testing.T) { "commit": "3b7c85ba", }, }, - } + }} pd, err := generatePrintable(bun, "") assert.NoError(t, err) diff --git a/pkg/porter/lifecycle.go b/pkg/porter/lifecycle.go index 19432f027f..8545692516 100644 --- a/pkg/porter/lifecycle.go +++ b/pkg/porter/lifecycle.go @@ -92,7 +92,7 @@ func (p *Porter) resolveBundleReference(opts *BundleActionOptions) (cnab.BundleR } bundleRef = cnab.BundleReference{ - Definition: lastRun.Bundle, + Definition: cnab.ExtendedBundle{lastRun.Bundle}, Digest: digest.Digest(lastRun.BundleDigest)} if lastRun.BundleReference != "" { diff --git a/pkg/porter/outputs.go b/pkg/porter/outputs.go index 6c1a5a8e9d..6bba1ca09a 100644 --- a/pkg/porter/outputs.go +++ b/pkg/porter/outputs.go @@ -5,7 +5,7 @@ import ( "sort" claims "get.porter.sh/porter/pkg/claims" - "get.porter.sh/porter/pkg/cnab/extensions" + "get.porter.sh/porter/pkg/cnab" "get.porter.sh/porter/pkg/context" "get.porter.sh/porter/pkg/printer" "github.com/cnabio/cnab-go/bundle" @@ -91,7 +91,7 @@ func NewDisplayValuesFromOutputs(bun bundle.Bundle, outputs claims.Outputs) Disp do.SetValue(output.Value) schema, ok := output.GetSchema(bun) if ok { - do.Type = extensions.GetParameterType(bun, &schema) + do.Type = cnab.GetParameterType(bun, &schema) if schema.WriteOnly != nil && *schema.WriteOnly { do.Sensitive = true } diff --git a/pkg/porter/parameters.go b/pkg/porter/parameters.go index 06b21b6bf6..265fcbd194 100644 --- a/pkg/porter/parameters.go +++ b/pkg/porter/parameters.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "get.porter.sh/porter/pkg/cnab/extensions" + "get.porter.sh/porter/pkg/cnab" "get.porter.sh/porter/pkg/context" "get.porter.sh/porter/pkg/editor" "get.porter.sh/porter/pkg/encoding" @@ -135,7 +135,7 @@ func (p *Porter) GenerateParameters(opts ParameterOptions) error { numExternalParams := 0 for name := range bundleRef.Definition.Parameters { - if !parameters.IsInternal(name, bundleRef.Definition) { + if !bundleRef.Definition.IsInternal(name) { numExternalParams += 1 } } @@ -443,7 +443,7 @@ func NewDisplayValuesFromParameters(bun bundle.Bundle, params map[string]interfa schema, ok := bun.Definitions[def.Definition] if ok { - dp.Type = extensions.GetParameterType(bun, schema) + dp.Type = cnab.GetParameterType(bun, schema) if schema.WriteOnly != nil && *schema.WriteOnly { dp.Sensitive = true } @@ -479,6 +479,9 @@ func (p *Porter) printDisplayValuesTable(values []DisplayValue) error { func (p *Porter) ParametersApply(o ApplyOptions) error { namespace, err := p.getNamespaceFromFile(o) + if err != nil { + return err + } var params parameters.ParameterSet err = encoding.UnmarshalFile(p.FileSystem, o.File, ¶ms) diff --git a/pkg/porter/publish.go b/pkg/porter/publish.go index ff46a3c3bf..d5ea942db1 100644 --- a/pkg/porter/publish.go +++ b/pkg/porter/publish.go @@ -1,7 +1,6 @@ package porter import ( - "bytes" "fmt" "path" "path/filepath" @@ -10,7 +9,6 @@ import ( "get.porter.sh/porter/pkg/build" "get.porter.sh/porter/pkg/cnab" portercontext "get.porter.sh/porter/pkg/context" - "github.com/cnabio/cnab-go/bundle" "github.com/cnabio/cnab-go/bundle/loader" "github.com/cnabio/cnab-go/packager" "github.com/opencontainers/go-digest" @@ -263,8 +261,8 @@ func (p *Porter) publishFromArchive(opts PublishOptions) error { return p.refreshCachedBundle(bundleRef) } -// extractBundle extracts a bundle using the provided opts and returnsthe extracted bundle -func (p *Porter) extractBundle(tmpDir, source string) (bundle.Bundle, error) { +// extractBundle extracts a bundle using the provided opts and returns the extracted bundle +func (p *Porter) extractBundle(tmpDir, source string) (cnab.ExtendedBundle, error) { if p.Debug { fmt.Fprintf(p.Err, "Extracting bundle from archive %s...\n", source) } @@ -273,15 +271,15 @@ func (p *Porter) extractBundle(tmpDir, source string) (bundle.Bundle, error) { imp := packager.NewImporter(source, tmpDir, l) err := imp.Import() if err != nil { - return bundle.Bundle{}, errors.Wrapf(err, "failed to extract bundle from archive %s", source) + return cnab.ExtendedBundle{}, errors.Wrapf(err, "failed to extract bundle from archive %s", source) } bun, err := l.Load(filepath.Join(tmpDir, strings.TrimSuffix(filepath.Base(source), ".tgz"), "bundle.json")) if err != nil { - return bundle.Bundle{}, errors.Wrapf(err, "failed to load bundle from archive %s", source) + return cnab.ExtendedBundle{}, errors.Wrapf(err, "failed to load bundle from archive %s", source) } - return *bun, nil + return cnab.ExtendedBundle{*bun}, nil } // pushUpdatedImage uses the provided layout to find the provided origImg, @@ -306,7 +304,7 @@ func pushUpdatedImage(layout registry.Layout, origImg string, newImgName image.N } // updateBundleWithNewImage updates a bundle with a new image (with digest) at the provided index -func (p *Porter) updateBundleWithNewImage(bun bundle.Bundle, newImg image.Name, digest image.Digest, index interface{}) error { +func (p *Porter) updateBundleWithNewImage(bun cnab.ExtendedBundle, newImg image.Name, digest image.Digest, index interface{}) error { taggedImage, err := p.rewriteImageWithDigest(newImg.String(), digest.String()) if err != nil { return errors.Wrapf(err, "unable to update image reference for %s", newImg.String()) @@ -359,22 +357,21 @@ func getNewImageNameFromBundleReference(origImg, bundleTag string) (image.Name, return newImgName, nil } -func (p *Porter) rewriteBundleWithInvocationImageDigest(digest digest.Digest, manifestPath string) (bundle.Bundle, error) { +func (p *Porter) rewriteBundleWithInvocationImageDigest(digest digest.Digest, manifestPath string) (cnab.ExtendedBundle, error) { taggedImage, err := p.rewriteImageWithDigest(p.Manifest.Image, digest.String()) if err != nil { - return bundle.Bundle{}, errors.Wrap(err, "unable to update invocation image reference") + return cnab.ExtendedBundle{}, errors.Wrap(err, "unable to update invocation image reference") } fmt.Fprintln(p.Out, "\nRewriting CNAB bundle.json...") err = p.buildBundle(taggedImage, digest) if err != nil { - return bundle.Bundle{}, errors.Wrap(err, "unable to rewrite CNAB bundle.json with updated invocation image digest") + return cnab.ExtendedBundle{}, errors.Wrap(err, "unable to rewrite CNAB bundle.json with updated invocation image digest") } - b, err := p.FileSystem.ReadFile(build.LOCAL_BUNDLE) - bun, err := bundle.ParseReader(bytes.NewBuffer(b)) + bun, err := cnab.LoadBundle(p.Context, build.LOCAL_BUNDLE) if err != nil { - return bundle.Bundle{}, errors.Wrap(err, "unable to load CNAB bundle") + return cnab.ExtendedBundle{}, errors.Wrap(err, "unable to load CNAB bundle") } return bun, nil diff --git a/pkg/porter/publish_test.go b/pkg/porter/publish_test.go index 02bb64dcf4..d0dac1540d 100644 --- a/pkg/porter/publish_test.go +++ b/pkg/porter/publish_test.go @@ -149,7 +149,7 @@ func TestPublish_UpdateBundleWithNewImage(t *testing.T) { p := NewTestPorter(t) defer p.Teardown() - bun := bundle.Bundle{ + bun := cnab.ExtendedBundle{bundle.Bundle{ Name: "mybuns", InvocationImages: []bundle.InvocationImage{ { @@ -167,7 +167,7 @@ func TestPublish_UpdateBundleWithNewImage(t *testing.T) { }, }, }, - } + }} tag := "myneworg/mynewbuns" digest, err := image.NewDigest("sha256:6b5a28ccbb76f12ce771a23757880c6083234255c5ba191fca1c5db1f71c1687") @@ -198,7 +198,7 @@ func TestPublish_RefreshCachedBundle(t *testing.T) { bundleRef := cnab.BundleReference{ Reference: cnab.MustParseOCIReference("myreg/mybuns"), - Definition: bundle.Bundle{Name: "myreg/mybuns"}, + Definition: cnab.ExtendedBundle{bundle.Bundle{Name: "myreg/mybuns"}}, } // No-Op; bundle does not yet exist in cache @@ -234,7 +234,7 @@ func TestPublish_RefreshCachedBundle_OnlyWarning(t *testing.T) { bundleRef := cnab.BundleReference{ Reference: cnab.MustParseOCIReference("myreg/mybuns"), - Definition: bundle.Bundle{Name: "myreg/mybuns"}, + Definition: cnab.ExtendedBundle{bundle.Bundle{Name: "myreg/mybuns"}}, } p.TestCache.FindBundleMock = func(ref cnab.OCIReference) (cachedBundle cache.CachedBundle, found bool, err error) { diff --git a/pkg/porter/stamp.go b/pkg/porter/stamp.go index d1497e049b..ad597bac88 100644 --- a/pkg/porter/stamp.go +++ b/pkg/porter/stamp.go @@ -65,6 +65,7 @@ func (p *Porter) IsBundleUpToDate(opts bundleFileOptions) (bool, error) { return false, errors.Wrapf(err, "could not load stamp from %s", opts.CNABFile) } + // TODO(carolynvs): change this to be a function on extended bundle mixins, err := p.getUsedMixins() if err != nil { return false, errors.Wrapf(err, "error while listing used mixins") diff --git a/pkg/runtime/runtime-manifest.go b/pkg/runtime/runtime-manifest.go index 6c6b23792a..22aadd6b17 100644 --- a/pkg/runtime/runtime-manifest.go +++ b/pkg/runtime/runtime-manifest.go @@ -8,7 +8,6 @@ import ( "strings" "get.porter.sh/porter/pkg/cnab" - "get.porter.sh/porter/pkg/cnab/extensions" "get.porter.sh/porter/pkg/config" "get.porter.sh/porter/pkg/context" "get.porter.sh/porter/pkg/manifest" @@ -26,7 +25,7 @@ type RuntimeManifest struct { Action string // bundle is the executing bundle definition - bundle bundle.Bundle + bundle cnab.ExtendedBundle // bundles is map of the dependencies bundle definitions, keyed by the alias used in the root manifest bundles map[string]bundle.Bundle @@ -286,7 +285,7 @@ func (m *RuntimeManifest) buildSourceData() (map[string]interface{}, error) { // Externally injected outputs (bundle level outputs and dependency outputs) are // injected through parameter sources. - bunExt, err := extensions.ProcessRequiredExtensions(m.bundle) + bunExt, err := m.bundle.ProcessRequiredExtensions() if err != nil { return nil, err } @@ -306,7 +305,7 @@ func (m *RuntimeManifest) buildSourceData() (map[string]interface{}, error) { for _, s := range sources.ListSourcesByPriority() { switch ps := s.(type) { - case extensions.DependencyOutputParameterSource: + case cnab.DependencyOutputParameterSource: outRef := manifest.DependencyOutputReference{Dependency: ps.Dependency, Output: ps.OutputName} // Ignore anything that isn't templated, because that's what we are building the source data for @@ -336,7 +335,7 @@ func (m *RuntimeManifest) buildSourceData() (map[string]interface{}, error) { m.setSensitiveValue(value) } - case extensions.OutputParameterSource: + case cnab.OutputParameterSource: // Ignore anything that isn't templated, because that's what we are building the source data for if _, isTemplated := templatedOutputs[ps.OutputName]; !isTemplated { continue @@ -513,7 +512,7 @@ func resolveImage(image *manifest.MappedImage, refString string) error { image.Tag = ref.Tag() } - if ref.IsRepositoryOnly(){ + if ref.IsRepositoryOnly() { image.Tag = "latest" // Populate this with latest so that the {{ can reference something }} } diff --git a/pkg/runtime/runtime-manifest_test.go b/pkg/runtime/runtime-manifest_test.go index cc5c9476ae..3083ea8e9b 100644 --- a/pkg/runtime/runtime-manifest_test.go +++ b/pkg/runtime/runtime-manifest_test.go @@ -6,7 +6,6 @@ import ( "testing" "get.porter.sh/porter/pkg/cnab" - "get.porter.sh/porter/pkg/cnab/extensions" "get.porter.sh/porter/pkg/config" "get.porter.sh/porter/pkg/context" "get.porter.sh/porter/pkg/manifest" @@ -404,15 +403,15 @@ func TestResolveStep_DependencyOutput(t *testing.T) { } rm := NewRuntimeManifest(cxt.Context, cnab.ActionInstall, m) - ps := extensions.ParameterSources{} + ps := cnab.ParameterSources{} ps.SetParameterFromDependencyOutput("porter-mysql-password", "mysql", "password") ps.SetParameterFromDependencyOutput("porter-mysql-root-password", "mysql", "root-password") - rm.bundle = bundle.Bundle{ + rm.bundle = cnab.ExtendedBundle{bundle.Bundle{ Custom: map[string]interface{}{ - extensions.ParameterSourcesExtensionKey: ps, + cnab.ParameterSourcesExtensionKey: ps, }, - RequiredExtensions: []string{extensions.ParameterSourcesExtensionKey}, - } + RequiredExtensions: []string{cnab.ParameterSourcesExtensionKey}, + }} rm.bundles = map[string]bundle.Bundle{ "mysql": { diff --git a/tests/smoke/main_test.go b/tests/smoke/main_test.go index e6b6a9e44e..a162122212 100644 --- a/tests/smoke/main_test.go +++ b/tests/smoke/main_test.go @@ -90,6 +90,7 @@ func (t Test) startMongo() error { func (t Test) RequirePorter(args ...string) { err := t.Porter(args...).RunV() require.NoError(t.T, err) + t.T.Log("done") } // Run a porter command returning stderr when it fails