diff --git a/action/action.go b/action/action.go index 58de7136..afcf0573 100644 --- a/action/action.go +++ b/action/action.go @@ -36,6 +36,11 @@ func selectInvocationImage(d driver.Driver, c *claim.Claim) (bundle.InvocationIm for _, ii := range c.Bundle.InvocationImages { if d.Handles(ii.ImageType) { + if c.RelocationMap != nil { + if img, ok := c.RelocationMap[ii.Image]; ok { + ii.Image = img + } + } return ii, nil } } diff --git a/action/action_test.go b/action/action_test.go index a0a58a0f..7d49cedf 100644 --- a/action/action_test.go +++ b/action/action_test.go @@ -14,7 +14,9 @@ import ( "github.com/deislabs/cnab-go/bundle" "github.com/deislabs/cnab-go/bundle/definition" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type mockFailingDriver struct { @@ -291,3 +293,29 @@ func TestSelectInvocationImage_DriverIncompatible(t *testing.T) { t.Fatalf("expected an error containing %q but got %q", want, got) } } + +func TestSelectInvocationImage_MapHaveImages_NotPresentInMap(t *testing.T) { + c := &claim.Claim{ + Bundle: mockBundle(), + RelocationMap: bundle.ImageRelocationMap{ + "some-image": "some-other-image", + }, + } + invImage, err := selectInvocationImage(&driver.DebugDriver{}, c) + require.NoError(t, err) + + assert.Equal(t, "foo/bar:0.1.0", invImage.Image) +} + +func TestSelectInvocationImage_MapHaveImages_IsPresentMap_returnsNewImageTag(t *testing.T) { + c := &claim.Claim{ + Bundle: mockBundle(), + RelocationMap: bundle.ImageRelocationMap{ + "foo/bar:0.1.0": "some/other:1.0", + }, + } + invImage, err := selectInvocationImage(&driver.DebugDriver{}, c) + require.NoError(t, err) + + assert.Equal(t, "some/other:1.0", invImage.Image) +} diff --git a/bundle/bundle.go b/bundle/bundle.go index 5bfe86e5..c6b5cdbe 100644 --- a/bundle/bundle.go +++ b/bundle/bundle.go @@ -102,6 +102,11 @@ type InvocationImage struct { BaseImage `mapstructure:",squash"` } +// Map that stores the relocated images +// The key is the Image in bundle.json and the value is the new Image +// from the relocated registry +type ImageRelocationMap map[string]string + // Location provides the location where a value should be written in // the invocation image. // diff --git a/claim/claim.go b/claim/claim.go index 7cf90505..c58064c9 100644 --- a/claim/claim.go +++ b/claim/claim.go @@ -35,14 +35,15 @@ const ( // provide the necessary data to upgrade, uninstall, and downgrade // a CNAB package. type Claim struct { - Name string `json:"name"` - Revision string `json:"revision"` - Created time.Time `json:"created"` - Modified time.Time `json:"modified"` - Bundle *bundle.Bundle `json:"bundle"` - Result Result `json:"result"` - Parameters map[string]interface{} `json:"parameters"` - Files map[string]string `json:"files"` + Name string `json:"name"` + Revision string `json:"revision"` + Created time.Time `json:"created"` + Modified time.Time `json:"modified"` + Bundle *bundle.Bundle `json:"bundle"` + Result Result `json:"result"` + Parameters map[string]interface{} `json:"parameters"` + Files map[string]string `json:"files"` + RelocationMap bundle.ImageRelocationMap `json:"relocationMap"` } // ValidName is a regular expression that indicates whether a name is a valid claim name. @@ -65,7 +66,8 @@ func New(name string) (*Claim, error) { Action: ActionUnknown, Status: StatusUnknown, }, - Parameters: map[string]interface{}{}, + Parameters: map[string]interface{}{}, + RelocationMap: bundle.ImageRelocationMap{}, }, nil } diff --git a/claim/claim_test.go b/claim/claim_test.go index 777e704b..a7790e6e 100644 --- a/claim/claim_test.go +++ b/claim/claim_test.go @@ -5,6 +5,8 @@ import ( "time" "github.com/stretchr/testify/assert" + + "github.com/deislabs/cnab-go/bundle" ) func TestNew(t *testing.T) { @@ -18,10 +20,14 @@ func TestNew(t *testing.T) { } func TestUpdate(t *testing.T) { + relocationMap := bundle.ImageRelocationMap{ + "some.registry/image1": "some.other.registry/image1", + } claim, err := New("claim") assert.NoError(t, err) oldMod := claim.Modified oldUlid := claim.Revision + claim.RelocationMap = relocationMap time.Sleep(1 * time.Millisecond) // Force the Update to happen at a new time. For those of us who remembered to press the Turbo button. @@ -32,6 +38,7 @@ func TestUpdate(t *testing.T) { is.NotEqual(oldUlid, claim.Revision) is.Equal("install", claim.Result.Action) is.Equal("success", claim.Result.Status) + is.Equal(relocationMap, claim.RelocationMap) } func TestValidName(t *testing.T) { diff --git a/claim/claimstore_test.go b/claim/claimstore_test.go index 8177cbc2..ff36e392 100644 --- a/claim/claimstore_test.go +++ b/claim/claimstore_test.go @@ -7,9 +7,10 @@ import ( "testing" "time" - "github.com/deislabs/cnab-go/bundle" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/deislabs/cnab-go/bundle" "github.com/deislabs/cnab-go/utils/crud" ) @@ -18,6 +19,9 @@ func TestCanSaveReadAndDelete(t *testing.T) { claim, err := New("foo") is.NoError(err) claim.Bundle = &bundle.Bundle{Name: "foobundle", Version: "0.1.2"} + claim.RelocationMap = bundle.ImageRelocationMap{ + "some.registry/image1": "some.other.registry/image1", + } tempDir, err := ioutil.TempDir("", "duffletest") if err != nil { @@ -33,6 +37,7 @@ func TestCanSaveReadAndDelete(t *testing.T) { c, err := store.Read("foo") is.NoError(err, "Failed to read: %s", err) is.Equal(c.Bundle, claim.Bundle, "Expected to read back bundle %s, got %s", claim.Bundle.Name, c.Bundle.Name) + is.Equal("some.other.registry/image1", c.RelocationMap["some.registry/image1"]) claims, err := store.List() is.NoError(err, "Failed to list: %s", err) @@ -46,44 +51,33 @@ func TestCanSaveReadAndDelete(t *testing.T) { } func TestCanUpdate(t *testing.T) { + is := assert.New(t) claim, err := New("foo") - assert.NoError(t, err) + is.NoError(err) claim.Bundle = &bundle.Bundle{Name: "foobundle", Version: "0.1.2"} rev := claim.Revision tempDir, err := ioutil.TempDir("", "duffletest") - if err != nil { - t.Fatalf("Failed to create temp dir: %s", err) - } + is.NoError(err, "Failed to create temp dir") defer os.RemoveAll(tempDir) storeDir := filepath.Join(tempDir, "claimstore") store := NewClaimStore(crud.NewFileSystemStore(storeDir, "json")) err = store.Store(*claim) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) time.Sleep(1 * time.Millisecond) claim.Update(ActionInstall, StatusSuccess) err = store.Store(*claim) - if err != nil { - t.Errorf("Failed to update: %s", err) - } + is.NoError(err, "Failed to update") c, err := store.Read("foo") - if err != nil { - t.Errorf("Failed to read: %s", err) - } + is.NoError(err, "Failed to read") - if c.Result.Action != ActionInstall { - t.Errorf("Expected to read back action %s, got %s", ActionInstall, c.Result.Action) - } - if c.Revision == rev { - t.Errorf("Expected to read back new revision, got old revision %s", rev) - } + is.Equal(ActionInstall, c.Result.Action, "wrong action") + is.NotEqual(rev, c.Revision, "revision did not update") } func TestReadAll(t *testing.T) {