From ba6cecfc989c00a57858e63a392533a24713eb6f Mon Sep 17 00:00:00 2001 From: Jeremy Rickard Date: Tue, 8 Oct 2019 09:41:45 -0600 Subject: [PATCH 1/7] Add support for wiring --- pkg/config/relocation.go | 4 +++ pkg/manifest/runtime-manifest.go | 44 +++++++++++++++++++++++++++ pkg/manifest/runtime-manifest_test.go | 40 ++++++++++++++++++++++++ pkg/porter/run.go | 27 ++++++++++++++++ pkg/porter/run_test.go | 2 +- pkg/porter/testdata/bundle.json | 1 + 6 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 pkg/config/relocation.go create mode 100644 pkg/porter/testdata/bundle.json diff --git a/pkg/config/relocation.go b/pkg/config/relocation.go new file mode 100644 index 000000000..89a521a13 --- /dev/null +++ b/pkg/config/relocation.go @@ -0,0 +1,4 @@ +package config + +// RelocationMapping represents a runtime provided mapping of a bundle image to a new tag +type RelocationMapping map[string]string diff --git a/pkg/manifest/runtime-manifest.go b/pkg/manifest/runtime-manifest.go index f6e66dba4..029b0a9e0 100644 --- a/pkg/manifest/runtime-manifest.go +++ b/pkg/manifest/runtime-manifest.go @@ -11,7 +11,9 @@ import ( "github.com/cbroglie/mustache" "github.com/deislabs/cnab-go/bundle" + "github.com/deislabs/porter/pkg/config" "github.com/deislabs/porter/pkg/runtime" + "github.com/docker/distribution/reference" "github.com/pkg/errors" "gopkg.in/yaml.v2" ) @@ -306,3 +308,45 @@ func (m *RuntimeManifest) Prepare() error { } return nil } + +// ResolveImages updates the RuntimeManifest to properly reflect that image map passed to the bundle via the +// mounted bundle.json and relocation mapping +func (m *RuntimeManifest) ResolveImages(bun *bundle.Bundle, reloMap config.RelocationMapping) error { + for alias, image := range bun.Images { + manifestImage := m.ImageMap[alias] + manifestImage.Digest = image.Digest + err := resolveImage(&manifestImage, image.Image) + if err != nil { + return errors.Wrap(err, "unable to update image map from bundle.json") + } + } + + for alias, reloRef := range reloMap { + manifestImage := m.ImageMap[alias] + err := resolveImage(&manifestImage, reloRef) + if err != nil { + return errors.Wrap(err, "unable to update image map from relocation mapping") + } + } + return nil +} + +func resolveImage(image *MappedImage, refString string) error { + //figure out what type of Reference it is so we can extract useful things for our image map + ref, err := reference.Parse(refString) + if err != nil { + return errors.Wrapf(err, "unable to parse docker image %s", refString) + } + switch v := ref.(type) { + case reference.Canonical: + image.Repository = v.Name() + image.Digest = v.Digest().String() + case reference.NamedTagged: + image.Tag = v.Tag() + image.Repository = v.Name() + case reference.Named: + image.Repository = v.Name() + image.Tag = "latest" //Populate this with latest so that the {{ can reference something }} + } + return nil +} diff --git a/pkg/manifest/runtime-manifest_test.go b/pkg/manifest/runtime-manifest_test.go index 7905c8fcb..dbf6a81be 100644 --- a/pkg/manifest/runtime-manifest_test.go +++ b/pkg/manifest/runtime-manifest_test.go @@ -863,3 +863,43 @@ func TestManifest_ResolveImageMapMissingImage(t *testing.T) { err := rm.ResolveStep(s) assert.Error(t, err) } + +func TestResolveImage(t *testing.T) { + tests := []struct { + name string + reference string + want MappedImage + }{ + { + name: "canonical reference", + reference: "deislabs/porter-hello@sha256:8b06c3da72dc9fa7002b9bc1f73a7421b4287c9cf0d3b08633287473707f9a63", + want: MappedImage{ + Repository: "deislabs/porter-hello", + Digest: "sha256:8b06c3da72dc9fa7002b9bc1f73a7421b4287c9cf0d3b08633287473707f9a63", + }, + }, + { + name: "tagged reference", + reference: "deislabs/porter-hello:v0.1.10", + want: MappedImage{ + Repository: "deislabs/porter-hello", + Tag: "v0.1.10", + }, + }, + { + name: "named reference", + reference: "deislabs/porter-hello", + want: MappedImage{ + Repository: "deislabs/porter-hello", + Tag: "latest", + }, + }, + } + for _, test := range tests { + got := &MappedImage{} + resolveImage(got, test.reference) + assert.Equal(t, test.want.Repository, got.Repository) + assert.Equal(t, test.want.Tag, got.Tag) + assert.Equal(t, test.want.Digest, got.Digest) + } +} diff --git a/pkg/porter/run.go b/pkg/porter/run.go index d780a3905..ac4d013bb 100644 --- a/pkg/porter/run.go +++ b/pkg/porter/run.go @@ -1,11 +1,13 @@ package porter import ( + "encoding/json" "fmt" "os" "path/filepath" "strconv" + "github.com/deislabs/cnab-go/bundle/loader" "github.com/deislabs/porter/pkg/config" "github.com/deislabs/porter/pkg/context" "github.com/deislabs/porter/pkg/manifest" @@ -102,6 +104,31 @@ func (p *Porter) Run(opts RunOptions) error { return err } + //Update the runtimeManifest images with the bundle.json and relocation mapping (if it's there) + l := loader.New() + bunBytes, err := p.FileSystem.ReadFile("/cnab/bundle.json") + if err != nil { + return errors.Wrap(err, "couldn't read runtime bundle.json") + } + rtb, err := l.LoadData(bunBytes) + if err != nil { + return errors.Wrap(err, "couldn't load runtime bundle.json") + } + var reloMap config.RelocationMapping + if _, err := p.FileSystem.Stat("/cnab/app/relocation-mapping.json"); err == nil { + reloBytes, err := p.FileSystem.ReadFile("/cnab/app/relocation-mapping.json") + if err != nil { + return errors.Wrap(err, "couldn't read relocation file") + } + err = json.Unmarshal(reloBytes, reloMap) + if err != nil { + return errors.Wrap(err, "couldn't load relocation file") + } + } + err = runtimeManifest.ResolveImages(rtb, reloMap) + if err != nil { + return errors.Wrap(err, "unable to resolve bundle images") + } err = p.FileSystem.MkdirAll(context.MixinOutputsDir, 0755) if err != nil { return errors.Wrapf(err, "could not create outputs directory %s", context.MixinOutputsDir) diff --git a/pkg/porter/run_test.go b/pkg/porter/run_test.go index bf552a55c..e885c5027 100644 --- a/pkg/porter/run_test.go +++ b/pkg/porter/run_test.go @@ -26,7 +26,7 @@ func TestPorter_Run(t *testing.T) { assert.True(t, commandOpts.Runtime, "the mixin command should be executed in runtime mode") assert.Equal(t, "install", commandOpts.Command, "should have executed the mixin's install command") }) - + p.TestConfig.TestContext.AddTestFile("testdata/bundle.json", "/cnab/bundle.json") p.TestConfig.TestContext.AddTestFile("testdata/porter.yaml", "porter.yaml") opts := NewRunOptions(p.Config) diff --git a/pkg/porter/testdata/bundle.json b/pkg/porter/testdata/bundle.json new file mode 100644 index 000000000..97846c3e8 --- /dev/null +++ b/pkg/porter/testdata/bundle.json @@ -0,0 +1 @@ +{"actions":{"zombies":{"description":"zombies","modifies":true}},"credentials":{"my-first-cred":{"env":"MY_FIRST_CRED","required":true},"my-second-cred":{"description":"My second cred","path":"/path/to/my-second-cred","required":true}},"custom":{"io.cnab.dependencies":null,"sh.porter":{"manifestDigest":"e3a1a9a6e900f449ac0b3a321bea923d64a0cd66ae29507d0d3259a1a817c921"}},"definitions":{"my-first-output":{"type":"string","writeOnly":true},"my-first-param":{"default":9,"type":"integer"},"my-second-output":{"description":"My second output","type":"boolean"},"my-second-param":{"default":"spring-music-demo","description":"My second parameter","type":"string","writeOnly":true},"porter-debug":{"default":false,"description":"Print debug information from Porter when executing the bundle","type":"boolean"}},"description":"A bundle with a custom action","invocationImages":[{"image":"porter-hello-custom:latest","imageType":"docker"}],"name":"HELLO_CUSTOM","outputs":{"my-first-output":{"applyTo":["install","upgrade"],"definition":"my-first-output","path":"/cnab/app/outputs/my-first-output"},"my-second-output":{"definition":"my-second-output","description":"My second output","path":"/cnab/app/outputs/my-second-output"}},"parameters":{"my-first-param":{"applyTo":["install"],"definition":"my-first-param","destination":{"env":"MY_FIRST_PARAM"}},"my-second-param":{"definition":"my-second-param","description":"My second parameter","destination":{"path":"/path/to/my-second-param"}},"porter-debug":{"definition":"porter-debug","description":"Print debug information from Porter when executing the bundle","destination":{"env":"PORTER_DEBUG"}}},"schemaVersion":"v1.0.0-WD","version":"0.1.0"} \ No newline at end of file From 6dbf67b6a17fd8cd1bd65e89d48208bc3bdb2306 Mon Sep 17 00:00:00 2001 From: Jeremy Rickard Date: Tue, 8 Oct 2019 12:16:01 -0600 Subject: [PATCH 2/7] Added tests --- pkg/{config => manifest}/relocation.go | 2 +- pkg/manifest/runtime-manifest.go | 6 ++ pkg/manifest/runtime-manifest_test.go | 131 ++++++++++++++++++++++++- pkg/porter/run.go | 2 +- 4 files changed, 138 insertions(+), 3 deletions(-) rename pkg/{config => manifest}/relocation.go (88%) diff --git a/pkg/config/relocation.go b/pkg/manifest/relocation.go similarity index 88% rename from pkg/config/relocation.go rename to pkg/manifest/relocation.go index 89a521a13..0fa6b18f3 100644 --- a/pkg/config/relocation.go +++ b/pkg/manifest/relocation.go @@ -1,4 +1,4 @@ -package config +package manifest // RelocationMapping represents a runtime provided mapping of a bundle image to a new tag type RelocationMapping map[string]string diff --git a/pkg/manifest/runtime-manifest.go b/pkg/manifest/runtime-manifest.go index 029b0a9e0..856996113 100644 --- a/pkg/manifest/runtime-manifest.go +++ b/pkg/manifest/runtime-manifest.go @@ -319,6 +319,7 @@ func (m *RuntimeManifest) ResolveImages(bun *bundle.Bundle, reloMap config.Reloc if err != nil { return errors.Wrap(err, "unable to update image map from bundle.json") } + m.ImageMap[alias] = manifestImage } for alias, reloRef := range reloMap { @@ -327,6 +328,7 @@ func (m *RuntimeManifest) ResolveImages(bun *bundle.Bundle, reloMap config.Reloc if err != nil { return errors.Wrap(err, "unable to update image map from relocation mapping") } + m.ImageMap[alias] = manifestImage } return nil } @@ -339,8 +341,12 @@ func resolveImage(image *MappedImage, refString string) error { } switch v := ref.(type) { case reference.Canonical: + if tagged, ok := ref.(reference.NamedTagged); ok { + image.Tag = tagged.Tag() + } image.Repository = v.Name() image.Digest = v.Digest().String() + case reference.NamedTagged: image.Tag = v.Tag() image.Repository = v.Name() diff --git a/pkg/manifest/runtime-manifest_test.go b/pkg/manifest/runtime-manifest_test.go index dbf6a81be..242e7c607 100644 --- a/pkg/manifest/runtime-manifest_test.go +++ b/pkg/manifest/runtime-manifest_test.go @@ -894,12 +894,141 @@ func TestResolveImage(t *testing.T) { Tag: "latest", }, }, + { + name: "the one with a hostname", + reference: "deislabs.io/deislabs/porter-hello", + want: MappedImage{ + Repository: "deislabs.io/deislabs/porter-hello", + Tag: "latest", + }, + }, + { + name: "the one with a hostname and port", + reference: "deislabs.io:9090/deislabs/porter-hello:foo", + want: MappedImage{ + Repository: "deislabs.io:9090/deislabs/porter-hello", + Tag: "foo", + }, + }, + { + + name: "tagged and digested", + reference: "deislabs/porter-hello:latest@sha256:8b06c3da72dc9fa7002b9bc1f73a7421b4287c9cf0d3b08633287473707f9a63", + want: MappedImage{ + Repository: "deislabs/porter-hello", + Tag: "latest", + Digest: "sha256:8b06c3da72dc9fa7002b9bc1f73a7421b4287c9cf0d3b08633287473707f9a63", + }, + }, } for _, test := range tests { got := &MappedImage{} - resolveImage(got, test.reference) + err := resolveImage(got, test.reference) + assert.NoError(t, err) assert.Equal(t, test.want.Repository, got.Repository) assert.Equal(t, test.want.Tag, got.Tag) assert.Equal(t, test.want.Digest, got.Digest) } } + +func TestResolveImageErrors(t *testing.T) { + tests := []struct { + name string + reference string + want string + }{ + { + name: "no algo digest", + reference: "deislabs/porter-hello@8b06c3da72dc9fa7002b9bc1f73a7421b4287c9cf0d3b08633287473707f9a63", + want: "unable to parse docker image %s: invalid reference format", + }, + { + name: "bad digest", + reference: "deislabs/porter-hello@sha256:8b06c3da72dc9fa7002b9bc1f73a7421b4287c9cf0d3b08633287473707f", + want: "unable to parse docker image %s: invalid checksum digest length", + }, + { + name: "bad digest algo", + reference: "deislabs/porter-hello@sha356:8b06c3da72dc9fa7002b9bc1f73a7421b4287c9cf0d3b08633287473707f9a63", + want: "unable to parse docker image %s: unsupported digest algorithm", + }, + { + name: "malformed tagged ref", + reference: "deislabs/porter-hello@latest", + want: "unable to parse docker image %s: invalid reference format", + }, + { + name: "too many ports tagged ref", + reference: "deislabs:8080:8080/porter-hello:latest", + want: "unable to parse docker image %s: invalid reference format", + }, + } + for _, test := range tests { + got := &MappedImage{} + err := resolveImage(got, test.reference) + assert.EqualError(t, err, fmt.Sprintf(test.want, test.reference)) + } +} + +func TestResolveImageWithUpdatedBundle(t *testing.T) { + cxt := context.NewTestContext(t) + m := &Manifest{ + ImageMap: map[string]MappedImage{ + "machine": MappedImage{ + Repository: "deislabs/ghost", + Tag: "latest", + Digest: "sha256:75c495e5ce9c428d482973d72e3ce9925e1db304a97946c9aa0b540d7537e041", + }, + }, + } + + img := bundle.Image{} + img.Image = "blah/ghost:latest" + img.Digest = "sha256:75c495e5ce9c428d482973d72e3ce9925e1db304a97946c9aa0b540d7537e041" + bun := &bundle.Bundle{ + Images: map[string]bundle.Image{ + "machine": img, + }, + } + + reloMap := RelocationMapping{} + + rm := NewRuntimeManifest(cxt.Context, ActionInstall, m) + err := rm.ResolveImages(bun, reloMap) + assert.NoError(t, err) + mi := rm.ImageMap["machine"] + assert.Equal(t, "blah/ghost", mi.Repository) + +} +func TestResolveImageWithRelo(t *testing.T) { + cxt := context.NewTestContext(t) + m := &Manifest{ + ImageMap: map[string]MappedImage{ + "machine": MappedImage{ + Repository: "deislabs/ghost", + Tag: "latest", + Digest: "sha256:75c495e5ce9c428d482973d72e3ce9925e1db304a97946c9aa0b540d7537e041", + }, + }, + } + + img := bundle.Image{} + img.Image = "deislabs/ghost:latest" + img.Digest = "sha256:75c495e5ce9c428d482973d72e3ce9925e1db304a97946c9aa0b540d7537e041" + bun := &bundle.Bundle{ + Images: map[string]bundle.Image{ + "machine": img, + }, + } + + reloMap := RelocationMapping{ + "machine": "cnabio/ghost:latest", + } + + rm := NewRuntimeManifest(cxt.Context, ActionInstall, m) + err := rm.ResolveImages(bun, reloMap) + assert.NoError(t, err) + mi := rm.ImageMap["machine"] + assert.Equal(t, "cnabio/ghost", mi.Repository) + +} diff --git a/pkg/porter/run.go b/pkg/porter/run.go index ac4d013bb..6d32b19a0 100644 --- a/pkg/porter/run.go +++ b/pkg/porter/run.go @@ -114,7 +114,7 @@ func (p *Porter) Run(opts RunOptions) error { if err != nil { return errors.Wrap(err, "couldn't load runtime bundle.json") } - var reloMap config.RelocationMapping + var reloMap manifest.RelocationMapping if _, err := p.FileSystem.Stat("/cnab/app/relocation-mapping.json"); err == nil { reloBytes, err := p.FileSystem.ReadFile("/cnab/app/relocation-mapping.json") if err != nil { From ffcf57a4a30ab187d6ee283a3784d7a548c726ef Mon Sep 17 00:00:00 2001 From: Jeremy Rickard Date: Tue, 8 Oct 2019 09:41:45 -0600 Subject: [PATCH 3/7] Add support for wiring --- pkg/config/relocation.go | 4 ++++ pkg/manifest/runtime-manifest.go | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 pkg/config/relocation.go diff --git a/pkg/config/relocation.go b/pkg/config/relocation.go new file mode 100644 index 000000000..89a521a13 --- /dev/null +++ b/pkg/config/relocation.go @@ -0,0 +1,4 @@ +package config + +// RelocationMapping represents a runtime provided mapping of a bundle image to a new tag +type RelocationMapping map[string]string diff --git a/pkg/manifest/runtime-manifest.go b/pkg/manifest/runtime-manifest.go index 856996113..3957ebc16 100644 --- a/pkg/manifest/runtime-manifest.go +++ b/pkg/manifest/runtime-manifest.go @@ -11,7 +11,6 @@ import ( "github.com/cbroglie/mustache" "github.com/deislabs/cnab-go/bundle" - "github.com/deislabs/porter/pkg/config" "github.com/deislabs/porter/pkg/runtime" "github.com/docker/distribution/reference" "github.com/pkg/errors" @@ -311,7 +310,7 @@ func (m *RuntimeManifest) Prepare() error { // ResolveImages updates the RuntimeManifest to properly reflect that image map passed to the bundle via the // mounted bundle.json and relocation mapping -func (m *RuntimeManifest) ResolveImages(bun *bundle.Bundle, reloMap config.RelocationMapping) error { +func (m *RuntimeManifest) ResolveImages(bun *bundle.Bundle, reloMap RelocationMapping) error { for alias, image := range bun.Images { manifestImage := m.ImageMap[alias] manifestImage.Digest = image.Digest From 2a2b5e5e475bd7654b574bbe96a6ec23f9e7aa38 Mon Sep 17 00:00:00 2001 From: Jeremy Rickard Date: Tue, 8 Oct 2019 12:16:01 -0600 Subject: [PATCH 4/7] Added tests --- pkg/config/relocation.go | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 pkg/config/relocation.go diff --git a/pkg/config/relocation.go b/pkg/config/relocation.go deleted file mode 100644 index 89a521a13..000000000 --- a/pkg/config/relocation.go +++ /dev/null @@ -1,4 +0,0 @@ -package config - -// RelocationMapping represents a runtime provided mapping of a bundle image to a new tag -type RelocationMapping map[string]string From 424aa7d9112e23ff8bf82dde8b772d98b5c4623a Mon Sep 17 00:00:00 2001 From: Jeremy Rickard Date: Wed, 9 Oct 2019 13:01:09 -0600 Subject: [PATCH 5/7] Address vdice comments, BYE BYE OriginalImage --- pkg/cnab/config_adapter/adapter_test.go | 13 ++++++------- pkg/manifest/manifest.go | 19 ++++++++----------- pkg/manifest/relocation.go | 2 +- pkg/manifest/runtime-manifest.go | 2 +- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/pkg/cnab/config_adapter/adapter_test.go b/pkg/cnab/config_adapter/adapter_test.go index 0918bdac6..90bea1fcf 100644 --- a/pkg/cnab/config_adapter/adapter_test.go +++ b/pkg/cnab/config_adapter/adapter_test.go @@ -236,13 +236,12 @@ func TestManifestConverter_generateImages(t *testing.T) { a := NewManifestConverter(c.Context, m, nil) mappedImage := manifest.MappedImage{ - Description: "un petite server", - Repository: "deislabs/myserver", - ImageType: "docker", - Digest: "abc123", - Size: 12, - MediaType: "download", - OriginalImage: "deis/myserver:1.0.0", + Description: "un petite server", + Repository: "deislabs/myserver", + ImageType: "docker", + Digest: "abc123", + Size: 12, + MediaType: "download", Labels: map[string]string{ "OS": "linux", "Architecture": "amd64", diff --git a/pkg/manifest/manifest.go b/pkg/manifest/manifest.go index aa6d92411..21302f09e 100644 --- a/pkg/manifest/manifest.go +++ b/pkg/manifest/manifest.go @@ -47,8 +47,6 @@ type Manifest struct { // ImageMap is a map of images referenced in the bundle. If an image relocation mapping is later provided, that // will be mounted at as a file at runtime to /cnab/app/relocation-mapping.json. - // TODO: porter should handle the relocation and overwrite the repository and tag (if present), and - // populate originalImage ImageMap map[string]MappedImage `yaml:"images,omitempty"` } @@ -258,15 +256,14 @@ func (m MixinDeclaration) MarshalYAML() (interface{}, error) { } type MappedImage struct { - Description string `yaml:"description"` - ImageType string `yaml:"imageType"` - Repository string `yaml:"repository"` - OriginalImage string `yaml:"originalImage,omitempty"` - Digest string `yaml:"digest,omitempty"` - Size uint64 `yaml:"size,omitempty"` - MediaType string `yaml:"mediaType,omitempty"` - Labels map[string]string `yaml:"labels,omitempty"` - Tag string `yaml:"tag,omitempty"` + Description string `yaml:"description"` + ImageType string `yaml:"imageType"` + Repository string `yaml:"repository"` + Digest string `yaml:"digest,omitempty"` + Size uint64 `yaml:"size,omitempty"` + MediaType string `yaml:"mediaType,omitempty"` + Labels map[string]string `yaml:"labels,omitempty"` + Tag string `yaml:"tag,omitempty"` } type Dependency struct { diff --git a/pkg/manifest/relocation.go b/pkg/manifest/relocation.go index 0fa6b18f3..67b1c2885 100644 --- a/pkg/manifest/relocation.go +++ b/pkg/manifest/relocation.go @@ -1,4 +1,4 @@ package manifest -// RelocationMapping represents a runtime provided mapping of a bundle image to a new tag +// RelocationMapping represents a runtime-provided mapping of a bundle image to a new tag type RelocationMapping map[string]string diff --git a/pkg/manifest/runtime-manifest.go b/pkg/manifest/runtime-manifest.go index 3957ebc16..809c538e9 100644 --- a/pkg/manifest/runtime-manifest.go +++ b/pkg/manifest/runtime-manifest.go @@ -308,7 +308,7 @@ func (m *RuntimeManifest) Prepare() error { return nil } -// ResolveImages updates the RuntimeManifest to properly reflect that image map passed to the bundle via the +// ResolveImages updates the RuntimeManifest to properly reflect the image map passed to the bundle via the // mounted bundle.json and relocation mapping func (m *RuntimeManifest) ResolveImages(bun *bundle.Bundle, reloMap RelocationMapping) error { for alias, image := range bun.Images { From 3845cbec9e10ddcd3a246a1b3fa0f1d1fe4894df Mon Sep 17 00:00:00 2001 From: Jeremy Rickard Date: Wed, 9 Oct 2019 13:37:16 -0600 Subject: [PATCH 6/7] updated logic for the relocation mapping. --- pkg/manifest/relocation.go | 4 -- pkg/manifest/runtime-manifest.go | 21 +++++--- pkg/manifest/runtime-manifest_test.go | 78 +++++++++++++++++++++++---- pkg/porter/run.go | 3 +- 4 files changed, 86 insertions(+), 20 deletions(-) delete mode 100644 pkg/manifest/relocation.go diff --git a/pkg/manifest/relocation.go b/pkg/manifest/relocation.go deleted file mode 100644 index 67b1c2885..000000000 --- a/pkg/manifest/relocation.go +++ /dev/null @@ -1,4 +0,0 @@ -package manifest - -// RelocationMapping represents a runtime-provided mapping of a bundle image to a new tag -type RelocationMapping map[string]string diff --git a/pkg/manifest/runtime-manifest.go b/pkg/manifest/runtime-manifest.go index 809c538e9..ed68bb68a 100644 --- a/pkg/manifest/runtime-manifest.go +++ b/pkg/manifest/runtime-manifest.go @@ -7,11 +7,11 @@ import ( "reflect" "strings" - "github.com/deislabs/porter/pkg/context" - "github.com/cbroglie/mustache" "github.com/deislabs/cnab-go/bundle" + "github.com/deislabs/porter/pkg/context" "github.com/deislabs/porter/pkg/runtime" + "github.com/docker/cnab-to-oci/relocation" "github.com/docker/distribution/reference" "github.com/pkg/errors" "gopkg.in/yaml.v2" @@ -310,19 +310,28 @@ func (m *RuntimeManifest) Prepare() error { // ResolveImages updates the RuntimeManifest to properly reflect the image map passed to the bundle via the // mounted bundle.json and relocation mapping -func (m *RuntimeManifest) ResolveImages(bun *bundle.Bundle, reloMap RelocationMapping) error { +func (m *RuntimeManifest) ResolveImages(bun *bundle.Bundle, reloMap relocation.ImageRelocationMap) error { + reverseLookup := make(map[string]string) for alias, image := range bun.Images { - manifestImage := m.ImageMap[alias] + manifestImage, ok := m.ImageMap[alias] + if !ok { + return fmt.Errorf("unable to find image in porter manifest: %s", alias) + } manifestImage.Digest = image.Digest err := resolveImage(&manifestImage, image.Image) if err != nil { return errors.Wrap(err, "unable to update image map from bundle.json") } m.ImageMap[alias] = manifestImage + reverseLookup[image.Image] = alias } - for alias, reloRef := range reloMap { - manifestImage := m.ImageMap[alias] + for oldRef, reloRef := range reloMap { + alias := reverseLookup[oldRef] + manifestImage, ok := m.ImageMap[alias] + if !ok { + return fmt.Errorf("unable to find relocated image: %s", oldRef) + } err := resolveImage(&manifestImage, reloRef) if err != nil { return errors.Wrap(err, "unable to update image map from relocation mapping") diff --git a/pkg/manifest/runtime-manifest_test.go b/pkg/manifest/runtime-manifest_test.go index 242e7c607..6141b51f2 100644 --- a/pkg/manifest/runtime-manifest_test.go +++ b/pkg/manifest/runtime-manifest_test.go @@ -5,11 +5,11 @@ import ( "os" "testing" - "github.com/deislabs/porter/pkg/config" - "github.com/deislabs/cnab-go/bundle" "github.com/deislabs/cnab-go/bundle/definition" + "github.com/deislabs/porter/pkg/config" "github.com/deislabs/porter/pkg/context" + "github.com/docker/cnab-to-oci/relocation" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gopkg.in/yaml.v2" @@ -991,16 +991,16 @@ func TestResolveImageWithUpdatedBundle(t *testing.T) { }, } - reloMap := RelocationMapping{} + reloMap := relocation.ImageRelocationMap{} rm := NewRuntimeManifest(cxt.Context, ActionInstall, m) err := rm.ResolveImages(bun, reloMap) assert.NoError(t, err) mi := rm.ImageMap["machine"] assert.Equal(t, "blah/ghost", mi.Repository) - } -func TestResolveImageWithRelo(t *testing.T) { + +func TestResolveImageWithUpdatedMismatchedBundle(t *testing.T) { cxt := context.NewTestContext(t) m := &Manifest{ ImageMap: map[string]MappedImage{ @@ -1013,22 +1013,82 @@ func TestResolveImageWithRelo(t *testing.T) { } img := bundle.Image{} - img.Image = "deislabs/ghost:latest" + img.Image = "blah/ghost:latest" img.Digest = "sha256:75c495e5ce9c428d482973d72e3ce9925e1db304a97946c9aa0b540d7537e041" + bun := &bundle.Bundle{ + Images: map[string]bundle.Image{ + "ghost": img, + }, + } + + reloMap := relocation.ImageRelocationMap{} + + rm := NewRuntimeManifest(cxt.Context, ActionInstall, m) + err := rm.ResolveImages(bun, reloMap) + assert.Error(t, err) + assert.EqualError(t, err, fmt.Sprintf("unable to find image in porter manifest: %s", "ghost")) + +} + +func TestResolveImageWithRelo(t *testing.T) { + cxt := context.NewTestContext(t) + m := &Manifest{ + ImageMap: map[string]MappedImage{ + "machine": MappedImage{ + Repository: "gabrtv/microservice", + Tag: "latest", + Digest: "sha256:cca460afa270d4c527981ef9ca4989346c56cf9b20217dcea37df1ece8120687", + }, + }, + } + + img := bundle.Image{} + img.Image = "gabrtv/microservice@sha256:cca460afa270d4c527981ef9ca4989346c56cf9b20217dcea37df1ece8120687" + img.Digest = "sha256:cca460afa270d4c527981ef9ca4989346c56cf9b20217dcea37df1ece8120687" bun := &bundle.Bundle{ Images: map[string]bundle.Image{ "machine": img, }, } - reloMap := RelocationMapping{ - "machine": "cnabio/ghost:latest", + reloMap := relocation.ImageRelocationMap{ + "gabrtv/microservice@sha256:cca460afa270d4c527981ef9ca4989346c56cf9b20217dcea37df1ece8120687": "my.registry/microservice@sha256:cca460afa270d4c527981ef9ca4989346c56cf9b20217dcea37df1ece8120687", } rm := NewRuntimeManifest(cxt.Context, ActionInstall, m) err := rm.ResolveImages(bun, reloMap) assert.NoError(t, err) mi := rm.ImageMap["machine"] - assert.Equal(t, "cnabio/ghost", mi.Repository) + assert.Equal(t, "my.registry/microservice", mi.Repository) +} + +func TestResolveImageBadRelocation(t *testing.T) { + cxt := context.NewTestContext(t) + m := &Manifest{ + ImageMap: map[string]MappedImage{ + "machine": MappedImage{ + Repository: "deislabs/ghost", + Tag: "latest", + Digest: "sha256:75c495e5ce9c428d482973d72e3ce9925e1db304a97946c9aa0b540d7537e041", + }, + }, + } + img := bundle.Image{} + img.Image = "deislabs/ghost:latest" + img.Digest = "sha256:75c495e5ce9c428d482973d72e3ce9925e1db304a97946c9aa0b540d7537e041" + bun := &bundle.Bundle{ + Images: map[string]bundle.Image{ + "machine": img, + }, + } + + reloMap := relocation.ImageRelocationMap{ + "deislabs/nogood:latest": "cnabio/ghost:latest", + } + + rm := NewRuntimeManifest(cxt.Context, ActionInstall, m) + err := rm.ResolveImages(bun, reloMap) + assert.Error(t, err) + assert.EqualError(t, err, fmt.Sprintf("unable to find relocated image: %s", "deislabs/nogood:latest")) } diff --git a/pkg/porter/run.go b/pkg/porter/run.go index 6d32b19a0..ffcc0a840 100644 --- a/pkg/porter/run.go +++ b/pkg/porter/run.go @@ -12,6 +12,7 @@ import ( "github.com/deislabs/porter/pkg/context" "github.com/deislabs/porter/pkg/manifest" "github.com/deislabs/porter/pkg/mixin" + "github.com/docker/cnab-to-oci/relocation" "github.com/pkg/errors" "gopkg.in/yaml.v2" ) @@ -114,7 +115,7 @@ func (p *Porter) Run(opts RunOptions) error { if err != nil { return errors.Wrap(err, "couldn't load runtime bundle.json") } - var reloMap manifest.RelocationMapping + var reloMap relocation.ImageRelocationMap if _, err := p.FileSystem.Stat("/cnab/app/relocation-mapping.json"); err == nil { reloBytes, err := p.FileSystem.ReadFile("/cnab/app/relocation-mapping.json") if err != nil { From 07c98d79815825ec53ccd93dbff7279130086c3b Mon Sep 17 00:00:00 2001 From: Jeremy Rickard Date: Wed, 9 Oct 2019 14:07:05 -0600 Subject: [PATCH 7/7] DEP FOR THE DEP GODS --- Gopkg.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Gopkg.lock b/Gopkg.lock index 0cc073e92..d71563f83 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1700,6 +1700,7 @@ "github.com/docker/cli/cli/command", "github.com/docker/cli/cli/config", "github.com/docker/cli/cli/flags", + "github.com/docker/cnab-to-oci/relocation", "github.com/docker/cnab-to-oci/remotes", "github.com/docker/compose-on-kubernetes", "github.com/docker/distribution/reference",