aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2019-11-22 11:39:49 -0500
committerDaniel J Walsh <dwalsh@redhat.com>2019-11-29 05:34:52 -0500
commit79bf5010eda37c07f577414ae71ecb8f8c8714a2 (patch)
treecd2d631a0c42d7bbb4f1b2631be8d833071644da
parentb4313b296a271097d26e481a0f03d22b9bab683b (diff)
downloadpodman-79bf5010eda37c07f577414ae71ecb8f8c8714a2.tar.gz
podman-79bf5010eda37c07f577414ae71ecb8f8c8714a2.tar.bz2
podman-79bf5010eda37c07f577414ae71ecb8f8c8714a2.zip
Add podman system reset command
This command will destroy all data created via podman. It will remove containers, images, volumes, pods. Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
-rwxr-xr-xAPI.md8
-rw-r--r--cmd/podman/cliconfig/config.go5
-rw-r--r--cmd/podman/reset.go71
-rw-r--r--cmd/podman/system.go1
-rw-r--r--cmd/podman/varlink/io.podman.varlink4
-rw-r--r--commands.md6
-rw-r--r--completions/bash/podman16
-rw-r--r--docs/source/markdown/podman-system-reset.1.md25
-rw-r--r--docs/source/markdown/podman-system.1.md5
-rw-r--r--libpod/reset.go107
-rw-r--r--libpod/runtime_migrate_unsupported.go4
-rw-r--r--pkg/adapter/reset.go13
-rw-r--r--pkg/adapter/reset_remote.go12
-rw-r--r--pkg/varlinkapi/system.go22
-rw-r--r--test/e2e/libpod_suite_test.go4
-rw-r--r--test/e2e/system_reset_test.go83
16 files changed, 383 insertions, 3 deletions
diff --git a/API.md b/API.md
index a02a8cf6f..3a66db83b 100755
--- a/API.md
+++ b/API.md
@@ -149,6 +149,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[func RemovePod(name: string, force: bool) string](#RemovePod)
+[func Reset() ](#Reset)
+
[func RestartContainer(name: string, timeout: int) string](#RestartContainer)
[func RestartPod(name: string) string](#RestartPod)
@@ -1059,6 +1061,12 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.RemovePod '{"name": "62f4
"pod": "62f4fd98cb57f529831e8f90610e54bba74bd6f02920ffb485e15376ed365c20"
}
~~~
+### <a name="Reset"></a>func Reset
+<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
+
+method Reset() </div>
+Reset resets Podman back to its initial state.
+Removes all Pods, Containers, Images and Volumes
### <a name="RestartContainer"></a>func RestartContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index a34afa827..df7ea6c33 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -658,6 +658,11 @@ type SystemPruneValues struct {
Volume bool
}
+type SystemResetValues struct {
+ PodmanCommand
+ Force bool
+}
+
type SystemRenumberValues struct {
PodmanCommand
}
diff --git a/cmd/podman/reset.go b/cmd/podman/reset.go
new file mode 100644
index 000000000..9d16dc978
--- /dev/null
+++ b/cmd/podman/reset.go
@@ -0,0 +1,71 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ systemResetCommand cliconfig.SystemResetValues
+ systemResetDescription = `Reset podman storage back to default state"
+
+ All containers will be stopped and removed, and all images, volumes and container content will be removed.
+`
+ _systemResetCommand = &cobra.Command{
+ Use: "reset",
+ Args: noSubArgs,
+ Short: "Reset podman storage",
+ Long: systemResetDescription,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ systemResetCommand.InputArgs = args
+ systemResetCommand.GlobalFlags = MainGlobalOpts
+ systemResetCommand.Remote = remoteclient
+ return systemResetCmd(&systemResetCommand)
+ },
+ }
+)
+
+func init() {
+ systemResetCommand.Command = _systemResetCommand
+ flags := systemResetCommand.Flags()
+ flags.BoolVarP(&systemResetCommand.Force, "force", "f", false, "Do not prompt for confirmation")
+
+ systemResetCommand.SetHelpTemplate(HelpTemplate())
+ systemResetCommand.SetUsageTemplate(UsageTemplate())
+}
+
+func systemResetCmd(c *cliconfig.SystemResetValues) error {
+ // Prompt for confirmation if --force is not set
+ if !c.Force {
+ reader := bufio.NewReader(os.Stdin)
+ fmt.Print(`
+WARNING! This will remove:
+ - all containers
+ - all pods
+ - all images
+ - all build cache
+Are you sure you want to continue? [y/N] `)
+ ans, err := reader.ReadString('\n')
+ if err != nil {
+ return errors.Wrapf(err, "error reading input")
+ }
+ if strings.ToLower(ans)[0] != 'y' {
+ return nil
+ }
+ }
+
+ runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
+ if err != nil {
+ return errors.Wrapf(err, "error creating libpod runtime")
+ }
+ // No shutdown, since storage will be destroyed when command completes
+
+ return runtime.Reset()
+}
diff --git a/cmd/podman/system.go b/cmd/podman/system.go
index 80080bf44..921d0c037 100644
--- a/cmd/podman/system.go
+++ b/cmd/podman/system.go
@@ -19,6 +19,7 @@ var (
)
var systemCommands = []*cobra.Command{
+ _systemResetCommand,
_infoCommand,
_pruneSystemCommand,
}
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index e76b9627e..a3fd27ed6 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -536,6 +536,10 @@ method GetVersion() -> (
remote_api_version: int
)
+# Reset resets Podman back to its initial state.
+# Removes all Pods, Containers, Images and Volumes
+method Reset() -> ()
+
# GetInfo returns a [PodmanInfo](#PodmanInfo) struct that describes podman and its host such as storage stats,
# build information of Podman, and system-wide registries.
method GetInfo() -> (info: PodmanInfo)
diff --git a/commands.md b/commands.md
index aae5d7e02..de9169a4b 100644
--- a/commands.md
+++ b/commands.md
@@ -78,6 +78,12 @@
| [podman-stats(1)](/docs/source/markdown/podman-stats.1.md) | Display a live stream of one or more containers' resource usage statistics |
| [podman-stop(1)](/docs/source/markdown/podman-stop.1.md) | Stops one or more running containers |
| [podman-system(1)](/docs/source/markdown/podman-system.1.md) | Manage podman |
+| [podman-system-df(1)](/docs/source/markdown/podman-system-df.1.md) | Show podman disk usage. |
+| [podman-system-info(1)](/docs/source/markdown/podman-info.1.md) | Displays Podman related system information. |
+| [podman-system-migrate(1)](/docs/source/markdown/podman-system-migrate.1.md) | Migrate existing containers to a new podman version. |
+| [podman-system-prune(1)](/docs/source/markdown/podman-system-prune.1.md) | Remove all unused container, image and volume data. |
+| [podman-system-renumber(1)](/docs/source/markdown/podman-system-renumber.1.md) | Migrate lock numbers to handle a change in maximum number of locks. |
+| [podman-system-reset(1)](/docs/source/markdown/podman-system-reset.1.md) | Reset storage back to original state. Remove all pods, containers, images, volumes. |
| [podman-tag(1)](/docs/source/markdown/podman-tag.1.md) | Add an additional name to a local image | [![...](/docs/source/markdown/play.png)](https://asciinema.org/a/133803) |
| [podman-top(1)](/docs/source/markdown/podman-top.1.md) | Display the running processes of a container |
| [podman-umount(1)](/docs/source/markdown/podman-umount.1.md) | Unmount a working container's root filesystem |
diff --git a/completions/bash/podman b/completions/bash/podman
index 6d145030f..5634a5d8c 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -1142,6 +1142,21 @@ _podman_container() {
esac
}
+_podman_system_reset() {
+ local options_with_args="
+ "
+ local boolean_options="
+ -h
+ --help
+ --force
+ "
+ case "$cur" in
+ -*)
+ COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
+ ;;
+ esac
+}
+
_podman_system_df() {
local options_with_args="
--format
@@ -1193,6 +1208,7 @@ _podman_system() {
df
info
prune
+ reset
"
__podman_subcommands "$subcommands" && return
diff --git a/docs/source/markdown/podman-system-reset.1.md b/docs/source/markdown/podman-system-reset.1.md
new file mode 100644
index 000000000..432f275f4
--- /dev/null
+++ b/docs/source/markdown/podman-system-reset.1.md
@@ -0,0 +1,25 @@
+% podman-system-reset(1)
+
+## NAME
+podman\-system\-reset - Reset storage back to initial state
+
+## SYNOPSIS
+**podman system reset**
+
+## DESCRIPTION
+**podman system reset** removes all pods, containers, images and volumes.
+
+## OPTIONS
+**--force**, **-f**
+
+Do not prompt for confirmation
+
+**--help**, **-h**
+
+Print usage statement
+
+## SEE ALSO
+`podman(1)`, `podman-system(1)`
+
+## HISTORY
+November 2019, Originally compiled by Dan Walsh (dwalsh at redhat dot com)
diff --git a/docs/source/markdown/podman-system.1.md b/docs/source/markdown/podman-system.1.md
index bbd541066..1af97290d 100644
--- a/docs/source/markdown/podman-system.1.md
+++ b/docs/source/markdown/podman-system.1.md
@@ -15,9 +15,10 @@ The system command allows you to manage the podman systems
| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
| df | [podman-system-df(1)](podman-system-df.1.md) | Show podman disk usage. |
| info | [podman-system-info(1)](podman-info.1.md) | Displays Podman related system information. |
-| prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused container, image and volume data |
-| renumber | [podman-system-renumber(1)](podman-system-renumber.1.md)| Migrate lock numbers to handle a change in maximum number of locks. |
| migrate | [podman-system-migrate(1)](podman-system-migrate.1.md)| Migrate existing containers to a new podman version. |
+| prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused container, image and volume data. |
+| renumber | [podman-system-renumber(1)](podman-system-renumber.1.md)| Migrate lock numbers to handle a change in maximum number of locks. |
+| reset | [podman-system-reset(1)](podman-system-reset.1.md) | Reset storage back to initial state. |
## SEE ALSO
podman(1)
diff --git a/libpod/reset.go b/libpod/reset.go
new file mode 100644
index 000000000..a35b476a4
--- /dev/null
+++ b/libpod/reset.go
@@ -0,0 +1,107 @@
+package libpod
+
+import (
+ "context"
+ "os"
+ "path/filepath"
+
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+// Reset removes all storage
+func (r *Runtime) Reset(ctx context.Context) error {
+
+ pods, err := r.GetAllPods()
+ if err != nil {
+ return err
+ }
+ for _, p := range pods {
+ if err := r.RemovePod(ctx, p, true, true); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchPod {
+ continue
+ }
+ logrus.Errorf("Error removing Pod %s: %v", p.ID(), err)
+ }
+ }
+
+ ctrs, err := r.GetAllContainers()
+ if err != nil {
+ return err
+ }
+
+ for _, c := range ctrs {
+ if err := r.RemoveContainer(ctx, c, true, true); err != nil {
+ if err := r.RemoveStorageContainer(c.ID(), true); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchCtr {
+ continue
+ }
+ logrus.Errorf("Error removing container %s: %v", c.ID(), err)
+ }
+ }
+ }
+
+ if err := stopPauseProcess(); err != nil {
+ logrus.Errorf("Error stopping pause process: %v", err)
+ }
+
+ ir := r.ImageRuntime()
+ images, err := ir.GetImages()
+ if err != nil {
+ return err
+ }
+
+ for _, i := range images {
+ if err := i.Remove(ctx, true); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchImage {
+ continue
+ }
+ logrus.Errorf("Error removing image %s: %v", i.ID(), err)
+ }
+ }
+ volumes, err := r.state.AllVolumes()
+ if err != nil {
+ return err
+ }
+ for _, v := range volumes {
+ if err := r.RemoveVolume(ctx, v, true); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchVolume {
+ continue
+ }
+ logrus.Errorf("Error removing volume %s: %v", v.config.Name, err)
+ }
+ }
+
+ _, prevError := r.store.Shutdown(true)
+ if err := os.RemoveAll(r.store.GraphRoot()); err != nil {
+ if prevError != nil {
+ logrus.Error(prevError)
+ }
+ prevError = err
+ }
+ if err := os.RemoveAll(r.store.RunRoot()); err != nil {
+ if prevError != nil {
+ logrus.Error(prevError)
+ }
+ prevError = err
+ }
+ if err := os.RemoveAll(r.config.TmpDir); err != nil {
+ if prevError != nil {
+ logrus.Error(prevError)
+ }
+ prevError = err
+ }
+ if rootless.IsRootless() {
+ configPath := filepath.Join(os.Getenv("HOME"), ".config/containers")
+ if err := os.RemoveAll(configPath); err != nil {
+ if prevError != nil {
+ logrus.Error(prevError)
+ }
+ prevError = err
+ }
+ }
+
+ return prevError
+}
diff --git a/libpod/runtime_migrate_unsupported.go b/libpod/runtime_migrate_unsupported.go
index 1a9e46fdc..e362cca63 100644
--- a/libpod/runtime_migrate_unsupported.go
+++ b/libpod/runtime_migrate_unsupported.go
@@ -9,3 +9,7 @@ import (
func (r *Runtime) migrate(ctx context.Context) error {
return nil
}
+
+func stopPauseProcess() error {
+ return nil
+}
diff --git a/pkg/adapter/reset.go b/pkg/adapter/reset.go
new file mode 100644
index 000000000..0decc3d15
--- /dev/null
+++ b/pkg/adapter/reset.go
@@ -0,0 +1,13 @@
+// +build !remoteclient
+
+package adapter
+
+import (
+ "context"
+)
+
+// Reset the container storage back to initial states.
+// Removes all Pods, Containers, Images and Volumes.
+func (r *LocalRuntime) Reset() error {
+ return r.Runtime.Reset(context.TODO())
+}
diff --git a/pkg/adapter/reset_remote.go b/pkg/adapter/reset_remote.go
new file mode 100644
index 000000000..663fab639
--- /dev/null
+++ b/pkg/adapter/reset_remote.go
@@ -0,0 +1,12 @@
+// +build remoteclient
+
+package adapter
+
+import (
+ "github.com/containers/libpod/cmd/podman/varlink"
+)
+
+// Info returns information for the host system and its components
+func (r RemoteRuntime) Reset() error {
+ return iopodman.Reset().Call(r.Conn)
+}
diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go
index f6057f5fc..b81ff11ba 100644
--- a/pkg/varlinkapi/system.go
+++ b/pkg/varlinkapi/system.go
@@ -3,12 +3,15 @@
package varlinkapi
import (
+ "context"
"fmt"
- "github.com/containers/libpod/libpod/define"
+ "os"
goruntime "runtime"
"time"
"github.com/containers/libpod/cmd/podman/varlink"
+ "github.com/containers/libpod/libpod/define"
+ "github.com/sirupsen/logrus"
)
// GetVersion ...
@@ -105,3 +108,20 @@ func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error {
podmanInfo.Insecure_registries = insecureRegistries
return call.ReplyGetInfo(podmanInfo)
}
+
+// GetVersion ...
+func (i *LibpodAPI) Reset(call iopodman.VarlinkCall) error {
+ if err := i.Runtime.Reset(context.TODO()); err != nil {
+ logrus.Errorf("Reset Failed: %v", err)
+ if err := call.ReplyErrorOccurred(err.Error()); err != nil {
+ logrus.Errorf("Failed to send ReplyErrorOccurred: %v", err)
+ }
+ os.Exit(define.ExecErrorCodeGeneric)
+ }
+ if err := call.ReplyReset(); err != nil {
+ logrus.Errorf("Failed to send ReplyReset: %v", err)
+ os.Exit(define.ExecErrorCodeGeneric)
+ }
+ os.Exit(0)
+ return nil
+}
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index 5239f4d8e..43f08bf03 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -135,3 +135,7 @@ func removeCache() {
func (p *PodmanTestIntegration) SeedImages() error {
return nil
}
+
+// We don't support running Varlink when local
+func (p *PodmanTestIntegration) StartVarlink() {
+}
diff --git a/test/e2e/system_reset_test.go b/test/e2e/system_reset_test.go
new file mode 100644
index 000000000..e5ce69739
--- /dev/null
+++ b/test/e2e/system_reset_test.go
@@ -0,0 +1,83 @@
+package integration
+
+import (
+ "fmt"
+ "os"
+
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("podman system reset", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ podmanTest.SeedImages()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds())
+ GinkgoWriter.Write([]byte(timedResult))
+ })
+
+ It("podman system reset", func() {
+ // system reset will not remove additional store images, so need to grab length
+
+ session := podmanTest.Podman([]string{"rmi", "--force", "--all"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"images", "-n"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ l := len(session.OutputToStringArray())
+
+ session = podmanTest.Podman([]string{"pull", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"volume", "create", "data"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"create", "-v", "data:/data", ALPINE, "echo", "hello"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"system", "reset", "-f"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // If remote then the varlink service should have exited
+ // On local tests this is a noop
+ podmanTest.StartVarlink()
+
+ session = podmanTest.Podman([]string{"images", "-n"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(len(session.OutputToStringArray())).To(Equal(l))
+
+ session = podmanTest.Podman([]string{"volume", "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(len(session.OutputToStringArray())).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"container", "ls", "-q"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(len(session.OutputToStringArray())).To(Equal(0))
+ })
+})