summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2020-10-27 17:04:44 -0400
committerGitHub <noreply@github.com>2020-10-27 17:04:44 -0400
commit7149a7cb396dd5951f9c632e79ba3c96a7797c5f (patch)
treeb3dcd6379cd01e4d9b4bd64d89fe75a092c7ec43
parent26c09291a3ea2b0e05d033a1ecf0441403d0d31a (diff)
parent61deec451f279cdc09b4415fe4988c2f8548e55a (diff)
downloadpodman-7149a7cb396dd5951f9c632e79ba3c96a7797c5f.tar.gz
podman-7149a7cb396dd5951f9c632e79ba3c96a7797c5f.tar.bz2
podman-7149a7cb396dd5951f9c632e79ba3c96a7797c5f.zip
Merge pull request #8102 from ashley-cui/inspect
Add pod, volume, network to inspect package
-rw-r--r--cmd/podman/inspect/inspect.go121
-rw-r--r--cmd/podman/networks/inspect.go44
-rw-r--r--cmd/podman/volumes/inspect.go40
-rw-r--r--docs/source/markdown/podman-inspect.1.md25
-rw-r--r--docs/source/markdown/podman.1.md2
-rw-r--r--go.mod1
-rw-r--r--pkg/api/handlers/libpod/networks.go14
-rw-r--r--pkg/domain/entities/engine_container.go4
-rw-r--r--pkg/domain/entities/network.go5
-rw-r--r--pkg/domain/entities/types.go2
-rw-r--r--pkg/domain/entities/volumes.go4
-rw-r--r--pkg/domain/infra/abi/network.go15
-rw-r--r--pkg/domain/infra/abi/volumes.go19
-rw-r--r--pkg/domain/infra/tunnel/network.go20
-rw-r--r--pkg/domain/infra/tunnel/volumes.go22
-rw-r--r--test/e2e/common_test.go8
-rw-r--r--test/e2e/inspect_test.go141
17 files changed, 360 insertions, 127 deletions
diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go
index a62a68959..9c400d506 100644
--- a/cmd/podman/inspect/inspect.go
+++ b/cmd/podman/inspect/inspect.go
@@ -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
}
diff --git a/cmd/podman/networks/inspect.go b/cmd/podman/networks/inspect.go
index 47503fd4b..25ee7e574 100644
--- a/cmd/podman/networks/inspect.go
+++ b/cmd/podman/networks/inspect.go
@@ -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
- }
-
- 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
- }
+ inspectOpts.Type = inspect.NetworkType
+ return inspect.Inspect(args, *inspectOpts)
- w := tabwriter.NewWriter(os.Stdout, 8, 2, 0, ' ', 0)
- defer w.Flush()
-
- return tmpl.Execute(w, responses)
- }
- return nil
}
diff --git a/cmd/podman/volumes/inspect.go b/cmd/podman/volumes/inspect.go
index 732a67333..c6edcf809 100644
--- a/cmd/podman/volumes/inspect.go
+++ b/cmd/podman/volumes/inspect.go
@@ -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)
}
diff --git a/docs/source/markdown/podman-inspect.1.md b/docs/source/markdown/podman-inspect.1.md
index a1dcd1a0e..eb7cf74c6 100644
--- a/docs/source/markdown/podman-inspect.1.md
+++ b/docs/source/markdown/podman-inspect.1.md
@@ -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)
diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md
index 87337fa3c..2d5110ad9 100644
--- a/docs/source/markdown/podman.1.md
+++ b/docs/source/markdown/podman.1.md
@@ -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. |
diff --git a/go.mod b/go.mod
index 9de0b20bc..a14d85979 100644
--- a/go.mod
+++ b/go.mod
@@ -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
diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go
index b7e2b3988..9f6103c45 100644
--- a/pkg/api/handlers/libpod/networks.go
+++ b/pkg/api/handlers/libpod/networks.go
@@ -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
}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index a20d3b404..8ab72dbd8 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -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)
diff --git a/pkg/domain/entities/network.go b/pkg/domain/entities/network.go
index 9beeeb042..0bab672a7 100644
--- a/pkg/domain/entities/network.go
+++ b/pkg/domain/entities/network.go
@@ -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{}
diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go
index 5fdd8afcb..d8ad2d891 100644
--- a/pkg/domain/entities/types.go
+++ b/pkg/domain/entities/types.go
@@ -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
diff --git a/pkg/domain/entities/volumes.go b/pkg/domain/entities/volumes.go
index fb8466d04..1bc1e4301 100644
--- a/pkg/domain/entities/volumes.go
+++ b/pkg/domain/entities/volumes.go
@@ -105,10 +105,6 @@ type VolumeRmReport struct {
Id string //nolint
}
-type VolumeInspectOptions struct {
- All bool
-}
-
type VolumeInspectReport struct {
*VolumeConfigResponse
}
diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go
index f40df828a..4f572fb88 100644
--- a/pkg/domain/infra/abi/network.go
+++ b/pkg/domain/infra/abi/network.go
@@ -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) {
diff --git a/pkg/domain/infra/abi/volumes.go b/pkg/domain/infra/abi/volumes.go
index 946f258af..a7262f61b 100644
--- a/pkg/domain/infra/abi/volumes.go
+++ b/pkg/domain/infra/abi/volumes.go
@@ -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) {
diff --git a/pkg/domain/infra/tunnel/network.go b/pkg/domain/infra/tunnel/network.go
index d155fdd9e..15527e02c 100644
--- a/pkg/domain/infra/tunnel/network.go
+++ b/pkg/domain/infra/tunnel/network.go
@@ -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) {
diff --git a/pkg/domain/infra/tunnel/volumes.go b/pkg/domain/infra/tunnel/volumes.go
index e432d3292..c0df2bb7b 100644
--- a/pkg/domain/infra/tunnel/volumes.go
+++ b/pkg/domain/infra/tunnel/volumes.go
@@ -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) {
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index bc8465a7c..3814d161d 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -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) {
diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go
index d4de7a65c..e8a82f9a1 100644
--- a/test/e2e/inspect_test.go
+++ b/test/e2e/inspect_test.go
@@ -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())
+ })
+
})