automation-tests/cmd/podman/inspect.go

195 lines
6.1 KiB
Go

package main
import (
"context"
"strings"
"github.com/containers/buildah/pkg/formats"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
const (
inspectTypeContainer = "container"
inspectTypeImage = "image"
inspectAll = "all"
)
var (
inspectCommand cliconfig.InspectValues
inspectDescription = `This displays the low-level information on containers and images identified by name or ID.
If given a name that matches both a container and an image, this command inspects the container. By default, this will render all results in a JSON array.`
_inspectCommand = cobra.Command{
Use: "inspect [flags] CONTAINER | IMAGE",
Short: "Display the configuration of a container or image",
Long: inspectDescription,
RunE: func(cmd *cobra.Command, args []string) error {
inspectCommand.InputArgs = args
inspectCommand.GlobalFlags = MainGlobalOpts
inspectCommand.Remote = remoteclient
return inspectCmd(&inspectCommand)
},
Example: `podman inspect alpine
podman inspect --format "imageId: {{.Id}} size: {{.Size}}" alpine
podman inspect --format "image: {{.ImageName}} driver: {{.Driver}}" myctr`,
}
)
func inspectInit(command *cliconfig.InspectValues) {
command.SetHelpTemplate(HelpTemplate())
command.SetUsageTemplate(UsageTemplate())
flags := command.Flags()
flags.StringVarP(&command.Format, "format", "f", "", "Change the output format to a Go template")
// -t flag applicable only to 'podman inspect', not 'image/container inspect'
ambiguous := strings.Contains(command.Use, "|")
if ambiguous {
flags.StringVarP(&command.TypeObject, "type", "t", inspectAll, "Return JSON for specified type, (image or container)")
}
if strings.Contains(command.Use, "CONTAINER") {
containers_only := " (containers only)"
if !ambiguous {
containers_only = ""
command.TypeObject = inspectTypeContainer
}
flags.BoolVarP(&command.Latest, "latest", "l", false, "Act on the latest container podman is aware of"+containers_only)
flags.BoolVarP(&command.Size, "size", "s", false, "Display total file size"+containers_only)
markFlagHiddenForRemoteClient("latest", flags)
} else {
command.TypeObject = inspectTypeImage
}
}
func init() {
inspectCommand.Command = &_inspectCommand
inspectInit(&inspectCommand)
}
func inspectCmd(c *cliconfig.InspectValues) error {
args := c.InputArgs
inspectType := c.TypeObject
latestContainer := c.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")
}
runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.DeferredShutdown(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.Format
if strings.Contains(outputFormat, "{{.Id}}") {
outputFormat = strings.Replace(outputFormat, "{{.Id}}", formats.IDString, -1)
}
// These fields were renamed, so we need to provide backward compat for
// the old names.
if strings.Contains(outputFormat, ".Src") {
outputFormat = strings.Replace(outputFormat, ".Src", ".Source", -1)
}
if strings.Contains(outputFormat, ".Dst") {
outputFormat = strings.Replace(outputFormat, ".Dst", ".Destination", -1)
}
if strings.Contains(outputFormat, ".ImageID") {
outputFormat = strings.Replace(outputFormat, ".ImageID", ".Image", -1)
}
if latestContainer {
lc, err := runtime.GetLatestContainer()
if err != nil {
return err
}
args = append(args, lc.ID())
inspectType = inspectTypeContainer
}
inspectedObjects, iterateErr := iterateInput(getContext(), c.Size, 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 out.Out()
}
// func iterateInput iterates the images|containers the user has requested and returns the inspect data and error
func iterateInput(ctx context.Context, size bool, 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
}
data, err = ctr.Inspect(size)
if err != nil {
inspectError = errors.Wrapf(err, "error inspecting container %s", 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 {
data, err = ctr.Inspect(size)
if err != nil {
inspectError = errors.Wrapf(err, "error inspecting container %s", ctr.ID())
break
}
}
}
if inspectError == nil {
inspectedItems = append(inspectedItems, data)
}
}
return inspectedItems, inspectError
}