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:
baude
2018-08-08 13:08:22 -05:00
committed by Atomic Bot
parent 879453eaf1
commit 06fafe4cd0
7 changed files with 235 additions and 0 deletions

View File

@ -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
View 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
}

View File

@ -31,6 +31,7 @@
| [podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers |[![...](/docs/play.png)](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. ||

View 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>

View File

@ -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
}

View File

@ -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 {

View 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))
})
})