Merge pull request #8102 from ashley-cui/inspect

Add pod, volume, network to inspect package
This commit is contained in:
OpenShift Merge Robot
2020-10-27 17:04:44 -04:00
committed by GitHub
17 changed files with 360 additions and 127 deletions

View File

@ -12,6 +12,7 @@ import (
"github.com/containers/common/pkg/report"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/cmd/podman/validate"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@ -19,12 +20,18 @@ import (
)
const (
// ImageType is the image type.
ImageType = "image"
// ContainerType is the container type.
ContainerType = "container"
// AllType can be of type ImageType or ContainerType.
AllType = "all"
// ContainerType is the container type.
ContainerType = "container"
// ImageType is the image type.
ImageType = "image"
//NetworkType is the network type
NetworkType = "network"
//PodType is the pod type.
PodType = "pod"
//VolumeType is the volume type
VolumeType = "volume"
)
// Pull in configured json library
@ -58,15 +65,16 @@ type inspector struct {
containerEngine entities.ContainerEngine
imageEngine entities.ImageEngine
options entities.InspectOptions
podOptions entities.PodInspectOptions
}
// newInspector creates a new inspector based on the specified options.
func newInspector(options entities.InspectOptions) (*inspector, error) {
switch options.Type {
case ImageType, ContainerType, AllType:
case ImageType, ContainerType, AllType, PodType, NetworkType, VolumeType:
// Valid types.
default:
return nil, errors.Errorf("invalid type %q: must be %q, %q or %q", options.Type, ImageType, ContainerType, AllType)
return nil, errors.Errorf("invalid type %q: must be %q, %q, %q, %q, %q, or %q", options.Type, ImageType, ContainerType, PodType, NetworkType, VolumeType, AllType)
}
if options.Type == ImageType {
if options.Latest {
@ -76,10 +84,18 @@ func newInspector(options entities.InspectOptions) (*inspector, error) {
return nil, errors.Errorf("size is not supported for type %q", ImageType)
}
}
if options.Type == PodType && options.Size {
return nil, errors.Errorf("size is not supported for type %q", PodType)
}
podOpts := entities.PodInspectOptions{
Latest: options.Latest,
Format: options.Format,
}
return &inspector{
containerEngine: registry.ContainerEngine(),
imageEngine: registry.ImageEngine(),
options: options,
podOptions: podOpts,
}, nil
}
@ -91,17 +107,19 @@ func (i *inspector) inspect(namesOrIDs []string) error {
ctx := context.Background()
if len(namesOrIDs) == 0 {
if !i.options.Latest {
return errors.New("no containers or images specified")
if !i.options.Latest && !i.options.All {
return errors.New("no names or ids specified")
}
}
tmpType := i.options.Type
if i.options.Latest {
if len(namesOrIDs) > 0 {
return errors.New("--latest and containers cannot be used together")
return errors.New("--latest and arguments cannot be used together")
}
if i.options.Type == AllType {
tmpType = ContainerType // -l works with --type=all, defaults to containertype
}
tmpType = ContainerType // -l works with --type=all
}
// Inspect - note that AllType requires us to expensively query one-by-one.
@ -131,10 +149,57 @@ func (i *inspector) inspect(namesOrIDs []string) error {
for i := range ctrData {
data = append(data, ctrData[i])
}
case PodType:
for _, pod := range namesOrIDs {
i.podOptions.NameOrID = pod
podData, err := i.containerEngine.PodInspect(ctx, i.podOptions)
if err != nil {
cause := errors.Cause(err)
if !strings.Contains(cause.Error(), define.ErrNoSuchPod.Error()) {
errs = []error{err}
} else {
return err
}
} else {
errs = nil
data = append(data, podData)
}
}
if i.podOptions.Latest { //latest means there are no names in the namesOrID array
podData, err := i.containerEngine.PodInspect(ctx, i.podOptions)
if err != nil {
cause := errors.Cause(err)
if !strings.Contains(cause.Error(), define.ErrNoSuchPod.Error()) {
errs = []error{err}
} else {
return err
}
} else {
errs = nil
data = append(data, podData)
}
}
case NetworkType:
networkData, allErrs, err := registry.ContainerEngine().NetworkInspect(ctx, namesOrIDs, i.options)
if err != nil {
return err
}
errs = allErrs
for i := range networkData {
data = append(data, networkData[i])
}
case VolumeType:
volumeData, allErrs, err := i.containerEngine.VolumeInspect(ctx, namesOrIDs, i.options)
if err != nil {
return err
}
errs = allErrs
for i := range volumeData {
data = append(data, volumeData[i])
}
default:
return errors.Errorf("invalid type %q: must be %q, %q or %q", i.options.Type, ImageType, ContainerType, AllType)
return errors.Errorf("invalid type %q: must be %q, %q, %q, %q, %q, or %q", i.options.Type, ImageType, ContainerType, PodType, NetworkType, VolumeType, AllType)
}
// Always print an empty array
if data == nil {
data = []interface{}{}
@ -195,11 +260,41 @@ func (i *inspector) inspectAll(ctx context.Context, namesOrIDs []string) ([]inte
if err != nil {
return nil, nil, err
}
if len(errs) == 0 {
data = append(data, imgData[0])
continue
}
volumeData, errs, err := i.containerEngine.VolumeInspect(ctx, []string{name}, i.options)
if err != nil {
return nil, nil, err
}
if len(errs) == 0 {
data = append(data, volumeData[0])
continue
}
networkData, errs, err := registry.ContainerEngine().NetworkInspect(ctx, namesOrIDs, i.options)
if err != nil {
return nil, nil, err
}
if len(errs) == 0 {
data = append(data, networkData[0])
continue
}
i.podOptions.NameOrID = name
podData, err := i.containerEngine.PodInspect(ctx, i.podOptions)
if err != nil {
cause := errors.Cause(err)
if !strings.Contains(cause.Error(), define.ErrNoSuchPod.Error()) {
return nil, nil, err
}
} else {
data = append(data, podData)
continue
}
if len(errs) > 0 {
allErrs = append(allErrs, errors.Errorf("no such object: %q", name))
continue
}
data = append(data, imgData[0])
}
return data, allErrs, nil
}

View File

@ -1,13 +1,7 @@
package network
import (
"encoding/json"
"fmt"
"os"
"text/tabwriter"
"text/template"
"github.com/containers/common/pkg/report"
"github.com/containers/podman/v2/cmd/podman/inspect"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/spf13/cobra"
@ -23,10 +17,7 @@ var (
Example: `podman network inspect podman`,
Args: cobra.MinimumNArgs(1),
}
)
var (
networkInspectOptions entities.NetworkInspectOptions
inspectOpts *entities.InspectOptions
)
func init() {
@ -35,36 +26,13 @@ func init() {
Command: networkinspectCommand,
Parent: networkCmd,
})
inspectOpts = new(entities.InspectOptions)
flags := networkinspectCommand.Flags()
flags.StringVarP(&networkInspectOptions.Format, "format", "f", "", "Pretty-print network to JSON or using a Go template")
flags.StringVarP(&inspectOpts.Format, "format", "f", "", "Pretty-print network to JSON or using a Go template")
}
func networkInspect(_ *cobra.Command, args []string) error {
responses, err := registry.ContainerEngine().NetworkInspect(registry.Context(), args, entities.NetworkInspectOptions{})
if err != nil {
return err
}
inspectOpts.Type = inspect.NetworkType
return inspect.Inspect(args, *inspectOpts)
switch {
case report.IsJSON(networkInspectOptions.Format) || networkInspectOptions.Format == "":
b, err := json.MarshalIndent(responses, "", " ")
if err != nil {
return err
}
fmt.Println(string(b))
default:
row := report.NormalizeFormat(networkInspectOptions.Format)
// There can be more than 1 in the inspect output.
row = "{{range . }}" + row + "{{end}}"
tmpl, err := template.New("inspectNetworks").Parse(row)
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stdout, 8, 2, 0, ' ', 0)
defer w.Flush()
return tmpl.Execute(w, responses)
}
return nil
}

View File

@ -1,16 +1,11 @@
package volumes
import (
"fmt"
"os"
"text/template"
"github.com/containers/common/pkg/report"
"github.com/containers/podman/v2/cmd/podman/inspect"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)
var (
@ -21,7 +16,7 @@ var (
Use: "inspect [options] VOLUME [VOLUME...]",
Short: "Display detailed information on one or more volumes",
Long: volumeInspectDescription,
RunE: inspect,
RunE: volumeInspect,
Example: `podman volume inspect myvol
podman volume inspect --all
podman volume inspect --format "{{.Driver}} {{.Scope}}" myvol`,
@ -29,8 +24,7 @@ var (
)
var (
inspectOpts = entities.VolumeInspectOptions{}
inspectFormat string
inspectOpts *entities.InspectOptions
)
func init() {
@ -39,34 +33,16 @@ func init() {
Command: inspectCommand,
Parent: volumeCmd,
})
inspectOpts = new(entities.InspectOptions)
flags := inspectCommand.Flags()
flags.BoolVarP(&inspectOpts.All, "all", "a", false, "Inspect all volumes")
flags.StringVarP(&inspectFormat, "format", "f", "json", "Format volume output using Go template")
flags.StringVarP(&inspectOpts.Format, "format", "f", "json", "Format volume output using Go template")
}
func inspect(cmd *cobra.Command, args []string) error {
func volumeInspect(cmd *cobra.Command, args []string) error {
if (inspectOpts.All && len(args) > 0) || (!inspectOpts.All && len(args) < 1) {
return errors.New("provide one or more volume names or use --all")
}
responses, err := registry.ContainerEngine().VolumeInspect(context.Background(), args, inspectOpts)
if err != nil {
return err
}
switch {
case report.IsJSON(inspectFormat), inspectFormat == "":
jsonOut, err := json.MarshalIndent(responses, "", " ")
if err != nil {
return errors.Wrapf(err, "error marshalling inspect JSON")
}
fmt.Println(string(jsonOut))
default:
row := "{{range . }}" + report.NormalizeFormat(inspectFormat) + "{{end}}"
tmpl, err := template.New("volumeInspect").Parse(row)
if err != nil {
return err
}
return tmpl.Execute(os.Stdout, responses)
}
return nil
inspectOpts.Type = inspect.VolumeType
return inspect.Inspect(args, *inspectOpts)
}

View File

@ -1,7 +1,7 @@
% podman-inspect(1)
## NAME
podman\-inspect - Display a container or image's configuration
podman\-inspect - Display a container, image, volume, network, or pod's configuration
## SYNOPSIS
**podman inspect** [*options*] *name* [...]
@ -9,8 +9,9 @@ podman\-inspect - Display a container or image's configuration
## DESCRIPTION
This displays the low-level information on containers and images identified by name or ID. By default, this will render
all results in a JSON array. If the container and image have the same name, this will return container JSON for
unspecified type. If a format is specified, the given template will be executed for each result.
all results in a JSON array. If the inspect type is all, the order of inspection is: containers, images, volumes, network, pods.
So, if a container has the same name as an image, then the container JSON will be returned, and so on.
If a format is specified, the given template will be executed for each result.
For more inspection options, see:
@ -25,7 +26,7 @@ For more inspection options, see:
**--type**, **-t**=*type*
Return JSON for the specified type. Type can be 'container', 'image' or 'all' (default: all)
Return JSON for the specified type. Type can be 'container', 'image', 'volume', 'network', 'pod', or 'all' (default: all)
(Only meaningful when invoked as *podman inspect*)
**--format**, **-f**=*format*
@ -38,6 +39,8 @@ The keys of the returned JSON can be used as the values for the --format flag (s
Instead of providing the container name or ID, use the last created container. If you use methods other than Podman
to run containers such as CRI-O, the last started container could be from either of those methods.
This option can be used to inspect the latest pod created when used with --type pod
The latest option is not supported on the remote client or when invoked as *podman image inspect*.
**--size**, **-s**
@ -148,6 +151,20 @@ podman container inspect --latest --format {{.EffectiveCaps}}
[CAP_CHOWN CAP_DAC_OVERRIDE CAP_FSETID CAP_FOWNER CAP_MKNOD CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SETFCAP CAP_SETPCAP CAP_NET_BIND_SERVICE CAP_SYS_CHROOT CAP_KILL CAP_AUDIT_WRITE]
```
```
# podman inspect myPod --type pod --format "{{.Name}}"
myPod
```
```
# podman inspect myVolume --type volume --format "{{.Name}}"
myVolume
```
```
# podman inspect nyNetwork --type network --format "{{.name}}"
myNetwork
```
## SEE ALSO
podman(1)

View File

@ -220,7 +220,7 @@ the exit codes follow the `chroot` standard, see below:
| [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. |
| [podman-info(1)](podman-info.1.md) | Displays Podman related system information. |
| [podman-init(1)](podman-init.1.md) | Initialize one or more containers |
| [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. |
| [podman-inspect(1)](podman-inspect.1.md) | Display a container, image, volume, network, or pod's configuration. |
| [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. |
| [podman-load(1)](podman-load.1.md) | Load an image from a container image archive into container storage. |
| [podman-login(1)](podman-login.1.md) | Login to a container registry. |

1
go.mod
View File

@ -63,7 +63,6 @@ require (
github.com/vishvananda/netlink v1.1.0
go.etcd.io/bbolt v1.3.5
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f

View File

@ -113,15 +113,15 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
return
}
name := utils.GetName(r)
options := entities.NetworkInspectOptions{}
options := entities.InspectOptions{}
ic := abi.ContainerEngine{Libpod: runtime}
reports, err := ic.NetworkInspect(r.Context(), []string{name}, options)
reports, errs, err := ic.NetworkInspect(r.Context(), []string{name}, options)
// If the network cannot be found, we return a 404.
if len(errs) > 0 {
utils.Error(w, "Something went wrong", http.StatusNotFound, define.ErrNoSuchNetwork)
return
}
if err != nil {
// If the network cannot be found, we return a 404.
if errors.Cause(err) == define.ErrNoSuchNetwork {
utils.Error(w, "Something went wrong", http.StatusNotFound, err)
return
}
utils.InternalServerError(w, err)
return
}

View File

@ -51,7 +51,7 @@ type ContainerEngine interface {
HealthCheckRun(ctx context.Context, nameOrID string, options HealthCheckOptions) (*define.HealthCheckResults, error)
Info(ctx context.Context) (*define.Info, error)
NetworkCreate(ctx context.Context, name string, options NetworkCreateOptions) (*NetworkCreateReport, error)
NetworkInspect(ctx context.Context, namesOrIds []string, options NetworkInspectOptions) ([]NetworkInspectReport, error)
NetworkInspect(ctx context.Context, namesOrIds []string, options InspectOptions) ([]NetworkInspectReport, []error, error)
NetworkList(ctx context.Context, options NetworkListOptions) ([]*NetworkListReport, error)
NetworkRm(ctx context.Context, namesOrIds []string, options NetworkRmOptions) ([]*NetworkRmReport, error)
PlayKube(ctx context.Context, path string, opts PlayKubeOptions) (*PlayKubeReport, error)
@ -76,7 +76,7 @@ type ContainerEngine interface {
VarlinkService(ctx context.Context, opts ServiceOptions) error
Version(ctx context.Context) (*SystemVersionReport, error)
VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IDOrNameResponse, error)
VolumeInspect(ctx context.Context, namesOrIds []string, opts VolumeInspectOptions) ([]*VolumeInspectReport, error)
VolumeInspect(ctx context.Context, namesOrIds []string, opts InspectOptions) ([]*VolumeInspectReport, []error, error)
VolumeList(ctx context.Context, opts VolumeListOptions) ([]*VolumeListReport, error)
VolumePrune(ctx context.Context) ([]*VolumePruneReport, error)
VolumeRm(ctx context.Context, namesOrIds []string, opts VolumeRmOptions) ([]*VolumeRmReport, error)

View File

@ -18,11 +18,6 @@ type NetworkListReport struct {
*libcni.NetworkConfigList
}
// NetworkInspectOptions describes options for inspect networks
type NetworkInspectOptions struct {
Format string
}
// NetworkInspectReport describes the results from inspect networks
type NetworkInspectReport map[string]interface{}

View File

@ -56,6 +56,8 @@ type InspectOptions struct {
Size bool `json:",omitempty"`
// Type -- return JSON for specified type.
Type string `json:",omitempty"`
// All -- inspect all
All bool `json:",omitempty"`
}
// All API and CLI diff commands and diff sub-commands use the same options

View File

@ -105,10 +105,6 @@ type VolumeRmReport struct {
Id string //nolint
}
type VolumeInspectOptions struct {
All bool
}
type VolumeInspectReport struct {
*VolumeConfigResponse
}

View File

@ -43,21 +43,26 @@ func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.Net
return reports, nil
}
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, options entities.NetworkInspectOptions) ([]entities.NetworkInspectReport, error) {
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]entities.NetworkInspectReport, []error, error) {
config, err := ic.Libpod.GetConfig()
if err != nil {
return nil, err
return nil, nil, err
}
var errs []error
rawCNINetworks := make([]entities.NetworkInspectReport, 0, len(namesOrIds))
for _, name := range namesOrIds {
rawList, err := network.InspectNetwork(config, name)
if err != nil {
return nil, err
if errors.Cause(err) == define.ErrNoSuchNetwork {
errs = append(errs, errors.Errorf("no such network %s", name))
continue
} else {
return nil, nil, errors.Wrapf(err, "error inspecting network %s", name)
}
}
rawCNINetworks = append(rawCNINetworks, rawList)
}
return rawCNINetworks, nil
return rawCNINetworks, errs, nil
}
func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, options entities.NetworkRmOptions) ([]*entities.NetworkRmReport, error) {

View File

@ -4,6 +4,7 @@ import (
"context"
"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/domain/filters"
"github.com/containers/podman/v2/pkg/domain/infra/abi/parse"
@ -71,9 +72,10 @@ func (ic *ContainerEngine) VolumeRm(ctx context.Context, namesOrIds []string, op
return reports, nil
}
func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []string, opts entities.VolumeInspectOptions) ([]*entities.VolumeInspectReport, error) {
func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []string, opts entities.InspectOptions) ([]*entities.VolumeInspectReport, []error, error) {
var (
err error
errs []error
vols []*libpod.Volume
)
@ -82,13 +84,18 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
if opts.All {
vols, err = ic.Libpod.GetAllVolumes()
if err != nil {
return nil, err
return nil, nil, err
}
} else {
for _, v := range namesOrIds {
vol, err := ic.Libpod.LookupVolume(v)
if err != nil {
return nil, errors.Wrapf(err, "error inspecting volume %s", v)
if errors.Cause(err) == define.ErrNoSuchVolume {
errs = append(errs, errors.Errorf("no such volume %s", v))
continue
} else {
return nil, nil, errors.Wrapf(err, "error inspecting volume %s", v)
}
}
vols = append(vols, vol)
}
@ -98,11 +105,11 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
var uid, gid int
uid, err = v.UID()
if err != nil {
return nil, err
return nil, nil, err
}
gid, err = v.GID()
if err != nil {
return nil, err
return nil, nil, err
}
config := entities.VolumeConfigResponse{
Name: v.Name(),
@ -117,7 +124,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
}
reports = append(reports, &entities.VolumeInspectReport{VolumeConfigResponse: &config})
}
return reports, nil
return reports, errs, nil
}
func (ic *ContainerEngine) VolumePrune(ctx context.Context) ([]*entities.VolumePruneReport, error) {

View File

@ -5,22 +5,34 @@ import (
"github.com/containers/podman/v2/pkg/bindings/network"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/pkg/errors"
)
func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.NetworkListOptions) ([]*entities.NetworkListReport, error) {
return network.List(ic.ClientCxt, options)
}
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, options entities.NetworkInspectOptions) ([]entities.NetworkInspectReport, error) {
reports := make([]entities.NetworkInspectReport, 0, len(namesOrIds))
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]entities.NetworkInspectReport, []error, error) {
var (
reports = make([]entities.NetworkInspectReport, 0, len(namesOrIds))
errs = []error{}
)
for _, name := range namesOrIds {
report, err := network.Inspect(ic.ClientCxt, name)
if err != nil {
return nil, err
errModel, ok := err.(entities.ErrorModel)
if !ok {
return nil, nil, err
}
if errModel.ResponseCode == 404 {
errs = append(errs, errors.Errorf("no such network %q", name))
continue
}
return nil, nil, err
}
reports = append(reports, report...)
}
return reports, nil
return reports, errs, nil
}
func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, options entities.NetworkRmOptions) ([]*entities.NetworkRmReport, error) {

View File

@ -5,6 +5,7 @@ import (
"github.com/containers/podman/v2/pkg/bindings/volumes"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/pkg/errors"
)
func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.VolumeCreateOptions) (*entities.IDOrNameResponse, error) {
@ -35,25 +36,36 @@ func (ic *ContainerEngine) VolumeRm(ctx context.Context, namesOrIds []string, op
return reports, nil
}
func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []string, opts entities.VolumeInspectOptions) ([]*entities.VolumeInspectReport, error) {
func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []string, opts entities.InspectOptions) ([]*entities.VolumeInspectReport, []error, error) {
var (
reports = make([]*entities.VolumeInspectReport, 0, len(namesOrIds))
errs = []error{}
)
if opts.All {
vols, err := volumes.List(ic.ClientCxt, nil)
if err != nil {
return nil, err
return nil, nil, err
}
for _, v := range vols {
namesOrIds = append(namesOrIds, v.Name)
}
}
reports := make([]*entities.VolumeInspectReport, 0, len(namesOrIds))
for _, id := range namesOrIds {
data, err := volumes.Inspect(ic.ClientCxt, id)
if err != nil {
return nil, err
errModel, ok := err.(entities.ErrorModel)
if !ok {
return nil, nil, err
}
if errModel.ResponseCode == 404 {
errs = append(errs, errors.Errorf("no such volume %q", id))
continue
}
return nil, nil, err
}
reports = append(reports, &entities.VolumeInspectReport{VolumeConfigResponse: data})
}
return reports, nil
return reports, errs, nil
}
func (ic *ContainerEngine) VolumePrune(ctx context.Context) ([]*entities.VolumePruneReport, error) {

View File

@ -515,6 +515,14 @@ func (s *PodmanSessionIntegration) InspectPodToJSON() define.InspectPodData {
return i
}
// InspectPodToJSON takes the sessions output from an inspect and returns json
func (s *PodmanSessionIntegration) InspectPodArrToJSON() []define.InspectPodData {
var i []define.InspectPodData
err := jsoniter.Unmarshal(s.Out.Contents(), &i)
Expect(err).To(BeNil())
return i
}
// CreatePod creates a pod with no infra container
// it optionally takes a pod name
func (p *PodmanTestIntegration) CreatePod(name string) (*PodmanSessionIntegration, int, string) {

View File

@ -289,4 +289,145 @@ var _ = Describe("Podman inspect", func() {
Expect(baseJSON[0].HostConfig.SecurityOpt).To(Equal([]string{"label=type:spc_t,label=level:s0", "seccomp=unconfined"}))
})
It("podman inspect pod", func() {
podName := "testpod"
create := podmanTest.PodmanNoCache([]string{"pod", "create", "--name", podName})
create.WaitWithDefaultTimeout()
Expect(create.ExitCode()).To(Equal(0))
inspect := podmanTest.Podman([]string{"inspect", podName})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.IsJSONOutputValid()).To(BeTrue())
podData := inspect.InspectPodArrToJSON()
Expect(podData[0].Name).To(Equal(podName))
})
It("podman inspect pod with type", func() {
podName := "testpod"
create := podmanTest.PodmanNoCache([]string{"pod", "create", "--name", podName})
create.WaitWithDefaultTimeout()
Expect(create.ExitCode()).To(Equal(0))
inspect := podmanTest.Podman([]string{"inspect", "--type", "pod", podName})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.IsJSONOutputValid()).To(BeTrue())
podData := inspect.InspectPodArrToJSON()
Expect(podData[0].Name).To(Equal(podName))
})
It("podman inspect latest pod", func() {
SkipIfRemote("--latest flag n/a")
podName := "testpod"
create := podmanTest.PodmanNoCache([]string{"pod", "create", "--name", podName})
create.WaitWithDefaultTimeout()
Expect(create.ExitCode()).To(Equal(0))
inspect := podmanTest.Podman([]string{"inspect", "--type", "pod", "--latest"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.IsJSONOutputValid()).To(BeTrue())
podData := inspect.InspectPodArrToJSON()
Expect(podData[0].Name).To(Equal(podName))
})
It("podman inspect latest defaults to latest container", func() {
SkipIfRemote("--latest flag n/a")
podName := "testpod"
pod := podmanTest.PodmanNoCache([]string{"pod", "create", "--name", podName})
pod.WaitWithDefaultTimeout()
Expect(pod.ExitCode()).To(Equal(0))
inspect1 := podmanTest.Podman([]string{"inspect", "--type", "pod", podName})
inspect1.WaitWithDefaultTimeout()
Expect(inspect1.ExitCode()).To(Equal(0))
Expect(inspect1.IsJSONOutputValid()).To(BeTrue())
podData := inspect1.InspectPodArrToJSON()
infra := podData[0].Containers[0].Name
inspect := podmanTest.Podman([]string{"inspect", "--latest"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.IsJSONOutputValid()).To(BeTrue())
containerData := inspect.InspectContainerToJSON()
Expect(containerData[0].Name).To(Equal(infra))
})
It("podman inspect network", func() {
name, path := generateNetworkConfig(podmanTest)
defer removeConf(path)
session := podmanTest.Podman([]string{"inspect", name, "--format", "{{.cniVersion}}"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.LineInOutputContains("0.3.0")).To(BeTrue())
})
It("podman inspect a volume", func() {
session := podmanTest.Podman([]string{"volume", "create", "myvol"})
session.WaitWithDefaultTimeout()
volName := session.OutputToString()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"inspect", volName})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.IsJSONOutputValid()).To(BeTrue())
})
It("podman inspect a volume with --format", func() {
session := podmanTest.Podman([]string{"volume", "create", "myvol"})
session.WaitWithDefaultTimeout()
volName := session.OutputToString()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"inspect", "--format", "{{.Name}}", volName})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal(volName))
})
It("podman inspect --type container on a pod should fail", func() {
podName := "testpod"
create := podmanTest.PodmanNoCache([]string{"pod", "create", "--name", podName})
create.WaitWithDefaultTimeout()
Expect(create.ExitCode()).To(Equal(0))
inspect := podmanTest.Podman([]string{"inspect", "--type", "container", podName})
inspect.WaitWithDefaultTimeout()
Expect(inspect).To(ExitWithError())
})
It("podman inspect --type network on a container should fail", func() {
ctrName := "testctr"
create := podmanTest.PodmanNoCache([]string{"create", "--name", ctrName, ALPINE})
create.WaitWithDefaultTimeout()
Expect(create.ExitCode()).To(Equal(0))
inspect := podmanTest.Podman([]string{"inspect", "--type", "network", ctrName})
inspect.WaitWithDefaultTimeout()
Expect(inspect).To(ExitWithError())
})
It("podman inspect --type pod on a container should fail", func() {
ctrName := "testctr"
create := podmanTest.PodmanNoCache([]string{"create", "--name", ctrName, ALPINE})
create.WaitWithDefaultTimeout()
Expect(create.ExitCode()).To(Equal(0))
inspect := podmanTest.Podman([]string{"inspect", "--type", "pod", ctrName})
inspect.WaitWithDefaultTimeout()
Expect(inspect).To(ExitWithError())
})
It("podman inspect --type volume on a container should fail", func() {
ctrName := "testctr"
create := podmanTest.PodmanNoCache([]string{"create", "--name", ctrName, ALPINE})
create.WaitWithDefaultTimeout()
Expect(create.ExitCode()).To(Equal(0))
inspect := podmanTest.Podman([]string{"inspect", "--type", "volume", ctrName})
inspect.WaitWithDefaultTimeout()
Expect(inspect).To(ExitWithError())
})
})