Skip to content
This repository has been archived by the owner on Jun 13, 2021. It is now read-only.

Commit

Permalink
apply relocation map when creating the installation
Browse files Browse the repository at this point in the history
Allow to replace local images by the one from the registry
using stored `relocation-map.json` when creating the installation.
The `bundle.json` is not modified.

Signed-off-by: Yves Brissaud <[email protected]>
  • Loading branch information
eunomie committed Nov 6, 2019
1 parent 43f9381 commit 160797a
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 25 deletions.
82 changes: 82 additions & 0 deletions e2e/relocation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"strings"
"testing"

"gotest.tools/assert/cmp"

"gotest.tools/assert"
"gotest.tools/icmd"
)
Expand Down Expand Up @@ -59,3 +61,83 @@ func TestRelocationMapCreatedOnPull(t *testing.T) {
assert.NilError(t, err)
})
}

func TestRelocationMapRun(t *testing.T) {
runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) {
cmd := info.configuredCmd
cfg := getDockerConfigDir(t, cmd)

path := filepath.Join("testdata", "local")
ref := info.registryAddress + "/test/local:a-tag"
bundlePath := filepath.Join(cfg, "app", "bundles", strings.Replace(info.registryAddress, ":", "_", 1), "test", "local", "_tags", "a-tag")

// Given a pushed application
build(t, cmd, dockerCli, ref, path)
cmd.Command = dockerCli.Command("app", "push", ref)
icmd.RunCmd(cmd).Assert(t, icmd.Success)
// And given application files are remove
assert.NilError(t, os.RemoveAll(bundlePath))
_, err := os.Stat(filepath.Join(bundlePath, "bundle.json"))
assert.Assert(t, os.IsNotExist(err))
// And given local images are removed
cmd.Command = dockerCli.Command("rmi", "web", "local:1.1.0-beta1-invoc", "worker")
icmd.RunCmd(cmd).Assert(t, icmd.Success)
// And given application is pulled from the registry
cmd.Command = dockerCli.Command("app", "pull", ref)
icmd.RunCmd(cmd).Assert(t, icmd.Success)

t.Run("with-relocation-map", func(t *testing.T) {
name := "test-relocation-map-run-with-relocation-map"
// When application is run
cmd.Command = dockerCli.Command("app", "run", "--name", name, ref)
icmd.RunCmd(cmd).Assert(t, icmd.Success)

// Then the application is running
cmd.Command = dockerCli.Command("app", "ls")
assert.Check(t, cmp.Contains(icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), name))

cmd.Command = dockerCli.Command("app", "rm", name)
icmd.RunCmd(cmd).Assert(t, icmd.Success)
})

t.Run("without-relocation-map", func(t *testing.T) {
name := "test-relocation-map-run-without-relocation-map"
// And given the relocation map is removed after the pull
assert.NilError(t, os.RemoveAll(filepath.Join(bundlePath, "relocation-map.json")))

// Then the application cannot be run
cmd.Command = dockerCli.Command("app", "run", "--name", name, ref)
icmd.RunCmd(cmd).Assert(t, icmd.Expected{ExitCode: 1})
})
})
}

func TestRelocationMapOnInspect(t *testing.T) {
runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) {
cmd := info.configuredCmd
cfg := getDockerConfigDir(t, cmd)

path := filepath.Join("testdata", "local")
ref := info.registryAddress + "/test/local:a-tag"
bundlePath := filepath.Join(cfg, "app", "bundles", strings.Replace(info.registryAddress, ":", "_", 1), "test", "local", "_tags", "a-tag")

// Given a pushed application
build(t, cmd, dockerCli, ref, path)
cmd.Command = dockerCli.Command("app", "push", ref)
icmd.RunCmd(cmd).Assert(t, icmd.Success)
// And given application files are remove
assert.NilError(t, os.RemoveAll(bundlePath))
_, err := os.Stat(filepath.Join(bundlePath, "bundle.json"))
assert.Assert(t, os.IsNotExist(err))
// And given local images are removed
cmd.Command = dockerCli.Command("rmi", "web", "local:1.1.0-beta1-invoc", "worker")
icmd.RunCmd(cmd).Assert(t, icmd.Success)
// And given application is pulled from the registry
cmd.Command = dockerCli.Command("app", "pull", ref)
icmd.RunCmd(cmd).Assert(t, icmd.Success)

// When inspect the image
cmd.Command = dockerCli.Command("app", "image", "inspect", ref)
icmd.RunCmd(cmd).Assert(t, icmd.Success)
})
}
1 change: 1 addition & 0 deletions internal/bundle/parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ func MergeBundleParameters(installation *store.Installation, ops ...MergeBundleO
params: userParams,
stderr: os.Stderr,
}

