mirror of
https://github.com/containers/podman.git
synced 2025-06-19 08:09:12 +08:00
podman-remote volume inspect|ls
add the ability to list and inspect volumes using the remote client and varlink Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
38
API.md
38
API.md
@ -53,6 +53,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
|
||||
|
||||
[func GetVersion() string, string, string, string, string, int](#GetVersion)
|
||||
|
||||
[func GetVolumes(args: []string, all: bool) Volume](#GetVolumes)
|
||||
|
||||
[func HistoryImage(name: string) ImageHistory](#HistoryImage)
|
||||
|
||||
[func ImageExists(name: string) int](#ImageExists)
|
||||
@ -175,6 +177,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
|
||||
|
||||
[type MoreResponse](#MoreResponse)
|
||||
|
||||
[type NotImplemented](#NotImplemented)
|
||||
|
||||
[type PodContainerErrorData](#PodContainerErrorData)
|
||||
|
||||
[type PodCreate](#PodCreate)
|
||||
@ -185,6 +189,10 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
|
||||
|
||||
[type Sockets](#Sockets)
|
||||
|
||||
[type StringResponse](#StringResponse)
|
||||
|
||||
[type Volume](#Volume)
|
||||
|
||||
[type VolumeCreateOpts](#VolumeCreateOpts)
|
||||
|
||||
[type VolumeRemoveOpts](#VolumeRemoveOpts)
|
||||
@ -516,6 +524,11 @@ $ varlink call unix:/run/podman/io.podman/io.podman.GetPodStats '{"name": "7f62b
|
||||
|
||||
method GetVersion() [string](https://godoc.org/builtin#string), [string](https://godoc.org/builtin#string), [string](https://godoc.org/builtin#string), [string](https://godoc.org/builtin#string), [string](https://godoc.org/builtin#string), [int](https://godoc.org/builtin#int)</div>
|
||||
GetVersion returns version and build information of the podman service
|
||||
### <a name="GetVolumes"></a>func GetVolumes
|
||||
<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>
|
||||
|
||||
### <a name="HistoryImage"></a>func HistoryImage
|
||||
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
|
||||
|
||||
@ -1480,6 +1493,11 @@ MoreResponse is a struct for when responses from varlink requires longer output
|
||||
logs [[]string](#[]string)
|
||||
|
||||
id [string](https://godoc.org/builtin#string)
|
||||
### <a name="NotImplemented"></a>type NotImplemented
|
||||
|
||||
|
||||
|
||||
comment [string](https://godoc.org/builtin#string)
|
||||
### <a name="PodContainerErrorData"></a>type PodContainerErrorData
|
||||
|
||||
|
||||
@ -1557,6 +1575,26 @@ container_id [string](https://godoc.org/builtin#string)
|
||||
io_socket [string](https://godoc.org/builtin#string)
|
||||
|
||||
control_socket [string](https://godoc.org/builtin#string)
|
||||
### <a name="StringResponse"></a>type StringResponse
|
||||
|
||||
|
||||
|
||||
message [string](https://godoc.org/builtin#string)
|
||||
### <a name="Volume"></a>type Volume
|
||||
|
||||
|
||||
|
||||
name [string](https://godoc.org/builtin#string)
|
||||
|
||||
labels [map[string]](#map[string])
|
||||
|
||||
mountPoint [string](https://godoc.org/builtin#string)
|
||||
|
||||
driver [string](https://godoc.org/builtin#string)
|
||||
|
||||
options [map[string]](#map[string])
|
||||
|
||||
scope [string](https://godoc.org/builtin#string)
|
||||
### <a name="VolumeCreateOpts"></a>type VolumeCreateOpts
|
||||
|
||||
|
||||
|
@ -36,6 +36,8 @@ func getVolumeSubCommands() []*cobra.Command {
|
||||
return []*cobra.Command{
|
||||
_volumeCreateCommand,
|
||||
_volumeRmCommand,
|
||||
_volumeLsCommand,
|
||||
_volumeInspectCommand,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,22 @@
|
||||
# in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in the upstream libpod repository.
|
||||
interface io.podman
|
||||
|
||||
type Volume (
|
||||
name: string,
|
||||
labels: [string]string,
|
||||
mountPoint: string,
|
||||
driver: string,
|
||||
options: [string]string,
|
||||
scope: string
|
||||
)
|
||||
|
||||
type NotImplemented (
|
||||
comment: string
|
||||
)
|
||||
|
||||
type StringResponse (
|
||||
message: string
|
||||
)
|
||||
|
||||
# ContainerChanges describes the return struct for ListContainerChanges
|
||||
type ContainerChanges (
|
||||
@ -1044,6 +1060,7 @@ method VolumeCreate(options: VolumeCreateOpts) -> (volumeName: string)
|
||||
|
||||
method VolumeRemove(options: VolumeRemoveOpts) -> (volumeNames: []string)
|
||||
|
||||
method GetVolumes(args: []string, all: bool) -> (volumes: []Volume)
|
||||
|
||||
# ImageNotFound means the image could not be found by the provided name or ID in local storage.
|
||||
error ImageNotFound (id: string)
|
||||
|
@ -2,9 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -39,22 +38,19 @@ func init() {
|
||||
}
|
||||
|
||||
func volumeInspectCmd(c *cliconfig.VolumeInspectValues) error {
|
||||
var err error
|
||||
if (c.All && len(c.InputArgs) > 0) || (!c.All && len(c.InputArgs) < 1) {
|
||||
return errors.New("provide one or more volume names or use --all")
|
||||
}
|
||||
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
opts := volumeLsOptions{
|
||||
Format: c.Format,
|
||||
vols, err := runtime.InspectVolumes(getContext(), c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vols, lastError := getVolumesFromContext(&c.PodmanCommand, runtime)
|
||||
if lastError != nil {
|
||||
logrus.Errorf("%q", lastError)
|
||||
}
|
||||
|
||||
return generateVolLsOutput(vols, opts, runtime)
|
||||
return generateVolLsOutput(vols, volumeLsOptions{Format: c.Format})
|
||||
}
|
||||
|
@ -6,8 +6,7 @@ import (
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||
"github.com/containers/libpod/cmd/podman/formats"
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/adapter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -71,7 +70,7 @@ func init() {
|
||||
}
|
||||
|
||||
func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
|
||||
runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
|
||||
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
@ -87,7 +86,7 @@ func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
|
||||
opts.Format = genVolLsFormat(c)
|
||||
|
||||
// Get the filter functions based on any filters set
|
||||
var filterFuncs []libpod.VolumeFilter
|
||||
var filterFuncs []adapter.VolumeFilter
|
||||
if c.Filter != "" {
|
||||
filters := strings.Split(c.Filter, ",")
|
||||
for _, f := range filters {
|
||||
@ -95,7 +94,7 @@ func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
|
||||
if len(filterSplit) < 2 {
|
||||
return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
|
||||
}
|
||||
generatedFunc, err := generateVolumeFilterFuncs(filterSplit[0], filterSplit[1], runtime)
|
||||
generatedFunc, err := generateVolumeFilterFuncs(filterSplit[0], filterSplit[1])
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "invalid filter")
|
||||
}
|
||||
@ -103,13 +102,12 @@ func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
|
||||
}
|
||||
}
|
||||
|
||||
volumes, err := runtime.GetAllVolumes()
|
||||
volumes, err := runtime.Volumes(getContext())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the volumes that match the filter
|
||||
volsFiltered := make([]*libpod.Volume, 0, len(volumes))
|
||||
volsFiltered := make([]*adapter.Volume, 0, len(volumes))
|
||||
for _, vol := range volumes {
|
||||
include := true
|
||||
for _, filter := range filterFuncs {
|
||||
@ -120,7 +118,7 @@ func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
|
||||
volsFiltered = append(volsFiltered, vol)
|
||||
}
|
||||
}
|
||||
return generateVolLsOutput(volsFiltered, opts, runtime)
|
||||
return generateVolLsOutput(volsFiltered, opts)
|
||||
}
|
||||
|
||||
// generate the template based on conditions given
|
||||
@ -206,7 +204,7 @@ func getVolTemplateOutput(lsParams []volumeLsJSONParams, opts volumeLsOptions) (
|
||||
}
|
||||
|
||||
// getVolJSONParams returns the volumes in JSON format
|
||||
func getVolJSONParams(volumes []*libpod.Volume, opts volumeLsOptions, runtime *libpod.Runtime) ([]volumeLsJSONParams, error) {
|
||||
func getVolJSONParams(volumes []*adapter.Volume) []volumeLsJSONParams {
|
||||
var lsOutput []volumeLsJSONParams
|
||||
|
||||
for _, volume := range volumes {
|
||||
@ -221,25 +219,19 @@ func getVolJSONParams(volumes []*libpod.Volume, opts volumeLsOptions, runtime *l
|
||||
|
||||
lsOutput = append(lsOutput, params)
|
||||
}
|
||||
return lsOutput, nil
|
||||
return lsOutput
|
||||
}
|
||||
|
||||
// generateVolLsOutput generates the output based on the format, JSON or Go Template, and prints it out
|
||||
func generateVolLsOutput(volumes []*libpod.Volume, opts volumeLsOptions, runtime *libpod.Runtime) error {
|
||||
func generateVolLsOutput(volumes []*adapter.Volume, opts volumeLsOptions) error {
|
||||
if len(volumes) == 0 && opts.Format != formats.JSONString {
|
||||
return nil
|
||||
}
|
||||
lsOutput, err := getVolJSONParams(volumes, opts, runtime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lsOutput := getVolJSONParams(volumes)
|
||||
var out formats.Writer
|
||||
|
||||
switch opts.Format {
|
||||
case formats.JSONString:
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to create JSON for volume output")
|
||||
}
|
||||
out = formats.JSONStructArray{Output: volLsToGeneric([]volumeLsTemplateParams{}, lsOutput)}
|
||||
default:
|
||||
lsOutput, err := getVolTemplateOutput(lsOutput, opts)
|
||||
@ -252,18 +244,18 @@ func generateVolLsOutput(volumes []*libpod.Volume, opts volumeLsOptions, runtime
|
||||
}
|
||||
|
||||
// generateVolumeFilterFuncs returns the true if the volume matches the filter set, otherwise it returns false.
|
||||
func generateVolumeFilterFuncs(filter, filterValue string, runtime *libpod.Runtime) (func(volume *libpod.Volume) bool, error) {
|
||||
func generateVolumeFilterFuncs(filter, filterValue string) (func(volume *adapter.Volume) bool, error) {
|
||||
switch filter {
|
||||
case "name":
|
||||
return func(v *libpod.Volume) bool {
|
||||
return func(v *adapter.Volume) bool {
|
||||
return strings.Contains(v.Name(), filterValue)
|
||||
}, nil
|
||||
case "driver":
|
||||
return func(v *libpod.Volume) bool {
|
||||
return func(v *adapter.Volume) bool {
|
||||
return v.Driver() == filterValue
|
||||
}, nil
|
||||
case "scope":
|
||||
return func(v *libpod.Volume) bool {
|
||||
return func(v *adapter.Volume) bool {
|
||||
return v.Scope() == filterValue
|
||||
}, nil
|
||||
case "label":
|
||||
@ -274,7 +266,7 @@ func generateVolumeFilterFuncs(filter, filterValue string, runtime *libpod.Runti
|
||||
} else {
|
||||
filterValue = ""
|
||||
}
|
||||
return func(v *libpod.Volume) bool {
|
||||
return func(v *adapter.Volume) bool {
|
||||
for labelKey, labelValue := range v.Labels() {
|
||||
if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
|
||||
return true
|
||||
@ -290,7 +282,7 @@ func generateVolumeFilterFuncs(filter, filterValue string, runtime *libpod.Runti
|
||||
} else {
|
||||
filterValue = ""
|
||||
}
|
||||
return func(v *libpod.Volume) bool {
|
||||
return func(v *adapter.Volume) bool {
|
||||
for labelKey, labelValue := range v.Options() {
|
||||
if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
|
||||
return true
|
||||
|
@ -35,6 +35,14 @@ type Container struct {
|
||||
*libpod.Container
|
||||
}
|
||||
|
||||
// Volume ...
|
||||
type Volume struct {
|
||||
*libpod.Volume
|
||||
}
|
||||
|
||||
// VolumeFilter is for filtering volumes on the client
|
||||
type VolumeFilter func(*Volume) bool
|
||||
|
||||
// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it
|
||||
func GetRuntime(c *cliconfig.PodmanCommand) (*LocalRuntime, error) {
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
@ -200,3 +208,49 @@ func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestM
|
||||
}
|
||||
return newImage.PushImageToHeuristicDestination(ctx, destination, manifestMIMEType, authfile, signaturePolicyPath, writer, forceCompress, signingOptions, dockerRegistryOptions, nil)
|
||||
}
|
||||
|
||||
// InspectVolumes returns a slice of volumes based on an arg list or --all
|
||||
func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeInspectValues) ([]*Volume, error) {
|
||||
var (
|
||||
volumes []*libpod.Volume
|
||||
err error
|
||||
)
|
||||
|
||||
if c.All {
|
||||
volumes, err = r.GetAllVolumes()
|
||||
} else {
|
||||
for _, v := range c.InputArgs {
|
||||
vol, err := r.GetVolume(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
volumes = append(volumes, vol)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return libpodVolumeToVolume(volumes), nil
|
||||
}
|
||||
|
||||
// Volumes returns a slice of localruntime volumes
|
||||
func (r *LocalRuntime) Volumes(ctx context.Context) ([]*Volume, error) {
|
||||
vols, err := r.GetAllVolumes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return libpodVolumeToVolume(vols), nil
|
||||
}
|
||||
|
||||
// libpodVolumeToVolume converts a slice of libpod volumes to a slice
|
||||
// of localruntime volumes (same as libpod)
|
||||
func libpodVolumeToVolume(volumes []*libpod.Volume) []*Volume {
|
||||
var vols []*Volume
|
||||
for _, v := range volumes {
|
||||
newVol := Volume{
|
||||
v,
|
||||
}
|
||||
vols = append(vols, &newVol)
|
||||
}
|
||||
return vols
|
||||
}
|
||||
|
@ -92,6 +92,18 @@ type remoteContainer struct {
|
||||
state *libpod.ContainerState
|
||||
}
|
||||
|
||||
type VolumeFilter func(*Volume) bool
|
||||
|
||||
// Volume is embed for libpod volumes
|
||||
type Volume struct {
|
||||
remoteVolume
|
||||
}
|
||||
|
||||
type remoteVolume struct {
|
||||
Runtime *LocalRuntime
|
||||
config *libpod.VolumeConfig
|
||||
}
|
||||
|
||||
// GetImages returns a slice of containerimages over a varlink connection
|
||||
func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) {
|
||||
var newImages []*ContainerImage
|
||||
@ -480,3 +492,45 @@ func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestM
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// InspectVolumes returns a slice of volumes based on an arg list or --all
|
||||
func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeInspectValues) ([]*Volume, error) {
|
||||
reply, err := iopodman.GetVolumes().Call(r.Conn, c.InputArgs, c.All)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return varlinkVolumeToVolume(r, reply), nil
|
||||
}
|
||||
|
||||
//Volumes returns a slice of adapter.volumes based on information about libpod
|
||||
// volumes over a varlink connection
|
||||
func (r *LocalRuntime) Volumes(ctx context.Context) ([]*Volume, error) {
|
||||
reply, err := iopodman.GetVolumes().Call(r.Conn, []string{}, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return varlinkVolumeToVolume(r, reply), nil
|
||||
}
|
||||
|
||||
func varlinkVolumeToVolume(r *LocalRuntime, volumes []iopodman.Volume) []*Volume {
|
||||
var vols []*Volume
|
||||
for _, v := range volumes {
|
||||
volumeConfig := libpod.VolumeConfig{
|
||||
Name: v.Name,
|
||||
Labels: v.Labels,
|
||||
MountPoint: v.MountPoint,
|
||||
Driver: v.Driver,
|
||||
Options: v.Options,
|
||||
Scope: v.Scope,
|
||||
}
|
||||
n := remoteVolume{
|
||||
Runtime: r,
|
||||
config: &volumeConfig,
|
||||
}
|
||||
newVol := Volume{
|
||||
n,
|
||||
}
|
||||
vols = append(vols, &newVol)
|
||||
}
|
||||
return vols
|
||||
}
|
||||
|
33
libpod/adapter/volumes_remote.go
Normal file
33
libpod/adapter/volumes_remote.go
Normal file
@ -0,0 +1,33 @@
|
||||
// +build remoteclient
|
||||
|
||||
package adapter
|
||||
|
||||
// Name returns the name of the volume
|
||||
func (v *Volume) Name() string {
|
||||
return v.config.Name
|
||||
}
|
||||
|
||||
//Labels returns the labels for a volume
|
||||
func (v *Volume) Labels() map[string]string {
|
||||
return v.config.Labels
|
||||
}
|
||||
|
||||
// Driver returns the driver for the volume
|
||||
func (v *Volume) Driver() string {
|
||||
return v.config.Driver
|
||||
}
|
||||
|
||||
// Options returns the options a volume was created with
|
||||
func (v *Volume) Options() map[string]string {
|
||||
return v.config.Options
|
||||
}
|
||||
|
||||
// MountPath returns the path the volume is mounted to
|
||||
func (v *Volume) MountPoint() string {
|
||||
return v.config.MountPoint
|
||||
}
|
||||
|
||||
// Scope returns the scope for an adapter.volume
|
||||
func (v *Volume) Scope() string {
|
||||
return v.config.Scope
|
||||
}
|
@ -36,3 +36,39 @@ func (i *LibpodAPI) VolumeRemove(call iopodman.VarlinkCall, options iopodman.Vol
|
||||
}
|
||||
return call.ReplyVolumeRemove(deletedVolumes)
|
||||
}
|
||||
|
||||
// GetVolumes returns all the volumes known to the remote system
|
||||
func (i *LibpodAPI) GetVolumes(call iopodman.VarlinkCall, args []string, all bool) error {
|
||||
var (
|
||||
err error
|
||||
reply []*libpod.Volume
|
||||
volumes []iopodman.Volume
|
||||
)
|
||||
if all {
|
||||
reply, err = i.Runtime.GetAllVolumes()
|
||||
} else {
|
||||
for _, v := range args {
|
||||
vol, err := i.Runtime.GetVolume(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reply = append(reply, vol)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return call.ReplyErrorOccurred(err.Error())
|
||||
}
|
||||
// Build the iopodman.volume struct for the return
|
||||
for _, v := range reply {
|
||||
newVol := iopodman.Volume{
|
||||
Driver: v.Driver(),
|
||||
Labels: v.Labels(),
|
||||
MountPoint: v.MountPoint(),
|
||||
Name: v.Name(),
|
||||
Options: v.Options(),
|
||||
Scope: v.Scope(),
|
||||
}
|
||||
volumes = append(volumes, newVol)
|
||||
}
|
||||
return call.ReplyGetVolumes(volumes)
|
||||
}
|
||||
|
Reference in New Issue
Block a user