summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2018-08-08 13:08:22 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2018-08-09 11:06:32 +0000
commit06fafe4cd04f29ee19078d6e78fdd792f2c1a37e (patch)
tree858649113e849d6b6c179126eb3b8740b0d2ee9d
parent879453eaf16675f732dd87fd250ccaaac72f4285 (diff)
downloadpodman-06fafe4cd04f29ee19078d6e78fdd792f2c1a37e.tar.gz
podman-06fafe4cd04f29ee19078d6e78fdd792f2c1a37e.tar.bz2
podman-06fafe4cd04f29ee19078d6e78fdd792f2c1a37e.zip
add podman pod inspect
first pass of podman pod inspect Signed-off-by: baude <bbaude@redhat.com> Closes: #1236 Approved by: rhatdan
-rw-r--r--cmd/podman/pod.go1
-rw-r--r--cmd/podman/pod_inspect.go65
-rw-r--r--commands.md1
-rw-r--r--docs/podman-pod-inspect.1.md48
-rw-r--r--libpod/pod.go50
-rw-r--r--test/e2e/libpod_suite_test.go9
-rw-r--r--test/e2e/pod_inspect_test.go61
7 files changed, 235 insertions, 0 deletions
diff --git a/cmd/podman/pod.go b/cmd/podman/pod.go
index ed79f0711..a298ca32b 100644
--- a/cmd/podman/pod.go
+++ b/cmd/podman/pod.go
@@ -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,
diff --git a/cmd/podman/pod_inspect.go b/cmd/podman/pod_inspect.go
new file mode 100644
index 000000000..6935335a6
--- /dev/null
+++ b/cmd/podman/pod_inspect.go
@@ -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
+}
diff --git a/commands.md b/commands.md
index 3ac195476..d3e8d93cc 100644
--- a/commands.md
+++ b/commands.md
@@ -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. ||
diff --git a/docs/podman-pod-inspect.1.md b/docs/podman-pod-inspect.1.md
new file mode 100644
index 000000000..edcd5dcef
--- /dev/null
+++ b/docs/podman-pod-inspect.1.md
@@ -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>
diff --git a/libpod/pod.go b/libpod/pod.go
index 2ad4f7d0e..46182680a 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -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
+}
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index e95b03cb9..3b7953672 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -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 {
diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go
new file mode 100644
index 000000000..b5c2bd1be
--- /dev/null
+++ b/test/e2e/pod_inspect_test.go
@@ -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))
+ })
+})