diff options
Diffstat (limited to 'test')
45 files changed, 1047 insertions, 349 deletions
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at index 36c2fc6aa..673858a3c 100644 --- a/test/apiv2/10-images.at +++ b/test/apiv2/10-images.at @@ -197,6 +197,14 @@ t POST "build?dockerfile=containerfile" $CONTAINERFILE_TAR 200 \ t POST libpod/images/prune 200 t POST libpod/images/prune 200 length=0 [] +# compat api must allow loading tar which contain multiple images +podman pull quay.io/libpod/alpine:latest quay.io/libpod/busybox:latest +podman save -o ${TMPD}/test.tar quay.io/libpod/alpine:latest quay.io/libpod/busybox:latest +t POST "images/load" ${TMPD}/test.tar 200 \ + .stream="Loaded image: quay.io/libpod/busybox:latest,quay.io/libpod/alpine:latest" +t GET libpod/images/quay.io/libpod/alpine:latest/exists 204 +t GET libpod/images/quay.io/libpod/busybox:latest/exists 204 + cleanBuildTest # vim: filetype=sh diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index 72003984f..cc5eda88e 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -18,6 +18,14 @@ podman rm -a -f &>/dev/null t GET "libpod/containers/json (at start: clean slate)" 200 length=0 +# Regression test for #12904 (race condition in logging code) +mytext="hi-there-$(random_string 15)" +podman run --rm -d --replace --name foo $IMAGE sh -c "echo $mytext;sleep 42" +# Logs output is prepended by ^A^X +t POST "containers/foo/attach?logs=true&stream=false" 200 \ + $'\001\030'$mytext +t POST "containers/foo/kill" 204 + podman run -v /tmp:/tmp $IMAGE true t GET libpod/containers/json 200 length=0 @@ -231,11 +239,16 @@ t GET containers/$cid/json 200 \ t POST containers/create Image=$IMAGE Entrypoint='["top"]' 201 \ .Id~[0-9a-f]\\{64\\} cid_top=$(jq -r '.Id' <<<"$output") +# .Network is N/A when rootless +network_expect= +if root; then + network_expect='.NetworkSettings.Networks.podman.NetworkID=podman' +fi t GET containers/${cid_top}/json 200 \ .Config.Entrypoint[0]="top" \ .Config.Cmd='[]' \ .Path="top" \ - .NetworkSettings.Networks.podman.NetworkID=podman + $network_expect t POST containers/${cid_top}/start 204 # make sure the container is running t GET containers/${cid_top}/json 200 \ @@ -359,11 +372,15 @@ t GET containers/$cid/json 200 \ t DELETE containers/$cid?v=true 204 # Test Compat Create with default network mode (#10569) +networkmode=slirp4netns +if root; then + networkmode=bridge +fi t POST containers/create Image=$IMAGE HostConfig='{"NetworkMode":"default"}' 201 \ .Id~[0-9a-f]\\{64\\} cid=$(jq -r '.Id' <<<"$output") t GET containers/$cid/json 200 \ - .HostConfig.NetworkMode="bridge" + .HostConfig.NetworkMode="$networkmode" t DELETE containers/$cid?v=true 204 @@ -403,3 +420,29 @@ t GET containers/$cid/json 200 \ .HostConfig.Binds[0]~/tmp:/mnt:.* \ t DELETE containers/$cid?v=true 204 + +# test apiv2 create/commit +t POST containers/create \ + Image=$IMAGE \ + Entrypoint='["echo"]' \ + Cmd='["param1","param2"]' \ + 201 \ + .Id~[0-9a-f]\\{64\\} +cid=$(jq -r '.Id' <<<"$output") + +# No such container +t POST "commit?container=nonesuch" 404 + +cparam="repo=newrepo&tag=v3&comment=abcd&author=eric" +cparam="$cparam&format=docker&changes=CMD%20/bin/bar%0aEXPOSE%209090" +t POST "commit?container=${cid:0:12}&$cparam" 201 \ + .Id~[0-9a-f]\\{64\\} +iid=$(jq -r '.Id' <<<"$output") +t GET images/$iid/json 200 \ + .RepoTags[0]=docker.io/library/newrepo:v3 \ + .Config.ExposedPorts~.*"9090/tcp" \ + .Config.Cmd~.*"/bin/bar" \ + .Comment="abcd" + +t DELETE containers/$cid 204 +t DELETE images/docker.io/library/newrepo:v3?force=false 200 diff --git a/test/apiv2/python/rest_api/fixtures/podman.py b/test/apiv2/python/rest_api/fixtures/podman.py index bae04f87d..c700571b9 100644 --- a/test/apiv2/python/rest_api/fixtures/podman.py +++ b/test/apiv2/python/rest_api/fixtures/podman.py @@ -44,7 +44,7 @@ class Podman: os.environ["CNI_CONFIG_PATH"] = os.path.join(self.anchor_directory, "cni", "net.d") os.makedirs(os.environ["CNI_CONFIG_PATH"], exist_ok=True) - self.cmd.append("--cni-config-dir=" + os.environ["CNI_CONFIG_PATH"]) + self.cmd.append("--network-config-dir=" + os.environ["CNI_CONFIG_PATH"]) cni_cfg = os.path.join(os.environ["CNI_CONFIG_PATH"], "87-podman-bridge.conflist") # json decoded and encoded to ensure legal json buf = json.loads( diff --git a/test/apiv2/python/rest_api/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py index 1b4597cf8..0386116a8 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_container.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py @@ -130,7 +130,7 @@ class ContainerTestCase(APITestCase): def test_attach(self): self.skipTest("FIXME: Test timeouts") - r = requests.post(self.uri(self.resolve_container("/containers/{}/attach")), timeout=5) + r = requests.post(self.uri(self.resolve_container("/containers/{}/attach?logs=true")), timeout=5) self.assertIn(r.status_code, (101, 500), r.text) def test_logs(self): diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2 index 19e8c12d0..56280f04e 100755 --- a/test/apiv2/test-apiv2 +++ b/test/apiv2/test-apiv2 @@ -45,8 +45,14 @@ echo 0 >$failures_file # Where the tests live TESTS_DIR=$(realpath $(dirname $0)) +# As of 2021-11 podman has one external helper binary, rootlessport, needed +# for rootless networking. +if [[ -z "$CONTAINERS_HELPER_BINARY_DIR" ]]; then + export CONTAINERS_HELPER_BINARY_DIR=$(realpath ${TESTS_DIR}/../../bin) +fi + # Path to podman binary -PODMAN_BIN=${PODMAN:-${TESTS_DIR}/../../bin/podman} +PODMAN_BIN=${PODMAN:-${CONTAINERS_HELPER_BINARY_DIR}/podman} # Cleanup handlers clean_up_server() { @@ -289,7 +295,8 @@ function t() { output="[$(file --brief $WORKDIR/curl.result.out)]" echo "$output" >>$LOG elif [[ -e $WORKDIR/curl.result.out ]]; then - output=$(< $WORKDIR/curl.result.out) + # Output from /logs sometimes includes NULs. Strip them. + output=$(tr -d '\0' < $WORKDIR/curl.result.out) if [[ $content_type =~ application/json ]] && [[ $method != "HEAD" ]]; then jq . <<<"$output" >>$LOG diff --git a/test/compose/test-compose b/test/compose/test-compose index beaf276fd..7c4bf2e91 100755 --- a/test/compose/test-compose +++ b/test/compose/test-compose @@ -220,7 +220,7 @@ function start_service() { --root $WORKDIR/root \ --runroot $WORKDIR/runroot \ --cgroup-manager=systemd \ - --cni-config-dir $WORKDIR/cni \ + --network-config-dir $WORKDIR/cni \ system service \ --time 0 unix://$DOCKER_SOCK \ &> $WORKDIR/server.log & @@ -247,7 +247,7 @@ function podman() { --storage-driver=vfs \ --root $WORKDIR/root \ --runroot $WORKDIR/runroot \ - --cni-config-dir $WORKDIR/cni \ + --network-config-dir $WORKDIR/cni \ "$@") echo -n "$output" >>$WORKDIR/output.log } diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go index 5dabe728a..a1c2f5e54 100644 --- a/test/e2e/build_test.go +++ b/test/e2e/build_test.go @@ -100,7 +100,7 @@ var _ = Describe("Podman build", func() { It("podman build with logfile", func() { logfile := filepath.Join(podmanTest.TempDir, "logfile") - session := podmanTest.Podman([]string{"build", "--pull-never", "--tag", "test", "--logfile", logfile, "build/basicalpine"}) + session := podmanTest.Podman([]string{"build", "--pull=never", "--tag", "test", "--logfile", logfile, "build/basicalpine"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -123,7 +123,7 @@ var _ = Describe("Podman build", func() { // If the context directory is pointing at a file and not a directory, // that's a no no, fail out. It("podman build context directory a file", func() { - session := podmanTest.Podman([]string{"build", "--pull-never", "build/context_dir_a_file"}) + session := podmanTest.Podman([]string{"build", "--pull=never", "build/context_dir_a_file"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(125)) }) @@ -308,6 +308,30 @@ RUN exit 5`, ALPINE) Expect(data).To(ContainSubstring(buildah.Version)) }) + It("podman build and check identity with always", func() { + // with --pull=always + session := podmanTest.Podman([]string{"build", "--pull=always", "-f", "build/basicalpine/Containerfile.path", "--no-cache", "-t", "test1", "build/basicalpine"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // Verify that OS and Arch are being set + inspect := podmanTest.Podman([]string{"image", "inspect", "--format", "{{ index .Config.Labels }}", "test1"}) + inspect.WaitWithDefaultTimeout() + data := inspect.OutputToString() + Expect(data).To(ContainSubstring(buildah.Version)) + + // with --pull-always + session = podmanTest.Podman([]string{"build", "--pull-always", "-f", "build/basicalpine/Containerfile.path", "--no-cache", "-t", "test2", "build/basicalpine"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // Verify that OS and Arch are being set + inspect = podmanTest.Podman([]string{"image", "inspect", "--format", "{{ index .Config.Labels }}", "test2"}) + inspect.WaitWithDefaultTimeout() + data = inspect.OutputToString() + Expect(data).To(ContainSubstring(buildah.Version)) + }) + It("podman remote test container/docker file is not inside context dir", func() { // Given // Switch to temp dir and restore it afterwards diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 64f40d2ed..f843a8984 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -5,6 +5,7 @@ import ( "fmt" "io/ioutil" "math/rand" + "net" "os" "os/exec" "path/filepath" @@ -46,7 +47,7 @@ type PodmanTestIntegration struct { PodmanTest ConmonBinary string Root string - CNIConfigDir string + NetworkConfigDir string OCIRuntime string RunRoot string StorageOptions string @@ -199,6 +200,7 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { host := GetHostDistributionInfo() cwd, _ := os.Getwd() + root := filepath.Join(tempDir, "root") podmanBinary := filepath.Join(cwd, "../../bin/podman") if os.Getenv("PODMAN_BINARY") != "" { podmanBinary = os.Getenv("PODMAN_BINARY") @@ -235,11 +237,26 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { ociRuntime = "crun" } os.Setenv("DISABLE_HC_SYSTEMD", "true") - CNIConfigDir := "/etc/cni/net.d" + + networkBackend := CNI + networkConfigDir := "/etc/cni/net.d" if rootless.IsRootless() { - CNIConfigDir = filepath.Join(os.Getenv("HOME"), ".config/cni/net.d") + networkConfigDir = filepath.Join(os.Getenv("HOME"), ".config/cni/net.d") + } + + if strings.ToLower(os.Getenv("NETWORK_BACKEND")) == "netavark" { + networkBackend = Netavark + networkConfigDir = "/etc/containers/networks" + if rootless.IsRootless() { + networkConfigDir = filepath.Join(root, "etc", "networks") + } + } + + if err := os.MkdirAll(root, 0755); err != nil { + panic(err) } - if err := os.MkdirAll(CNIConfigDir, 0755); err != nil { + + if err := os.MkdirAll(networkConfigDir, 0755); err != nil { panic(err) } @@ -251,7 +268,6 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { storageFs = os.Getenv("STORAGE_FS") storageOptions = "--storage-driver " + storageFs } - p := &PodmanTestIntegration{ PodmanTest: PodmanTest{ PodmanBinary: podmanBinary, @@ -260,11 +276,12 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { RemoteTest: remote, ImageCacheFS: storageFs, ImageCacheDir: ImageCacheDir, + NetworkBackend: networkBackend, }, ConmonBinary: conmonBinary, - Root: filepath.Join(tempDir, "root"), + Root: root, TmpDir: tempDir, - CNIConfigDir: CNIConfigDir, + NetworkConfigDir: networkConfigDir, OCIRuntime: ociRuntime, RunRoot: filepath.Join(tempDir, "runroot"), StorageOptions: storageOptions, @@ -719,6 +736,14 @@ func SkipIfRemote(reason string) { Skip("[remote]: " + reason) } +func SkipIfNotRemote(reason string) { + checkReason(reason) + if IsRemote() { + return + } + Skip("[local]: " + reason) +} + // SkipIfInContainer skips a test if the test is run inside a container func SkipIfInContainer(reason string) { checkReason(reason) @@ -746,6 +771,18 @@ func SkipIfNotActive(unit string, reason string) { } } +func SkipIfNetavark(p *PodmanTestIntegration) { + if p.NetworkBackend == Netavark { + Skip("This test is not compatible with the netavark network backend") + } +} + +func SkipUntilAardvark(p *PodmanTestIntegration) { + if p.NetworkBackend == Netavark { + Skip("Re-enable when aardvark is functional") + } +} + // PodmanAsUser is the exec call to podman on the filesystem with the specified uid/gid and environment func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, cwd string, env []string) *PodmanSessionIntegration { podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env, false, false, nil, nil) @@ -807,7 +844,9 @@ func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache boo if p.RemoteTest { return args } - var debug string + var ( + debug string + ) if _, ok := os.LookupEnv("DEBUG"); ok { debug = "--log-level=debug --syslog=true " } @@ -817,12 +856,19 @@ func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache boo eventsType = "none" } - podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend %s", - debug, p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager, p.TmpDir, eventsType), " ") + networkBackend := p.NetworkBackend.ToString() + networkDir := p.NetworkConfigDir + if p.NetworkBackend == Netavark { + networkDir = p.NetworkConfigDir + } + podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --network-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend %s", + debug, p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, networkDir, p.CgroupManager, p.TmpDir, eventsType), " ") if os.Getenv("HOOK_OPTION") != "" { podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION")) } + podmanOptions = append(podmanOptions, "--network-backend", networkBackend) + podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...) if !noCache { cacheOptions := []string{"--storage-opt", @@ -834,6 +880,11 @@ func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache boo } func writeConf(conf []byte, confPath string) { + if _, err := os.Stat(filepath.Dir(confPath)); os.IsNotExist(err) { + if err := os.MkdirAll(filepath.Dir(confPath), 777); err != nil { + fmt.Println(err) + } + } if err := ioutil.WriteFile(confPath, conf, 777); err != nil { fmt.Println(err) } @@ -848,10 +899,15 @@ func removeConf(confPath string) { // generateNetworkConfig generates a cni config with a random name // it returns the network name and the filepath func generateNetworkConfig(p *PodmanTestIntegration) (string, string) { + var ( + path string + conf string + ) // generate a random name to prevent conflicts with other tests name := "net" + stringid.GenerateNonCryptoID() - path := filepath.Join(p.CNIConfigDir, fmt.Sprintf("%s.conflist", name)) - conf := fmt.Sprintf(`{ + if p.NetworkBackend != Netavark { + path = filepath.Join(p.NetworkConfigDir, fmt.Sprintf("%s.conflist", name)) + conf = fmt.Sprintf(`{ "cniVersion": "0.3.0", "name": "%s", "plugins": [ @@ -876,12 +932,35 @@ func generateNetworkConfig(p *PodmanTestIntegration) (string, string) { } ] }`, name) + } else { + path = filepath.Join(p.NetworkConfigDir, fmt.Sprintf("%s.json", name)) + conf = fmt.Sprintf(` +{ + "name": "%s", + "id": "e1ef2749024b88f5663ca693a9118e036d6bfc48bcfe460faf45e9614a513e5c", + "driver": "bridge", + "network_interface": "netavark1", + "created": "2022-01-05T14:15:10.975493521-06:00", + "subnets": [ + { + "subnet": "10.100.0.0/16", + "gateway": "10.100.0.1" + } + ], + "ipv6_enabled": false, + "internal": false, + "dns_enabled": true, + "ipam_options": { + "driver": "host-local" + } +} +`, name) + } writeConf([]byte(conf), path) - return name, path } -func (p *PodmanTestIntegration) removeCNINetwork(name string) { +func (p *PodmanTestIntegration) removeNetwork(name string) { session := p.Podman([]string{"network", "rm", "-f", name}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(BeNumerically("<=", 1), "Exit code must be 0 or 1") @@ -929,3 +1008,33 @@ func writeYaml(content string, fileName string) error { return nil } + +// GetPort finds an unused port on the system +func GetPort() int { + a, err := net.ResolveTCPAddr("tcp", "localhost:0") + if err != nil { + Fail(fmt.Sprintf("unable to get free port: %v", err)) + } + + l, err := net.ListenTCP("tcp", a) + if err != nil { + Fail(fmt.Sprintf("unable to get free port: %v", err)) + } + defer l.Close() + return l.Addr().(*net.TCPAddr).Port +} + +func ncz(port int) bool { + timeout := 500 * time.Millisecond + for i := 0; i < 5; i++ { + ncCmd := []string{"-z", "localhost", fmt.Sprintf("%d", port)} + fmt.Printf("Running: nc %s\n", strings.Join(ncCmd, " ")) + check := SystemExec("nc", ncCmd) + if check.ExitCode() == 0 { + return true + } + time.Sleep(timeout) + timeout++ + } + return false +} diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go index 57279ae9c..bfed01854 100644 --- a/test/e2e/containers_conf_test.go +++ b/test/e2e/containers_conf_test.go @@ -11,10 +11,11 @@ import ( . "github.com/containers/podman/v4/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gbytes" . "github.com/onsi/gomega/gexec" ) -var _ = Describe("Podman run", func() { +var _ = Describe("Verify podman containers.conf usage", func() { var ( tempdir string err error @@ -43,9 +44,9 @@ var _ = Describe("Podman run", func() { os.Unsetenv("CONTAINERS_CONF") }) - It("podman run limits test", func() { + It("limits test", func() { SkipIfRootlessCgroupsV1("Setting limits not supported on cgroupv1 for rootless users") - //containers.conf is set to "nofile=500:500" + // containers.conf is set to "nofile=500:500" session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -57,33 +58,41 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).To(ContainSubstring("2048")) }) - It("podman run with containers.conf having additional env", func() { - //containers.conf default env includes foo + It("having additional env", func() { + // containers.conf default env includes foo session := podmanTest.Podman([]string{"run", ALPINE, "printenv"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToString()).To(ContainSubstring("foo=bar")) }) - It("podman run with additional devices", func() { - //containers.conf devices includes notone + It("additional devices", func() { + // containers.conf devices includes notone session := podmanTest.Podman([]string{"run", "--device", "/dev/null:/dev/bar", ALPINE, "ls", "/dev"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(ContainSubstring("bar")) - Expect(session.OutputToString()).To(ContainSubstring("notone")) + Expect(session.OutputToString()).To( + And( + ContainSubstring("bar"), + ContainSubstring("notone"), + )) }) - It("podman run shm-size", func() { - //containers.conf default sets shm-size=201k, which ends up as 200k + It("shm-size", func() { + // containers.conf default sets shm-size=201k, which ends up as 200k session := podmanTest.Podman([]string{"run", ALPINE, "grep", "shm", "/proc/self/mounts"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToString()).To(ContainSubstring("size=200k")) + + session = podmanTest.Podman([]string{"run", "--shm-size", "1g", ALPINE, "grep", "shm", "/proc/self/mounts"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("size=1048576k")) }) - It("podman Capabilities in containers.conf", func() { - SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") + It("add capabilities", func() { + SkipIfRootlessCgroupsV1("Not supported for rootless + CGroupsV1") cap := podmanTest.Podman([]string{"run", ALPINE, "grep", "CapEff", "/proc/self/status"}) cap.WaitWithDefaultTimeout() Expect(cap).Should(Exit(0)) @@ -98,17 +107,20 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).ToNot(Equal(cap.OutputToString())) }) - It("podman Regular capabilities", func() { + It("regular capabilities", func() { setup := podmanTest.RunTopContainer("test1") setup.WaitWithDefaultTimeout() result := podmanTest.Podman([]string{"top", "test1", "capeff"}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) - Expect(result.OutputToString()).To(ContainSubstring("SYS_CHROOT")) - Expect(result.OutputToString()).To(ContainSubstring("NET_RAW")) + Expect(result.Out.Contents()).To( + And( + ContainSubstring("SYS_CHROOT"), + ContainSubstring("NET_RAW"), + )) }) - It("podman drop capabilities", func() { + It("drop capabilities", func() { os.Setenv("CONTAINERS_CONF", "config/containers-caps.conf") if IsRemote() { podmanTest.RestartRemoteService() @@ -118,8 +130,11 @@ var _ = Describe("Podman run", func() { result := podmanTest.Podman([]string{"container", "top", "test1", "capeff"}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) - Expect(result.OutputToString()).ToNot(ContainSubstring("SYS_CHROOT")) - Expect(result.OutputToString()).ToNot(ContainSubstring("NET_RAW")) + Expect(result.Out.Contents()).ToNot( + And( + ContainSubstring("SYS_CHROOT"), + ContainSubstring("NET_RAW"), + )) }) verifyNSHandling := func(nspath, option string) { @@ -128,7 +143,7 @@ var _ = Describe("Podman run", func() { if IsRemote() { podmanTest.RestartRemoteService() } - //containers.conf default ipcns to default to host + // containers.conf default ipcns to default to host session := podmanTest.Podman([]string{"run", ALPINE, "ls", "-l", nspath}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -137,7 +152,7 @@ var _ = Describe("Podman run", func() { cmd := exec.Command("ls", "-l", nspath) res, err := cmd.Output() - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) fields = strings.Split(string(res), " ") hostNS := strings.TrimSuffix(fields[len(fields)-1], "\n") Expect(hostNS).To(Equal(ctrNS)) @@ -148,23 +163,23 @@ var _ = Describe("Podman run", func() { Expect(hostNS).ToNot(Equal(ctrNS)) } - It("podman compare netns", func() { + It("netns", func() { verifyNSHandling("/proc/self/ns/net", "--network") }) - It("podman compare ipcns", func() { + It("ipcns", func() { verifyNSHandling("/proc/self/ns/ipc", "--ipc") }) - It("podman compare utsns", func() { + It("utsns", func() { verifyNSHandling("/proc/self/ns/uts", "--uts") }) - It("podman compare pidns", func() { + It("pidns", func() { verifyNSHandling("/proc/self/ns/pid", "--pid") }) - It("podman compare cgroupns", func() { + It("cgroupns", func() { verifyNSHandling("/proc/self/ns/cgroup", "--cgroupns") }) @@ -185,17 +200,17 @@ var _ = Describe("Podman run", func() { cmd := exec.Command("journalctl", "--no-pager", "-o", "json", "--output-fields=CONTAINER_TAG", fmt.Sprintf("CONTAINER_ID_FULL=%s", cid)) out, err := cmd.CombinedOutput() - Expect(err).To(BeNil()) - Expect(string(out)).To(ContainSubstring("alpine")) + Expect(err).ToNot(HaveOccurred()) + Expect(out).To(ContainSubstring("alpine")) }) - It("podman containers.conf additionalvolumes", func() { + It("add volumes", func() { conffile := filepath.Join(podmanTest.TempDir, "container.conf") tempdir, err = CreateTempDirInTempDir() - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) err := ioutil.WriteFile(conffile, []byte(fmt.Sprintf("[containers]\nvolumes=[\"%s:%s:Z\",]\n", tempdir, tempdir)), 0755) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) os.Setenv("CONTAINERS_CONF", conffile) if IsRemote() { @@ -206,8 +221,8 @@ var _ = Describe("Podman run", func() { Expect(result).Should(Exit(0)) }) - It("podman run containers.conf sysctl test", func() { - //containers.conf is set to "net.ipv4.ping_group_range=0 1000" + It("sysctl test", func() { + // containers.conf is set to "net.ipv4.ping_group_range=0 1000" session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "cat", "/proc/sys/net/ipv4/ping_group_range"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -220,47 +235,49 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).ToNot((ContainSubstring("1000"))) }) - It("podman run containers.conf search domain", func() { + It("search domain", func() { session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("search foobar.com"))) }) - It("podman run add dns server", func() { + It("add dns server", func() { session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("nameserver 1.2.3.4"))) }) - It("podman run add dns option", func() { + It("add dns option", func() { session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("options debug"))) }) - It("podman run containers.conf remove all search domain", func() { + It("remove all search domain", func() { session := podmanTest.Podman([]string{"run", "--dns-search=.", ALPINE, "cat", "/etc/resolv.conf"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToStringArray()).To(Not(ContainElement(HavePrefix("search")))) }) - It("podman run use containers.conf search domain", func() { + It("add search domain", func() { session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("search"))) - Expect(session.OutputToString()).To(ContainSubstring("foobar.com")) - - Expect(session.OutputToString()).To(ContainSubstring("1.2.3.4")) - Expect(session.OutputToString()).To(ContainSubstring("debug")) + Expect(session.Out.Contents()).To( + And( + ContainSubstring("foobar.com"), + ContainSubstring("1.2.3.4"), + ContainSubstring("debug"), + )) }) - It("podman run containers.conf timezone", func() { - //containers.conf timezone set to Pacific/Honolulu + It("add timezone", func() { + // containers.conf timezone set to Pacific/Honolulu session := podmanTest.Podman([]string{"run", "--tz", "", ALPINE, "date", "+'%H %Z'"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -273,8 +290,8 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).To(ContainSubstring("EST")) }) - It("podman run containers.conf umask", func() { - //containers.conf umask set to 0002 + It("add umask", func() { + // containers.conf umask set to 0002 if !strings.Contains(podmanTest.OCIRuntime, "crun") { Skip("Test only works on crun") } @@ -285,16 +302,14 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).To(Equal("0002")) }) - It("podman set network cmd options slirp options to allow host loopback", func() { + It("network slirp options to allow host loopback", func() { session := podmanTest.Podman([]string{"run", "--network", "slirp4netns", ALPINE, "ping", "-c1", "10.0.2.2"}) session.Wait(30) Expect(session).Should(Exit(0)) }) - It("podman-remote test localcontainers.conf versus remote containers.conf", func() { - if !IsRemote() { - Skip("this test is only for remote") - } + It("podman-remote test localcontainers.conf", func() { + SkipIfNotRemote("this test is only for remote") os.Setenv("CONTAINERS_CONF", "config/containers-remote.conf") // Configuration that comes from remote server @@ -309,34 +324,41 @@ var _ = Describe("Podman run", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("search"))) - Expect(session.OutputToString()).To(ContainSubstring("foobar.com")) - Expect(session.OutputToString()).To(ContainSubstring("1.2.3.4")) - Expect(session.OutputToString()).To(ContainSubstring("debug")) + Expect(session.Out.Contents()).To( + And( + ContainSubstring("foobar.com"), + ContainSubstring("1.2.3.4"), + ContainSubstring("debug"), + )) // sysctls session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/proc/sys/net/ipv4/ping_group_range"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(ContainSubstring("1000")) + Expect(session.Out.Contents()).To(ContainSubstring("1000")) // shm-size session = podmanTest.Podman([]string{"run", ALPINE, "grep", "shm", "/proc/self/mounts"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(ContainSubstring("size=200k")) + Expect(session.Out.Contents()).To(ContainSubstring("size=200k")) // ulimits session = podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(ContainSubstring("500")) + Expect(session.Out.Contents()).To(ContainSubstring("500")) // Configuration that comes from remote client // Timezone session = podmanTest.Podman([]string{"run", ALPINE, "date", "+'%H %Z'"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(Or(ContainSubstring("EST"), ContainSubstring("EDT"))) + Expect(session.Out.Contents()).To( + Or( + ContainSubstring("EST"), + ContainSubstring("EDT"), + )) // Umask session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "sh", "-c", "umask"}) @@ -345,48 +367,48 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).To(Equal("0022")) }) - It("podman run containers.conf annotations test", func() { - //containers.conf is set to "run.oci.keep_original_groups=1" + It("add annotations", func() { + // containers.conf is set to "run.oci.keep_original_groups=1" session := podmanTest.Podman([]string{"create", "--rm", "--name", "test", fedoraMinimal}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) inspect := podmanTest.Podman([]string{"inspect", "--format", "{{ .Config.Annotations }}", "test"}) inspect.WaitWithDefaultTimeout() - Expect(inspect.OutputToString()).To(ContainSubstring("run.oci.keep_original_groups:1")) + Expect(inspect.Out.Contents()).To(ContainSubstring("run.oci.keep_original_groups:1")) }) - It("podman run with --add-host and no-hosts=true fails", func() { + It("--add-host and no-hosts=true fails", func() { session := podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", ALPINE, "top"}) session.WaitWithDefaultTimeout() Expect(session).To(ExitWithError()) - Expect(session.ErrorToString()).To(ContainSubstring("--no-hosts and --add-host cannot be set together")) + Expect(session.Err.Contents()).To(ContainSubstring("--no-hosts and --add-host cannot be set together")) session = podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", "--no-hosts=false", ALPINE, "top"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) }) - It("podman run with no-hosts=true /etc/hosts does not include hostname", func() { + It("no-hosts=true /etc/hosts does not include hostname", func() { session := podmanTest.Podman([]string{"run", "--rm", "--name", "test", ALPINE, "cat", "/etc/hosts"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(Not(ContainSubstring("test"))) + Expect(session.Out.Contents()).ToNot(ContainSubstring("test")) session = podmanTest.Podman([]string{"run", "--rm", "--name", "test", "--no-hosts=false", ALPINE, "cat", "/etc/hosts"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(ContainSubstring("test")) + Expect(session.Out.Contents()).To(ContainSubstring("test")) }) - It("podman info seccomp profile path", func() { + It("seccomp profile path", func() { configPath := filepath.Join(podmanTest.TempDir, "containers.conf") os.Setenv("CONTAINERS_CONF", configPath) profile := filepath.Join(podmanTest.TempDir, "seccomp.json") containersConf := []byte(fmt.Sprintf("[containers]\nseccomp_profile=\"%s\"", profile)) err = ioutil.WriteFile(configPath, containersConf, os.ModePerm) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) if IsRemote() { podmanTest.RestartRemoteService() @@ -398,7 +420,7 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).To(Equal(profile)) }) - It("podman info image_copy_tmp_dir", func() { + It("add image_copy_tmp_dir", func() { session := podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -409,7 +431,7 @@ var _ = Describe("Podman run", func() { containersConf := []byte("[engine]\nimage_copy_tmp_dir=\"/foobar\"") err = ioutil.WriteFile(configPath, containersConf, os.ModePerm) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) if IsRemote() { podmanTest.RestartRemoteService() @@ -422,7 +444,7 @@ var _ = Describe("Podman run", func() { containersConf = []byte("[engine]\nimage_copy_tmp_dir=\"storage\"") err = ioutil.WriteFile(configPath, containersConf, os.ModePerm) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) if IsRemote() { podmanTest.RestartRemoteService() } @@ -430,11 +452,11 @@ var _ = Describe("Podman run", func() { session = podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.OutputToString()).To(ContainSubstring("containers/storage/tmp")) + Expect(session.Out.Contents()).To(ContainSubstring("containers/storage/tmp")) containersConf = []byte("[engine]\nimage_copy_tmp_dir=\"storage1\"") err = ioutil.WriteFile(configPath, containersConf, os.ModePerm) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) if IsRemote() { podmanTest.RestartRemoteService() } @@ -442,18 +464,20 @@ var _ = Describe("Podman run", func() { session = podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - Expect(session.ErrorToString()).To(ContainSubstring("invalid image_copy_tmp_dir")) + Expect(session.Err.Contents()).To(ContainSubstring("invalid image_copy_tmp_dir")) }) - It("podman system service --help shows (default 20)", func() { - SkipIfRemote("this test is only for local") + // FIXME not sure why this is here + It("system service --help shows (default 20)", func() { + SkipIfRemote("system service is not supported on clients") + result := podmanTest.Podman([]string{"system", "service", "--help"}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(0)) - Expect(result.OutputToString()).To(ContainSubstring("(default 1234)")) + Expect(result.Out.Contents()).To(ContainSubstring("(default 1234)")) }) - It("podman bad infra_image name in containers.conf", func() { + It("bad infra_image name", func() { infra1 := "i.do/not/exist:image" infra2 := "i.still.do/not/exist:image" errorString := "initializing source docker://" + infra1 @@ -463,7 +487,7 @@ var _ = Describe("Podman run", func() { containersConf := []byte("[engine]\ninfra_image=\"" + infra1 + "\"") err = ioutil.WriteFile(configPath, containersConf, os.ModePerm) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) if IsRemote() { podmanTest.RestartRemoteService() @@ -472,27 +496,52 @@ var _ = Describe("Podman run", func() { result := podmanTest.Podman([]string{"pod", "create", "--infra-image", infra2}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(125)) - Expect(result.ErrorToString()).To(ContainSubstring(error2String)) + Expect(result.Err.Contents()).To(ContainSubstring(error2String)) result = podmanTest.Podman([]string{"pod", "create"}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(125)) - Expect(result.ErrorToString()).To(ContainSubstring(errorString)) + Expect(result.Err.Contents()).To(ContainSubstring(errorString)) result = podmanTest.Podman([]string{"create", "--pod", "new:pod1", ALPINE}) result.WaitWithDefaultTimeout() Expect(result).Should(Exit(125)) - Expect(result.ErrorToString()).To(ContainSubstring(errorString)) + Expect(result.Err.Contents()).To(ContainSubstring(errorString)) + }) + + It("set .engine.remote=true", func() { + SkipIfRemote("only meaningful when running ABI/local") + + // Need to restore CONTAINERS_CONF or AfterEach() will fail + if path, found := os.LookupEnv("CONTAINERS_CONF"); found { + defer os.Setenv("CONTAINERS_CONF", path) + } + + configPath := filepath.Join(podmanTest.TempDir, "containers-engine-remote.conf") + os.Setenv("CONTAINERS_CONF", configPath) + defer os.Remove(configPath) + + err := ioutil.WriteFile(configPath, []byte("[engine]\nremote=true"), os.ModePerm) + Expect(err).ToNot(HaveOccurred()) + + // podmanTest.Podman() cannot be used as it was initialized remote==false + cmd := exec.Command(podmanTest.PodmanBinary, "info", "--format", "{{.Host.ServiceIsRemote}}") + session, err := Start(cmd, GinkgoWriter, GinkgoWriter) + Expect(err).ToNot(HaveOccurred()) + + description := "Should have failed as there is no running remote API service available." + Eventually(session, DefaultWaitTimeout).Should(Exit(125), description) + Expect(session.Err).Should(Say("Error: unable to connect to Podman socket")) }) It("podman containers.conf cgroups=disabled", func() { if !strings.Contains(podmanTest.OCIRuntime, "crun") { Skip("FIXME: requires crun") } - conffile := filepath.Join(podmanTest.TempDir, "container.conf") + conffile := filepath.Join(podmanTest.TempDir, "container.conf") err := ioutil.WriteFile(conffile, []byte("[containers]\ncgroups=\"disabled\"\n"), 0755) - Expect(err).To(BeNil()) + Expect(err).ToNot(HaveOccurred()) result := podmanTest.Podman([]string{"create", ALPINE, "true"}) result.WaitWithDefaultTimeout() @@ -500,7 +549,7 @@ var _ = Describe("Podman run", func() { inspect := podmanTest.Podman([]string{"inspect", "--format", "{{ .HostConfig.Cgroups }}", result.OutputToString()}) inspect.WaitWithDefaultTimeout() - Expect(inspect.OutputToString()).To(Not(Equal("disabled"))) + Expect(inspect.OutputToString()).ToNot(Equal("disabled")) os.Setenv("CONTAINERS_CONF", conffile) if IsRemote() { @@ -515,4 +564,16 @@ var _ = Describe("Podman run", func() { Expect(inspect.OutputToString()).To(Equal("disabled")) }) + It("podman containers.conf runtime", func() { + SkipIfRemote("--runtime option is not available for remote commands") + conffile := filepath.Join(podmanTest.TempDir, "container.conf") + err := ioutil.WriteFile(conffile, []byte("[engine]\nruntime=\"testruntime\"\n"), 0755) + Expect(err).ToNot(HaveOccurred()) + + os.Setenv("CONTAINERS_CONF", conffile) + result := podmanTest.Podman([]string{"--help"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(result.OutputToString()).To(ContainSubstring("Path to the OCI-compatible binary used to run containers. (default \"testruntime\")")) + }) }) diff --git a/test/e2e/create_staticip_test.go b/test/e2e/create_staticip_test.go index 5d234d717..4a1d926e0 100644 --- a/test/e2e/create_staticip_test.go +++ b/test/e2e/create_staticip_test.go @@ -106,6 +106,10 @@ var _ = Describe("Podman create with --ip flag", func() { result = podmanTest.Podman([]string{"start", "test2"}) result.WaitWithDefaultTimeout() Expect(result).To(ExitWithError()) - Expect(result.ErrorToString()).To(ContainSubstring("requested IP address " + ip + " is not available")) + if podmanTest.NetworkBackend == CNI { + Expect(result.ErrorToString()).To(ContainSubstring("requested IP address " + ip + " is not available")) + } else if podmanTest.NetworkBackend == Netavark { + Expect(result.ErrorToString()).To(ContainSubstring("requested ip address %s is already allocated", ip)) + } }) }) diff --git a/test/e2e/create_staticmac_test.go b/test/e2e/create_staticmac_test.go index c6694ff7f..5fd8e3bd6 100644 --- a/test/e2e/create_staticmac_test.go +++ b/test/e2e/create_staticmac_test.go @@ -52,7 +52,7 @@ var _ = Describe("Podman run with --mac-address flag", func() { net := "n1" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", net}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(session).Should(Exit(0)) result := podmanTest.Podman([]string{"run", "--network", net, "--mac-address", "92:d0:c6:00:29:34", ALPINE, "ip", "addr"}) diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go index addf0ded0..6a4a394ef 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -598,7 +598,7 @@ var _ = Describe("Podman create", func() { session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) session = podmanTest.Podman([]string{"create", "--pod", name, "--network", netName, ALPINE, "top"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go index 976048886..55b9a8037 100644 --- a/test/e2e/generate_systemd_test.go +++ b/test/e2e/generate_systemd_test.go @@ -159,6 +159,50 @@ var _ = Describe("Podman generate systemd", func() { Expect(session.OutputToString()).To(ContainSubstring("podman stop -t 5")) }) + It("podman generate systemd with user-defined dependencies", func() { + n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", nginx}) + n.WaitWithDefaultTimeout() + Expect(n).Should(Exit(0)) + + session := podmanTest.Podman([]string{"generate", "systemd", "--wants", "foobar.service", "nginx"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // The generated systemd unit should contain the User-defined Wants option + Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies")) + Expect(session.OutputToString()).To(ContainSubstring("Wants=foobar.service")) + + session = podmanTest.Podman([]string{"generate", "systemd", "--after", "foobar.service", "nginx"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // The generated systemd unit should contain the User-defined After option + Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies")) + Expect(session.OutputToString()).To(ContainSubstring("After=foobar.service")) + + session = podmanTest.Podman([]string{"generate", "systemd", "--requires", "foobar.service", "nginx"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // The generated systemd unit should contain the User-defined Requires option + Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies")) + Expect(session.OutputToString()).To(ContainSubstring("Requires=foobar.service")) + + session = podmanTest.Podman([]string{ + "generate", "systemd", + "--wants", "foobar.service", "--wants", "barfoo.service", + "--after", "foobar.service", "--after", "barfoo.service", + "--requires", "foobar.service", "--requires", "barfoo.service", "nginx"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // The generated systemd unit should contain the User-defined Want, After, Requires options + Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies")) + Expect(session.OutputToString()).To(ContainSubstring("Wants=foobar.service barfoo.service")) + Expect(session.OutputToString()).To(ContainSubstring("After=foobar.service barfoo.service")) + Expect(session.OutputToString()).To(ContainSubstring("Requires=foobar.service barfoo.service")) + }) + It("podman generate systemd pod --name", func() { n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"}) n.WaitWithDefaultTimeout() @@ -213,6 +257,54 @@ var _ = Describe("Podman generate systemd", func() { Expect(session.OutputToString()).To(ContainSubstring("/container-foo-1.service")) }) + It("podman generate systemd pod with user-defined dependencies", func() { + n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"}) + n.WaitWithDefaultTimeout() + Expect(n).Should(Exit(0)) + + n = podmanTest.Podman([]string{"create", "--pod", "foo", "--name", "foo-1", "alpine", "top"}) + n.WaitWithDefaultTimeout() + Expect(n).Should(Exit(0)) + + session := podmanTest.Podman([]string{"generate", "systemd", "--name", "--wants", "foobar.service", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // The generated systemd unit should contain the User-defined Wants option + Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies")) + Expect(session.OutputToString()).To(ContainSubstring("Wants=foobar.service")) + + session = podmanTest.Podman([]string{"generate", "systemd", "--name", "--after", "foobar.service", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // The generated systemd unit should contain the User-defined After option + Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies")) + Expect(session.OutputToString()).To(ContainSubstring("After=foobar.service")) + + session = podmanTest.Podman([]string{"generate", "systemd", "--name", "--requires", "foobar.service", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // The generated systemd unit should contain the User-defined Requires option + Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies")) + Expect(session.OutputToString()).To(ContainSubstring("Requires=foobar.service")) + + session = podmanTest.Podman([]string{ + "generate", "systemd", "--name", + "--wants", "foobar.service", "--wants", "barfoo.service", + "--after", "foobar.service", "--after", "barfoo.service", + "--requires", "foobar.service", "--requires", "barfoo.service", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // The generated systemd unit should contain the User-defined Want, After, Requires options + Expect(session.OutputToString()).To(ContainSubstring("# User-defined dependencies")) + Expect(session.OutputToString()).To(ContainSubstring("Wants=foobar.service barfoo.service")) + Expect(session.OutputToString()).To(ContainSubstring("After=foobar.service barfoo.service")) + Expect(session.OutputToString()).To(ContainSubstring("Requires=foobar.service barfoo.service")) + }) + It("podman generate systemd --new --name foo", func() { n := podmanTest.Podman([]string{"create", "--name", "foo", "alpine", "top"}) n.WaitWithDefaultTimeout() diff --git a/test/e2e/libpod_suite_remote_test.go b/test/e2e/libpod_suite_remote_test.go index 37381a561..b4a59c54d 100644 --- a/test/e2e/libpod_suite_remote_test.go +++ b/test/e2e/libpod_suite_remote_test.go @@ -153,8 +153,9 @@ func (p *PodmanTestIntegration) StopRemoteService() { // MakeOptions assembles all the podman main options func getRemoteOptions(p *PodmanTestIntegration, args []string) []string { - podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s", - p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager), " ") + networkDir := p.NetworkConfigDir + podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --network-config-dir %s --cgroup-manager %s", + p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, networkDir, p.CgroupManager), " ") if os.Getenv("HOOK_OPTION") != "" { podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION")) } diff --git a/test/e2e/login_logout_test.go b/test/e2e/login_logout_test.go index 3d0f44dc1..1280b3e83 100644 --- a/test/e2e/login_logout_test.go +++ b/test/e2e/login_logout_test.go @@ -11,7 +11,6 @@ import ( . "github.com/containers/podman/v4/test/utils" . "github.com/onsi/ginkgo" - "github.com/onsi/ginkgo/config" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gexec" ) @@ -24,7 +23,6 @@ var _ = Describe("Podman login and logout", func() { authPath string certPath string certDirPath string - port int server string testImg string registriesConfWithSearch []byte @@ -62,7 +60,7 @@ var _ = Describe("Podman login and logout", func() { f.WriteString(session.OutputToString()) f.Sync() - port = 4999 + config.GinkgoConfig.ParallelNode + port := GetPort() server = strings.Join([]string{"localhost", strconv.Itoa(port)}, ":") registriesConfWithSearch = []byte(fmt.Sprintf("[registries.search]\nregistries = ['%s']", server)) diff --git a/test/e2e/network_connect_disconnect_test.go b/test/e2e/network_connect_disconnect_test.go index 82b9dcd09..baef142ba 100644 --- a/test/e2e/network_connect_disconnect_test.go +++ b/test/e2e/network_connect_disconnect_test.go @@ -45,7 +45,7 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) dis := podmanTest.Podman([]string{"network", "disconnect", netName, "foobar"}) dis.WaitWithDefaultTimeout() @@ -57,12 +57,12 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) session = podmanTest.Podman([]string{"create", "--name", "test", "--network", "slirp4netns", ALPINE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) con := podmanTest.Podman([]string{"network", "disconnect", netName, "test"}) con.WaitWithDefaultTimeout() @@ -75,7 +75,7 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) ctr := podmanTest.Podman([]string{"run", "-dt", "--name", "test", "--network", netName, ALPINE, "top"}) ctr.WaitWithDefaultTimeout() @@ -111,7 +111,7 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) dis := podmanTest.Podman([]string{"network", "connect", netName, "foobar"}) dis.WaitWithDefaultTimeout() @@ -123,12 +123,12 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) session = podmanTest.Podman([]string{"create", "--name", "test", "--network", "slirp4netns", ALPINE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) con := podmanTest.Podman([]string{"network", "connect", netName, "test"}) con.WaitWithDefaultTimeout() @@ -141,7 +141,7 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) ctr := podmanTest.Podman([]string{"create", "--name", "test", "--network", netName, ALPINE, "top"}) ctr.WaitWithDefaultTimeout() @@ -164,7 +164,7 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) ctr := podmanTest.Podman([]string{"run", "-dt", "--name", "test", "--network", netName, ALPINE, "top"}) ctr.WaitWithDefaultTimeout() @@ -180,7 +180,7 @@ var _ = Describe("Podman network connect and disconnect", func() { session = podmanTest.Podman([]string{"network", "create", newNetName, "--subnet", "10.11.100.0/24"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(newNetName) + defer podmanTest.removeNetwork(newNetName) ip := "10.11.100.99" mac := "44:11:44:11:44:11" @@ -218,13 +218,13 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName1}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName1) + defer podmanTest.removeNetwork(netName1) netName2 := "connect2" + stringid.GenerateNonCryptoID() session = podmanTest.Podman([]string{"network", "create", netName2}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName2) + defer podmanTest.removeNetwork(netName2) ctr := podmanTest.Podman([]string{"create", "--name", "test", "--network", netName1, ALPINE, "top"}) ctr.WaitWithDefaultTimeout() @@ -257,7 +257,7 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) session = podmanTest.Podman([]string{"network", "ls", "--format", "{{.ID}}", "--filter", "name=" + netName}) session.WaitWithDefaultTimeout() @@ -277,7 +277,7 @@ var _ = Describe("Podman network connect and disconnect", func() { session = podmanTest.Podman([]string{"network", "create", newNetName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(newNetName) + defer podmanTest.removeNetwork(newNetName) session = podmanTest.Podman([]string{"network", "ls", "--format", "{{.ID}}", "--filter", "name=" + newNetName}) session.WaitWithDefaultTimeout() @@ -304,13 +304,13 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName1}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName1) + defer podmanTest.removeNetwork(netName1) netName2 := "aliasTest" + stringid.GenerateNonCryptoID() session2 := podmanTest.Podman([]string{"network", "create", netName2}) session2.WaitWithDefaultTimeout() Expect(session2).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName2) + defer podmanTest.removeNetwork(netName2) ctr := podmanTest.Podman([]string{"create", "--name", "test", "--network", netName1 + "," + netName2, ALPINE, "top"}) ctr.WaitWithDefaultTimeout() @@ -349,7 +349,7 @@ var _ = Describe("Podman network connect and disconnect", func() { session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) session = podmanTest.Podman([]string{"network", "ls", "--format", "{{.ID}}", "--filter", "name=" + netName}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go index ade78a308..7589adaab 100644 --- a/test/e2e/network_create_test.go +++ b/test/e2e/network_create_test.go @@ -45,7 +45,7 @@ var _ = Describe("Podman network create", func() { netName := "subnet-" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ip-range", "10.11.12.0/26", netName}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) Expect(nc).Should(Exit(0)) // Inspect the network configuration @@ -88,7 +88,7 @@ var _ = Describe("Podman network create", func() { netName := "ipv6-" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", netName}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) Expect(nc).Should(Exit(0)) // Inspect the network configuration @@ -127,7 +127,7 @@ var _ = Describe("Podman network create", func() { netName := "dual-" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:3:2::/64", "--ipv6", netName}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) Expect(nc).Should(Exit(0)) // Inspect the network configuration @@ -160,7 +160,7 @@ var _ = Describe("Podman network create", func() { netName2 := "dual-" + stringid.GenerateNonCryptoID() nc = podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:10:3:2::/64", "--ipv6", netName2}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName2) + defer podmanTest.removeNetwork(netName2) Expect(nc).Should(Exit(0)) // Inspect the network configuration @@ -215,7 +215,7 @@ var _ = Describe("Podman network create", func() { nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ipv6", name}) nc.WaitWithDefaultTimeout() Expect(nc).To(Exit(0)) - defer podmanTest.removeCNINetwork(name) + defer podmanTest.removeNetwork(name) nc = podmanTest.Podman([]string{"network", "inspect", name}) nc.WaitWithDefaultTimeout() @@ -229,7 +229,7 @@ var _ = Describe("Podman network create", func() { nc := podmanTest.Podman([]string{"network", "create", "--ipv6", name}) nc.WaitWithDefaultTimeout() Expect(nc).To(Exit(0)) - defer podmanTest.removeCNINetwork(name) + defer podmanTest.removeNetwork(name) nc = podmanTest.Podman([]string{"network", "inspect", name}) nc.WaitWithDefaultTimeout() @@ -254,7 +254,7 @@ var _ = Describe("Podman network create", func() { netName := "same-" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", netName}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) Expect(nc).Should(Exit(0)) ncFail := podmanTest.Podman([]string{"network", "create", netName}) @@ -266,13 +266,13 @@ var _ = Describe("Podman network create", func() { netName1 := "sub1-" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", netName1}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName1) + defer podmanTest.removeNetwork(netName1) Expect(nc).Should(Exit(0)) netName2 := "sub2-" + stringid.GenerateNonCryptoID() ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", netName2}) ncFail.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName2) + defer podmanTest.removeNetwork(netName2) Expect(ncFail).To(ExitWithError()) }) @@ -280,13 +280,13 @@ var _ = Describe("Podman network create", func() { netName1 := "subipv61-" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", netName1}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName1) + defer podmanTest.removeNetwork(netName1) Expect(nc).Should(Exit(0)) netName2 := "subipv62-" + stringid.GenerateNonCryptoID() ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", netName2}) ncFail.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName2) + defer podmanTest.removeNetwork(netName2) Expect(ncFail).To(ExitWithError()) }) @@ -300,7 +300,7 @@ var _ = Describe("Podman network create", func() { net := "mtu-test" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "--opt", "mtu=9000", net}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(nc).Should(Exit(0)) nc = podmanTest.Podman([]string{"network", "inspect", net}) @@ -313,7 +313,7 @@ var _ = Describe("Podman network create", func() { net := "vlan-test" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "--opt", "vlan=9", net}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(nc).Should(Exit(0)) nc = podmanTest.Podman([]string{"network", "inspect", net}) @@ -326,15 +326,16 @@ var _ = Describe("Podman network create", func() { net := "invalid-test" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "--opt", "foo=bar", net}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(nc).To(ExitWithError()) }) It("podman network create with internal should not have dnsname", func() { + SkipUntilAardvark(podmanTest) net := "internal-test" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "--internal", net}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(nc).Should(Exit(0)) // Not performing this check on remote tests because it is a logrus error which does // not come back via stderr on the remote client. @@ -356,4 +357,82 @@ var _ = Describe("Podman network create", func() { } }) + It("podman network create with multiple subnets", func() { + name := "subnets-" + stringid.GenerateNonCryptoID() + subnet1 := "10.10.0.0/24" + subnet2 := "10.10.1.0/24" + nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--subnet", subnet2, name}) + nc.WaitWithDefaultTimeout() + defer podmanTest.removeNetwork(name) + Expect(nc).To(Exit(0)) + Expect(nc.OutputToString()).To(Equal(name)) + + inspect := podmanTest.Podman([]string{"network", "inspect", name}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).To(Exit(0)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet1)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet2)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"ipv6_enabled": false`)) + }) + + It("podman network create with multiple subnets dual stack", func() { + name := "subnets-" + stringid.GenerateNonCryptoID() + subnet1 := "10.10.2.0/24" + subnet2 := "fd52:2a5a:747e:3acd::/64" + nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--subnet", subnet2, name}) + nc.WaitWithDefaultTimeout() + defer podmanTest.removeNetwork(name) + Expect(nc).To(Exit(0)) + Expect(nc.OutputToString()).To(Equal(name)) + + inspect := podmanTest.Podman([]string{"network", "inspect", name}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).To(Exit(0)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet1)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet2)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"ipv6_enabled": true`)) + }) + + It("podman network create with multiple subnets dual stack with gateway and range", func() { + name := "subnets-" + stringid.GenerateNonCryptoID() + subnet1 := "10.10.3.0/24" + gw1 := "10.10.3.10" + range1 := "10.10.3.0/26" + subnet2 := "fd52:2a5a:747e:3acd::/64" + gw2 := "fd52:2a5a:747e:3acd::10" + nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--gateway", gw1, "--ip-range", range1, "--subnet", subnet2, "--gateway", gw2, name}) + nc.WaitWithDefaultTimeout() + defer podmanTest.removeNetwork(name) + Expect(nc).To(Exit(0)) + Expect(nc.OutputToString()).To(Equal(name)) + + inspect := podmanTest.Podman([]string{"network", "inspect", name}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).To(Exit(0)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet1)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"gateway": "` + gw1)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"start_ip": "10.10.3.1",`)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"end_ip": "10.10.3.63"`)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet2)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"gateway": "` + gw2)) + Expect(inspect.OutputToString()).To(ContainSubstring(`"ipv6_enabled": true`)) + }) + + It("podman network create invalid options with multiple subnets", func() { + name := "subnets-" + stringid.GenerateNonCryptoID() + subnet1 := "10.10.3.0/24" + gw1 := "10.10.3.10" + gw2 := "fd52:2a5a:747e:3acd::10" + nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--gateway", gw1, "--gateway", gw2, name}) + nc.WaitWithDefaultTimeout() + Expect(nc).To(Exit(125)) + Expect(nc.ErrorToString()).To(Equal("Error: cannot set more gateways than subnets")) + + range1 := "10.10.3.0/26" + range2 := "10.10.3.0/28" + nc = podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--ip-range", range1, "--ip-range", range2, name}) + nc.WaitWithDefaultTimeout() + Expect(nc).To(Exit(125)) + Expect(nc.ErrorToString()).To(Equal("Error: cannot set more ranges than subnets")) + }) }) diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go index 877ad37b8..bd30a1f5d 100644 --- a/test/e2e/network_test.go +++ b/test/e2e/network_test.go @@ -38,6 +38,26 @@ var _ = Describe("Podman network", func() { }) + It("podman --cni-config-dir backwards compat", func() { + SkipIfRemote("--cni-config-dir only works locally") + netDir, err := CreateTempDirInTempDir() + Expect(err).ToNot(HaveOccurred()) + defer os.RemoveAll(netDir) + session := podmanTest.Podman([]string{"--cni-config-dir", netDir, "network", "ls", "--noheading"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + // default network always exists + Expect(session.OutputToStringArray()).To(HaveLen(1)) + + // check that the only file in the directory is the network lockfile + dir, err := os.Open(netDir) + Expect(err).ToNot(HaveOccurred()) + names, err := dir.Readdirnames(5) + Expect(err).ToNot(HaveOccurred()) + Expect(names).To(HaveLen(1)) + Expect(names[0]).To(Or(Equal("netavark.lock"), Equal("cni.lock"))) + }) + It("podman network list", func() { name, path := generateNetworkConfig(podmanTest) defer removeConf(path) @@ -98,13 +118,13 @@ var _ = Describe("Podman network", func() { label2 := "abcdef" session := podmanTest.Podman([]string{"network", "create", "--label", label1, net1}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net1) + defer podmanTest.removeNetwork(net1) Expect(session).Should(Exit(0)) net2 := "labelnet" + stringid.GenerateNonCryptoID() session = podmanTest.Podman([]string{"network", "create", "--label", label1, "--label", label2, net2}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net2) + defer podmanTest.removeNetwork(net2) Expect(session).Should(Exit(0)) session = podmanTest.Podman([]string{"network", "ls", "--filter", "label=" + label1}) @@ -124,7 +144,7 @@ var _ = Describe("Podman network", func() { net := "net" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", net}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(session).Should(Exit(0)) session = podmanTest.Podman([]string{"network", "ls", "--filter", "namr=ab"}) @@ -149,9 +169,16 @@ var _ = Describe("Podman network", func() { netID := "6073aefe03cdf8f29be5b23ea9795c431868a3a22066a6290b187691614fee84" session := podmanTest.Podman([]string{"network", "create", net}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(session).Should(Exit(0)) + if podmanTest.NetworkBackend == Netavark { + // netavark uses a different algo for determining the id and it is not repeatable + getid := podmanTest.Podman([]string{"network", "inspect", net, "--format", "{{.ID}}"}) + getid.WaitWithDefaultTimeout() + Expect(getid).Should(Exit(0)) + netID = getid.OutputToString() + } // Tests Default Table Output session = podmanTest.Podman([]string{"network", "ls", "--filter", "id=" + netID}) session.WaitWithDefaultTimeout() @@ -250,7 +277,7 @@ var _ = Describe("Podman network", func() { netName := "net-" + stringid.GenerateNonCryptoID() network := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.50.0/24", netName}) network.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) Expect(network).Should(Exit(0)) ctrName := "testCtr" @@ -280,13 +307,13 @@ var _ = Describe("Podman network", func() { netName1 := "net1-" + stringid.GenerateNonCryptoID() network1 := podmanTest.Podman([]string{"network", "create", netName1}) network1.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName1) + defer podmanTest.removeNetwork(netName1) Expect(network1).Should(Exit(0)) netName2 := "net2-" + stringid.GenerateNonCryptoID() network2 := podmanTest.Podman([]string{"network", "create", netName2}) network2.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName2) + defer podmanTest.removeNetwork(netName2) Expect(network2).Should(Exit(0)) ctrName := "testCtr" @@ -317,13 +344,13 @@ var _ = Describe("Podman network", func() { netName1 := "net1-" + stringid.GenerateNonCryptoID() network1 := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.51.0/25", netName1}) network1.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName1) + defer podmanTest.removeNetwork(netName1) Expect(network1).Should(Exit(0)) netName2 := "net2-" + stringid.GenerateNonCryptoID() network2 := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.51.128/26", netName2}) network2.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName2) + defer podmanTest.removeNetwork(netName2) Expect(network2).Should(Exit(0)) ctrName := "testCtr" @@ -360,7 +387,7 @@ var _ = Describe("Podman network", func() { session := podmanTest.Podman([]string{"network", "create", network}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(network) + defer podmanTest.removeNetwork(network) Expect(session).Should(Exit(0)) session = podmanTest.Podman([]string{"run", "--name", container, "--network", network, "-d", ALPINE, "top"}) @@ -386,7 +413,7 @@ var _ = Describe("Podman network", func() { netName := "net-" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) Expect(session).Should(Exit(0)) session = podmanTest.Podman([]string{"pod", "create", "--network", netName}) @@ -422,13 +449,13 @@ var _ = Describe("Podman network", func() { netName1 := "net1-" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", netName1}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName1) + defer podmanTest.removeNetwork(netName1) Expect(session).Should(Exit(0)) netName2 := "net2-" + stringid.GenerateNonCryptoID() session = podmanTest.Podman([]string{"network", "create", netName2}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName2) + defer podmanTest.removeNetwork(netName2) Expect(session).Should(Exit(0)) session = podmanTest.Podman([]string{"network", "rm", netName1, netName2}) @@ -440,11 +467,12 @@ var _ = Describe("Podman network", func() { }) It("podman network with multiple aliases", func() { + SkipUntilAardvark(podmanTest) var worked bool netName := "aliasTest" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) Expect(session).Should(Exit(0)) interval := time.Duration(250 * time.Millisecond) @@ -490,10 +518,12 @@ var _ = Describe("Podman network", func() { }) It("podman network create/remove macvlan", func() { + // Netavark currently does not do dhcp so the this test fails + SkipIfNetavark(podmanTest) net := "macvlan" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "--macvlan", "lo", net}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(nc).Should(Exit(0)) nc = podmanTest.Podman([]string{"network", "rm", net}) @@ -502,10 +532,12 @@ var _ = Describe("Podman network", func() { }) It("podman network create/remove macvlan as driver (-d) no device name", func() { + // Netavark currently does not do dhcp so the this test fails + SkipIfNetavark(podmanTest) net := "macvlan" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "-d", "macvlan", net}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(nc).Should(Exit(0)) inspect := podmanTest.Podman([]string{"network", "inspect", net}) @@ -527,10 +559,12 @@ var _ = Describe("Podman network", func() { }) It("podman network create/remove macvlan as driver (-d) with device name", func() { + // Netavark currently does not do dhcp so the this test fails + SkipIfNetavark(podmanTest) net := "macvlan" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "-d", "macvlan", "-o", "parent=lo", net}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(nc).Should(Exit(0)) inspect := podmanTest.Podman([]string{"network", "inspect", net}) @@ -557,7 +591,7 @@ var _ = Describe("Podman network", func() { net := "net" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", net}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(session).Should(Exit(0)) session = podmanTest.Podman([]string{"network", "exists", net}) @@ -573,7 +607,7 @@ var _ = Describe("Podman network", func() { net := "macvlan" + stringid.GenerateNonCryptoID() nc := podmanTest.Podman([]string{"network", "create", "-d", "macvlan", "-o", "parent=lo", "-o", "mtu=1500", "--gateway", "192.168.1.254", "--subnet", "192.168.1.0/24", net}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(nc).Should(Exit(0)) inspect := podmanTest.Podman([]string{"network", "inspect", net}) @@ -602,7 +636,7 @@ var _ = Describe("Podman network", func() { It("podman network prune --filter", func() { // set custom cni directory to prevent flakes - podmanTest.CNIConfigDir = tempdir + podmanTest.NetworkConfigDir = tempdir if IsRemote() { podmanTest.RestartRemoteService() } @@ -610,7 +644,7 @@ var _ = Describe("Podman network", func() { nc := podmanTest.Podman([]string{"network", "create", net1}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net1) + defer podmanTest.removeNetwork(net1) Expect(nc).Should(Exit(0)) list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"}) @@ -650,7 +684,7 @@ var _ = Describe("Podman network", func() { It("podman network prune", func() { // set custom cni directory to prevent flakes - podmanTest.CNIConfigDir = tempdir + podmanTest.NetworkConfigDir = tempdir if IsRemote() { podmanTest.RestartRemoteService() } @@ -664,12 +698,12 @@ var _ = Describe("Podman network", func() { net2 := net + "2" nc := podmanTest.Podman([]string{"network", "create", net1}) nc.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net1) + defer podmanTest.removeNetwork(net1) Expect(nc).Should(Exit(0)) nc2 := podmanTest.Podman([]string{"network", "create", net2}) nc2.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net2) + defer podmanTest.removeNetwork(net2) Expect(nc2).Should(Exit(0)) list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"}) diff --git a/test/e2e/play_build_test.go b/test/e2e/play_build_test.go index bbebf7949..70e042b4d 100644 --- a/test/e2e/play_build_test.go +++ b/test/e2e/play_build_test.go @@ -173,7 +173,7 @@ LABEL marge=mom err = writeYaml(testYAML, filepath.Join(yamlDir, "top.yaml")) Expect(err).To(BeNil()) - // build an image called foobar but make sure it doesnt have + // build an image called foobar but make sure it doesn't have // the same label as the yaml buildfile, so we can check that // the image is NOT rebuilt. err = writeYaml(prebuiltImage, filepath.Join(yamlDir, "Containerfile")) @@ -220,7 +220,7 @@ LABEL marge=mom err = writeYaml(testYAML, filepath.Join(yamlDir, "top.yaml")) Expect(err).To(BeNil()) - // build an image called foobar but make sure it doesnt have + // build an image called foobar but make sure it doesn't have // the same label as the yaml buildfile, so we can check that // the image is NOT rebuilt. err = writeYaml(prebuiltImage, filepath.Join(yamlDir, "Containerfile")) diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index 63c9bf7f3..c0c71652e 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -78,6 +78,25 @@ spec: - 24h status: {} ` + +var podWithoutConfigMapDefined = ` +apiVersion: v1 +kind: Pod +metadata: + name: testpod1 +spec: + containers: + - name: alpine + image: quay.io/libpod/alpine:latest + volumeMounts: + - name: mycm + mountPath: /mycm + volumes: + - name: mycm + configMap: + name: mycm +` + var sharedNamespacePodYaml = ` apiVersion: v1 kind: Pod @@ -1235,6 +1254,16 @@ var _ = Describe("Podman play kube", func() { } }) + It("podman play kube with non-existing configmap", func() { + err := writeYaml(podWithoutConfigMapDefined, kubeYaml) + Expect(err).To(BeNil()) + + kube := podmanTest.Podman([]string{"play", "kube", kubeYaml}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(125)) + Expect(kube.ErrorToString()).To(ContainSubstring("failed to create volume \"mycm\": no such ConfigMap \"mycm\"")) + }) + It("podman play kube test HostAliases with --no-hosts", func() { pod := getPod(withHostAliases("192.168.1.2", []string{ "test1.podman.io", @@ -2161,7 +2190,7 @@ spec: net := "playkube" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.31.0/24", net}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(session).Should(Exit(0)) ips := []string{"10.25.31.5", "10.25.31.10", "10.25.31.15"} @@ -2205,12 +2234,12 @@ spec: net := podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.11.0/24", net1}) net.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net1) + defer podmanTest.removeNetwork(net1) Expect(net).Should(Exit(0)) net = podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.12.0/24", net2}) net.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net2) + defer podmanTest.removeNetwork(net2) Expect(net).Should(Exit(0)) ip1 := "10.0.11.5" @@ -2955,7 +2984,7 @@ invalid kube kind inspect = podmanTest.Podman([]string{"inspect", podName + "-" + ctr02Name, "--format", "'{{.Config.Labels}}'"}) inspect.WaitWithDefaultTimeout() Expect(inspect).Should(Exit(0)) - Expect(inspect.OutputToString()).To(ContainSubstring(`map[]`)) + Expect(inspect.OutputToString()).NotTo(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue)) }) It("podman play kube teardown", func() { diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index cd7f72ac0..04e8cfd07 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -109,7 +109,8 @@ var _ = Describe("Podman pod create", func() { It("podman create pod with network portbindings", func() { name := "test" - session := podmanTest.Podman([]string{"pod", "create", "--name", name, "-p", "8081:80"}) + port := GetPort() + session := podmanTest.Podman([]string{"pod", "create", "--name", name, "-p", fmt.Sprintf("%d:80", port)}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) pod := session.OutputToString() @@ -117,24 +118,21 @@ var _ = Describe("Podman pod create", func() { webserver := podmanTest.Podman([]string{"run", "--pod", pod, "-dt", nginx}) webserver.WaitWithDefaultTimeout() Expect(webserver).Should(Exit(0)) - - check := SystemExec("nc", []string{"-z", "localhost", "8081"}) - Expect(check).Should(Exit(0)) + Expect(ncz(port)).To(BeTrue()) }) It("podman create pod with id file with network portbindings", func() { file := filepath.Join(podmanTest.TempDir, "pod.id") name := "test" - session := podmanTest.Podman([]string{"pod", "create", "--name", name, "--pod-id-file", file, "-p", "8082:80"}) + port := GetPort() + session := podmanTest.Podman([]string{"pod", "create", "--name", name, "--pod-id-file", file, "-p", fmt.Sprintf("%d:80", port)}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) webserver := podmanTest.Podman([]string{"run", "--pod-id-file", file, "-dt", nginx}) webserver.WaitWithDefaultTimeout() Expect(webserver).Should(Exit(0)) - - check := SystemExec("nc", []string{"-z", "localhost", "8082"}) - Expect(check).Should(Exit(0)) + Expect(ncz(port)).To(BeTrue()) }) It("podman create pod with no infra but portbindings should fail", func() { diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go index 29ee73d35..a0a1e1438 100644 --- a/test/e2e/pod_ps_test.go +++ b/test/e2e/pod_ps_test.go @@ -299,7 +299,7 @@ var _ = Describe("Podman ps", func() { session := podmanTest.Podman([]string{"network", "create", net}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) session = podmanTest.Podman([]string{"pod", "create", "--network", net}) session.WaitWithDefaultTimeout() @@ -338,12 +338,12 @@ var _ = Describe("Podman ps", func() { session = podmanTest.Podman([]string{"network", "create", net1}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(net1) + defer podmanTest.removeNetwork(net1) net2 := stringid.GenerateNonCryptoID() session = podmanTest.Podman([]string{"network", "create", net2}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(net2) + defer podmanTest.removeNetwork(net2) session = podmanTest.Podman([]string{"pod", "create", "--network", net1 + "," + net2}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go index 0c93c430b..021ebc30b 100644 --- a/test/e2e/ps_test.go +++ b/test/e2e/ps_test.go @@ -822,7 +822,7 @@ var _ = Describe("Podman ps", func() { session := podmanTest.Podman([]string{"network", "create", net}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) session = podmanTest.Podman([]string{"create", "--network", net, ALPINE}) session.WaitWithDefaultTimeout() @@ -865,12 +865,12 @@ var _ = Describe("Podman ps", func() { session = podmanTest.Podman([]string{"network", "create", net1}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(net1) + defer podmanTest.removeNetwork(net1) net2 := stringid.GenerateNonCryptoID() session = podmanTest.Podman([]string{"network", "create", net2}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - defer podmanTest.removeCNINetwork(net2) + defer podmanTest.removeNetwork(net2) session = podmanTest.Podman([]string{"create", "--network", net1 + "," + net2, ALPINE}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index 87b1f143e..4c056df10 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -78,9 +78,9 @@ var _ = Describe("Podman run networking", func() { It("podman run network expose port 222", func() { SkipIfRootless("iptables is not supported for rootless users") session := podmanTest.Podman([]string{"run", "-dt", "--expose", "222-223", "-P", ALPINE, "/bin/sh"}) - session.Wait(30) + session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - results := SystemExec("iptables", []string{"-t", "nat", "-L"}) + results := SystemExec("iptables", []string{"-t", "nat", "-nvL"}) Expect(results).Should(Exit(0)) Expect(results.OutputToString()).To(ContainSubstring("222")) Expect(results.OutputToString()).To(ContainSubstring("223")) @@ -371,31 +371,35 @@ EXPOSE 2004-2005/tcp`, ALPINE) Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) - It("podman run network expose host port 80 to container port 8000", func() { + It("podman run network expose host port 80 to container port", func() { SkipIfRootless("iptables is not supported for rootless users") - session := podmanTest.Podman([]string{"run", "-dt", "-p", "80:8000", ALPINE, "/bin/sh"}) - session.Wait(30) + port1 := GetPort() + port2 := GetPort() + session := podmanTest.Podman([]string{"run", "-dt", "-p", fmt.Sprintf("%d:%d", port1, port2), ALPINE, "/bin/sh"}) + session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) results := SystemExec("iptables", []string{"-t", "nat", "-L"}) Expect(results).Should(Exit(0)) - Expect(results.OutputToString()).To(ContainSubstring("8000")) + Expect(results.OutputToString()).To(ContainSubstring(fmt.Sprintf("%d", port2))) - ncBusy := SystemExec("nc", []string{"-l", "-p", "80"}) + ncBusy := SystemExec("nc", []string{"-l", "-p", fmt.Sprintf("%d", port1)}) Expect(ncBusy).To(ExitWithError()) }) It("podman run network expose host port 18081 to container port 8000 using rootlesskit port handler", func() { - session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=rootlesskit", "-dt", "-p", "18081:8000", ALPINE, "/bin/sh"}) - session.Wait(30) + port1 := GetPort() + port2 := GetPort() + session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=rootlesskit", "-dt", "-p", fmt.Sprintf("%d:%d", port2, port1), ALPINE, "/bin/sh"}) + session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - ncBusy := SystemExec("nc", []string{"-l", "-p", "18081"}) + ncBusy := SystemExec("nc", []string{"-l", "-p", fmt.Sprintf("%d", port2)}) Expect(ncBusy).To(ExitWithError()) }) It("podman run slirp4netns verify net.ipv6.conf.default.accept_dad=0", func() { session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:enable_ipv6=true", ALPINE, "ip", "addr"}) - session.Wait(30) + session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) // check the ipv6 setup id done without delay (https://github.com/containers/podman/issues/11062) Expect(session.OutputToString()).To(ContainSubstring("inet6 fd00::")) @@ -403,12 +407,12 @@ EXPOSE 2004-2005/tcp`, ALPINE) const ipv6ConfDefaultAcceptDadSysctl = "/proc/sys/net/ipv6/conf/all/accept_dad" cat := SystemExec("cat", []string{ipv6ConfDefaultAcceptDadSysctl}) - cat.Wait(30) + cat.WaitWithDefaultTimeout() Expect(cat).Should(Exit(0)) sysctlValue := cat.OutputToString() session = podmanTest.Podman([]string{"run", "--network", "slirp4netns:enable_ipv6=true", ALPINE, "cat", ipv6ConfDefaultAcceptDadSysctl}) - session.Wait(30) + session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToString()).To(Equal(sysctlValue)) }) @@ -460,19 +464,20 @@ EXPOSE 2004-2005/tcp`, ALPINE) slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"}) Expect(slirp4netnsHelp).Should(Exit(0)) networkConfiguration := "slirp4netns:outbound_addr=127.0.0.1,allow_host_loopback=true" + port := GetPort() if strings.Contains(slirp4netnsHelp.OutputToString(), "outbound-addr") { - ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", "8083"}) - session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8083"}) - session.Wait(30) - ncListener.Wait(30) + ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", fmt.Sprintf("%d", port)}) + session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", fmt.Sprintf("%d", port)}) + session.WaitWithDefaultTimeout() + ncListener.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(ncListener).Should(Exit(0)) Expect(ncListener.ErrorToString()).To(ContainSubstring("127.0.0.1")) } else { - session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8083"}) - session.Wait(30) + session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", fmt.Sprintf("%d", port)}) + session.WaitWithDefaultTimeout() Expect(session).To(ExitWithError()) Expect(session.ErrorToString()).To(ContainSubstring("outbound_addr not supported")) } @@ -481,14 +486,15 @@ EXPOSE 2004-2005/tcp`, ALPINE) It("podman run network bind to HostIP", func() { ip, err := utils.HostIP() Expect(err).To(BeNil()) + port := GetPort() slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"}) Expect(slirp4netnsHelp).Should(Exit(0)) networkConfiguration := fmt.Sprintf("slirp4netns:outbound_addr=%s,allow_host_loopback=true", ip.String()) if strings.Contains(slirp4netnsHelp.OutputToString(), "outbound-addr") { - ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", "8084"}) - session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8084"}) + ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", fmt.Sprintf("%d", port)}) + session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", fmt.Sprintf("%d", port)}) session.Wait(30) ncListener.Wait(30) @@ -496,7 +502,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) Expect(ncListener).Should(Exit(0)) Expect(ncListener.ErrorToString()).To(ContainSubstring(ip.String())) } else { - session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8084"}) + session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", fmt.Sprintf("%d", port)}) session.Wait(30) Expect(session).To(ExitWithError()) Expect(session.ErrorToString()).To(ContainSubstring("outbound_addr not supported")) @@ -505,10 +511,10 @@ EXPOSE 2004-2005/tcp`, ALPINE) It("podman run network expose ports in image metadata", func() { session := podmanTest.Podman([]string{"create", "--name", "test", "-t", "-P", nginx}) - session.Wait(90) + session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) results := podmanTest.Podman([]string{"inspect", "test"}) - results.Wait(30) + results.WaitWithDefaultTimeout() Expect(results).Should(Exit(0)) Expect(results.OutputToString()).To(ContainSubstring(`"80/tcp":`)) }) @@ -533,7 +539,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) It("podman run forward sctp protocol", func() { SkipIfRootless("sctp protocol only works as root") session := podmanTest.Podman([]string{"--log-level=info", "run", "--name=test", "-p", "80/sctp", "-p", "81/sctp", ALPINE}) - session.Wait(90) + session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) // we can only check logrus on local podman if !IsRemote() { @@ -541,7 +547,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) Expect(strings.Count(session.ErrorToString(), "Port reservation for SCTP is not supported")).To(Equal(1), "`Port reservation for SCTP is not supported` is not displayed exactly one time in the logrus logs") } results := podmanTest.Podman([]string{"inspect", "test"}) - results.Wait(30) + results.WaitWithDefaultTimeout() Expect(results).Should(Exit(0)) Expect(results.OutputToString()).To(ContainSubstring(`"80/sctp":`)) Expect(results.OutputToString()).To(ContainSubstring(`"81/sctp":`)) @@ -701,7 +707,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.30.0/24", netName}) create.WaitWithDefaultTimeout() Expect(create).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) run := podmanTest.Podman([]string{"run", "-t", "-i", "--rm", "--net", netName, "--ip", ipAddr, ALPINE, "ip", "addr"}) run.WaitWithDefaultTimeout() @@ -710,11 +716,12 @@ EXPOSE 2004-2005/tcp`, ALPINE) }) It("podman cni network works across user ns", func() { + SkipUntilAardvark(podmanTest) netName := stringid.GenerateNonCryptoID() create := podmanTest.Podman([]string{"network", "create", netName}) create.WaitWithDefaultTimeout() Expect(create).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) name := "nc-server" run := podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "-d", "--name", name, "--net", netName, ALPINE, "nc", "-l", "-p", "9480"}) @@ -740,7 +747,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.40.0/24", netName}) create.WaitWithDefaultTimeout() Expect(create).Should(Exit(0)) - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) run := podmanTest.Podman([]string{"run", "-t", "-i", "--rm", "--pod", "new:" + podname, "--net", netName, "--ip", ipAddr, ALPINE, "ip", "addr"}) run.WaitWithDefaultTimeout() @@ -808,6 +815,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) }) It("podman run check dnsname plugin", func() { + SkipUntilAardvark(podmanTest) pod := "testpod" session := podmanTest.Podman([]string{"pod", "create", "--name", pod}) session.WaitWithDefaultTimeout() @@ -816,7 +824,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) net := "IntTest" + stringid.GenerateNonCryptoID() session = podmanTest.Podman([]string{"network", "create", net}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(session).Should(Exit(0)) pod2 := "testpod2" @@ -843,10 +851,11 @@ EXPOSE 2004-2005/tcp`, ALPINE) }) It("podman run check dnsname adds dns search domain", func() { + SkipUntilAardvark(podmanTest) net := "dnsname" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", net}) session.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(net) + defer podmanTest.removeNetwork(net) Expect(session).Should(Exit(0)) session = podmanTest.Podman([]string{"run", "--network", net, ALPINE, "cat", "/etc/resolv.conf"}) @@ -867,4 +876,17 @@ EXPOSE 2004-2005/tcp`, ALPINE) Expect(inspectOut[0].NetworkSettings.Networks).To(HaveLen(1)) Expect(inspectOut[0].NetworkSettings.Networks).To(HaveKey("podman")) }) + + // see https://github.com/containers/podman/issues/12972 + It("podman run check network-alias works on networks without dns", func() { + net := "dns" + stringid.GenerateNonCryptoID() + session := podmanTest.Podman([]string{"network", "create", "--disable-dns", net}) + session.WaitWithDefaultTimeout() + defer podmanTest.removeNetwork(net) + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"run", "--network", net, "--network-alias", "abcdef", ALPINE, "true"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + }) }) diff --git a/test/e2e/run_staticip_test.go b/test/e2e/run_staticip_test.go index cf014d46e..b78a37495 100644 --- a/test/e2e/run_staticip_test.go +++ b/test/e2e/run_staticip_test.go @@ -71,7 +71,7 @@ var _ = Describe("Podman run with --ip flag", func() { ipv6 := "fd46:db93:aa76:ac37::10" net := podmanTest.Podman([]string{"network", "create", "--subnet", "fd46:db93:aa76:ac37::/64", netName}) net.WaitWithDefaultTimeout() - defer podmanTest.removeCNINetwork(netName) + defer podmanTest.removeNetwork(netName) Expect(net).To(Exit(0)) result := podmanTest.Podman([]string{"run", "-ti", "--network", netName, "--ip6", ipv6, ALPINE, "ip", "addr"}) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 62a454e29..91a2eddad 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1926,4 +1926,14 @@ WORKDIR /madethis`, BB) Expect(session).Should(Exit(0)) Expect(session.OutputToString()).To(ContainSubstring("i686")) }) + + It("podman run /dev/shm has nosuid,noexec,nodev", func() { + session := podmanTest.Podman([]string{"run", ALPINE, "grep", "/dev/shm", "/proc/self/mountinfo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + output := session.OutputToString() + Expect(output).To(ContainSubstring("nosuid")) + Expect(output).To(ContainSubstring("noexec")) + Expect(output).To(ContainSubstring("nodev")) + }) }) diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index 00faf8089..d23c5dc14 100644 --- a/test/e2e/run_volume_test.go +++ b/test/e2e/run_volume_test.go @@ -260,6 +260,60 @@ var _ = Describe("Podman run with volumes", func() { }) + It("podman support overlay on named volume with custom upperdir and workdir", func() { + SkipIfRemote("Overlay volumes only work locally") + if os.Getenv("container") != "" { + Skip("Overlay mounts not supported when running in a container") + } + if rootless.IsRootless() { + if _, err := exec.LookPath("fuse-overlayfs"); err != nil { + Skip("Fuse-Overlayfs required for rootless overlay mount test") + } + } + + // create persistent upperdir on host + upperDir := filepath.Join(tempdir, "upper") + err := os.Mkdir(upperDir, 0755) + Expect(err).To(BeNil(), "mkdir "+upperDir) + + // create persistent workdir on host + workDir := filepath.Join(tempdir, "work") + err = os.Mkdir(workDir, 0755) + Expect(err).To(BeNil(), "mkdir "+workDir) + + overlayOpts := fmt.Sprintf("upperdir=%s,workdir=%s", upperDir, workDir) + + session := podmanTest.Podman([]string{"volume", "create", "myvolume"}) + session.WaitWithDefaultTimeout() + volName := session.OutputToString() + Expect(session).Should(Exit(0)) + + // create file on actual volume + session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data", ALPINE, "sh", "-c", "echo hello >> " + "/data/test"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // create file on overlay volume + session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O," + overlayOpts, ALPINE, "sh", "-c", "echo hello >> " + "/data/overlay"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O," + overlayOpts, ALPINE, "sh", "-c", "ls /data"}) + session.WaitWithDefaultTimeout() + // must contain `overlay` file since it should be persistent on specified upper and workdir + Expect(session.OutputToString()).To(ContainSubstring("overlay")) + // this should be there since `test` was written on actual volume not on any overlay + Expect(session.OutputToString()).To(ContainSubstring("test")) + + session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O", ALPINE, "sh", "-c", "ls /data"}) + session.WaitWithDefaultTimeout() + // must not contain `overlay` file which was on custom upper and workdir since we have not specified any upper or workdir + Expect(session.OutputToString()).To(Not(ContainSubstring("overlay"))) + // this should be there since `test` was written on actual volume not on any overlay + Expect(session.OutputToString()).To(ContainSubstring("test")) + + }) + It("podman run with noexec can't exec", func() { session := podmanTest.Podman([]string{"run", "--rm", "-v", "/bin:/hostbin:noexec", ALPINE, "/hostbin/ls", "/"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go index f8d6019b0..07198d799 100644 --- a/test/e2e/search_test.go +++ b/test/e2e/search_test.go @@ -32,18 +32,6 @@ var _ = Describe("Podman search", func() { podmanTest *PodmanTestIntegration ) - var registryEndpoints = []endpoint{ - {"localhost", "5001"}, - {"localhost", "5002"}, - {"localhost", "5003"}, - {"localhost", "5004"}, - {"localhost", "5005"}, - {"localhost", "5006"}, - {"localhost", "5007"}, - {"localhost", "5008"}, - {"localhost", "5009"}, - } - const regFileContents = ` [registries.search] registries = ['{{.Host}}:{{.Port}}'] @@ -217,21 +205,19 @@ registries = ['{{.Host}}:{{.Port}}']` if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } - lock := GetPortLock(registryEndpoints[0].Port) - defer lock.Unlock() - + port := GetPort() fakereg := podmanTest.Podman([]string{"run", "-d", "--name", "registry", - "-p", fmt.Sprintf("%s:5000", registryEndpoints[0].Port), + "-p", fmt.Sprintf("%d:5000", port), registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) fakereg.WaitWithDefaultTimeout() Expect(fakereg).Should(Exit(0)) if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) { - Skip("Cannot start docker registry.") + Fail("Cannot start docker registry on port %s", port) } - + ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"} search := podmanTest.Podman([]string{"search", - fmt.Sprintf("%s/fake/image:andtag", registryEndpoints[0].Address()), "--tls-verify=false"}) + fmt.Sprintf("%s/fake/image:andtag", ep.Address()), "--tls-verify=false"}) search.WaitWithDefaultTimeout() // if this test succeeded, there will be no output (there is no entry named fake/image:andtag in an empty registry) @@ -245,20 +231,19 @@ registries = ['{{.Host}}:{{.Port}}']` if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } - lock := GetPortLock(registryEndpoints[3].Port) - defer lock.Unlock() + port := GetPort() registry := podmanTest.Podman([]string{"run", "-d", "--name", "registry3", - "-p", fmt.Sprintf("%s:5000", registryEndpoints[3].Port), registry, + "-p", fmt.Sprintf("%d:5000", port), registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) registry.WaitWithDefaultTimeout() Expect(registry).Should(Exit(0)) if !WaitContainerReady(podmanTest, "registry3", "listening on", 20, 1) { - Skip("Cannot start docker registry.") + Fail("Cannot start docker registry on port %s", port) } - + ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"} podmanTest.RestoreArtifact(ALPINE) - image := fmt.Sprintf("%s/my-alpine", registryEndpoints[3].Address()) + image := fmt.Sprintf("%s/my-alpine", ep.Address()) push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image}) push.WaitWithDefaultTimeout() Expect(push).Should(Exit(0)) @@ -269,7 +254,7 @@ registries = ['{{.Host}}:{{.Port}}']` Expect(search.OutputToString()).ShouldNot(BeEmpty()) // podman search v2 registry with empty query - searchEmpty := podmanTest.Podman([]string{"search", fmt.Sprintf("%s/", registryEndpoints[3].Address()), "--tls-verify=false"}) + searchEmpty := podmanTest.Podman([]string{"search", fmt.Sprintf("%s/", ep.Address()), "--tls-verify=false"}) searchEmpty.WaitWithDefaultTimeout() Expect(searchEmpty).Should(Exit(0)) Expect(len(searchEmpty.OutputToStringArray())).To(BeNumerically(">=", 1)) @@ -281,26 +266,26 @@ registries = ['{{.Host}}:{{.Port}}']` Skip("No registry image for ppc64le") } - lock := GetPortLock(registryEndpoints[4].Port) - defer lock.Unlock() - registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%s:5000", registryEndpoints[4].Port), + port := GetPort() + ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"} + registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port), "--name", "registry4", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"}) registry.WaitWithDefaultTimeout() Expect(registry).Should(Exit(0)) if !WaitContainerReady(podmanTest, "registry4", "listening on", 20, 1) { - Skip("Cannot start docker registry.") + Fail("unable to start registry on port %s", port) } podmanTest.RestoreArtifact(ALPINE) - image := fmt.Sprintf("%s/my-alpine", registryEndpoints[4].Address()) + image := fmt.Sprintf("%s/my-alpine", ep.Address()) push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image}) push.WaitWithDefaultTimeout() Expect(push).Should(Exit(0)) // registries.conf set up var buffer bytes.Buffer - registryFileTmpl.Execute(&buffer, registryEndpoints[4]) + registryFileTmpl.Execute(&buffer, ep) podmanTest.setRegistriesConfigEnv(buffer.Bytes()) ioutil.WriteFile(fmt.Sprintf("%s/registry4.conf", tempdir), buffer.Bytes(), 0644) if IsRemote() { @@ -323,25 +308,25 @@ registries = ['{{.Host}}:{{.Port}}']` if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } - lock := GetPortLock(registryEndpoints[5].Port) - defer lock.Unlock() - registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%s:5000", registryEndpoints[5].Port), + port := GetPort() + ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"} + registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port), "--name", "registry5", registry}) registry.WaitWithDefaultTimeout() Expect(registry).Should(Exit(0)) if !WaitContainerReady(podmanTest, "registry5", "listening on", 20, 1) { - Skip("Cannot start docker registry.") + Fail("Cannot start docker registry on port %s", port) } podmanTest.RestoreArtifact(ALPINE) - image := fmt.Sprintf("%s/my-alpine", registryEndpoints[5].Address()) + image := fmt.Sprintf("%s/my-alpine", ep.Address()) push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image}) push.WaitWithDefaultTimeout() Expect(push).Should(Exit(0)) var buffer bytes.Buffer - registryFileTmpl.Execute(&buffer, registryEndpoints[5]) + registryFileTmpl.Execute(&buffer, ep) podmanTest.setRegistriesConfigEnv(buffer.Bytes()) ioutil.WriteFile(fmt.Sprintf("%s/registry5.conf", tempdir), buffer.Bytes(), 0644) @@ -360,25 +345,25 @@ registries = ['{{.Host}}:{{.Port}}']` if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } - lock := GetPortLock(registryEndpoints[6].Port) - defer lock.Unlock() - registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%s:5000", registryEndpoints[6].Port), + port := GetPort() + ep := endpoint{Port: fmt.Sprintf("%d", port), Host: "localhost"} + registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port), "--name", "registry6", registry}) registry.WaitWithDefaultTimeout() Expect(registry).Should(Exit(0)) if !WaitContainerReady(podmanTest, "registry6", "listening on", 20, 1) { - Skip("Cannot start docker registry.") + Fail("Cannot start docker registry on port %s", port) } podmanTest.RestoreArtifact(ALPINE) - image := fmt.Sprintf("%s/my-alpine", registryEndpoints[6].Address()) + image := fmt.Sprintf("%s/my-alpine", ep.Address()) push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image}) push.WaitWithDefaultTimeout() Expect(push).Should(Exit(0)) var buffer bytes.Buffer - registryFileBadTmpl.Execute(&buffer, registryEndpoints[6]) + registryFileBadTmpl.Execute(&buffer, ep) podmanTest.setRegistriesConfigEnv(buffer.Bytes()) ioutil.WriteFile(fmt.Sprintf("%s/registry6.conf", tempdir), buffer.Bytes(), 0644) @@ -402,36 +387,36 @@ registries = ['{{.Host}}:{{.Port}}']` if podmanTest.Host.Arch == "ppc64le" { Skip("No registry image for ppc64le") } - lock7 := GetPortLock(registryEndpoints[7].Port) - defer lock7.Unlock() - lock8 := GetPortLock("6000") - defer lock8.Unlock() + port1 := GetPort() + port2 := GetPort() + port3 := GetPort() + ep3 := endpoint{Port: fmt.Sprintf("%d", port3), Host: "localhost"} - registryLocal := podmanTest.Podman([]string{"run", "-d", "--net=host", "-p", fmt.Sprintf("%s:5000", registryEndpoints[7].Port), + registryLocal := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d", port1), "--name", "registry7", registry}) registryLocal.WaitWithDefaultTimeout() Expect(registryLocal).Should(Exit(0)) if !WaitContainerReady(podmanTest, "registry7", "listening on", 20, 1) { - Skip("Cannot start docker registry.") + Fail("Cannot start docker registry on port %s", port1) } - registryLocal = podmanTest.Podman([]string{"run", "-d", "-p", "6000:5000", "--name", "registry8", registry}) + registryLocal = podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%d:5000", port2), "--name", "registry8", registry}) registryLocal.WaitWithDefaultTimeout() Expect(registryLocal).Should(Exit(0)) if !WaitContainerReady(podmanTest, "registry8", "listening on", 20, 1) { - Skip("Cannot start docker registry.") + Fail("Cannot start docker registry on port %s", port2) } podmanTest.RestoreArtifact(ALPINE) - push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:6000/my-alpine"}) + push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, fmt.Sprintf("localhost:%d/my-alpine", port2)}) push.WaitWithDefaultTimeout() Expect(push).Should(Exit(0)) // registries.conf set up var buffer bytes.Buffer - registryFileTwoTmpl.Execute(&buffer, registryEndpoints[8]) + registryFileTwoTmpl.Execute(&buffer, ep3) podmanTest.setRegistriesConfigEnv(buffer.Bytes()) ioutil.WriteFile(fmt.Sprintf("%s/registry8.conf", tempdir), buffer.Bytes(), 0644) diff --git a/test/e2e/stats_test.go b/test/e2e/stats_test.go index 8788369eb..7435a0e3b 100644 --- a/test/e2e/stats_test.go +++ b/test/e2e/stats_test.go @@ -185,6 +185,19 @@ var _ = Describe("Podman stats", func() { Expect(session).Should(Exit(0)) }) + It("podman reads slirp4netns network stats", func() { + session := podmanTest.Podman([]string{"run", "-d", "--network", "slirp4netns", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + cid := session.OutputToString() + + stats := podmanTest.Podman([]string{"stats", "--format", "'{{.NetIO}}'", "--no-stream", cid}) + stats.WaitWithDefaultTimeout() + Expect(stats).Should(Exit(0)) + Expect(stats.OutputToString()).To(Not(ContainSubstring("-- / --"))) + }) + // Regression test for #8265 It("podman stats with custom memory limits", func() { // Run three containers. One with a memory limit. Make sure diff --git a/test/e2e/system_reset_test.go b/test/e2e/system_reset_test.go index 641f98c38..f413ce147 100644 --- a/test/e2e/system_reset_test.go +++ b/test/e2e/system_reset_test.go @@ -38,6 +38,10 @@ var _ = Describe("podman system reset", func() { SkipIfRemote("system reset not supported on podman --remote") // system reset will not remove additional store images, so need to grab length + // change the network dir so that we do not conflict with other tests + // that would use the same network dir and cause unnecessary flakes + podmanTest.NetworkConfigDir = tempdir + session := podmanTest.Podman([]string{"rmi", "--force", "--all"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -56,16 +60,16 @@ var _ = Describe("podman system reset", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"network", "create"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"system", "reset", "-f"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.ErrorToString()).To(Not(ContainSubstring("Failed to add pause process"))) - // If remote then the API service should have exited - // On local tests this is a noop - podmanTest.StartRemoteService() - session = podmanTest.Podman([]string{"images", "-n"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -80,5 +84,11 @@ var _ = Describe("podman system reset", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToStringArray()).To(BeEmpty()) + + session = podmanTest.Podman([]string{"network", "ls", "-q"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + // default network should exists + Expect(session.OutputToStringArray()).To(HaveLen(1)) }) }) diff --git a/test/e2e/volume_create_test.go b/test/e2e/volume_create_test.go index 966bc932a..0ac91abd3 100644 --- a/test/e2e/volume_create_test.go +++ b/test/e2e/volume_create_test.go @@ -144,7 +144,7 @@ var _ = Describe("Podman volume create", func() { Expect(inspectGID).Should(Exit(0)) Expect(inspectGID.OutputToString()).To(Equal(gid)) - // options should containt `uid=3000,gid=4000:3000:4000` + // options should contain `uid=3000,gid=4000:3000:4000` optionFormat := `{{ .Options.o }}:{{ .Options.UID }}:{{ .Options.GID }}` optionStrFormatExpect := fmt.Sprintf(`uid=%s,gid=%s:%s:%s`, uid, gid, uid, gid) inspectOpts := podmanTest.Podman([]string{"volume", "inspect", "--format", optionFormat, volName}) diff --git a/test/python/docker/__init__.py b/test/python/docker/__init__.py index f75185192..816667b82 100644 --- a/test/python/docker/__init__.py +++ b/test/python/docker/__init__.py @@ -42,22 +42,25 @@ class Podman(object): os.environ["CONTAINERS_REGISTRIES_CONF"] = os.path.join( self.anchor_directory, "registry.conf" ) - p = configparser.ConfigParser() - p.read_dict( - { - "registries.search": {"registries": "['quay.io', 'docker.io']"}, - "registries.insecure": {"registries": "[]"}, - "registries.block": {"registries": "[]"}, - } - ) + conf = """unqualified-search-registries = ["docker.io", "quay.io"] + +[[registry]] +location="localhost:5000" +insecure=true + +[[registry.mirror]] +location = "mirror.localhost:5000" + +""" + with open(os.environ["CONTAINERS_REGISTRIES_CONF"], "w") as w: - p.write(w) + w.write(conf) os.environ["CNI_CONFIG_PATH"] = os.path.join( self.anchor_directory, "cni", "net.d" ) os.makedirs(os.environ["CNI_CONFIG_PATH"], exist_ok=True) - self.cmd.append("--cni-config-dir=" + os.environ["CNI_CONFIG_PATH"]) + self.cmd.append("--network-config-dir=" + os.environ["CNI_CONFIG_PATH"]) cni_cfg = os.path.join( os.environ["CNI_CONFIG_PATH"], "87-podman-bridge.conflist" ) diff --git a/test/python/docker/compat/test_system.py b/test/python/docker/compat/test_system.py index 131b18991..a928de0ee 100644 --- a/test/python/docker/compat/test_system.py +++ b/test/python/docker/compat/test_system.py @@ -54,7 +54,10 @@ class TestSystem(unittest.TestCase): return super().tearDownClass() def test_Info(self): - self.assertIsNotNone(self.client.info()) + info = self.client.info() + self.assertIsNotNone(info) + self.assertEqual(info["RegistryConfig"]["IndexConfigs"]["localhost:5000"]["Secure"], False) + self.assertEqual(info["RegistryConfig"]["IndexConfigs"]["localhost:5000"]["Mirrors"], ["mirror.localhost:5000"]) def test_info_container_details(self): info = self.client.info() diff --git a/test/system/005-info.bats b/test/system/005-info.bats index 045045fa6..0f7e8b2e4 100644 --- a/test/system/005-info.bats +++ b/test/system/005-info.bats @@ -43,7 +43,6 @@ host.conmon.package | .*conmon.* host.cgroupManager | \\\(systemd\\\|cgroupfs\\\) host.cgroupVersion | v[12] host.ociRuntime.path | $expr_path -host.ociRuntime.package | .*\\\(crun\\\|runc\\\).* store.configFile | $expr_path store.graphDriverName | [a-z0-9]\\\+\\\$ store.graphRoot | $expr_path @@ -89,6 +88,18 @@ host.slirp4netns.executable | $expr_path is "$output" ".*graphOptions: {}" "output includes graphOptions: {}" } +@test "podman info netavark " { + # Confirm netavark in use when explicitely required by execution environment. + if [[ "$NETWORK_BACKEND" == "netavark" ]]; then + if ! is_netavark; then + # Assume is_netavark() will provide debugging feedback. + die "Netavark driver testing required, but not in use by podman." + fi + else + skip "Netavark testing not requested (\$NETWORK_BACKEND='$NETWORK_BACKEND')" + fi +} + @test "podman --root PATH info - basic output" { if ! is_remote; then run_podman --storage-driver=vfs --root ${PODMAN_TMPDIR}/nothing-here-move-along info --format '{{ .Store.GraphOptions }}' diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 2d5ecab39..ec85ef166 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -5,18 +5,8 @@ load helpers @test "podman run - basic tests" { rand=$(random_string 30) - # 2019-09 Fedora 31 and rawhide (32) are switching from runc to crun - # because of cgroups v2; crun emits different error messages. - # Default to runc: - err_no_such_cmd="Error: .*: starting container process caused.*exec:.*stat /no/such/command: no such file or directory" - err_no_exec_dir="Error: .*: starting container process caused.*exec:.* permission denied" - - # ...but check the configured runtime engine, and switch to crun as needed - run_podman info --format '{{ .Host.OCIRuntime.Path }}' - if expr "$output" : ".*/crun"; then - err_no_such_cmd="Error: crun: executable file.* not found in \$PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found" - err_no_exec_dir="Error: crun: open executable: Operation not permitted: OCI permission denied" - fi + err_no_such_cmd="Error:.*/no/such/command.*[Nn]o such file or directory" + err_no_exec_dir="Error:.*exec.*permission denied" tests=" true | 0 | diff --git a/test/system/120-load.bats b/test/system/120-load.bats index b1d181d50..8bf785081 100644 --- a/test/system/120-load.bats +++ b/test/system/120-load.bats @@ -80,26 +80,76 @@ verify_iid_and_name() { @test "podman image scp transfer" { skip_if_remote "only applicable under local podman" + if is_ubuntu; then + skip "I don't have time to deal with this" + fi - skip "FIXME FIXME FIXME: this needs a big rewrite" - - get_iid_and_name + # The testing is the same whether we're root or rootless; all that + # differs is the destination (not-me) username. if is_rootless; then + # Simple: push to root. whoami=$(id -un) - # FIXME: first, test that we can sudo. If we can't, skip. - # FIXME: test 'scp $IMAGE root@localhost::' - # FIXME: then test the rest - # FIXME: check output - run_podman image scp $whoami@localhost::$iid root@localhost:: - is "$output" "Loaded image.*: $iid" "...." - - # FIXME: "-q" is a NOP - run_podman image scp -q $whoami@localhost::$iid root@localhost:: + notme=root + _sudo() { command sudo -n "$@"; } else - # root - # FIXME: identify a rootless user. DO NOT CREATE ONE. - run_podman image scp root@localhost::$iid 1000:1000@localhost:: + # Harder: our CI infrastructure needs to define this & set up the acct + whoami=root + notme=${PODMAN_ROOTLESS_USER} + if [[ -z "$notme" ]]; then + skip "To run this test, set PODMAN_ROOTLESS_USER to a safe username" + fi + _sudo() { command sudo -n -u "$notme" "$@"; } fi + + # If we can't sudo, we can't test. + _sudo true || skip "cannot sudo to $notme" + + # Preserve digest of original image; we will compare against it later + run_podman image inspect --format '{{.Digest}}' $IMAGE + src_digest=$output + + # image name that is not likely to exist in the destination + newname=foo.bar/nonesuch/c_$(random_string 10 | tr A-Z a-z):mytag + run_podman tag $IMAGE $newname + + # Copy it there. + run_podman image scp $newname ${notme}@localhost:: + is "$output" "Copying blob .*Copying config.*Writing manifest.*Storing signatures" + + # confirm that image was copied. FIXME: also try $PODMAN image inspect? + _sudo $PODMAN image exists $newname + + # Copy it back, this time using -q + run_podman untag $IMAGE $newname + run_podman image scp -q ${notme}@localhost::$newname + + expect="Loaded image(s): $newname" + is "$output" "$expect" "-q silences output" + + # Confirm that we have it, and that its digest matches our original + run_podman image inspect --format '{{.Digest}}' $newname + is "$output" "$src_digest" "Digest of re-fetched image matches original" + + # Clean up + _sudo $PODMAN image rm $newname + run_podman untag $IMAGE $newname + + # Negative test for nonexistent image. + # FIXME: error message is 2 lines, the 2nd being "exit status 125". + # FIXME: is that fixable, or do we have to live with it? + nope="nope.nope/nonesuch:notag" + run_podman 125 image scp ${notme}@localhost::$nope + is "$output" "Error: $nope: image not known.*" "Pulling nonexistent image" + + run_podman 125 image scp $nope ${notme}@localhost:: + is "$output" "Error: $nope: image not known.*" "Pushing nonexistent image" + + # Negative test for copying to a different name + run_podman 125 image scp $IMAGE ${notme}@localhost::newname:newtag + is "$output" "Error: cannot specify an image rename: invalid argument" \ + "Pushing with a different name: not allowed" + + # FIXME: any point in copying by image ID? What else should we test? } diff --git a/test/system/160-volumes.bats b/test/system/160-volumes.bats index b6030ba3c..a3c972b3e 100644 --- a/test/system/160-volumes.bats +++ b/test/system/160-volumes.bats @@ -213,6 +213,8 @@ EOF # Podman volume user test @test "podman volume user test" { is_rootless || skip "only meaningful when run rootless" + skip_if_remote "not applicable on podman-remote" + user="1000:2000" newuser="100:200" tmpdir=${PODMAN_TMPDIR}/volume_$(random_string) @@ -375,7 +377,7 @@ NeedsChown | true run_podman run --rm --volume $myvolume:/etc $IMAGE ls /etc/passwd run_podman volume inspect --format '{{ .NeedsCopyUp }}' $myvolume - is "${output}" "false" "If content in dest '/etc' non-empty NeedsCopyUP should still have happend and be false" + is "${output}" "false" "If content in dest '/etc' non-empty NeedsCopyUP should still have happened and be false" run_podman volume inspect --format '{{.Mountpoint}}' $myvolume mountpoint="$output" diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats index b40359193..34dfaa8f6 100644 --- a/test/system/200-pod.bats +++ b/test/system/200-pod.bats @@ -29,8 +29,7 @@ function teardown() { } @test "podman pod top - containers in different PID namespaces" { - # With infra=false, we don't get a /pause container (we also - # don't pull k8s.gcr.io/pause ) + # With infra=false, we don't get a /pause container no_infra='--infra=false' run_podman pod create $no_infra podid="$output" @@ -148,9 +147,6 @@ EOF # Pod no longer exists run_podman 1 pod exists $podid run_podman 1 pod exists $podname - - # Pause image hasn't been pulled - run_podman 1 image exists k8s.gcr.io/pause:3.5 } # Random byte @@ -329,8 +325,6 @@ EOF local infra_name="infra_container_$(random_string 10 | tr A-Z a-z)" local pod_name="$(random_string 10 | tr A-Z a-z)" - # Note that the internal pause image is built even when --infra-image is - # set to the K8s one. run_podman --noout pod create --name $pod_name --infra-name "$infra_name" --infra-image "k8s.gcr.io/pause:3.5" is "$output" "" "output should be empty" run_podman '?' pod create --infra-name "$infra_name" @@ -339,9 +333,6 @@ EOF fi run_podman pod rm -f $pod_name run_podman images -a - - # Pause image hasn't been pulled - run_podman 1 image exists k8s.gcr.io/pause:3.5 } @test "podman pod create --share" { diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats index 7540270bd..5a8bf4218 100644 --- a/test/system/255-auto-update.bats +++ b/test/system/255-auto-update.bats @@ -373,8 +373,10 @@ EOF systemctl enable --now podman-auto-update-$cname.timer systemctl list-timers --all - # While systemd v245 and later uses 'Finished', older versions uses 'Started' for oneshot services - local expect='(Finished|Started) Podman auto-update testing service' + # systemd <245 displays 'Started Podman auto-update ...' + # systemd 245 - <250 displays 'Finished Podman auto-update ...' + # systemd 250 - ???? displays 'Finished <unit name> - Podman auto-...' + local expect='(Started|Finished.*) Podman auto-update testing service' local failed_start=failed local count=0 while [ $count -lt 120 ]; do diff --git a/test/system/272-system-connection.bats b/test/system/272-system-connection.bats index 4e9ac4dd6..7b70f60f4 100644 --- a/test/system/272-system-connection.bats +++ b/test/system/272-system-connection.bats @@ -124,10 +124,14 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true" \ # If we have ssh access to localhost (unlikely in CI), test that. @test "podman system connection - ssh" { - rand=$(random_string 20) - echo $rand >$PODMAN_TMPDIR/testfile + # system connection only really works if we have an agent + run ssh-add -l + test "$status" -eq 0 || skip "Not running under ssh-agent" + test "${#lines[@]}" -ge 1 || skip "ssh agent has no identities" # Can we actually ssh to localhost? + rand=$(random_string 20) + echo $rand >$PODMAN_TMPDIR/testfile run ssh -q -o BatchMode=yes \ -o UserKnownHostsFile=/dev/null \ -o StrictHostKeyChecking=no \ diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats index dbdfd4b9d..056a056f6 100644 --- a/test/system/410-selinux.bats +++ b/test/system/410-selinux.bats @@ -245,7 +245,8 @@ function check_label() { is "$output" "system_u:object_r:container_file_t:$level $tmpdir" \ "Confined Relabel Correctly" - if is_rootless; then + # podman-remote has no 'unshare' + if is_rootless && ! is_remote; then run_podman unshare touch $tmpdir/test1 # Relabel entire directory run_podman unshare chcon system_u:object_r:usr_t:s0 $tmpdir diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index 5a721c965..9b39ebf97 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -256,13 +256,17 @@ load helpers # rootless cannot modify iptables if ! is_rootless; then - # flush the CNI iptables here - run iptables -t nat -F CNI-HOSTPORT-DNAT + # flush the port forwarding iptable rule here + chain="CNI-HOSTPORT-DNAT" + if is_netavark; then + chain="NETAVARK-HOSTPORT-DNAT" + fi + run iptables -t nat -F "$chain" # check that we cannot curl (timeout after 5 sec) run timeout 5 curl -s $SERVER/index.txt if [ "$status" -ne 124 ]; then - die "curl did not timeout, status code: $status" + die "curl did not timeout, status code: $status" fi fi @@ -589,4 +593,25 @@ load helpers run_podman network rm -t 0 -f $netname } +@test "podman run CONTAINERS_CONF dns options" { + skip_if_remote "CONTAINERS_CONF redirect does not work on remote" + # Test on the CLI and via containers.conf + containersconf=$PODMAN_TMPDIR/containers.conf + + searchIP="100.100.100.100" + cat >$containersconf <<EOF +[containers] + dns_searches = [ "example.com"] + dns_servers = [ + "1.1.1.1", + "$searchIP", + "1.0.0.1", + "8.8.8.8", +] +EOF + CONTAINERS_CONF=$containersconf run_podman run --rm $IMAGE grep "example.com" /etc/resolv.conf + CONTAINERS_CONF=$containersconf run_podman run --rm $IMAGE grep $searchIP /etc/resolv.conf + is "$output" "nameserver $searchIP" "Should only be one $searchIP not multiple" +} + # vim: filetype=sh diff --git a/test/system/README.md b/test/system/README.md index fe6d1ed52..76626b6dd 100644 --- a/test/system/README.md +++ b/test/system/README.md @@ -49,6 +49,7 @@ Running tests To run the tests locally in your sandbox, you can use one of these methods: * make;PODMAN=./bin/podman bats ./test/system/070-build.bats # runs just the specified test * make;PODMAN=./bin/podman bats ./test/system # runs all +* make;PODMAN=./bin/podman NETWORK_BACKEND=netavark bats ./test/system # Assert & enable netavark testing To test as root: * $ PODMAN=./bin/podman sudo --preserve-env=PODMAN bats test/system diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 36a88fc10..c622a5172 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -341,6 +341,15 @@ function is_cgroupsv2() { test "$cgroup_type" = "cgroup2fs" } +# True if podman is using netavark +function is_netavark() { + run_podman info --format '{{.Host.NetworkBackend}}' + if [[ "$output" =~ netavark ]]; then + return 0 + fi + return 1 +} + # Returns the OCI runtime *basename* (typically crun or runc). Much as we'd # love to cache this result, we probably shouldn't. function podman_runtime() { diff --git a/test/utils/utils.go b/test/utils/utils.go index 1f5067950..14092a2a5 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -12,12 +12,34 @@ import ( "strings" "time" + "github.com/sirupsen/logrus" + "github.com/containers/storage/pkg/parsers/kernel" . "github.com/onsi/ginkgo" //nolint:golint,stylecheck . "github.com/onsi/gomega" //nolint:golint,stylecheck . "github.com/onsi/gomega/gexec" //nolint:golint,stylecheck ) +type NetworkBackend int + +const ( + // Container Networking backend + CNI NetworkBackend = iota + // Netavark network backend + Netavark NetworkBackend = iota +) + +func (n NetworkBackend) ToString() string { + switch n { + case CNI: + return "cni" + case Netavark: + return "netavark" + } + logrus.Errorf("unknown network backend: %q", n) + return "" +} + var ( DefaultWaitTimeout = 90 OSReleasePath = "/etc/os-release" @@ -34,17 +56,18 @@ type PodmanTestCommon interface { // PodmanTest struct for command line options type PodmanTest struct { - PodmanMakeOptions func(args []string, noEvents, noCache bool) []string + ImageCacheDir string + ImageCacheFS string + NetworkBackend NetworkBackend PodmanBinary string - TempDir string - RemoteTest bool + PodmanMakeOptions func(args []string, noEvents, noCache bool) []string + RemoteCommand *exec.Cmd RemotePodmanBinary string RemoteSession *os.Process RemoteSocket string RemoteSocketLock string // If not "", should be removed _after_ RemoteSocket is removed - RemoteCommand *exec.Cmd - ImageCacheDir string - ImageCacheFS string + RemoteTest bool + TempDir string } // PodmanSession wraps the gexec.session so we can extend it @@ -73,8 +96,10 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string if p.RemoteTest { podmanBinary = p.RemotePodmanBinary } - runCmd := append(wrapper, podmanBinary) + if p.NetworkBackend == Netavark { + runCmd = append(runCmd, []string{"--network-backend", "netavark"}...) + } if p.RemoteTest { podmanOptions = append([]string{"--remote", "--url", p.RemoteSocket}, podmanOptions...) } |