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>
This commit is contained in:
Daniel J Walsh
2019-11-22 11:39:49 -05:00
parent b4313b296a
commit 79bf5010ed
16 changed files with 383 additions and 3 deletions

8
API.md
View File

@ -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;">

View File

@ -658,6 +658,11 @@ type SystemPruneValues struct {
Volume bool
}
type SystemResetValues struct {
PodmanCommand
Force bool
}
type SystemRenumberValues struct {
PodmanCommand
}

71
cmd/podman/reset.go Normal file
View File

@ -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()
}

View File

@ -19,6 +19,7 @@ var (
)
var systemCommands = []*cobra.Command{
_systemResetCommand,
_infoCommand,
_pruneSystemCommand,
}

View File

@ -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)

View File

@ -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 |

View File

@ -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

View File

@ -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)

View File

@ -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)

107
libpod/reset.go Normal file
View File

@ -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
}

View File

@ -9,3 +9,7 @@ import (
func (r *Runtime) migrate(ctx context.Context) error {
return nil
}
func stopPauseProcess() error {
return nil
}

13
pkg/adapter/reset.go Normal file
View File

@ -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())
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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() {
}

View File

@ -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))
})
})