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

Commit

Permalink
Allow rm of multiple apps in one command
Browse files Browse the repository at this point in the history
Adds ability to remove multiple running apps with a single command. E.g.:
	docker app rm app1 app2
Attempts to remove all listed apps before returning any errors same as with docker app image rm.

Signed-off-by: Nick Adcock <[email protected]>
  • Loading branch information
zappy-shu committed Dec 2, 2019
1 parent d119541 commit 3453532
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 29 deletions.
77 changes: 56 additions & 21 deletions e2e/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,16 +341,8 @@ func TestDockerAppLifecycle(t *testing.T) {

// Install a Docker Application Package with an existing failed installation is fine
cmd.Command = dockerCli.Command("app", "run", appName, "--name", appName)
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(),
[]string{
fmt.Sprintf("WARNING: installing over previously failed installation %q", appName),
fmt.Sprintf("Creating network %s_back", appName),
fmt.Sprintf("Creating network %s_front", appName),
fmt.Sprintf("Creating service %s_db", appName),
fmt.Sprintf("Creating service %s_api", appName),
fmt.Sprintf("Creating service %s_web", appName),
})
assertAppLabels(t, &cmd, appName, "db")
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), expectedAppRunOutput(appName, true))
assertAppDbLabels(t, &cmd, appName)

// List the installed application
cmd.Command = dockerCli.Command("app", "ls")
Expand All @@ -375,21 +367,64 @@ func TestDockerAppLifecycle(t *testing.T) {
fmt.Sprintf("Updating service %s_api", appName),
fmt.Sprintf("Updating service %s_web", appName),
})
assertAppLabels(t, &cmd, appName, "db")
assertAppDbLabels(t, &cmd, appName)

// Uninstall the application
cmd.Command = dockerCli.Command("app", "rm", appName)
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(),
[]string{
fmt.Sprintf("Removing service %s_api", appName),
fmt.Sprintf("Removing service %s_db", appName),
fmt.Sprintf("Removing service %s_web", appName),
fmt.Sprintf("Removing network %s_front", appName),
fmt.Sprintf("Removing network %s_back", appName),
})
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), expectedAppRmOutput(appName))
})
}

func TestDockerAppLifecycleMultiRm(t *testing.T) {
runWithDindSwarmAndRegistry(t, func(info dindSwarmAndRegistryInfo) {
cmd := info.configuredCmd
appName := strings.ToLower(strings.Replace(t.Name(), "/", "_", 1))
tmpDir := fs.NewDir(t, appName)
defer tmpDir.Remove()

cmd.Command = dockerCli.Command("app", "build", "--tag", appName, "testdata/simple")
icmd.RunCmd(cmd).Assert(t, icmd.Success)

// Install multiple applications
cmd.Command = dockerCli.Command("app", "run", appName, "--name", appName)
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), expectedAppRunOutput(appName, false))
assertAppDbLabels(t, &cmd, appName)
appName2 := appName + "2"
cmd.Command = dockerCli.Command("app", "run", appName, "--name", appName2, "--set", "web_port=8083")
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), expectedAppRunOutput(appName2, false))
assertAppDbLabels(t, &cmd, appName2)

// Uninstall multiple applications
cmd.Command = dockerCli.Command("app", "rm", appName, appName2)
checkContains(t, icmd.RunCmd(cmd).Assert(t, icmd.Success).Combined(), append(expectedAppRmOutput(appName), expectedAppRmOutput(appName2)...))
})
}

func expectedAppRunOutput(appName string, prevFailed bool) []string {
expected := []string{}
if prevFailed {
expected = append(expected, fmt.Sprintf("WARNING: installing over previously failed installation %q", appName))
}
expected = append(expected,
fmt.Sprintf("Creating network %s_back", appName),
fmt.Sprintf("Creating network %s_front", appName),
fmt.Sprintf("Creating service %s_db", appName),
fmt.Sprintf("Creating service %s_api", appName),
fmt.Sprintf("Creating service %s_web", appName),
)
return expected
}

func expectedAppRmOutput(appName string) []string {
return []string{
fmt.Sprintf("Removing service %s_api", appName),
fmt.Sprintf("Removing service %s_db", appName),
fmt.Sprintf("Removing service %s_web", appName),
fmt.Sprintf("Removing network %s_front", appName),
fmt.Sprintf("Removing network %s_back", appName),
}
}

func TestCredentials(t *testing.T) {
credSet := &credentials.CredentialSet{
Name: "test-creds",
Expand Down Expand Up @@ -499,8 +534,8 @@ func TestCredentials(t *testing.T) {
})
}

func assertAppLabels(t *testing.T, cmd *icmd.Cmd, appName, containerName string) {
cmd.Command = dockerCli.Command("inspect", fmt.Sprintf("%s_%s", appName, containerName))
func assertAppDbLabels(t *testing.T, cmd *icmd.Cmd, appName string) {
cmd.Command = dockerCli.Command("inspect", fmt.Sprintf("%s_db", appName))
checkContains(t, icmd.RunCmd(*cmd).Assert(t, icmd.Success).Combined(),
[]string{
fmt.Sprintf(`"%s": "%s"`, internal.LabelAppNamespace, appName),
Expand Down
33 changes: 25 additions & 8 deletions internal/commands/remove.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package commands

import (
"errors"
"fmt"
"os"
"strings"

"github.com/docker/app/internal/cliopts"
"github.com/docker/app/internal/cnab"
"github.com/docker/app/internal/packager"
"github.com/docker/app/internal/store"

"github.com/deislabs/cnab-go/driver"

Expand All @@ -30,9 +33,23 @@ func removeCmd(dockerCli command.Cli, installerContext *cliopts.InstallerContext
Short: "Remove a running App",
Aliases: []string{"remove"},
Example: `$ docker app rm myrunningapp`,
Args: cli.ExactArgs(1),
Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return runRemove(dockerCli, args[0], opts, installerContext)
_, installationStore, credentialStore, err := prepareStores(dockerCli.CurrentContext())
if err != nil {
return err
}

errs := []string{}
for _, arg := range args {
if err := runRemove(dockerCli, arg, opts, installerContext, installationStore, credentialStore); err != nil {
errs = append(errs, fmt.Sprintf("Error: %s", err))
}
}
if len(errs) > 0 {
return errors.New(strings.Join(errs, "\n"))
}
return nil
},
}
opts.credentialOptions.addFlags(cmd.Flags())
Expand All @@ -41,12 +58,12 @@ func removeCmd(dockerCli command.Cli, installerContext *cliopts.InstallerContext
return cmd
}

func runRemove(dockerCli command.Cli, installationName string, opts removeOptions, installerContext *cliopts.InstallerContextOptions) (mainErr error) {
_, installationStore, credentialStore, err := prepareStores(dockerCli.CurrentContext())
if err != nil {
return err
}

func runRemove(dockerCli command.Cli,
installationName string,
opts removeOptions,
installerContext *cliopts.InstallerContextOptions,
installationStore store.InstallationStore,
credentialStore store.CredentialStore) (mainErr error) {
installation, err := installationStore.Read(installationName)
if err != nil {
return err
Expand Down

0 comments on commit 3453532

Please sign in to comment.