diff options
-rw-r--r-- | cmd/podman/shared/container_inspect.go | 44 | ||||
-rw-r--r-- | libpod/container_inspect.go | 114 | ||||
-rw-r--r-- | test/e2e/common_test.go | 27 | ||||
-rw-r--r-- | test/e2e/port_test.go | 30 | ||||
-rw-r--r-- | vendor.conf | 2 | ||||
-rw-r--r-- | vendor/github.com/containers/buildah/buildah.go | 2 | ||||
-rw-r--r-- | vendor/github.com/containers/buildah/run_linux.go | 8 |
7 files changed, 168 insertions, 59 deletions
diff --git a/cmd/podman/shared/container_inspect.go b/cmd/podman/shared/container_inspect.go index fed089d29..c89daf6bb 100644 --- a/cmd/podman/shared/container_inspect.go +++ b/cmd/podman/shared/container_inspect.go @@ -1,9 +1,6 @@ package shared import ( - "strings" - - "github.com/containers/image/manifest" "github.com/containers/libpod/libpod" cc "github.com/containers/libpod/pkg/spec" "github.com/docker/go-connections/nat" @@ -17,7 +14,6 @@ import ( type InspectContainer struct { *libpod.InspectContainerData HostConfig *InspectContainerHostConfig `json:"HostConfig"` - Config *InspectContainerConfig `json:"Config"` } // InspectContainerHostConfig holds Container configuration that is not specific @@ -82,31 +78,6 @@ type InspectContainerHostConfig struct { Tmpfs []string `json:"Tmpfs"` } -// InspectContainerConfig holds further data about a container, again mostly -// not directly stored in Libpod. This struct is matched to the output of -// `docker inspect`. -type InspectContainerConfig struct { - Hostname string `json:"Hostname"` - DomainName string `json:"Domainname"` //TODO - User specs.User `json:"User"` - AttachStdin bool `json:"AttachStdin"` //TODO - AttachStdout bool `json:"AttachStdout"` //TODO - AttachStderr bool `json:"AttachStderr"` //TODO - Tty bool `json:"Tty"` - OpenStdin bool `json:"OpenStdin"` - StdinOnce bool `json:"StdinOnce"` //TODO - Env []string `json:"Env"` - Cmd []string `json:"Cmd"` - Image string `json:"Image"` - Volumes map[string]struct{} `json:"Volumes"` - WorkingDir string `json:"WorkingDir"` - Entrypoint string `json:"Entrypoint"` - Labels map[string]string `json:"Labels"` - Annotations map[string]string `json:"Annotations"` - StopSignal uint `json:"StopSignal"` - Healthcheck *manifest.Schema2HealthConfig `json:"Healthcheck,omitempty"` -} - // InspectLogConfig holds information about a container's configured log driver // and is presently unused. It is retained for Docker compatibility. type InspectLogConfig struct { @@ -181,21 +152,6 @@ func GetCtrInspectInfo(config *libpod.ContainerConfig, ctrInspectData *libpod.In SecurityOpt: createArtifact.SecurityOpts, Tmpfs: createArtifact.Tmpfs, }, - &InspectContainerConfig{ - Hostname: spec.Hostname, - User: spec.Process.User, - Env: spec.Process.Env, - Image: config.RootfsImageName, - WorkingDir: spec.Process.Cwd, - Labels: config.Labels, - Annotations: spec.Annotations, - Tty: spec.Process.Terminal, - OpenStdin: config.Stdin, - StopSignal: config.StopSignal, - Cmd: config.Spec.Process.Args, - Entrypoint: strings.Join(createArtifact.Entrypoint, " "), - Healthcheck: config.HealthCheckConfig, - }, } return data, nil } diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 0a62ceb7c..752823634 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -1,8 +1,10 @@ package libpod import ( + "strings" "time" + "github.com/containers/image/manifest" "github.com/containers/libpod/libpod/driver" "github.com/cri-o/ocicni/pkg/ocicni" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -49,6 +51,53 @@ type InspectContainerData struct { ExitCommand []string `json:"ExitCommand"` Namespace string `json:"Namespace"` IsInfra bool `json:"IsInfra"` + Config *InspectContainerConfig `json:"Config"` +} + +// InspectContainerConfig holds further data about how a container was initially +// configured. +type InspectContainerConfig struct { + // Container hostname + Hostname string `json:"Hostname"` + // Container domain name - unused at present + DomainName string `json:"Domainname"` + // User the container was launched with + User string `json:"User"` + // Unused, at present + AttachStdin bool `json:"AttachStdin"` + // Unused, at present + AttachStdout bool `json:"AttachStdout"` + // Unused, at present + AttachStderr bool `json:"AttachStderr"` + // Whether the container creates a TTY + Tty bool `json:"Tty"` + // Whether the container leaves STDIN open + OpenStdin bool `json:"OpenStdin"` + // Whether STDIN is only left open once. + // Presently not supported by Podman, unused. + StdinOnce bool `json:"StdinOnce"` + // Container environment variables + Env []string `json:"Env"` + // Container command + Cmd []string `json:"Cmd"` + // Container image + Image string `json:"Image"` + // Unused, at present. I've never seen this field populated. + Volumes map[string]struct{} `json:"Volumes"` + // Container working directory + WorkingDir string `json:"WorkingDir"` + // Container entrypoint + Entrypoint string `json:"Entrypoint"` + // On-build arguments - presently unused. More of Buildah's domain. + OnBuild *string `json:"OnBuild"` + // Container labels + Labels map[string]string `json:"Labels"` + // Container annotations + Annotations map[string]string `json:"Annotations"` + // Container stop signal + StopSignal uint `json:"StopSignal"` + // Configured healthcheck for the container + Healthcheck *manifest.Schema2HealthConfig `json:"Healthcheck,omitempty"` } // InspectMount provides a record of a single mount in a container. It contains @@ -192,7 +241,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data) } } - mounts, err := c.getInspectMounts() + mounts, err := c.getInspectMounts(spec) if err != nil { return nil, err } @@ -284,6 +333,12 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data) // Get information on the container's network namespace (if present) data = c.getContainerNetworkInfo(data) + inspectConfig, err := c.generateInspectContainerConfig(spec) + if err != nil { + return nil, err + } + data.Config = inspectConfig + if size { rootFsSize, err := c.rootFsSize() if err != nil { @@ -302,7 +357,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data) // Get inspect-formatted mounts list. // Only includes user-specified mounts. Only includes bind mounts and named // volumes, not tmpfs volumes. -func (c *Container) getInspectMounts() ([]*InspectMount, error) { +func (c *Container) getInspectMounts(ctrSpec *spec.Spec) ([]*InspectMount, error) { inspectMounts := []*InspectMount{} // No mounts, return early @@ -319,7 +374,7 @@ func (c *Container) getInspectMounts() ([]*InspectMount, error) { for _, namedVol := range c.config.NamedVolumes { namedVolumes[namedVol.Dest] = namedVol } - for _, mount := range c.config.Spec.Mounts { + for _, mount := range ctrSpec.Mounts { mounts[mount.Destination] = mount } @@ -401,3 +456,56 @@ func parseMountOptionsForInspect(options []string, mount *InspectMount) { mount.Mode = zZ mount.Options = otherOpts } + +// Generate the InspectContainerConfig struct for the Config field of Inspect. +func (c *Container) generateInspectContainerConfig(spec *spec.Spec) (*InspectContainerConfig, error) { + ctrConfig := new(InspectContainerConfig) + + ctrConfig.Hostname = c.Hostname() + ctrConfig.User = c.config.User + if spec.Process != nil { + ctrConfig.Tty = spec.Process.Terminal + ctrConfig.Env = []string{} + for _, val := range spec.Process.Env { + ctrConfig.Env = append(ctrConfig.Env, val) + } + ctrConfig.WorkingDir = spec.Process.Cwd + } + + ctrConfig.OpenStdin = c.config.Stdin + ctrConfig.Image = c.config.RootfsImageName + + // Leave empty is not explicitly overwritten by user + if len(c.config.Command) != 0 { + ctrConfig.Cmd = []string{} + for _, val := range c.config.Command { + ctrConfig.Cmd = append(ctrConfig.Cmd, val) + } + } + + // Leave empty if not explicitly overwritten by user + if len(c.config.Entrypoint) != 0 { + ctrConfig.Entrypoint = strings.Join(c.config.Entrypoint, " ") + } + + if len(c.config.Labels) != 0 { + ctrConfig.Labels = make(map[string]string) + for k, v := range c.config.Labels { + ctrConfig.Labels[k] = v + } + } + + if len(spec.Annotations) != 0 { + ctrConfig.Annotations = make(map[string]string) + for k, v := range spec.Annotations { + ctrConfig.Annotations[k] = v + } + } + + ctrConfig.StopSignal = c.config.StopSignal + // TODO: should JSON deep copy this to ensure internal pointers don't + // leak. + ctrConfig.Healthcheck = c.config.HealthCheckConfig + + return ctrConfig, nil +} diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 9529346b4..8b6eab892 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -10,6 +10,7 @@ import ( "sort" "strings" "testing" + "time" "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" @@ -22,6 +23,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/gexec" + "github.com/pkg/errors" ) var ( @@ -367,6 +369,18 @@ func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionInteg return session, session.ExitCode(), session.OutputToString() } +// RunNginxWithHealthCheck runs the alpine nginx container with an optional name and adds a healthcheck into it +func (p *PodmanTestIntegration) RunNginxWithHealthCheck(name string) (*PodmanSessionIntegration, string) { + var podmanArgs = []string{"run"} + if name != "" { + podmanArgs = append(podmanArgs, "--name", name) + } + podmanArgs = append(podmanArgs, "-dt", "-P", "--healthcheck-command", "CMD-SHELL curl http://localhost/", nginx) + session := p.Podman(podmanArgs) + session.WaitWithDefaultTimeout() + return session, session.OutputToString() +} + func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSessionIntegration, int, string) { var podmanArgs = []string{"run", "--pod", pod} if name != "" { @@ -508,3 +522,16 @@ func (p *PodmanTestIntegration) ImageExistsInMainStore(idOrName string) bool { results.WaitWithDefaultTimeout() return Expect(results.ExitCode()).To(Equal(0)) } + +func (p *PodmanTestIntegration) RunHealthCheck(cid string) error { + for i := 0; i < 10; i++ { + hc := p.Podman([]string{"healthcheck", "run", cid}) + hc.WaitWithDefaultTimeout() + if hc.ExitCode() == 0 { + return nil + } + fmt.Printf("Waiting for %s to pass healthcheck\n", cid) + time.Sleep(1 * time.Second) + } + return errors.Errorf("unable to detect %s as running", cid) +} diff --git a/test/e2e/port_test.go b/test/e2e/port_test.go index e45118361..26c5fd7d0 100644 --- a/test/e2e/port_test.go +++ b/test/e2e/port_test.go @@ -48,11 +48,14 @@ var _ = Describe("Podman port", func() { Expect(result.ExitCode()).ToNot(Equal(0)) }) - It("podman port -l nginx", func() { - session := podmanTest.Podman([]string{"run", "-dt", "-P", nginx}) - session.WaitWithDefaultTimeout() + It("podman port -l nginx", func() { + session, cid := podmanTest.RunNginxWithHealthCheck("") Expect(session.ExitCode()).To(Equal(0)) + if err := podmanTest.RunHealthCheck(cid); err != nil { + Fail(err.Error()) + } + result := podmanTest.Podman([]string{"port", "-l"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -61,10 +64,13 @@ var _ = Describe("Podman port", func() { }) It("podman container port -l nginx", func() { - session := podmanTest.Podman([]string{"container", "run", "-dt", "-P", nginx}) - session.WaitWithDefaultTimeout() + session, cid := podmanTest.RunNginxWithHealthCheck("") Expect(session.ExitCode()).To(Equal(0)) + if err := podmanTest.RunHealthCheck(cid); err != nil { + Fail(err.Error()) + } + result := podmanTest.Podman([]string{"container", "port", "-l"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -73,10 +79,13 @@ var _ = Describe("Podman port", func() { }) It("podman port -l port nginx", func() { - session := podmanTest.Podman([]string{"run", "-dt", "-P", nginx}) - session.WaitWithDefaultTimeout() + session, cid := podmanTest.RunNginxWithHealthCheck("") Expect(session.ExitCode()).To(Equal(0)) + if err := podmanTest.RunHealthCheck(cid); err != nil { + Fail(err.Error()) + } + result := podmanTest.Podman([]string{"port", "-l", "80"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) @@ -85,10 +94,13 @@ var _ = Describe("Podman port", func() { }) It("podman port -a nginx", func() { - session := podmanTest.Podman([]string{"run", "-dt", "-P", nginx}) - session.WaitWithDefaultTimeout() + session, cid := podmanTest.RunNginxWithHealthCheck("") Expect(session.ExitCode()).To(Equal(0)) + if err := podmanTest.RunHealthCheck(cid); err != nil { + Fail(err.Error()) + } + result := podmanTest.Podman([]string{"port", "-a"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) diff --git a/vendor.conf b/vendor.conf index 9b9044b66..b8ac20a4e 100644 --- a/vendor.conf +++ b/vendor.conf @@ -93,7 +93,7 @@ k8s.io/api kubernetes-1.10.13-beta.0 https://github.com/kubernetes/api k8s.io/apimachinery kubernetes-1.10.13-beta.0 https://github.com/kubernetes/apimachinery k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7 -github.com/containers/buildah v1.8.4 +github.com/containers/buildah v1.9.0 github.com/varlink/go 0f1d566d194b9d6d48e0d47c5e4d822628919066 # TODO: Gotty has not been updated since 2012. Can we find replacement? github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512 diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go index b97e048cc..329835d7a 100644 --- a/vendor/github.com/containers/buildah/buildah.go +++ b/vendor/github.com/containers/buildah/buildah.go @@ -26,7 +26,7 @@ const ( Package = "buildah" // Version for the Package. Bump version in contrib/rpm/buildah.spec // too. - Version = "1.8.4" + Version = "1.9.0" // The value we use to identify what type of information, currently a // serialized Builder structure, we are using as per-container state. // This should only be changed when we make incompatible changes to diff --git a/vendor/github.com/containers/buildah/run_linux.go b/vendor/github.com/containers/buildah/run_linux.go index 55f9502b2..0bf37da59 100644 --- a/vendor/github.com/containers/buildah/run_linux.go +++ b/vendor/github.com/containers/buildah/run_linux.go @@ -1134,8 +1134,14 @@ func runCopyStdio(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copy setNonblock(wfd, writeDesc[wfd], false) } - setNonblock(stdioPipe[unix.Stdin][1], writeDesc[stdioPipe[unix.Stdin][1]], true) + if copyPipes { + setNonblock(stdioPipe[unix.Stdin][1], writeDesc[stdioPipe[unix.Stdin][1]], true) + } + + runCopyStdioPassData(stdio, copyPipes, stdioPipe, copyConsole, consoleListener, finishCopy, finishedCopy, spec, relayMap, relayBuffer, readDesc, writeDesc) +} +func runCopyStdioPassData(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copyConsole bool, consoleListener *net.UnixListener, finishCopy []int, finishedCopy chan struct{}, spec *specs.Spec, relayMap map[int]int, relayBuffer map[int]*bytes.Buffer, readDesc map[int]string, writeDesc map[int]string) { closeStdin := false // Pass data back and forth. |