Files
podman/cmd/podman/inspect.go
baude eadaa5fb42 podman-remote inspect
base enablement of the inspect command.

Signed-off-by: baude <bbaude@redhat.com>
2019-01-18 15:43:11 -06:00

198 lines
5.8 KiB
Go

package main
import (
"context"
"encoding/json"
"strings"
"github.com/containers/libpod/cmd/podman/formats"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod/adapter"
cc "github.com/containers/libpod/pkg/spec"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
const (
inspectTypeContainer = "container"
inspectTypeImage = "image"
inspectAll = "all"
)
var (
inspectFlags = []cli.Flag{
cli.StringFlag{
Name: "type, t",
Value: inspectAll,
Usage: "Return JSON for specified type, (e.g image, container or task)",
},
cli.StringFlag{
Name: "format, f",
Usage: "Change the output format to a Go template",
},
cli.BoolFlag{
Name: "size",
Usage: "Display total file size if the type is container",
},
LatestFlag,
}
inspectDescription = "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."
inspectCommand = cli.Command{
Name: "inspect",
Usage: "Displays the configuration of a container or image",
Description: inspectDescription,
Flags: sortFlags(inspectFlags),
Action: inspectCmd,
ArgsUsage: "CONTAINER-OR-IMAGE [CONTAINER-OR-IMAGE]...",
OnUsageError: usageErrorHandler,
}
)
func inspectCmd(c *cli.Context) error {
args := c.Args()
inspectType := c.String("type")
latestContainer := c.Bool("latest")
if len(args) == 0 && !latestContainer {
return errors.Errorf("container or image name must be specified: podman inspect [options [...]] name")
}
if len(args) > 0 && latestContainer {
return errors.Errorf("you cannot provide additional arguments with --latest")
}
if err := validateFlags(c, inspectFlags); err != nil {
return err
}
runtime, err := adapter.GetRuntime(c)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
if !util.StringInSlice(inspectType, []string{inspectTypeContainer, inspectTypeImage, inspectAll}) {
return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll)
}
outputFormat := c.String("format")
if strings.Contains(outputFormat, "{{.Id}}") {
outputFormat = strings.Replace(outputFormat, "{{.Id}}", formats.IDString, -1)
}
if latestContainer {
lc, err := runtime.GetLatestContainer()
if err != nil {
return err
}
args = append(args, lc.ID())
inspectType = inspectTypeContainer
}
inspectedObjects, iterateErr := iterateInput(getContext(), c, args, runtime, inspectType)
if iterateErr != nil {
return iterateErr
}
var out formats.Writer
if outputFormat != "" && outputFormat != formats.JSONString {
//template
out = formats.StdoutTemplateArray{Output: inspectedObjects, Template: outputFormat}
} else {
// default is json output
out = formats.JSONStructArray{Output: inspectedObjects}
}
return formats.Writer(out).Out()
}
// func iterateInput iterates the images|containers the user has requested and returns the inspect data and error
func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *adapter.LocalRuntime, inspectType string) ([]interface{}, error) {
var (
data interface{}
inspectedItems []interface{}
inspectError error
)
for _, input := range args {
switch inspectType {
case inspectTypeContainer:
ctr, err := runtime.LookupContainer(input)
if err != nil {
inspectError = errors.Wrapf(err, "error looking up container %q", input)
break
}
libpodInspectData, err := ctr.Inspect(c.Bool("size"))
if err != nil {
inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID())
break
}
artifact, err := getArtifact(ctr)
if inspectError != nil {
inspectError = err
break
}
data, err = shared.GetCtrInspectInfo(ctr.Config(), libpodInspectData, artifact)
if err != nil {
inspectError = errors.Wrapf(err, "error parsing container data %q", ctr.ID())
break
}
case inspectTypeImage:
image, err := runtime.NewImageFromLocal(input)
if err != nil {
inspectError = errors.Wrapf(err, "error getting image %q", input)
break
}
data, err = image.Inspect(ctx)
if err != nil {
inspectError = errors.Wrapf(err, "error parsing image data %q", image.ID())
break
}
case inspectAll:
ctr, err := runtime.LookupContainer(input)
if err != nil {
image, err := runtime.NewImageFromLocal(input)
if err != nil {
inspectError = errors.Wrapf(err, "error getting image %q", input)
break
}
data, err = image.Inspect(ctx)
if err != nil {
inspectError = errors.Wrapf(err, "error parsing image data %q", image.ID())
break
}
} else {
libpodInspectData, err := ctr.Inspect(c.Bool("size"))
if err != nil {
inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID())
break
}
artifact, inspectError := getArtifact(ctr)
if inspectError != nil {
inspectError = err
break
}
data, err = shared.GetCtrInspectInfo(ctr.Config(), libpodInspectData, artifact)
if err != nil {
inspectError = errors.Wrapf(err, "error parsing container data %s", ctr.ID())
break
}
}
}
if inspectError == nil {
inspectedItems = append(inspectedItems, data)
}
}
return inspectedItems, inspectError
}
func getArtifact(ctr *adapter.Container) (*cc.CreateConfig, error) {
var createArtifact cc.CreateConfig
artifact, err := ctr.GetArtifact("create-config")
if err != nil {
return nil, err
}
if err := json.Unmarshal(artifact, &createArtifact); err != nil {
return nil, err
}
return &createArtifact, nil
}