for _, op := range ops {
if err := op(cfg); err != nil {
return err
Expand Down
52 changes: 39 additions & 13 deletions internal/bundle/parameters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"strings"
"testing"

"github.com/docker/app/internal/relocated"

"github.com/deislabs/cnab-go/bundle"
"github.com/deislabs/cnab-go/bundle/definition"
"github.com/deislabs/cnab-go/claim"
Expand Down Expand Up @@ -113,18 +115,18 @@ func withParameterAndValues(name, typ string, allowedValues []interface{}) bundl
}
}

func prepareBundle(ops ...bundleOperator) *bundle.Bundle {
b := &bundle.Bundle{}
func prepareBundle(ops ...bundleOperator) *relocated.Bundle {
b := relocated.FromBundle(&bundle.Bundle{})
for _, op := range ops {
op(b)
op(b.Bundle)
}
return b
}

func TestWithOrchestratorParameters(t *testing.T) {
testCases := []struct {
name string
bundle *bundle.Bundle
bundle *relocated.Bundle
expected map[string]string
}{
{
Expand All @@ -146,7 +148,7 @@ func TestWithOrchestratorParameters(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
actual := map[string]string{}
err := WithOrchestratorParameters("kubernetes", "my-namespace")(&MergeBundleConfig{
bundle: testCase.bundle,
bundle: testCase.bundle.Bundle,
params: actual,
})
assert.NilError(t, err)
Expand All @@ -166,7 +168,10 @@ func TestMergeBundleParameters(t *testing.T) {
return nil
}
bundle := prepareBundle(withParameterAndDefault("param", "string", "default"))
i := &store.Installation{Claim: claim.Claim{Bundle: bundle}}
i := &store.Installation{
Claim: claim.Claim{Bundle: bundle.Bundle},
RelocationMap: bundle.RelocationMap,
}
err := MergeBundleParameters(i,
first,
second,
Expand All @@ -180,7 +185,10 @@ func TestMergeBundleParameters(t *testing.T) {

t.Run("Default values", func(t *testing.T) {
bundle := prepareBundle(withParameterAndDefault("param", "string", "default"))
i := &store.Installation{Claim: claim.Claim{Bundle: bundle}}
i := &store.Installation{
Claim: claim.Claim{Bundle: bundle.Bundle},
RelocationMap: bundle.RelocationMap,
}
err := MergeBundleParameters(i)
assert.NilError(t, err)
expected := map[string]interface{}{
Expand All @@ -195,7 +203,10 @@ func TestMergeBundleParameters(t *testing.T) {
return nil
}
bundle := prepareBundle(withParameter("param", "integer"))
i := &store.Installation{Claim: claim.Claim{Bundle: bundle}}
i := &store.Installation{
Claim: claim.Claim{Bundle: bundle.Bundle},
RelocationMap: bundle.RelocationMap,
}
err := MergeBundleParameters(i, withIntValue)
assert.NilError(t, err)
expected := map[string]interface{}{
Expand All @@ -206,7 +217,10 @@ func TestMergeBundleParameters(t *testing.T) {

t.Run("Default values", func(t *testing.T) {
bundle := prepareBundle(withParameterAndDefault("param", "string", "default"))
i := &store.Installation{Claim: claim.Claim{Bundle: bundle}}
i := &store.Installation{
Claim: claim.Claim{Bundle: bundle.Bundle},
RelocationMap: bundle.RelocationMap,
}
err := MergeBundleParameters(i)
assert.NilError(t, err)
expected := map[string]interface{}{
Expand All @@ -221,7 +235,10 @@ func TestMergeBundleParameters(t *testing.T) {
return nil
}
bundle := prepareBundle()
i := &store.Installation{Claim: claim.Claim{Bundle: bundle}}
i := &store.Installation{
Claim: claim.Claim{Bundle: bundle.Bundle},
RelocationMap: bundle.RelocationMap,
}
buf := new(bytes.Buffer)
err := MergeBundleParameters(i, withUndefined, WithErrorWriter(buf))
assert.NilError(t, err)
Expand All @@ -239,7 +256,10 @@ func TestMergeBundleParameters(t *testing.T) {
return nil
}
bundle := prepareBundle()
i := &store.Installation{Claim: claim.Claim{Bundle: bundle}}
i := &store.Installation{
Claim: claim.Claim{Bundle: bundle.Bundle},
RelocationMap: bundle.RelocationMap,
}
err := MergeBundleParameters(i, withUndefined, withStdErr)
assert.NilError(t, err)
assert.Equal(t, w.String(), "Warning: parameter \"param\" is not defined in the bundle\n")
Expand All @@ -251,7 +271,10 @@ func TestMergeBundleParameters(t *testing.T) {
return nil
}
bundle := prepareBundle(withParameter("param", "integer"))
i := &store.Installation{Claim: claim.Claim{Bundle: bundle}}
i := &store.Installation{
Claim: claim.Claim{Bundle: bundle.Bundle},
RelocationMap: bundle.RelocationMap,
}
err := MergeBundleParameters(i, withIntValue)
assert.ErrorContains(t, err, "invalid value for parameter")
})
Expand All @@ -262,7 +285,10 @@ func TestMergeBundleParameters(t *testing.T) {
return nil
}
bundle := prepareBundle(withParameterAndValues("param", "string", []interface{}{"valid"}))
i := &store.Installation{Claim: claim.Claim{Bundle: bundle}}
i := &store.Installation{
Claim: claim.Claim{Bundle: bundle.Bundle},
RelocationMap: bundle.RelocationMap,
}
err := MergeBundleParameters(i, withInvalidValue)
assert.ErrorContains(t, err, "invalid value for parameter")
})
Expand Down
3 changes: 1 addition & 2 deletions internal/commands/image/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,10 @@ func runInspect(dockerCli command.Cli, appname string, opts inspectOptions) erro
if err != nil {
return err
}
installation, err := appstore.NewInstallation("custom-action", ref.String())
installation, err := appstore.NewInstallation("custom-action", ref.String(), bndl)
if err != nil {
return err
}
installation.Bundle = bndl.Bundle

driverImpl, errBuf := cnab.PrepareDriver(dockerCli, cnab.BindMount{}, nil)
a := &action.RunCustom{
Expand Down
3 changes: 1 addition & 2 deletions internal/commands/image/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,10 @@ func prepareCustomAction(actionName string, dockerCli command.Cli, appname strin
if err != nil {
return nil, nil, nil, errors.Wrapf(err, "could not render %q: no such App image", appname)
}
installation, err := appstore.NewInstallation("custom-action", ref.String())
installation, err := appstore.NewInstallation("custom-action", ref.String(), bundle)
if err != nil {
return nil, nil, nil, err
}
installation.Bundle = bundle.Bundle

if err := bdl.MergeBundleParameters(installation,
bdl.WithFileParameters(paramsOpts.ParametersFiles),
Expand Down
3 changes: 1 addition & 2 deletions internal/commands/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,12 @@ func runBundle(dockerCli command.Cli, bndl *relocated.Bundle, opts runOptions, r
} else {
logrus.Debug(err)
}
installation, err := store.NewInstallation(installationName, ref)
installation, err := store.NewInstallation(installationName, ref, bndl)
if err != nil {
return err
}

driverImpl, errBuf := cnab.PrepareDriver(dockerCli, bind, nil)
installation.Bundle = bndl.Bundle

if err := bdl.MergeBundleParameters(installation,
bdl.WithFileParameters(opts.ParametersFiles),
Expand Down
37 changes: 31 additions & 6 deletions internal/store/installation.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import (
"encoding/json"
"fmt"

"github.com/docker/app/internal/relocated"

"github.com/docker/cnab-to-oci/relocation"

"github.com/deislabs/cnab-go/claim"
"github.com/deislabs/cnab-go/utils/crud"
)
Expand All @@ -20,18 +24,24 @@ type InstallationStore interface {
// It persists the result of an installation and its parameters and context.
type Installation struct {
claim.Claim
Reference string `json:"reference,omitempty"`
RelocationMap relocation.ImageRelocationMap
Reference string `json:"reference,omitempty"`
}

func NewInstallation(name string, reference string) (*Installation, error) {
func NewInstallation(name string, reference string, bndl *relocated.Bundle) (*Installation, error) {
c, err := claim.New(name)
if err != nil {
return nil, err
}
return &Installation{
Claim: *c,
Reference: reference,
}, nil
c.Bundle = bndl.Bundle
i := &Installation{
Claim: *c,
Reference: reference,
RelocationMap: bndl.RelocationMap,
}
i.ApplyRelocationMap()

return i, nil
}

// SetParameter sets the parameter value if the installation bundle has
Expand All @@ -42,6 +52,21 @@ func (i Installation) SetParameter(name string, value string) {
}
}

func (i *Installation) ApplyRelocationMap() {
for idx, def := range i.Bundle.InvocationImages {
if img, ok := i.RelocationMap[def.Image]; ok {
def.Image = img
i.Bundle.InvocationImages[idx] = def
}
}
for name, def := range i.Bundle.Images {
if img, ok := i.RelocationMap[def.Image]; ok {
def.Image = img
i.Bundle.Images[name] = def
}
}
}

var _ InstallationStore = &installationStore{}

type installationStore struct {
Expand Down
Loading

0 comments on commit 160797a

Please sign in to comment.