From 27120bfbab65e4a423e4801a0d93bdb661779a98 Mon Sep 17 00:00:00 2001 From: Yuan-Hao Chen Date: Fri, 19 Jun 2020 00:59:50 +0800 Subject: correct the absolute path of `rm` executable Signed-off-by: Yuan-Hao Chen --- test/e2e/generate_systemd_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go index 497e8f71e..f43a4f865 100644 --- a/test/e2e/generate_systemd_test.go +++ b/test/e2e/generate_systemd_test.go @@ -362,7 +362,7 @@ var _ = Describe("Podman generate systemd", func() { found, _ = session.GrepString("pod create --infra-conmon-pidfile %t/pod-foo.pid --pod-id-file %t/pod-foo.pod-id --name foo") Expect(found).To(BeTrue()) - found, _ = session.GrepString("ExecStartPre=/usr/bin/rm -f %t/pod-foo.pid %t/pod-foo.pod-id") + found, _ = session.GrepString("ExecStartPre=/bin/rm -f %t/pod-foo.pid %t/pod-foo.pod-id") Expect(found).To(BeTrue()) found, _ = session.GrepString("pod stop --ignore --pod-id-file %t/pod-foo.pod-id -t 10") -- cgit v1.2.3-54-g00ecf From 37abb88aa02773e76ccb87183c8ac6cbb9cf2071 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Thu, 18 Jun 2020 09:48:52 -0400 Subject: Fix podman build handling of --http-proxy flag Also fixed a todo for handling of cgroup manager while I was in there. Signed-off-by: Daniel J Walsh --- cmd/podman/images/build.go | 20 ++++++++------------ test/e2e/build_test.go | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 12 deletions(-) (limited to 'test') diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go index 2efc795cd..23bfcab79 100644 --- a/cmd/podman/images/build.go +++ b/cmd/podman/images/build.go @@ -9,6 +9,7 @@ import ( "github.com/containers/buildah/imagebuildah" buildahCLI "github.com/containers/buildah/pkg/cli" "github.com/containers/buildah/pkg/parse" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/cmd/podman/utils" "github.com/containers/libpod/pkg/domain/entities" @@ -396,16 +397,10 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil runtimeFlags = append(runtimeFlags, "--"+arg) } - // FIXME: the code below needs to be enabled (and adjusted) once the - // global/root flags are supported. - - // conf, err := runtime.GetConfig() - // if err != nil { - // return err - // } - // if conf != nil && conf.Engine.CgroupManager == config.SystemdCgroupsManager { - // runtimeFlags = append(runtimeFlags, "--systemd-cgroup") - // } + containerConfig := registry.PodmanConfig() + if containerConfig.Engine.CgroupManager == config.SystemdCgroupsManager { + runtimeFlags = append(runtimeFlags, "--systemd-cgroup") + } opts := imagebuildah.BuildOptions{ AddCapabilities: flags.CapAdd, @@ -418,12 +413,13 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil CNIPluginPath: flags.CNIPlugInPath, CommonBuildOpts: &buildah.CommonBuildOptions{ AddHost: flags.AddHost, - CgroupParent: flags.CgroupParent, CPUPeriod: flags.CPUPeriod, CPUQuota: flags.CPUQuota, - CPUShares: flags.CPUShares, CPUSetCPUs: flags.CPUSetCPUs, CPUSetMems: flags.CPUSetMems, + CPUShares: flags.CPUShares, + CgroupParent: flags.CgroupParent, + HTTPProxy: flags.HTTPProxy, Memory: memoryLimit, MemorySwap: memorySwap, ShmSize: flags.ShmSize, diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go index 9e41fd231..0cf5283ad 100644 --- a/test/e2e/build_test.go +++ b/test/e2e/build_test.go @@ -195,4 +195,21 @@ var _ = Describe("Podman build", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman build --http_proxy flag", func() { + SkipIfRemote() + os.Setenv("http_proxy", "1.2.3.4") + podmanTest.RestoreAllArtifacts() + dockerfile := `FROM docker.io/library/alpine:latest +RUN printenv http_proxy` + + dockerfilePath := filepath.Join(podmanTest.TempDir, "Dockerfile") + err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755) + Expect(err).To(BeNil()) + session := podmanTest.PodmanNoCache([]string{"build", "--file", dockerfilePath, podmanTest.TempDir}) + session.Wait(120) + Expect(session.ExitCode()).To(Equal(0)) + ok, _ := session.GrepString("1.2.3.4") + Expect(ok).To(BeTrue()) + os.Unsetenv("http_proxy") + }) }) -- cgit v1.2.3-54-g00ecf From 07f535d8b7595388e9e45203f2d7a77cbf78b977 Mon Sep 17 00:00:00 2001 From: jgallucci32 Date: Sat, 20 Jun 2020 09:45:18 -0700 Subject: Stop following logs using timers This incorporates code from PR #6591 and #6614 but does not use event channels to detect container state and rather uses timers with a defined wait duration before calling t.StopAtEOF() to ensure the last log entry is output before a container exits. The polling interval is set to 250 milliseconds based on polling interval defined in hpcloud/tail here: https://github.com/hpcloud/tail/blob/v1.0.0/watch/polling.go#L117 Co-authored-by: Qi Wang Signed-off-by: jgallucci32 --- libpod/container_log.go | 30 ++++++++++++++++++++++++++++++ test/e2e/logs_test.go | 12 ++++++++++++ 2 files changed, 42 insertions(+) (limited to 'test') diff --git a/libpod/container_log.go b/libpod/container_log.go index 071882bc2..9a2f8aa2f 100644 --- a/libpod/container_log.go +++ b/libpod/container_log.go @@ -1,7 +1,9 @@ package libpod import ( + "fmt" "os" + "time" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/logs" @@ -81,5 +83,33 @@ func (c *Container) readFromLogFile(options *logs.LogOptions, logChannel chan *l } options.WaitGroup.Done() }() + // Check if container is still running or paused + if options.Follow { + go func() { + for { + state, err := c.State() + if err != nil { + time.Sleep(250 * time.Millisecond) + tailError := t.StopAtEOF() + if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { + logrus.Error(tailError) + } + if errors.Cause(err) != define.ErrNoSuchCtr { + logrus.Error(err) + } + break + } + if state != define.ContainerStateRunning && state != define.ContainerStatePaused { + time.Sleep(250 * time.Millisecond) + tailError := t.StopAtEOF() + if tailError != nil && fmt.Sprintf("%v", tailError) != "tail: stop at eof" { + logrus.Error(tailError) + } + break + } + time.Sleep(250 * time.Millisecond) + } + }() + } return nil } diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go index a4a59acb2..fc0739d3d 100644 --- a/test/e2e/logs_test.go +++ b/test/e2e/logs_test.go @@ -311,4 +311,16 @@ var _ = Describe("Podman logs", func() { logs.WaitWithDefaultTimeout() Expect(logs).To(Not(Exit(0))) }) + + It("follow output stopped container", func() { + containerName := "logs-f" + + logc := podmanTest.Podman([]string{"run", "--name", containerName, "-d", ALPINE}) + logc.WaitWithDefaultTimeout() + Expect(logc).To(Exit(0)) + + results := podmanTest.Podman([]string{"logs", "-f", containerName}) + results.WaitWithDefaultTimeout() + Expect(results).To(Exit(0)) + }) }) -- cgit v1.2.3-54-g00ecf From 36d8b6979429d8f9c2e1cbdee104f6724978766d Mon Sep 17 00:00:00 2001 From: jgallucci32 Date: Mon, 22 Jun 2020 06:38:53 -0700 Subject: Add explicit command to alpine container in test case. Signed-off-by: jgallucci32 --- test/e2e/logs_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go index fc0739d3d..cf69cbd3e 100644 --- a/test/e2e/logs_test.go +++ b/test/e2e/logs_test.go @@ -315,7 +315,7 @@ var _ = Describe("Podman logs", func() { It("follow output stopped container", func() { containerName := "logs-f" - logc := podmanTest.Podman([]string{"run", "--name", containerName, "-d", ALPINE}) + logc := podmanTest.Podman([]string{"run", "--name", containerName, "-d", ALPINE, "true"}) logc.WaitWithDefaultTimeout() Expect(logc).To(Exit(0)) -- cgit v1.2.3-54-g00ecf From cd0b18c24f9835e8bb258b906800f0975fbe9e2f Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Tue, 23 Jun 2020 11:17:42 +0200 Subject: image load: no args required Disable the args requirement of `image load`. Instead of requiring a lower bound, we really need an upper one with at most 1 argument. Extend the system tests to prevent future regressions. Fixes: #6718 Signed-off-by: Valentin Rothberg --- cmd/podman/images/load.go | 2 +- test/system/120-load.bats | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/cmd/podman/images/load.go b/cmd/podman/images/load.go index a984ad81f..115e9a070 100644 --- a/cmd/podman/images/load.go +++ b/cmd/podman/images/load.go @@ -30,7 +30,7 @@ var ( } imageLoadCommand = &cobra.Command{ - Args: cobra.MinimumNArgs(1), + Args: loadCommand.Args, Use: loadCommand.Use, Short: loadCommand.Short, Long: loadCommand.Long, diff --git a/test/system/120-load.bats b/test/system/120-load.bats index 15df6adec..f290c1888 100644 --- a/test/system/120-load.bats +++ b/test/system/120-load.bats @@ -44,6 +44,11 @@ verify_iid_and_name() { run_podman load < $archive verify_iid_and_name ":" + # Same as above, using stdin but with `podman image load` + run_podman rmi $iid + run_podman image load < $archive + verify_iid_and_name ":" + # Cleanup: since load-by-iid doesn't preserve name, re-tag it; # otherwise our global teardown will rmi and re-pull our standard image. run_podman tag $iid $img_name @@ -57,9 +62,14 @@ verify_iid_and_name() { # Load using -i; this time the image should be tagged. run_podman load -i $archive verify_iid_and_name $img_name + run_podman rmi $iid - # Same as above, using stdin + # Also make sure that `image load` behaves the same. + run_podman image load -i $archive + verify_iid_and_name $img_name run_podman rmi $iid + + # Same as above, using stdin run_podman load < $archive verify_iid_and_name $img_name } @@ -97,4 +107,10 @@ verify_iid_and_name() { "Diagnostic from 'podman load' without redirection or -i" } +@test "podman load - at most 1 arg(s)" { + run_podman 125 load 1 2 3 + is "$output" \ + "Error: accepts at most 1 arg(s), received 3" +} + # vim: filetype=sh -- cgit v1.2.3-54-g00ecf From d94644d35a6b7056f75da28b8a090ca250e121db Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 24 Jun 2020 11:25:47 +0200 Subject: libpod: specify mappings to the storage specify the mappings in the container configuration to the storage when creating the container so that the correct mappings can be configured. Regression introduced with Podman 2.0. Closes: https://github.com/containers/libpod/issues/6735 Signed-off-by: Giuseppe Scrivano --- libpod/container_internal.go | 20 ++++++++++++++++++++ test/e2e/run_userns_test.go | 7 +++++++ 2 files changed, 27 insertions(+) (limited to 'test') diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 73e0b2118..db64f5eeb 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -22,6 +22,7 @@ import ( "github.com/containers/libpod/pkg/selinux" "github.com/containers/storage" "github.com/containers/storage/pkg/archive" + "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/mount" securejoin "github.com/cyphar/filepath-securejoin" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -360,6 +361,25 @@ func (c *Container) setupStorageMapping(dest, from *storage.IDMappingOptions) { } dest.AutoUserNsOpts.InitialSize = initialSize + 1 } + } else if c.config.Spec.Linux != nil { + dest.UIDMap = nil + for _, r := range c.config.Spec.Linux.UIDMappings { + u := idtools.IDMap{ + ContainerID: int(r.ContainerID), + HostID: int(r.HostID), + Size: int(r.Size), + } + dest.UIDMap = append(dest.UIDMap, u) + } + dest.GIDMap = nil + for _, r := range c.config.Spec.Linux.GIDMappings { + g := idtools.IDMap{ + ContainerID: int(r.ContainerID), + HostID: int(r.HostID), + Size: int(r.Size), + } + dest.GIDMap = append(dest.GIDMap, g) + } } } diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go index 5b9a99daa..be0981408 100644 --- a/test/e2e/run_userns_test.go +++ b/test/e2e/run_userns_test.go @@ -89,6 +89,13 @@ var _ = Describe("Podman UserNS support", func() { Expect(ok).To(BeTrue()) }) + It("podman --userns=keep-id root owns /usr", func() { + session := podmanTest.Podman([]string{"run", "--userns=keep-id", "alpine", "stat", "-c%u", "/usr"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal("0")) + }) + It("podman --userns=keep-id --user root:root", func() { session := podmanTest.Podman([]string{"run", "--userns=keep-id", "--user", "root:root", "alpine", "id", "-u"}) session.WaitWithDefaultTimeout() -- cgit v1.2.3-54-g00ecf From 639b809c80dc2fce76c4d24459d06c469777868f Mon Sep 17 00:00:00 2001 From: Qi Wang Date: Tue, 23 Jun 2020 11:29:11 -0400 Subject: Reformat inspect network settings Reformat ports of inspect network settings to compatible with docker inspect. Close #5380 Signed-off-by: Qi Wang --- libpod/define/container_inspect.go | 15 ++++---- libpod/networking_linux.go | 16 ++++++-- test/e2e/run_networking_test.go | 76 +++++++++++++++++--------------------- 3 files changed, 54 insertions(+), 53 deletions(-) (limited to 'test') diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go index 27ada8706..3fbeb8f0b 100644 --- a/libpod/define/container_inspect.go +++ b/libpod/define/container_inspect.go @@ -5,7 +5,6 @@ import ( "github.com/containers/image/v5/manifest" "github.com/containers/libpod/libpod/driver" - "github.com/cri-o/ocicni/pkg/ocicni" ) // InspectContainerConfig holds further data about how a container was initially @@ -571,13 +570,13 @@ type InspectAdditionalNetwork struct { type InspectNetworkSettings struct { InspectBasicNetworkConfig - Bridge string `json:"Bridge"` - SandboxID string `json:"SandboxID"` - HairpinMode bool `json:"HairpinMode"` - LinkLocalIPv6Address string `json:"LinkLocalIPv6Address"` - LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen"` - Ports []ocicni.PortMapping `json:"Ports"` - SandboxKey string `json:"SandboxKey"` + Bridge string `json:"Bridge"` + SandboxID string `json:"SandboxID"` + HairpinMode bool `json:"HairpinMode"` + LinkLocalIPv6Address string `json:"LinkLocalIPv6Address"` + LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen"` + Ports map[string][]InspectHostPort `json:"Ports"` + SandboxKey string `json:"SandboxKey"` // Networks contains information on non-default CNI networks this // container has joined. // It is a map of network name to network information. diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 0c9d28701..f53573645 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -587,10 +587,20 @@ func getContainerNetIO(ctr *Container) (*netlink.LinkStatistics, error) { // network. func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, error) { settings := new(define.InspectNetworkSettings) - settings.Ports = []ocicni.PortMapping{} + settings.Ports = make(map[string][]define.InspectHostPort) if c.config.PortMappings != nil { - // TODO: This may not be safe. - settings.Ports = c.config.PortMappings + for _, port := range c.config.PortMappings { + key := fmt.Sprintf("%d/%s", port.ContainerPort, port.Protocol) + mapping := settings.Ports[key] + if mapping == nil { + mapping = []define.InspectHostPort{} + } + mapping = append(mapping, define.InspectHostPort{ + HostIP: port.HostIP, + HostPort: fmt.Sprintf("%d", port.HostPort), + }) + settings.Ports[key] = mapping + } } // We can't do more if the network is down. diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index 4fad85f00..afba12ccd 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -71,10 +71,9 @@ var _ = Describe("Podman run networking", func() { inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].ContainerPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].Protocol).To(Equal("tcp")) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("80")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) It("podman run -p 8080:80", func() { @@ -84,10 +83,9 @@ var _ = Describe("Podman run networking", func() { inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostPort).To(Equal(int32(8080))) - Expect(inspectOut[0].NetworkSettings.Ports[0].ContainerPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].Protocol).To(Equal("tcp")) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) It("podman run -p 80/udp", func() { @@ -97,10 +95,9 @@ var _ = Describe("Podman run networking", func() { inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].ContainerPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].Protocol).To(Equal("udp")) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("80")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("")) }) It("podman run -p 127.0.0.1:8080:80", func() { @@ -110,10 +107,9 @@ var _ = Describe("Podman run networking", func() { inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostPort).To(Equal(int32(8080))) - Expect(inspectOut[0].NetworkSettings.Ports[0].ContainerPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].Protocol).To(Equal("tcp")) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostIP).To(Equal("127.0.0.1")) + Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("127.0.0.1")) }) It("podman run -p 127.0.0.1:8080:80/udp", func() { @@ -123,10 +119,9 @@ var _ = Describe("Podman run networking", func() { inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostPort).To(Equal(int32(8080))) - Expect(inspectOut[0].NetworkSettings.Ports[0].ContainerPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].Protocol).To(Equal("udp")) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostIP).To(Equal("127.0.0.1")) + Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("127.0.0.1")) }) It("podman run -p [::1]:8080:80/udp", func() { @@ -136,10 +131,9 @@ var _ = Describe("Podman run networking", func() { inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostPort).To(Equal(int32(8080))) - Expect(inspectOut[0].NetworkSettings.Ports[0].ContainerPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].Protocol).To(Equal("udp")) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostIP).To(Equal("::1")) + Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("::1")) }) It("podman run -p [::1]:8080:80/tcp", func() { @@ -149,10 +143,9 @@ var _ = Describe("Podman run networking", func() { inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostPort).To(Equal(int32(8080))) - Expect(inspectOut[0].NetworkSettings.Ports[0].ContainerPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].Protocol).To(Equal("tcp")) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostIP).To(Equal("::1")) + Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("8080")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("::1")) }) It("podman run --expose 80 -P", func() { @@ -162,10 +155,9 @@ var _ = Describe("Podman run networking", func() { inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostPort).To(Not(Equal(int32(0)))) - Expect(inspectOut[0].NetworkSettings.Ports[0].ContainerPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].Protocol).To(Equal("tcp")) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Not(Equal("0"))) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) It("podman run --expose 80/udp -P", func() { @@ -175,10 +167,9 @@ var _ = Describe("Podman run networking", func() { inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostPort).To(Not(Equal(int32(0)))) - Expect(inspectOut[0].NetworkSettings.Ports[0].ContainerPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].Protocol).To(Equal("udp")) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["80/udp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostPort).To(Not(Equal("0"))) + Expect(inspectOut[0].NetworkSettings.Ports["80/udp"][0].HostIP).To(Equal("")) }) It("podman run --expose 80 -p 80", func() { @@ -188,10 +179,9 @@ var _ = Describe("Podman run networking", func() { inspectOut := podmanTest.InspectContainer(name) Expect(len(inspectOut)).To(Equal(1)) Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].ContainerPort).To(Equal(int32(80))) - Expect(inspectOut[0].NetworkSettings.Ports[0].Protocol).To(Equal("tcp")) - Expect(inspectOut[0].NetworkSettings.Ports[0].HostIP).To(Equal("")) + Expect(len(inspectOut[0].NetworkSettings.Ports["80/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostPort).To(Equal("80")) + Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) It("podman run network expose host port 80 to container port 8000", func() { @@ -214,7 +204,7 @@ var _ = Describe("Podman run networking", func() { results := podmanTest.Podman([]string{"inspect", "-l"}) results.Wait(30) Expect(results.ExitCode()).To(Equal(0)) - Expect(results.OutputToString()).To(ContainSubstring(": 80,")) + Expect(results.OutputToString()).To(ContainSubstring(`"80/tcp":`)) }) It("podman run network expose duplicate host port results in error", func() { @@ -229,7 +219,9 @@ var _ = Describe("Podman run networking", func() { Expect(inspect.ExitCode()).To(Equal(0)) containerConfig := inspect.InspectContainerToJSON() - Expect(containerConfig[0].NetworkSettings.Ports[0].HostPort).ToNot(Equal(80)) + Expect(containerConfig[0].NetworkSettings.Ports).To(Not(BeNil())) + Expect(containerConfig[0].NetworkSettings.Ports["80/tcp"]).To(Not(BeNil())) + Expect(containerConfig[0].NetworkSettings.Ports["80/tcp"][0].HostPort).ToNot(Equal(80)) }) It("podman run hostname test", func() { -- cgit v1.2.3-54-g00ecf From 6594d5d6558437d4cdb11a72eda175ead407ec75 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Wed, 24 Jun 2020 14:44:42 +0200 Subject: podman untag: error if tag doesn't exist Throw an error if a specified tag does not exist. Also make sure that the user input is normalized as we already do for `podman tag`. To prevent regressions, add a set of end-to-end and systemd tests. Last but not least, update the docs and add bash completions. Signed-off-by: Valentin Rothberg --- completions/bash/podman | 24 +++++++++++ docs/source/markdown/podman-untag.1.md | 8 ++-- libpod/define/errors.go | 3 ++ libpod/image/errors.go | 2 + libpod/image/image.go | 13 +++++- test/e2e/untag_test.go | 76 ++++++++++++++++++++++------------ test/system/020-tag.bats | 35 ++++++++++++++++ 7 files changed, 127 insertions(+), 34 deletions(-) create mode 100644 test/system/020-tag.bats (limited to 'test') diff --git a/completions/bash/podman b/completions/bash/podman index 053dd7047..abcf54416 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -1572,6 +1572,11 @@ _podman_image_tag() { _podman_tag } + +_podman_image_untag() { + _podman_untag +} + _podman_image() { local boolean_options=" --help @@ -1593,6 +1598,7 @@ _podman_image() { sign tag trust + untag " local aliases=" list @@ -2459,6 +2465,23 @@ _podman_tag() { esac } +_podman_untag() { + local options_with_args=" + " + local boolean_options=" + --help + -h + " + case "$cur" in + -*) + COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur")) + ;; + *) + __podman_complete_images + ;; + esac +} + __podman_top_descriptors() { podman top --list-descriptors } @@ -3587,6 +3610,7 @@ _podman_podman() { umount unmount unpause + untag varlink version volume diff --git a/docs/source/markdown/podman-untag.1.md b/docs/source/markdown/podman-untag.1.md index 3a54283d6..c83a0544c 100644 --- a/docs/source/markdown/podman-untag.1.md +++ b/docs/source/markdown/podman-untag.1.md @@ -4,14 +4,12 @@ podman\-untag - Removes one or more names from a locally-stored image ## SYNOPSIS -**podman untag** *image*[:*tag*] [*target-names*[:*tag*]] [*options*] +**podman untag** [*options*] *image* [*name*[:*tag*]...] -**podman image untag** *image*[:*tag*] [target-names[:*tag*]] [*options*] +**podman image untag** [*options*] *image* [*name*[:*tag*]...] ## DESCRIPTION -Removes one or all names of an image. A name refers to the entire image name, -including the optional *tag* after the `:`. If no target image names are -specified, `untag` will remove all tags for the image at once. +Remove one or more names from an image in the local storage. The image can be referred to by ID or reference. If a no name is specified, all names are removed the image. If a specified name is a short name and does not include a registry `localhost/` will be prefixed (e.g., `fedora` -> `localhost/fedora`). If a specified name does not include a tag `:latest` will be appended (e.g., `localhost/fedora` -> `localhost/fedora:latest`). ## OPTIONS diff --git a/libpod/define/errors.go b/libpod/define/errors.go index e0c9811fe..98dc603d1 100644 --- a/libpod/define/errors.go +++ b/libpod/define/errors.go @@ -17,6 +17,9 @@ var ( // ErrNoSuchImage indicates the requested image does not exist ErrNoSuchImage = image.ErrNoSuchImage + // ErrNoSuchTag indicates the requested image tag does not exist + ErrNoSuchTag = image.ErrNoSuchTag + // ErrNoSuchVolume indicates the requested volume does not exist ErrNoSuchVolume = errors.New("no such volume") diff --git a/libpod/image/errors.go b/libpod/image/errors.go index 4088946cb..ddbf7be4b 100644 --- a/libpod/image/errors.go +++ b/libpod/image/errors.go @@ -12,4 +12,6 @@ var ( ErrNoSuchPod = errors.New("no such pod") // ErrNoSuchImage indicates the requested image does not exist ErrNoSuchImage = errors.New("no such image") + // ErrNoSuchTag indicates the requested image tag does not exist + ErrNoSuchTag = errors.New("no such tag") ) diff --git a/libpod/image/image.go b/libpod/image/image.go index d81f7e911..83e7467e9 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -559,15 +559,24 @@ func (i *Image) TagImage(tag string) error { return nil } -// UntagImage removes a tag from the given image +// UntagImage removes the specified tag from the image. +// If the tag does not exist, ErrNoSuchTag is returned. func (i *Image) UntagImage(tag string) error { if err := i.reloadImage(); err != nil { return err } + + // Normalize the tag as we do with TagImage. + ref, err := NormalizedTag(tag) + if err != nil { + return err + } + tag = ref.String() + var newTags []string tags := i.Names() if !util.StringInSlice(tag, tags) { - return nil + return errors.Wrapf(ErrNoSuchTag, "%q", tag) } for _, t := range tags { if tag != t { diff --git a/test/e2e/untag_test.go b/test/e2e/untag_test.go index dc1a6208e..8a1c8091d 100644 --- a/test/e2e/untag_test.go +++ b/test/e2e/untag_test.go @@ -23,13 +23,6 @@ var _ = Describe("Podman untag", func() { podmanTest = PodmanTestCreate(tempdir) podmanTest.Setup() podmanTest.RestoreAllArtifacts() - - for _, tag := range []string{"test", "foo", "bar"} { - session := podmanTest.PodmanNoCache([]string{"tag", ALPINE, tag}) - session.WaitWithDefaultTimeout() - Expect(session.ExitCode()).To(Equal(0)) - } - }) AfterEach(func() { @@ -40,34 +33,63 @@ var _ = Describe("Podman untag", func() { }) It("podman untag all", func() { - session := podmanTest.PodmanNoCache([]string{"untag", ALPINE}) + tags := []string{ALPINE, "registry.com/foo:bar", "localhost/foo:bar"} + + cmd := []string{"tag"} + cmd = append(cmd, tags...) + session := podmanTest.PodmanNoCache(cmd) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - results := podmanTest.PodmanNoCache([]string{"images", ALPINE}) - results.WaitWithDefaultTimeout() - Expect(results.ExitCode()).To(Equal(0)) - Expect(results.OutputToStringArray()).To(HaveLen(1)) - }) + // Make sure that all tags exists. + for _, t := range tags { + session = podmanTest.PodmanNoCache([]string{"image", "exists", t}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + } - It("podman untag single", func() { - session := podmanTest.PodmanNoCache([]string{"untag", ALPINE, "localhost/test:latest"}) + // No arguments -> remove all tags. + session = podmanTest.PodmanNoCache([]string{"untag", ALPINE}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - results := podmanTest.PodmanNoCache([]string{"images"}) - results.WaitWithDefaultTimeout() - Expect(results.ExitCode()).To(Equal(0)) - Expect(results.OutputToStringArray()).To(HaveLen(6)) - Expect(results.LineInOuputStartsWith("docker.io/library/alpine")).To(BeTrue()) - Expect(results.LineInOuputStartsWith("localhost/foo")).To(BeTrue()) - Expect(results.LineInOuputStartsWith("localhost/bar")).To(BeTrue()) - Expect(results.LineInOuputStartsWith("localhost/test")).To(BeFalse()) + // Make sure that none of tags exists anymore. + for _, t := range tags { + session = podmanTest.PodmanNoCache([]string{"image", "exists", t}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(1)) + } }) - It("podman untag not enough arguments", func() { - session := podmanTest.PodmanNoCache([]string{"untag"}) - session.WaitWithDefaultTimeout() - Expect(session.ExitCode()).NotTo(Equal(0)) + It("podman tag/untag - tag normalization", func() { + tests := []struct { + tag, normalized string + }{ + {"registry.com/image:latest", "registry.com/image:latest"}, + {"registry.com/image", "registry.com/image:latest"}, + {"image:latest", "localhost/image:latest"}, + {"image", "localhost/image:latest"}, + } + + // Make sure that the user input is normalized correctly for + // `podman tag` and `podman untag`. + for _, tt := range tests { + session := podmanTest.PodmanNoCache([]string{"tag", ALPINE, tt.tag}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.PodmanNoCache([]string{"image", "exists", tt.normalized}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.PodmanNoCache([]string{"untag", ALPINE, tt.tag}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.PodmanNoCache([]string{"image", "exists", tt.normalized}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(1)) + } }) + }) diff --git a/test/system/020-tag.bats b/test/system/020-tag.bats new file mode 100644 index 000000000..7593ad68f --- /dev/null +++ b/test/system/020-tag.bats @@ -0,0 +1,35 @@ +#!/usr/bin/env bats + +load helpers + +# helper function for "podman tag/untag" test +function _tag_and_check() { + local tag_as="$1" + local check_as="$2" + + run_podman tag $IMAGE $tag_as + run_podman image exists $check_as + run_podman untag $IMAGE $check_as + run_podman 1 image exists $check_as +} + +@test "podman tag/untag" { + # Test a fully-qualified image reference. + _tag_and_check registry.com/image:latest registry.com/image:latest + + # Test a reference without tag and make sure ":latest" is appended. + _tag_and_check registry.com/image registry.com/image:latest + + # Test a tagged short image and make sure "localhost/" is prepended. + _tag_and_check image:latest localhost/image:latest + + # Test a short image without tag and make sure "localhost/" is + # prepended and ":latest" is appended. + _tag_and_check image localhost/image:latest + + # Test error case. + run_podman 125 untag $IMAGE registry.com/foo:bar + is "$output" "Error: \"registry.com/foo:bar\": no such tag" +} + +# vim: filetype=sh -- cgit v1.2.3-54-g00ecf From eb9fd40d21ba2ce28ef1fdf411d6fb838dee9b4b Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 23 Jun 2020 13:33:42 -0400 Subject: Set stop signal to 15 when not explicitly set When going through the output of `podman inspect` to try and identify another issue, I noticed that Podman 2.0 was setting StopSignal to 0 on containers by default. After chasing it through the command line and SpecGen, I determined that we were actually not setting a default in Libpod, which is strange because I swear we used to do that. I re-added the disappeared default and now all is well again. Also, while I was looking for the bug in SpecGen, I found a bunch of TODOs that have already been done. Eliminate the comments for these. Signed-off-by: Matthew Heon --- cmd/podman/common/specgen.go | 18 ------------------ libpod/runtime_ctr.go | 4 ++-- test/e2e/create_test.go | 13 +++++++++++++ 3 files changed, 15 insertions(+), 20 deletions(-) (limited to 'test') diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index e6a524358..26d18faf0 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -535,7 +535,6 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.SeccompPolicy = c.SeccompPolicy - // TODO: should parse out options s.VolumesFrom = c.VolumesFrom // Only add read-only tmpfs mounts in case that we are read-only and the @@ -547,22 +546,10 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.Mounts = mounts s.Volumes = volumes - // TODO any idea why this was done - // devices := rtc.Containers.Devices - // TODO conflict on populate? - // - // if c.Changed("device") { - // devices = append(devices, c.StringSlice("device")...) - // } - for _, dev := range c.Devices { s.Devices = append(s.Devices, specs.LinuxDevice{Path: dev}) } - // TODO things i cannot find in spec - // we dont think these are in the spec - // init - initbinary - // initpath s.Init = c.Init s.InitPath = c.InitPath s.Stdin = c.Interactive @@ -587,11 +574,6 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.Rlimits = append(s.Rlimits, rl) } - // Tmpfs: c.StringArray("tmpfs"), - - // TODO how to handle this? - // Syslog: c.Bool("syslog"), - logOpts := make(map[string]string) for _, o := range c.LogOptions { split := strings.SplitN(o, "=", 2) diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 0431861b5..f1752cbeb 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -83,6 +83,8 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf return nil, errors.Wrapf(err, "converting containers.conf ShmSize %s to an int", r.config.Containers.ShmSize) } ctr.config.ShmSize = size + ctr.config.StopSignal = 15 + ctr.config.StopTimeout = r.config.Engine.StopTimeout } else { // This is a restore from an imported checkpoint ctr.restoreFromCheckpoint = true @@ -107,8 +109,6 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf ctr.state.BindMounts = make(map[string]string) - ctr.config.StopTimeout = r.config.Engine.StopTimeout - ctr.config.OCIRuntime = r.defaultOCIRuntime.Name() // Set namespace based on current runtime namespace diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go index 52ce0b46a..44bb5c45f 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -458,4 +458,17 @@ var _ = Describe("Podman create", func() { Expect(session.ExitCode()).To(Equal(0)) } }) + + It("podman create sets default stop signal 15", func() { + ctrName := "testCtr" + session := podmanTest.Podman([]string{"create", "--name", ctrName, ALPINE, "/bin/sh"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + inspect := podmanTest.Podman([]string{"inspect", ctrName}) + inspect.WaitWithDefaultTimeout() + data := inspect.InspectContainerToJSON() + Expect(len(data)).To(Equal(1)) + Expect(data[0].Config.StopSignal).To(Equal(uint(15))) + }) }) -- cgit v1.2.3-54-g00ecf