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

Commit

Permalink
Add command to remove applicationh images
Browse files Browse the repository at this point in the history
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
  • Loading branch information
rumpl committed Sep 27, 2019
1 parent acbaab0 commit 6182b38
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 14 deletions.
53 changes: 40 additions & 13 deletions e2e/images_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,58 @@ b-simple-app latest simple
`
)

func insertBundles(t *testing.T, cmd icmd.Cmd, dir *fs.Dir, info dindSwarmAndRegistryInfo) string {
// Push an application so that we can later pull it by digest
cmd.Command = dockerCli.Command("app", "push", "--tag", info.registryAddress+"/c-myapp", "--insecure-registries="+info.registryAddress, filepath.Join("testdata", "push-pull", "push-pull.dockerapp"))
r := icmd.RunCmd(cmd).Assert(t, icmd.Success)

// Get the digest from the output of the pull command
out := r.Stdout()
matches := reg.FindAllStringSubmatch(out, 1)
digest := matches[0][1]

// Pull the app by digest
cmd.Command = dockerCli.Command("app", "pull", "--insecure-registries="+info.registryAddress, info.registryAddress+"/c-myapp@"+digest)
icmd.RunCmd(cmd).Assert(t, icmd.Success)

cmd.Command = dockerCli.Command("app", "bundle", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "b-simple-app", "--output", dir.Join("simple-bundle.json"))
icmd.RunCmd(cmd).Assert(t, icmd.Success)
cmd.Command = dockerCli.Command("app", "bundle", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "a-simple-app", "--output", dir.Join("simple-bundle.json"))
icmd.RunCmd(cmd).Assert(t, icmd.Success)

return digest
}

func TestImageList(t *testing.T) {
runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) {
cmd := info.configuredCmd
dir := fs.NewDir(t, "")
defer dir.Remove()

// Push an application so that we can later pull it by digest
cmd.Command = dockerCli.Command("app", "push", "--tag", info.registryAddress+"/c-myapp", "--insecure-registries="+info.registryAddress, filepath.Join("testdata", "push-pull", "push-pull.dockerapp"))
r := icmd.RunCmd(cmd).Assert(t, icmd.Success)
insertBundles(t, cmd, dir, info)

expectedOutput := fmt.Sprintf(expected, info.registryAddress+"/c-myapp")
cmd.Command = dockerCli.Command("app", "image", "ls")
result := icmd.RunCmd(cmd).Assert(t, icmd.Success)
assert.Equal(t, result.Stdout(), expectedOutput)
})
}

func TestImageRm(t *testing.T) {
runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) {
cmd := info.configuredCmd
dir := fs.NewDir(t, "")
defer dir.Remove()

// Get the digest from the output of the pull command
out := r.Stdout()
matches := reg.FindAllStringSubmatch(out, 1)
digest := matches[0][1]
digest := insertBundles(t, cmd, dir, info)

// Pull the app by digest
cmd.Command = dockerCli.Command("app", "pull", "--insecure-registries="+info.registryAddress, info.registryAddress+"/c-myapp@"+digest)
cmd.Command = dockerCli.Command("app", "image", "rm", info.registryAddress+"/c-myapp@"+digest)
icmd.RunCmd(cmd).Assert(t, icmd.Success)

cmd.Command = dockerCli.Command("app", "bundle", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "b-simple-app", "--output", dir.Join("simple-bundle.json"))
icmd.RunCmd(cmd).Assert(t, icmd.Success)
cmd.Command = dockerCli.Command("app", "bundle", filepath.Join("testdata", "simple", "simple.dockerapp"), "--tag", "a-simple-app", "--output", dir.Join("simple-bundle.json"))
cmd.Command = dockerCli.Command("app", "image", "rm", "a-simple-app:latest", "b-simple-app:latest")
icmd.RunCmd(cmd).Assert(t, icmd.Success)

expectedOutput := fmt.Sprintf(expected, info.registryAddress+"/c-myapp")
expectedOutput := "REPOSITORY TAG APP NAME\n"
cmd.Command = dockerCli.Command("app", "image", "ls")
result := icmd.RunCmd(cmd).Assert(t, icmd.Success)
assert.Equal(t, result.Stdout(), expectedOutput)
Expand Down
5 changes: 4 additions & 1 deletion internal/commands/image/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ func Cmd(dockerCli command.Cli) *cobra.Command {
Use: "image",
}

cmd.AddCommand(listCmd(dockerCli))
cmd.AddCommand(
listCmd(dockerCli),
rmCmd(),
)

return cmd
}
57 changes: 57 additions & 0 deletions internal/commands/image/rm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package image

import (
"fmt"

"github.com/docker/cli/cli"

"github.com/docker/app/internal/store"
"github.com/docker/cli/cli/config"
"github.com/docker/distribution/reference"
"github.com/spf13/cobra"
)

func rmCmd() *cobra.Command {
return &cobra.Command{
Use: "rm [IMAGE] [IMAGE...]",
Short: "Remove an application image",
Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
appstore, err := store.NewApplicationStore(config.Dir())
if err != nil {
return err
}

bundleStore, err := appstore.BundleStore()
if err != nil {
return err
}

for _, arg := range args {
ref, err := reference.ParseNormalizedNamed(arg)
if err != nil {
fmt.Println("Error:", err.Error())
continue
}

rmErr := runRm(bundleStore, arg)
if rmErr != nil {
fmt.Println("Error:", rmErr.Error())
} else {
fmt.Println("Deleted: " + ref.String())
}
}

return err
},
}
}

func runRm(bundleStore store.BundleStore, app string) error {
ref, err := reference.ParseNormalizedNamed(app)
if err != nil {
return err
}

return bundleStore.Remove(ref)
}
15 changes: 15 additions & 0 deletions internal/store/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type BundleStore interface {
Store(ref reference.Named, bndle *bundle.Bundle) error
Read(ref reference.Named) (*bundle.Bundle, error)
List() ([]reference.Named, error)
Remove(ref reference.Named) error

LookupOrPullBundle(ref reference.Named, pullRef bool, config *configfile.ConfigFile, insecureRegistries []string) (*bundle.Bundle, error)
}
Expand Down Expand Up @@ -97,6 +98,20 @@ func (b *bundleStore) List() ([]reference.Named, error) {
return references, nil
}

// Remove removes a bundle from the bundle store.
func (b *bundleStore) Remove(ref reference.Named) error {
if _, err := b.Read(ref); err != nil {
return errors.New("no such image " + ref.String())
}

path, err := b.storePath(ref)
if err != nil {
return err
}

return os.Remove(path)
}

// LookupOrPullBundle will fetch the given bundle from the local
// bundle store, or if it is missing from the registry, and returns
// it. Always pulls if pullRef is true. If it pulls then the local
Expand Down
46 changes: 46 additions & 0 deletions internal/store/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,49 @@ func TestList(t *testing.T) {
assert.Equal(t, bundles[1].String(), "docker.io/my-repo/b-bundle@sha256:"+testSha)
})
}

func TestRemove(t *testing.T) {
dockerConfigDir := fs.NewDir(t, t.Name(), fs.WithMode(0755))
defer dockerConfigDir.Remove()
appstore, err := NewApplicationStore(dockerConfigDir.Path())
assert.NilError(t, err)
bundleStore, err := appstore.BundleStore()
assert.NilError(t, err)

refs := []reference.Named{
parseRefOrDie(t, "my-repo/a-bundle:my-tag"),
parseRefOrDie(t, "my-repo/b-bundle@sha256:"+testSha),
}

bndl := &bundle.Bundle{Name: "bundle-name"}
for _, ref := range refs {
err = bundleStore.Store(ref, bndl)
assert.NilError(t, err)
}

t.Run("error on unknown", func(t *testing.T) {
err := bundleStore.Remove(parseRefOrDie(t, "my-repo/some-bundle:1.0.0"))
assert.Equal(t, err.Error(), "no such image docker.io/my-repo/some-bundle:1.0.0")
})

t.Run("remove tagged and digested", func(t *testing.T) {
bundles, err := bundleStore.List()
assert.NilError(t, err)
assert.Equal(t, len(bundles), 2)

err = bundleStore.Remove(refs[0])

// Once removed there should be none left
assert.NilError(t, err)
bundles, err = bundleStore.List()
assert.NilError(t, err)
assert.Equal(t, len(bundles), 1)

err = bundleStore.Remove(refs[1])
assert.NilError(t, err)

bundles, err = bundleStore.List()
assert.NilError(t, err)
assert.Equal(t, len(bundles), 0)
})
}

0 comments on commit 6182b38

Please sign in to comment.