mirror of
https://github.com/containers/podman.git
synced 2025-10-17 19:24:04 +08:00
Merge pull request #8102 from ashley-cui/inspect
Add pod, volume, network to inspect package
This commit is contained in:
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
1
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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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{}
|
||||
|
||||
|
@ -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
|
||||
|
@ -105,10 +105,6 @@ type VolumeRmReport struct {
|
||||
Id string //nolint
|
||||
}
|
||||
|
||||
type VolumeInspectOptions struct {
|
||||
All bool
|
||||
}
|
||||
|
||||
type VolumeInspectReport struct {
|
||||
*VolumeConfigResponse
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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())
|
||||
})
|
||||
|
||||
})
|
||||
|
Reference in New Issue
Block a user