github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/cmd/podman/inspect.go (about) 1 package main 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/containers/buildah/pkg/formats" 8 "github.com/containers/libpod/cmd/podman/cliconfig" 9 "github.com/containers/libpod/pkg/adapter" 10 "github.com/containers/libpod/pkg/util" 11 "github.com/pkg/errors" 12 "github.com/spf13/cobra" 13 ) 14 15 const ( 16 inspectTypeContainer = "container" 17 inspectTypeImage = "image" 18 inspectAll = "all" 19 ) 20 21 var ( 22 inspectCommand cliconfig.InspectValues 23 24 inspectDescription = `This displays the low-level information on containers and images identified by name or ID. 25 26 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.` 27 _inspectCommand = cobra.Command{ 28 Use: "inspect [flags] CONTAINER | IMAGE", 29 Short: "Display the configuration of a container or image", 30 Long: inspectDescription, 31 RunE: func(cmd *cobra.Command, args []string) error { 32 inspectCommand.InputArgs = args 33 inspectCommand.GlobalFlags = MainGlobalOpts 34 inspectCommand.Remote = remoteclient 35 return inspectCmd(&inspectCommand) 36 }, 37 Example: `podman inspect alpine 38 podman inspect --format "imageId: {{.Id}} size: {{.Size}}" alpine 39 podman inspect --format "image: {{.ImageName}} driver: {{.Driver}}" myctr`, 40 } 41 ) 42 43 func inspectInit(command *cliconfig.InspectValues) { 44 command.SetHelpTemplate(HelpTemplate()) 45 command.SetUsageTemplate(UsageTemplate()) 46 flags := command.Flags() 47 flags.StringVarP(&command.Format, "format", "f", "", "Change the output format to a Go template") 48 49 // -t flag applicable only to 'podman inspect', not 'image/container inspect' 50 ambiguous := strings.Contains(command.Use, "|") 51 if ambiguous { 52 flags.StringVarP(&command.TypeObject, "type", "t", inspectAll, "Return JSON for specified type, (image or container)") 53 } 54 55 if strings.Contains(command.Use, "CONTAINER") { 56 containers_only := " (containers only)" 57 if !ambiguous { 58 containers_only = "" 59 command.TypeObject = inspectTypeContainer 60 } 61 flags.BoolVarP(&command.Latest, "latest", "l", false, "Act on the latest container podman is aware of"+containers_only) 62 flags.BoolVarP(&command.Size, "size", "s", false, "Display total file size"+containers_only) 63 markFlagHiddenForRemoteClient("latest", flags) 64 } else { 65 command.TypeObject = inspectTypeImage 66 } 67 } 68 func init() { 69 inspectCommand.Command = &_inspectCommand 70 inspectInit(&inspectCommand) 71 } 72 73 func inspectCmd(c *cliconfig.InspectValues) error { 74 args := c.InputArgs 75 inspectType := c.TypeObject 76 latestContainer := c.Latest 77 if len(args) == 0 && !latestContainer { 78 return errors.Errorf("container or image name must be specified: podman inspect [options [...]] name") 79 } 80 81 if len(args) > 0 && latestContainer { 82 return errors.Errorf("you cannot provide additional arguments with --latest") 83 } 84 85 runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) 86 if err != nil { 87 return errors.Wrapf(err, "error creating libpod runtime") 88 } 89 defer runtime.DeferredShutdown(false) 90 91 if !util.StringInSlice(inspectType, []string{inspectTypeContainer, inspectTypeImage, inspectAll}) { 92 return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll) 93 } 94 95 outputFormat := c.Format 96 if strings.Contains(outputFormat, "{{.Id}}") { 97 outputFormat = strings.Replace(outputFormat, "{{.Id}}", formats.IDString, -1) 98 } 99 // These fields were renamed, so we need to provide backward compat for 100 // the old names. 101 if strings.Contains(outputFormat, ".Src") { 102 outputFormat = strings.Replace(outputFormat, ".Src", ".Source", -1) 103 } 104 if strings.Contains(outputFormat, ".Dst") { 105 outputFormat = strings.Replace(outputFormat, ".Dst", ".Destination", -1) 106 } 107 if strings.Contains(outputFormat, ".ImageID") { 108 outputFormat = strings.Replace(outputFormat, ".ImageID", ".Image", -1) 109 } 110 if latestContainer { 111 lc, err := runtime.GetLatestContainer() 112 if err != nil { 113 return err 114 } 115 args = append(args, lc.ID()) 116 inspectType = inspectTypeContainer 117 } 118 119 inspectedObjects, iterateErr := iterateInput(getContext(), c.Size, args, runtime, inspectType) 120 if iterateErr != nil { 121 return iterateErr 122 } 123 124 var out formats.Writer 125 if outputFormat != "" && outputFormat != formats.JSONString { 126 //template 127 out = formats.StdoutTemplateArray{Output: inspectedObjects, Template: outputFormat} 128 } else { 129 // default is json output 130 out = formats.JSONStructArray{Output: inspectedObjects} 131 } 132 133 return out.Out() 134 } 135 136 // func iterateInput iterates the images|containers the user has requested and returns the inspect data and error 137 func iterateInput(ctx context.Context, size bool, args []string, runtime *adapter.LocalRuntime, inspectType string) ([]interface{}, error) { 138 var ( 139 data interface{} 140 inspectedItems []interface{} 141 inspectError error 142 ) 143 144 for _, input := range args { 145 switch inspectType { 146 case inspectTypeContainer: 147 ctr, err := runtime.LookupContainer(input) 148 if err != nil { 149 inspectError = errors.Wrapf(err, "error looking up container %q", input) 150 break 151 } 152 data, err = ctr.Inspect(size) 153 if err != nil { 154 inspectError = errors.Wrapf(err, "error inspecting container %s", ctr.ID()) 155 break 156 } 157 case inspectTypeImage: 158 image, err := runtime.NewImageFromLocal(input) 159 if err != nil { 160 inspectError = errors.Wrapf(err, "error getting image %q", input) 161 break 162 } 163 data, err = image.Inspect(ctx) 164 if err != nil { 165 inspectError = errors.Wrapf(err, "error parsing image data %q", image.ID()) 166 break 167 } 168 case inspectAll: 169 ctr, err := runtime.LookupContainer(input) 170 if err != nil { 171 image, err := runtime.NewImageFromLocal(input) 172 if err != nil { 173 inspectError = errors.Wrapf(err, "error getting image %q", input) 174 break 175 } 176 data, err = image.Inspect(ctx) 177 if err != nil { 178 inspectError = errors.Wrapf(err, "error parsing image data %q", image.ID()) 179 break 180 } 181 } else { 182 data, err = ctr.Inspect(size) 183 if err != nil { 184 inspectError = errors.Wrapf(err, "error inspecting container %s", ctr.ID()) 185 break 186 } 187 } 188 } 189 if inspectError == nil { 190 inspectedItems = append(inspectedItems, data) 191 } 192 } 193 return inspectedItems, inspectError 194 }