enable podman-remote volume prune

allow users to remotely prune volumes.

this is the last volume command for remote enablement.  as such,
the volume commands are being folded back into main because they
are supported for both local and remote clients.

also, enable all volume tests that do not use containers
as containers are not enabled for the remote client yet.

Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
baude 2019-02-11 15:36:24 -06:00
parent 0cd2243596
commit 5be818e715
14 changed files with 101 additions and 52 deletions

15
API.md
View file

@ -131,6 +131,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[func VolumeRemove(options: VolumeRemoveOpts) []string](#VolumeRemove)
[func VolumesPrune() []string, []string](#VolumesPrune)
[func WaitContainer(name: string) int](#WaitContainer)
[type BuildInfo](#BuildInfo)
@ -530,7 +532,7 @@ GetVersion returns version and build information of the podman service
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method GetVolumes(args: [[]string](#[]string), all: [bool](https://godoc.org/builtin#bool)) [Volume](#Volume)</div>
GetVolumes gets slice of the volumes on a remote host
### <a name="HistoryImage"></a>func HistoryImage
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
@ -773,7 +775,7 @@ the image cannot be found in local storage; otherwise it will return a [MoreResp
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method ReceiveFile(path: [string](https://godoc.org/builtin#string), delete: [bool](https://godoc.org/builtin#bool)) [int](https://godoc.org/builtin#int)</div>
ReceiveFile allows the host to send a remote client a file
### <a name="RemoveContainer"></a>func RemoveContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
@ -856,7 +858,7 @@ search results per registry.
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method SendFile(type: [string](https://godoc.org/builtin#string), length: [int](https://godoc.org/builtin#int)) [string](https://godoc.org/builtin#string)</div>
Sendfile allows a remote client to send a file to the host
### <a name="StartContainer"></a>func StartContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
@ -956,12 +958,17 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.UnpausePod '{"name": "foo
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method VolumeCreate(options: [VolumeCreateOpts](#VolumeCreateOpts)) [string](https://godoc.org/builtin#string)</div>
VolumeCreate creates a volume on a remote host
### <a name="VolumeRemove"></a>func VolumeRemove
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method VolumeRemove(options: [VolumeRemoveOpts](#VolumeRemoveOpts)) [[]string](#[]string)</div>
VolumeRemove removes a volume on a remote host
### <a name="VolumesPrune"></a>func VolumesPrune
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method VolumesPrune() [[]string](#[]string), [[]string](#[]string)</div>
VolumesPrune removes unused volumes on the host
### <a name="WaitContainer"></a>func WaitContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">

View file

@ -114,18 +114,6 @@ func getPodSubCommands() []*cobra.Command {
}
}
// Commands that the local client implements
func getVolumeSubCommands() []*cobra.Command {
return []*cobra.Command{
_volumeCreateCommand,
_volumeLsCommand,
_volumeRmCommand,
_volumeInspectCommand,
_volumePruneCommand,
}
}
// Commands that the local client implements
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{
_containerKubeCommand,

View file

@ -31,16 +31,6 @@ func getPodSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
// commands that only the remoteclient implements
func getVolumeSubCommands() []*cobra.Command {
return []*cobra.Command{
_volumeCreateCommand,
_volumeRmCommand,
_volumeLsCommand,
_volumeInspectCommand,
}
}
// commands that only the remoteclient implements
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{}

View file

@ -1070,15 +1070,24 @@ method ContainerInspectData(name: string) -> (config: string)
# development of Podman only and generally should not be used.
method ContainerStateData(name: string) -> (config: string)
# Sendfile allows a remote client to send a file to the host
method SendFile(type: string, length: int) -> (file_handle: string)
# ReceiveFile allows the host to send a remote client a file
method ReceiveFile(path: string, delete: bool) -> (len: int)
# VolumeCreate creates a volume on a remote host
method VolumeCreate(options: VolumeCreateOpts) -> (volumeName: string)
# VolumeRemove removes a volume on a remote host
method VolumeRemove(options: VolumeRemoveOpts) -> (volumeNames: []string)
# GetVolumes gets slice of the volumes on a remote host
method GetVolumes(args: []string, all: bool) -> (volumes: []Volume)
# VolumesPrune removes unused volumes on the host
method VolumesPrune() -> (prunedNames: []string, prunedErrors: []string)
# ImageNotFound means the image could not be found by the provided name or ID in local storage.
error ImageNotFound (id: string)

View file

@ -16,8 +16,16 @@ var volumeCommand = cliconfig.PodmanCommand{
Long: volumeDescription,
},
}
var volumeSubcommands = []*cobra.Command{
_volumeCreateCommand,
_volumeLsCommand,
_volumeRmCommand,
_volumeInspectCommand,
_volumePruneCommand,
}
func init() {
volumeCommand.AddCommand(getVolumeSubCommands()...)
volumeCommand.SetUsageTemplate(UsageTemplate())
volumeCommand.AddCommand(volumeSubcommands...)
rootCmd.AddCommand(volumeCommand.Command)
}

View file

@ -8,7 +8,6 @@ import (
"strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@ -44,23 +43,20 @@ func init() {
}
func volumePrune(runtime *adapter.LocalRuntime, ctx context.Context) error {
var lastError error
volumes, err := runtime.GetAllVolumes()
if err != nil {
return err
prunedNames, prunedErrors := runtime.PruneVolumes(ctx)
for _, name := range prunedNames {
fmt.Println(name)
}
if len(prunedErrors) == 0 {
return nil
}
// Grab the last error
lastError := prunedErrors[len(prunedErrors)-1]
// Remove the last error from the error slice
prunedErrors = prunedErrors[:len(prunedErrors)-1]
for _, vol := range volumes {
err = runtime.RemoveVolume(ctx, vol, false, true)
if err == nil {
fmt.Println(vol.Name())
} else if err != libpod.ErrVolumeBeingUsed {
if lastError != nil {
logrus.Errorf("%q", lastError)
}
lastError = errors.Wrapf(err, "failed to remove volume %q", vol.Name())
}
for _, err := range prunedErrors {
logrus.Errorf("%q", err)
}
return lastError
}
@ -85,6 +81,5 @@ func volumePruneCmd(c *cliconfig.VolumePruneValues) error {
return nil
}
}
return volumePrune(runtime, getContext())
}

View file

@ -305,3 +305,8 @@ func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, opti
return r.Runtime.Build(ctx, options, dockerfiles...)
}
// PruneVolumes is a wrapper function for libpod PruneVolumes
func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) {
return r.Runtime.PruneVolumes(ctx)
}

View file

@ -642,3 +642,17 @@ func varlinkVolumeToVolume(r *LocalRuntime, volumes []iopodman.Volume) []*Volume
}
return vols
}
// PruneVolumes removes all unused volumes from the remote system
func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) {
var errs []error
prunedNames, prunedErrors, err := iopodman.VolumesPrune().Call(r.Conn)
if err != nil {
return []string{}, []error{err}
}
// We need to transform the string results of the error into actual error types
for _, e := range prunedErrors {
errs = append(errs, errors.New(e))
}
return prunedNames, errs
}

View file

@ -154,3 +154,27 @@ func (r *Runtime) GetAllVolumes() ([]*Volume, error) {
return r.state.AllVolumes()
}
// PruneVolumes removes unused volumes from the system
func (r *Runtime) PruneVolumes(ctx context.Context) ([]string, []error) {
var (
prunedIDs []string
pruneErrors []error
)
vols, err := r.GetAllVolumes()
if err != nil {
pruneErrors = append(pruneErrors, err)
return nil, pruneErrors
}
for _, vol := range vols {
if err := r.RemoveVolume(ctx, vol, false, true); err != nil {
if err != ErrVolumeBeingUsed {
pruneErrors = append(pruneErrors, err)
}
continue
}
prunedIDs = append(prunedIDs, vol.Name())
}
return prunedIDs, pruneErrors
}

View file

@ -72,3 +72,19 @@ func (i *LibpodAPI) GetVolumes(call iopodman.VarlinkCall, args []string, all boo
}
return call.ReplyGetVolumes(volumes)
}
// VolumesPrune removes unused images via a varlink call
func (i *LibpodAPI) VolumesPrune(call iopodman.VarlinkCall) error {
var errs []string
prunedNames, prunedErrors := i.Runtime.PruneVolumes(getContext())
if len(prunedErrors) == 0 {
return call.ReplyVolumesPrune(prunedNames, []string{})
}
// We need to take the errors and capture their strings to go back over
// varlink
for _, e := range prunedErrors {
errs = append(errs, e.Error())
}
return call.ReplyVolumesPrune(prunedNames, errs)
}

View file

@ -1,5 +1,3 @@
// +build !remoteclient
package integration
import (

View file

@ -1,5 +1,3 @@
// +build !remoteclient
package integration
import (

View file

@ -1,5 +1,3 @@
// +build !remoteclient
package integration
import (

View file

@ -1,5 +1,3 @@
// +build !remoteclient
package integration
import (
@ -50,6 +48,7 @@ var _ = Describe("Podman volume rm", func() {
})
It("podman rm with --force flag", func() {
SkipIfRemote()
session := podmanTest.Podman([]string{"create", "-v", "myvol:/myvol", ALPINE, "ls"})
cid := session.OutputToString()
session.WaitWithDefaultTimeout()