mirror of
https://github.com/containers/podman.git
synced 2025-07-03 09:17:15 +08:00
add podman pod inspect
first pass of podman pod inspect Signed-off-by: baude <bbaude@redhat.com> Closes: #1236 Approved by: rhatdan
This commit is contained in:
@ -11,6 +11,7 @@ Pods are a group of one or more containers sharing the same network, pid and ipc
|
||||
`
|
||||
podSubCommands = []cli.Command{
|
||||
podCreateCommand,
|
||||
podInspectCommand,
|
||||
podKillCommand,
|
||||
podPauseCommand,
|
||||
podPsCommand,
|
||||
|
65
cmd/podman/pod_inspect.go
Normal file
65
cmd/podman/pod_inspect.go
Normal file
@ -0,0 +1,65 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectatomic/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/projectatomic/libpod/libpod"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
podInspectFlags = []cli.Flag{
|
||||
LatestPodFlag,
|
||||
}
|
||||
podInspectDescription = "display the configuration for a pod by name or id"
|
||||
podInspectCommand = cli.Command{
|
||||
Name: "inspect",
|
||||
Usage: "displays a pod configuration",
|
||||
Description: podInspectDescription,
|
||||
Flags: podInspectFlags,
|
||||
Action: podInspectCmd,
|
||||
UseShortOptionHandling: true,
|
||||
ArgsUsage: "[POD_NAME_OR_ID]",
|
||||
}
|
||||
)
|
||||
|
||||
func podInspectCmd(c *cli.Context) error {
|
||||
var (
|
||||
pod *libpod.Pod
|
||||
)
|
||||
if err := checkMutuallyExclusiveFlags(c); err != nil {
|
||||
return err
|
||||
}
|
||||
args := c.Args()
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
if c.Bool("latest") {
|
||||
pod, err = runtime.GetLatestPod()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to get latest pod")
|
||||
}
|
||||
} else {
|
||||
pod, err = runtime.LookupPod(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
podInspectData, err := pod.Inspect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b, err := json.MarshalIndent(&podInspectData, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(b))
|
||||
return nil
|
||||
}
|
@ -31,6 +31,7 @@
|
||||
| [podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers |[](https://asciinema.org/a/141292)|
|
||||
| [podman-pod(1)](/docs/podman-pod.1.md) | Simple management tool for groups of containers, called pods ||
|
||||
| [podman-pod-create(1)](/docs/podman-pod-create.1.md) | Create a new pod ||
|
||||
| [podman-pod-inspect(1)](/docs/podman-pod-inspect.1.md) | Inspect a pod ||
|
||||
| [podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. ||
|
||||
| [podman-pod-ps(1)](/docs/podman-pod-ps.1.md) | List the pods on the system ||
|
||||
| [podman-pod-pause(1)](podman-pod-pause.1.md) | Pause one or more pods. ||
|
||||
|
48
docs/podman-pod-inspect.1.md
Normal file
48
docs/podman-pod-inspect.1.md
Normal file
@ -0,0 +1,48 @@
|
||||
% podman-pod-inspect "1"
|
||||
|
||||
## NAME
|
||||
podman\-pod\-inspect - Displays information describing a pod
|
||||
|
||||
## SYNOPSIS
|
||||
**podman pod inspect** [*options*] *pod* ...
|
||||
|
||||
## DESCRIPTION
|
||||
Displays configuration and state information about a given pod. It also displays information about containers
|
||||
that belong to the pod.
|
||||
|
||||
## OPTIONS
|
||||
**--latest, -l**
|
||||
|
||||
Instead of providing the pod name or ID, use the last created pod. If you use methods other than Podman
|
||||
to run pods such as CRI-O, the last started pod could be from either of those methods.
|
||||
|
||||
|
||||
## EXAMPLE
|
||||
```
|
||||
# podman pod inspect foobar
|
||||
{
|
||||
"Config": {
|
||||
"id": "3513ca70583dd7ef2bac83331350f6b6c47d7b4e526c908e49d89ebf720e4693",
|
||||
"name": "foobar",
|
||||
"labels": {},
|
||||
"cgroupParent": "/libpod_parent",
|
||||
"UsePodCgroup": true,
|
||||
"created": "2018-08-08T11:15:18.823115347-05:00"
|
||||
},
|
||||
"State": {
|
||||
"CgroupPath": ""
|
||||
},
|
||||
"Containers": [
|
||||
{
|
||||
"id": "d53f8bf1e9730281264aac6e6586e327429f62c704abea4b6afb5d8a2b2c9f2c",
|
||||
"state": "configured"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## SEE ALSO
|
||||
podman-pod(1), podman-pod-ps(1)
|
||||
|
||||
## HISTORY
|
||||
August 2018, Originally compiled by Brent Baude <bbaude@redhat.com>
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/ulule/deepcopier"
|
||||
)
|
||||
|
||||
// Pod represents a group of containers that are managed together.
|
||||
@ -59,6 +60,20 @@ type podState struct {
|
||||
CgroupPath string
|
||||
}
|
||||
|
||||
// PodInspect represents the data we want to display for
|
||||
// podman pod inspect
|
||||
type PodInspect struct {
|
||||
Config *PodConfig
|
||||
State *podState
|
||||
Containers []PodContainerInfo
|
||||
}
|
||||
|
||||
// PodContainerInfo keeps information on a container in a pod
|
||||
type PodContainerInfo struct {
|
||||
ID string `json:"id"`
|
||||
State string `json:"state"`
|
||||
}
|
||||
|
||||
// ID retrieves the pod's ID
|
||||
func (p *Pod) ID() string {
|
||||
return p.config.ID
|
||||
@ -696,3 +711,38 @@ func (p *Pod) Status() (map[string]ContainerStatus, error) {
|
||||
// TODO add pod batching
|
||||
// Lock pod to avoid lock contention
|
||||
// Store and lock all containers (no RemoveContainer in batch guarantees cache will not become stale)
|
||||
|
||||
// Inspect returns a PodInspect struct to describe the pod
|
||||
func (p *Pod) Inspect() (*PodInspect, error) {
|
||||
var (
|
||||
podContainers []PodContainerInfo
|
||||
)
|
||||
|
||||
containers, err := p.AllContainers()
|
||||
if err != nil {
|
||||
return &PodInspect{}, err
|
||||
}
|
||||
for _, c := range containers {
|
||||
containerStatus := "unknown"
|
||||
// Ignoring possible errors here because we dont want this to be
|
||||
// catastrophic in nature
|
||||
containerState, err := c.State()
|
||||
if err == nil {
|
||||
containerStatus = containerState.String()
|
||||
}
|
||||
pc := PodContainerInfo{
|
||||
ID: c.ID(),
|
||||
State: containerStatus,
|
||||
}
|
||||
podContainers = append(podContainers, pc)
|
||||
}
|
||||
|
||||
config := new(PodConfig)
|
||||
deepcopier.Copy(p.config).To(config)
|
||||
inspectData := PodInspect{
|
||||
Config: config,
|
||||
State: p.state,
|
||||
Containers: podContainers,
|
||||
}
|
||||
return &inspectData, nil
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/gexec"
|
||||
"github.com/projectatomic/libpod/libpod"
|
||||
"github.com/projectatomic/libpod/pkg/inspect"
|
||||
)
|
||||
|
||||
@ -339,6 +340,14 @@ func (s *PodmanSession) InspectContainerToJSON() []inspect.ContainerData {
|
||||
return i
|
||||
}
|
||||
|
||||
// InspectPodToJSON takes the sessions output from a pod inspect and returns json
|
||||
func (s *PodmanSession) InspectPodToJSON() libpod.PodInspect {
|
||||
var i libpod.PodInspect
|
||||
err := json.Unmarshal(s.Out.Contents(), &i)
|
||||
Expect(err).To(BeNil())
|
||||
return i
|
||||
}
|
||||
|
||||
// InspectImageJSON takes the session output of an inspect
|
||||
// image and returns json
|
||||
func (s *PodmanSession) InspectImageJSON() []inspect.ImageData {
|
||||
|
61
test/e2e/pod_inspect_test.go
Normal file
61
test/e2e/pod_inspect_test.go
Normal file
@ -0,0 +1,61 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("Podman pod inspect", func() {
|
||||
var (
|
||||
tempdir string
|
||||
err error
|
||||
podmanTest PodmanTest
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
tempdir, err = CreateTempDirInTempDir()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
podmanTest = PodmanCreate(tempdir)
|
||||
podmanTest.RestoreAllArtifacts()
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
podmanTest.CleanupPod()
|
||||
f := CurrentGinkgoTestDescription()
|
||||
timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds())
|
||||
GinkgoWriter.Write([]byte(timedResult))
|
||||
})
|
||||
|
||||
It("podman inspect bogus pod", func() {
|
||||
session := podmanTest.Podman([]string{"pod", "inspect", "foobar"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Not(Equal(0)))
|
||||
})
|
||||
|
||||
It("podman inspect a pod", func() {
|
||||
session := podmanTest.Podman([]string{"pod", "create"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
podid := session.OutputToString()
|
||||
|
||||
session = podmanTest.RunTopContainerInPod("", podid)
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
session = podmanTest.RunTopContainerInPod("", podid)
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
|
||||
inspect := podmanTest.Podman([]string{"pod", "inspect", podid})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect.ExitCode()).To(Equal(0))
|
||||
Expect(inspect.IsJSONOutputValid()).To(BeTrue())
|
||||
podData := inspect.InspectPodToJSON()
|
||||
Expect(podData.Config.ID).To(Equal(podid))
|
||||
})
|
||||
})
|
Reference in New Issue
Block a user