mirror of
https://github.com/containers/podman.git
synced 2025-10-09 23:15:39 +08:00
Add artifact fallback to podman inspect command
This commit implements automatic artifact fallback for the podman inspect command as requested in GitHub issue #27075. Changes made: - Add ArtifactType constant to cmd/podman/common/inspect.go - Update AutocompleteInspectType to include artifact type in completions - Add artifact case to main inspect switch statement for explicit --type artifact - Implement artifact fallback in inspectAll function for automatic detection - Update shell completion to recognize artifacts in getEntityType function - Update command help text, usage, and examples to include artifacts - Update podman-inspect.1.md man page with artifact documentation - Add comprehensive e2e tests for artifact inspect functionality The inspect command now automatically falls back to artifact inspection when no container, image, volume, network, or pod matches the specified name. Users can also explicitly use --type artifact for direct artifact inspection. This maintains backward compatibility while extending functionality to support the artifact object type seamlessly. Examples: podman inspect myartifact # Auto-detects artifact podman inspect --type artifact myartifact # Explicit artifact type podman inspect --format '{{.Name}}' myartifact # Format support Fixes: https://github.com/containers/podman/issues/27075 Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
@ -1476,6 +1476,10 @@ func getEntityType(cmd *cobra.Command, args []string, o any) any {
|
||||
if networks, _ := getNetworks(cmd, args[0], completeDefault); len(networks) > 0 {
|
||||
return &entities.NetworkInspectReport{}
|
||||
}
|
||||
// artifact logic
|
||||
if artifacts, _ := getArtifacts(cmd, args[0]); len(artifacts) > 0 {
|
||||
return &entities.ArtifactInspectReport{}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
@ -1641,7 +1645,7 @@ func AutocompleteImageSort(_ *cobra.Command, _ []string, _ string) ([]string, co
|
||||
|
||||
// AutocompleteInspectType - Autocomplete inspect type options.
|
||||
func AutocompleteInspectType(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
|
||||
types := []string{AllType, ContainerType, ImageType, NetworkType, PodType, VolumeType}
|
||||
types := []string{AllType, ArtifactType, ContainerType, ImageType, NetworkType, PodType, VolumeType}
|
||||
return types, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@ package common
|
||||
const (
|
||||
// AllType can be of type ImageType or ContainerType.
|
||||
AllType = "all"
|
||||
// ArtifactType is the artifact type.
|
||||
ArtifactType = "artifact"
|
||||
// ContainerType is the container type.
|
||||
ContainerType = "container"
|
||||
// ImageType is the image type.
|
||||
|
@ -12,6 +12,7 @@ var (
|
||||
inspectDescription = `Displays the low-level information on an object identified by name or ID.
|
||||
For more inspection options, see:
|
||||
|
||||
podman artifact inspect
|
||||
podman container inspect
|
||||
podman image inspect
|
||||
podman network inspect
|
||||
@ -20,7 +21,7 @@ var (
|
||||
|
||||
// Command: podman _inspect_ Object_ID
|
||||
inspectCmd = &cobra.Command{
|
||||
Use: "inspect [options] {CONTAINER|IMAGE|POD|NETWORK|VOLUME} [...]",
|
||||
Use: "inspect [options] {ARTIFACT|CONTAINER|IMAGE|POD|NETWORK|VOLUME} [...]",
|
||||
Short: "Display the configuration of object denoted by ID",
|
||||
RunE: inspectExec,
|
||||
Long: inspectDescription,
|
||||
@ -28,6 +29,7 @@ var (
|
||||
ValidArgsFunction: common.AutocompleteInspect,
|
||||
Example: `podman inspect fedora
|
||||
podman inspect --type image fedora
|
||||
podman inspect --type artifact quay.io/myimage/myartifact:latest
|
||||
podman inspect CtrID ImgID
|
||||
podman inspect --format "imageId: {{.Id}} size: {{.Size}}" fedora`,
|
||||
}
|
||||
|
@ -151,9 +151,18 @@ func (i *inspector) inspect(namesOrIDs []string) error {
|
||||
for i := range volumeData {
|
||||
data = append(data, volumeData[i])
|
||||
}
|
||||
case common.ArtifactType:
|
||||
for _, name := range namesOrIDs {
|
||||
artifactData, err := i.imageEngine.ArtifactInspect(ctx, name, entities.ArtifactInspectOptions{})
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
data = append(data, artifactData)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("invalid type %q: must be %q, %q, %q, %q, %q, or %q", i.options.Type,
|
||||
common.ImageType, common.ContainerType, common.PodType, common.NetworkType, common.VolumeType, common.AllType)
|
||||
return fmt.Errorf("invalid type %q: must be %q, %q, %q, %q, %q, %q, or %q", i.options.Type,
|
||||
common.ImageType, common.ContainerType, common.PodType, common.NetworkType, common.VolumeType, common.ArtifactType, common.AllType)
|
||||
}
|
||||
// Always print an empty array
|
||||
if data == nil {
|
||||
@ -236,6 +245,11 @@ func (i *inspector) inspectAll(ctx context.Context, namesOrIDs []string) ([]any,
|
||||
data = append(data, podData[0])
|
||||
continue
|
||||
}
|
||||
artifactData, err := i.imageEngine.ArtifactInspect(ctx, name, entities.ArtifactInspectOptions{})
|
||||
if err == nil {
|
||||
data = append(data, artifactData)
|
||||
continue
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
allErrs = append(allErrs, fmt.Errorf("no such object: %q", name))
|
||||
continue
|
||||
|
@ -1,19 +1,20 @@
|
||||
% podman-inspect 1
|
||||
|
||||
## NAME
|
||||
podman\-inspect - Display a container, image, volume, network, or pod's configuration
|
||||
podman\-inspect - Display artifact, container, image, volume, network, or pod's configuration
|
||||
|
||||
## SYNOPSIS
|
||||
**podman inspect** [*options*] *name* [...]
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
This displays the low-level information on containers and images identified by name or ID. By default, this renders
|
||||
all results in a JSON array. If the inspect type is all, the order of inspection is: containers, images, volumes, network, pods.
|
||||
This displays the low-level information on artifacts, containers, and images identified by name or ID. By default, this renders
|
||||
all results in a JSON array. If the inspect type is all, the order of inspection is: containers, images, volumes, network, pods, artifacts.
|
||||
If a container has the same name as an image, then the container JSON is returned, and so on.
|
||||
If a format is specified, the given template is executed for each result.
|
||||
|
||||
For more inspection options, see also
|
||||
[podman-artifact-inspect(1)](podman-artifact-inspect.1.md),
|
||||
[podman-container-inspect(1)](podman-container-inspect.1.md),
|
||||
[podman-image-inspect(1)](podman-image-inspect.1.md),
|
||||
[podman-network-inspect(1)](podman-network-inspect.1.md),
|
||||
@ -35,7 +36,7 @@ In addition to normal output, display the total file size if the type is a conta
|
||||
|
||||
#### **--type**, **-t**=*type*
|
||||
|
||||
Return JSON for the specified type. Type can be 'container', 'image', 'volume', 'network', 'pod', or 'all' (default: all)
|
||||
Return JSON for the specified type. Type can be 'artifact', 'container', 'image', 'volume', 'network', 'pod', or 'all' (default: all)
|
||||
(Only meaningful when invoked as *podman inspect*)
|
||||
|
||||
## EXAMPLES
|
||||
@ -164,8 +165,22 @@ Inspect the specified network for the `Name` format specifier:
|
||||
myNetwork
|
||||
```
|
||||
|
||||
Inspect the specified artifact:
|
||||
```
|
||||
# podman inspect quay.io/myimage/myartifact:latest --type artifact
|
||||
{
|
||||
"Manifest": {
|
||||
"schemaVersion": 2,
|
||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||
...
|
||||
},
|
||||
"Name": "quay.io/myimage/myartifact:latest",
|
||||
"Digest": "sha256:..."
|
||||
}
|
||||
```
|
||||
|
||||
## SEE ALSO
|
||||
**[podman(1)](podman.1.md)**, **[podman-container-inspect(1)](podman-container-inspect.1.md)**, **[podman-image-inspect(1)](podman-image-inspect.1.md)**, **[podman-network-inspect(1)](podman-network-inspect.1.md)**, **[podman-pod-inspect(1)](podman-pod-inspect.1.md)**, **[podman-volume-inspect(1)](podman-volume-inspect.1.md)**
|
||||
**[podman(1)](podman.1.md)**, **[podman-artifact-inspect(1)](podman-artifact-inspect.1.md)**, **[podman-container-inspect(1)](podman-container-inspect.1.md)**, **[podman-image-inspect(1)](podman-image-inspect.1.md)**, **[podman-network-inspect(1)](podman-network-inspect.1.md)**, **[podman-pod-inspect(1)](podman-pod-inspect.1.md)**, **[podman-volume-inspect(1)](podman-volume-inspect.1.md)**
|
||||
|
||||
## HISTORY
|
||||
July 2017, Originally compiled by Dan Walsh <dwalsh@redhat.com>
|
||||
|
@ -367,7 +367,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) | Display 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, image, volume, network, or pod's configuration. |
|
||||
| [podman-inspect(1)](podman-inspect.1.md) | Display artifact, 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 image(s) from a tar archive into container storage. |
|
||||
| [podman-login(1)](podman-login.1.md) | Log in to a container registry. |
|
||||
|
@ -597,4 +597,46 @@ var _ = Describe("Podman inspect", func() {
|
||||
Expect(session.OutputToString()).To(ContainSubstring(commandNotFound))
|
||||
})
|
||||
|
||||
It("podman inspect artifact", func() {
|
||||
artifactFile, err := createArtifactFile(1024)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
artifactName := "localhost/test/myartifact"
|
||||
add := podmanTest.Podman([]string{"artifact", "add", artifactName, artifactFile})
|
||||
add.WaitWithDefaultTimeout()
|
||||
Expect(add).Should(ExitCleanly())
|
||||
|
||||
// Test explicit artifact type
|
||||
inspect := podmanTest.Podman([]string{"inspect", "--type", "artifact", artifactName})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(ExitCleanly())
|
||||
Expect(inspect.OutputToString()).To(BeValidJSON())
|
||||
|
||||
// Test fallback to artifact when no other object type matches
|
||||
inspect = podmanTest.Podman([]string{"inspect", artifactName})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(ExitCleanly())
|
||||
Expect(inspect.OutputToString()).To(BeValidJSON())
|
||||
|
||||
// Verify that the output contains artifact-specific fields
|
||||
Expect(inspect.OutputToString()).To(ContainSubstring("Manifest"))
|
||||
Expect(inspect.OutputToString()).To(ContainSubstring("Digest"))
|
||||
|
||||
// Test format with artifact-specific fields
|
||||
inspect = podmanTest.Podman([]string{"inspect", "--format", "{{.Name}}", artifactName})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(ExitCleanly())
|
||||
Expect(inspect.OutputToString()).To(Equal(artifactName))
|
||||
|
||||
inspect2 := podmanTest.Podman([]string{"inspect", "--format", "{{.Digest}}", artifactName})
|
||||
inspect2.WaitWithDefaultTimeout()
|
||||
Expect(inspect2).Should(ExitCleanly())
|
||||
Expect(inspect2.OutputToString()).To(ContainSubstring("sha256:"))
|
||||
|
||||
// Clean up
|
||||
rm := podmanTest.Podman([]string{"artifact", "rm", artifactName})
|
||||
rm.WaitWithDefaultTimeout()
|
||||
Expect(rm).Should(ExitCleanly())
|
||||
})
|
||||
|
||||
})
|
||||
|
Reference in New Issue
Block a user