summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/apiv2/35-networks.at21
-rw-r--r--test/apiv2/40-pods.at4
-rw-r--r--test/e2e/build_test.go23
-rw-r--r--test/e2e/common_test.go6
-rw-r--r--test/e2e/generate_kube_test.go29
-rw-r--r--test/e2e/generate_systemd_test.go40
-rw-r--r--test/e2e/load_test.go8
-rw-r--r--test/e2e/network_create_test.go2
-rw-r--r--test/e2e/network_test.go26
-rw-r--r--test/e2e/play_kube_test.go44
-rw-r--r--test/e2e/ps_test.go6
-rw-r--r--test/e2e/pull_test.go43
-rw-r--r--test/e2e/run_apparmor_test.go13
-rw-r--r--test/e2e/run_networking_test.go10
-rw-r--r--test/e2e/run_passwd_test.go54
-rw-r--r--test/e2e/run_privileged_test.go42
-rw-r--r--test/e2e/run_test.go4
-rw-r--r--test/e2e/run_userns_test.go7
-rw-r--r--test/e2e/runlabel_test.go18
-rw-r--r--test/e2e/save_test.go47
l---------test/e2e/testdata/image1
-rw-r--r--test/system/001-basic.bats11
-rw-r--r--test/system/010-images.bats14
-rw-r--r--test/system/030-run.bats41
-rw-r--r--test/system/055-rm.bats2
-rw-r--r--test/system/110-history.bats3
-rw-r--r--test/system/120-load.bats34
-rw-r--r--test/system/130-kill.bats2
-rw-r--r--test/system/150-login.bats43
-rw-r--r--test/system/260-sdnotify.bats5
-rw-r--r--test/system/500-networking.bats13
-rwxr-xr-xtest/system/build-testimage59
-rw-r--r--test/system/helpers.bash6
33 files changed, 570 insertions, 111 deletions
diff --git a/test/apiv2/35-networks.at b/test/apiv2/35-networks.at
index 4c032c072..143d6c07b 100644
--- a/test/apiv2/35-networks.at
+++ b/test/apiv2/35-networks.at
@@ -21,6 +21,27 @@ if root; then
t POST libpod/networks/create '"Subnet":{"IP":"10.10.1.0","Mask":[0,255,255,0]}' 500 \
.cause~'.*mask is invalid'
+ # network list
+ t GET libpod/networks/json 200
+ t GET libpod/networks/json?filter=name=network1 200 \
+ length=1 \
+ .[0].Name=network1
+ t GET networks 200
+
+ #network list docker endpoint
+ #filters={"name":["network1","network2"]}
+ t GET networks?filters=%7B%22name%22%3A%5B%22network1%22%2C%22network2%22%5D%7D 200 \
+ length=2
+ #filters={"name":["network"]}
+ t GET networks?filters=%7B%22name%22%3A%5B%22network%22%5D%7D 200 \
+ length=2
+ # invalid filter filters={"label":"abc"}
+ t GET networks?filters=%7B%22label%22%3A%5B%22abc%22%5D%7D 500 \
+ .cause="only the name filter for listing networks is implemented"
+ # invalid filter filters={"label":"abc","name":["network"]}
+ t GET networks?filters=%7B%22label%22%3A%22abc%22%2C%22name%22%3A%5B%22network%22%5D%7D 500 \
+ .cause="only the name filter for listing networks is implemented"
+
# clean the network
t DELETE libpod/networks/network1 200 \
.[0].Name~network1 \
diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at
index 3df541de5..fdb61a84d 100644
--- a/test/apiv2/40-pods.at
+++ b/test/apiv2/40-pods.at
@@ -102,6 +102,10 @@ t GET libpod/pods/stats?namesOrIDs=fakename 404 \
t DELETE libpod/pods/bar?force=true 200
+# test the fake name
+t GET libpod/pods/fakename/top 404 \
+ .cause="no such pod"
+
t GET libpod/pods/foo/top 200 \
.Processes[0][-1]="/pause " \
.Titles[-1]="COMMAND"
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 9fd82e149..0b6e919d0 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -57,6 +57,29 @@ var _ = Describe("Podman build", func() {
Expect(session.ExitCode()).To(Equal(0))
})
+ It("podman build with logfile", func() {
+ SkipIfRemote()
+ logfile := filepath.Join(podmanTest.TempDir, "logfile")
+ session := podmanTest.PodmanNoCache([]string{"build", "--tag", "test", "--logfile", logfile, "build/basicalpine"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // Verify that OS and Arch are being set
+ inspect := podmanTest.PodmanNoCache([]string{"inspect", "test"})
+ inspect.WaitWithDefaultTimeout()
+ data := inspect.InspectImageJSON()
+ Expect(data[0].Os).To(Equal(runtime.GOOS))
+ Expect(data[0].Architecture).To(Equal(runtime.GOARCH))
+
+ st, err := os.Stat(logfile)
+ Expect(err).To(BeNil())
+ Expect(st.Size()).To(Not(Equal(0)))
+
+ session = podmanTest.PodmanNoCache([]string{"rmi", "alpine"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
// 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() {
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index ed55484e3..b6bbae15b 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -245,6 +245,12 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
}
os.Setenv("DISABLE_HC_SYSTEMD", "true")
CNIConfigDir := "/etc/cni/net.d"
+ if rootless.IsRootless() {
+ CNIConfigDir = filepath.Join(os.Getenv("HOME"), ".config/cni/net.d")
+ }
+ if err := os.MkdirAll(CNIConfigDir, 0755); err != nil {
+ panic(err)
+ }
storageFs := STORAGE_FS
if rootless.IsRootless() {
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 3c3fb5a4d..e886c6000 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -348,4 +348,33 @@ var _ = Describe("Podman generate kube", func() {
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.OutputToString()).To(ContainSubstring(vol1))
})
+
+ It("podman generate kube sharing pid namespace", func() {
+ podName := "test"
+ podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--share", "pid"})
+ podSession.WaitWithDefaultTimeout()
+ Expect(podSession.ExitCode()).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"create", "--pod", podName, "--name", "test1", ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ outputFile := filepath.Join(podmanTest.RunRoot, "pod.yaml")
+ kube := podmanTest.Podman([]string{"generate", "kube", podName, "-f", outputFile})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ rm := podmanTest.Podman([]string{"pod", "rm", "-f", podName})
+ rm.WaitWithDefaultTimeout()
+ Expect(rm.ExitCode()).To(Equal(0))
+
+ play := podmanTest.Podman([]string{"play", "kube", outputFile})
+ play.WaitWithDefaultTimeout()
+ Expect(play.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"pod", "inspect", podName})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`"pid"`))
+ })
})
diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index 60d9162d1..da2f67754 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -1,5 +1,3 @@
-// +build !remote
-
package integration
import (
@@ -61,7 +59,7 @@ var _ = Describe("Podman generate systemd", func() {
session = podmanTest.Podman([]string{"generate", "systemd", "--restart-policy", "bogus", "foobar"})
session.WaitWithDefaultTimeout()
Expect(session).To(ExitWithError())
- found, _ := session.ErrorGrepString("Error: bogus is not a valid restart policy")
+ found, _ := session.ErrorGrepString("bogus is not a valid restart policy")
Expect(found).Should(BeTrue())
})
@@ -191,7 +189,7 @@ var _ = Describe("Podman generate systemd", func() {
Expect(found).To(BeTrue())
})
- It("podman generate systemd --new", func() {
+ It("podman generate systemd --new --name foo", func() {
n := podmanTest.Podman([]string{"create", "--name", "foo", "alpine", "top"})
n.WaitWithDefaultTimeout()
Expect(n.ExitCode()).To(Equal(0))
@@ -204,6 +202,29 @@ var _ = Describe("Podman generate systemd", func() {
found, _ := session.GrepString("# container-foo.service")
Expect(found).To(BeTrue())
+ found, _ = session.GrepString(" --replace ")
+ Expect(found).To(BeTrue())
+
+ found, _ = session.GrepString("stop --ignore --cidfile %t/container-foo.ctr-id -t 42")
+ Expect(found).To(BeTrue())
+ })
+
+ It("podman generate systemd --new --name=foo", func() {
+ n := podmanTest.Podman([]string{"create", "--name=foo", "alpine", "top"})
+ n.WaitWithDefaultTimeout()
+ Expect(n.ExitCode()).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"generate", "systemd", "-t", "42", "--name", "--new", "foo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // Grepping the output (in addition to unit tests)
+ found, _ := session.GrepString("# container-foo.service")
+ Expect(found).To(BeTrue())
+
+ found, _ = session.GrepString(" --replace ")
+ Expect(found).To(BeTrue())
+
found, _ = session.GrepString("stop --ignore --cidfile %t/container-foo.ctr-id -t 42")
Expect(found).To(BeTrue())
})
@@ -383,4 +404,15 @@ var _ = Describe("Podman generate systemd", func() {
found, _ = session.GrepString("pod rm --ignore -f --pod-id-file %t/pod-foo.pod-id")
Expect(found).To(BeTrue())
})
+
+ It("podman generate systemd --format json", func() {
+ n := podmanTest.Podman([]string{"create", "--name", "foo", ALPINE})
+ n.WaitWithDefaultTimeout()
+ Expect(n.ExitCode()).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"generate", "systemd", "--format", "json", "foo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.IsJSONOutputValid()).To(BeTrue())
+ })
})
diff --git a/test/e2e/load_test.go b/test/e2e/load_test.go
index 6a7f15e1f..2b401a09d 100644
--- a/test/e2e/load_test.go
+++ b/test/e2e/load_test.go
@@ -269,4 +269,12 @@ var _ = Describe("Podman load", func() {
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
})
+
+ It("podman load multi-image archive", func() {
+ result := podmanTest.PodmanNoCache([]string{"load", "-i", "./testdata/image/docker-two-images.tar.xz"})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.LineInOutputContains("example.com/empty:latest")).To(BeTrue())
+ Expect(result.LineInOutputContains("example.com/empty/but:different")).To(BeTrue())
+ })
})
diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go
index f97e6c1f1..13d515d8e 100644
--- a/test/e2e/network_create_test.go
+++ b/test/e2e/network_create_test.go
@@ -74,7 +74,6 @@ var _ = Describe("Podman network create", func() {
)
BeforeEach(func() {
- SkipIfRootless()
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
@@ -180,6 +179,7 @@ var _ = Describe("Podman network create", func() {
It("podman network create with name and IPv6 subnet", func() {
SkipIfRemote()
+ SkipIfRootless()
var (
results []network.NcList
)
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index f427afa67..c35b82fc1 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -1,5 +1,3 @@
-// +build !remote
-
package integration
import (
@@ -9,6 +7,7 @@ import (
"path/filepath"
"strings"
+ "github.com/containers/podman/v2/pkg/rootless"
. "github.com/containers/podman/v2/test/utils"
"github.com/containers/storage/pkg/stringid"
. "github.com/onsi/ginkgo"
@@ -34,7 +33,6 @@ var _ = Describe("Podman network", func() {
)
BeforeEach(func() {
- SkipIfRootless()
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
@@ -76,13 +74,12 @@ var _ = Describe("Podman network", func() {
}
]
}`
- cniPath = "/etc/cni/net.d"
)
It("podman network list", func() {
// Setup, use uuid to prevent conflict with other tests
uuid := stringid.GenerateNonCryptoID()
- secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ secondPath := filepath.Join(podmanTest.CNIConfigDir, fmt.Sprintf("%s.conflist", uuid))
writeConf([]byte(secondConf), secondPath)
defer removeConf(secondPath)
@@ -95,7 +92,7 @@ var _ = Describe("Podman network", func() {
It("podman network list -q", func() {
// Setup, use uuid to prevent conflict with other tests
uuid := stringid.GenerateNonCryptoID()
- secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ secondPath := filepath.Join(podmanTest.CNIConfigDir, fmt.Sprintf("%s.conflist", uuid))
writeConf([]byte(secondConf), secondPath)
defer removeConf(secondPath)
@@ -108,7 +105,7 @@ var _ = Describe("Podman network", func() {
It("podman network list --filter success", func() {
// Setup, use uuid to prevent conflict with other tests
uuid := stringid.GenerateNonCryptoID()
- secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ secondPath := filepath.Join(podmanTest.CNIConfigDir, fmt.Sprintf("%s.conflist", uuid))
writeConf([]byte(secondConf), secondPath)
defer removeConf(secondPath)
@@ -121,7 +118,7 @@ var _ = Describe("Podman network", func() {
It("podman network list --filter failure", func() {
// Setup, use uuid to prevent conflict with other tests
uuid := stringid.GenerateNonCryptoID()
- secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ secondPath := filepath.Join(podmanTest.CNIConfigDir, fmt.Sprintf("%s.conflist", uuid))
writeConf([]byte(secondConf), secondPath)
defer removeConf(secondPath)
@@ -140,7 +137,7 @@ var _ = Describe("Podman network", func() {
It("podman network rm", func() {
// Setup, use uuid to prevent conflict with other tests
uuid := stringid.GenerateNonCryptoID()
- secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ secondPath := filepath.Join(podmanTest.CNIConfigDir, fmt.Sprintf("%s.conflist", uuid))
writeConf([]byte(secondConf), secondPath)
defer removeConf(secondPath)
@@ -168,11 +165,16 @@ var _ = Describe("Podman network", func() {
It("podman network inspect", func() {
// Setup, use uuid to prevent conflict with other tests
uuid := stringid.GenerateNonCryptoID()
- secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ secondPath := filepath.Join(podmanTest.CNIConfigDir, fmt.Sprintf("%s.conflist", uuid))
writeConf([]byte(secondConf), secondPath)
defer removeConf(secondPath)
- session := podmanTest.Podman([]string{"network", "inspect", "podman-integrationtest", "podman"})
+ expectedNetworks := []string{"podman-integrationtest"}
+ if !rootless.IsRootless() {
+ // rootful image contains "podman/cni/87-podman-bridge.conflist" for "podman" network
+ expectedNetworks = append(expectedNetworks, "podman")
+ }
+ session := podmanTest.Podman(append([]string{"network", "inspect"}, expectedNetworks...))
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.IsJSONOutputValid()).To(BeTrue())
@@ -181,7 +183,7 @@ var _ = Describe("Podman network", func() {
It("podman network inspect", func() {
// Setup, use uuid to prevent conflict with other tests
uuid := stringid.GenerateNonCryptoID()
- secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ secondPath := filepath.Join(podmanTest.CNIConfigDir, fmt.Sprintf("%s.conflist", uuid))
writeConf([]byte(secondConf), secondPath)
defer removeConf(secondPath)
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 121cea017..5e01971cb 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -99,6 +99,12 @@ spec:
hostPort: {{ .Port }}
protocol: TCP
workingDir: /
+ volumeMounts:
+ {{ if .VolumeMount }}
+ - name: {{.VolumeName}}
+ mountPath: {{ .VolumeMountPath }}
+ readonly: {{.VolumeReadOnly}}
+ {{ end }}
{{ end }}
{{ end }}
{{ end }}
@@ -383,12 +389,16 @@ type Ctr struct {
PullPolicy string
HostIP string
Port string
+ VolumeMount bool
+ VolumeMountPath string
+ VolumeName string
+ VolumeReadOnly bool
}
// getCtr takes a list of ctrOptions and returns a Ctr with sane defaults
// and the configured options
func getCtr(options ...ctrOption) *Ctr {
- c := Ctr{defaultCtrName, defaultCtrImage, defaultCtrCmd, defaultCtrArg, true, false, nil, nil, "", "", ""}
+ c := Ctr{defaultCtrName, defaultCtrImage, defaultCtrCmd, defaultCtrArg, true, false, nil, nil, "", "", "", false, "", "", false}
for _, option := range options {
option(&c)
}
@@ -448,6 +458,15 @@ func withHostIP(ip string, port string) ctrOption {
}
}
+func withVolumeMount(mountPath string, readonly bool) ctrOption {
+ return func(c *Ctr) {
+ c.VolumeMountPath = mountPath
+ c.VolumeName = defaultVolName
+ c.VolumeReadOnly = readonly
+ c.VolumeMount = true
+ }
+}
+
func getCtrNameInPod(pod *Pod) string {
return fmt.Sprintf("%s-%s", pod.Name, defaultCtrName)
}
@@ -1035,4 +1054,27 @@ spec:
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).NotTo(Equal(0))
})
+
+ It("podman play kube test with read only volume", func() {
+ hostPathLocation := filepath.Join(tempdir, "file")
+ f, err := os.Create(hostPathLocation)
+ Expect(err).To(BeNil())
+ f.Close()
+
+ ctr := getCtr(withVolumeMount(hostPathLocation, true), withImage(BB))
+ pod := getPod(withVolume(getVolume("File", hostPathLocation)), withCtr(ctr))
+ err = generatePodKubeYaml(pod, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{.HostConfig.Binds}}'"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+
+ correct := fmt.Sprintf("%s:%s:%s", hostPathLocation, hostPathLocation, "ro")
+ Expect(inspect.OutputToString()).To(ContainSubstring(correct))
+ })
})
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index a734d399d..a2338c924 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -104,11 +104,13 @@ var _ = Describe("Podman ps", func() {
SkipIfRemote()
_, ec, _ := podmanTest.RunLsContainer("")
Expect(ec).To(Equal(0))
+ _, ec, _ = podmanTest.RunLsContainer("")
+ Expect(ec).To(Equal(0))
- result := podmanTest.Podman([]string{"ps", "--latest"})
+ result := podmanTest.Podman([]string{"ps", "-q", "--latest"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
- Expect(len(result.OutputToStringArray())).Should(BeNumerically(">", 0))
+ Expect(len(result.OutputToStringArray())).Should(Equal(1))
})
It("podman ps last flag", func() {
diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go
index 6d1cb6cbc..98b81876a 100644
--- a/test/e2e/pull_test.go
+++ b/test/e2e/pull_test.go
@@ -251,6 +251,49 @@ var _ = Describe("Podman pull", func() {
session = podmanTest.PodmanNoCache([]string{"rmi", "alpine"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
+
+ // Pulling a multi-image archive without further specifying
+ // which image _must_ error out. Pulling is restricted to one
+ // image.
+ session = podmanTest.PodmanNoCache([]string{"pull", fmt.Sprintf("docker-archive:./testdata/image/docker-two-images.tar.xz")})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(125))
+ expectedError := "Unexpected tar manifest.json: expected 1 item, got 2"
+ found, _ := session.ErrorGrepString(expectedError)
+ Expect(found).To(Equal(true))
+
+ // Now pull _one_ image from a multi-image archive via the name
+ // and index syntax.
+ session = podmanTest.PodmanNoCache([]string{"pull", fmt.Sprintf("docker-archive:./testdata/image/docker-two-images.tar.xz:@0")})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.PodmanNoCache([]string{"pull", fmt.Sprintf("docker-archive:./testdata/image/docker-two-images.tar.xz:example.com/empty:latest")})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.PodmanNoCache([]string{"pull", fmt.Sprintf("docker-archive:./testdata/image/docker-two-images.tar.xz:@1")})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.PodmanNoCache([]string{"pull", fmt.Sprintf("docker-archive:./testdata/image/docker-two-images.tar.xz:example.com/empty/but:different")})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // Now check for some errors.
+ session = podmanTest.PodmanNoCache([]string{"pull", fmt.Sprintf("docker-archive:./testdata/image/docker-two-images.tar.xz:foo.com/does/not/exist:latest")})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(125))
+ expectedError = "Tag \"foo.com/does/not/exist:latest\" not found"
+ found, _ = session.ErrorGrepString(expectedError)
+ Expect(found).To(Equal(true))
+
+ session = podmanTest.PodmanNoCache([]string{"pull", fmt.Sprintf("docker-archive:./testdata/image/docker-two-images.tar.xz:@2")})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(125))
+ expectedError = "Invalid source index @2, only 2 manifest items available"
+ found, _ = session.ErrorGrepString(expectedError)
+ Expect(found).To(Equal(true))
})
It("podman pull from oci-archive", func() {
diff --git a/test/e2e/run_apparmor_test.go b/test/e2e/run_apparmor_test.go
index 53cac9529..7d522a752 100644
--- a/test/e2e/run_apparmor_test.go
+++ b/test/e2e/run_apparmor_test.go
@@ -155,4 +155,17 @@ profile aa-test-profile flags=(attach_disconnected,mediate_deleted) {
inspect := podmanTest.InspectContainer(cid)
Expect(inspect[0].AppArmorProfile).To(Equal(""))
})
+
+ It("podman run apparmor disabled unconfined", func() {
+ skipIfAppArmorEnabled()
+
+ session := podmanTest.Podman([]string{"create", "--security-opt", "apparmor=unconfined", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ cid := session.OutputToString()
+ // Verify that apparmor.Profile is being set
+ inspect := podmanTest.InspectContainer(cid)
+ Expect(inspect[0].AppArmorProfile).To(Equal(""))
+ })
})
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index a48f7c83e..c20bfe631 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -535,15 +535,12 @@ var _ = Describe("Podman run networking", func() {
create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.30.0/24", netName})
create.WaitWithDefaultTimeout()
Expect(create.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(netName)
run := podmanTest.Podman([]string{"run", "-t", "-i", "--rm", "--net", netName, "--ip", ipAddr, ALPINE, "ip", "addr"})
run.WaitWithDefaultTimeout()
Expect(run.ExitCode()).To(BeZero())
Expect(run.OutputToString()).To(ContainSubstring(ipAddr))
-
- netrm := podmanTest.Podman([]string{"network", "rm", netName})
- netrm.WaitWithDefaultTimeout()
- Expect(netrm.ExitCode()).To(BeZero())
})
It("podman run with new:pod and static-ip", func() {
@@ -555,6 +552,7 @@ var _ = Describe("Podman run networking", func() {
create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.40.0/24", netName})
create.WaitWithDefaultTimeout()
Expect(create.ExitCode()).To(BeZero())
+ defer podmanTest.removeCNINetwork(netName)
run := podmanTest.Podman([]string{"run", "-t", "-i", "--rm", "--pod", "new:" + podname, "--net", netName, "--ip", ipAddr, ALPINE, "ip", "addr"})
run.WaitWithDefaultTimeout()
@@ -564,9 +562,5 @@ var _ = Describe("Podman run networking", func() {
podrm := podmanTest.Podman([]string{"pod", "rm", "-f", podname})
podrm.WaitWithDefaultTimeout()
Expect(podrm.ExitCode()).To(BeZero())
-
- netrm := podmanTest.Podman([]string{"network", "rm", netName})
- netrm.WaitWithDefaultTimeout()
- Expect(netrm.ExitCode()).To(BeZero())
})
})
diff --git a/test/e2e/run_passwd_test.go b/test/e2e/run_passwd_test.go
index c48876dee..dfb8c72a1 100644
--- a/test/e2e/run_passwd_test.go
+++ b/test/e2e/run_passwd_test.go
@@ -71,4 +71,58 @@ USER 1000`
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Not(ContainSubstring("passwd")))
})
+
+ It("podman run with no user specified does not change --group specified", func() {
+ session := podmanTest.Podman([]string{"run", "--read-only", BB, "mount"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("/etc/group")).To(BeFalse())
+ })
+
+ It("podman run group specified in container", func() {
+ session := podmanTest.Podman([]string{"run", "--read-only", "-u", "root:bin", BB, "mount"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("/etc/group")).To(BeFalse())
+ })
+
+ It("podman run non-numeric group not specified in container", func() {
+ session := podmanTest.Podman([]string{"run", "--read-only", "-u", "root:doesnotexist", BB, "mount"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ })
+
+ It("podman run numeric group specified in container", func() {
+ session := podmanTest.Podman([]string{"run", "--read-only", "-u", "root:11", BB, "mount"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("/etc/group")).To(BeFalse())
+ })
+
+ It("podman run numeric group not specified in container", func() {
+ session := podmanTest.Podman([]string{"run", "--read-only", "-u", "20001:20001", BB, "mount"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("/etc/group")).To(BeTrue())
+ })
+
+ It("podman run numeric user not specified in container modifies group", func() {
+ session := podmanTest.Podman([]string{"run", "--read-only", "-u", "20001", BB, "mount"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("/etc/group")).To(BeTrue())
+ })
+
+ It("podman run numeric group from image and no group file", func() {
+ SkipIfRemote()
+ dockerfile := `FROM alpine
+RUN rm -f /etc/passwd /etc/shadow /etc/group
+USER 1000`
+ imgName := "testimg"
+ podmanTest.BuildImage(dockerfile, imgName, "false")
+ session := podmanTest.Podman([]string{"run", "--rm", imgName, "ls", "/etc/"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Not(ContainSubstring("/etc/group")))
+ })
})
diff --git a/test/e2e/run_privileged_test.go b/test/e2e/run_privileged_test.go
index ca8da981f..064ba7d2c 100644
--- a/test/e2e/run_privileged_test.go
+++ b/test/e2e/run_privileged_test.go
@@ -2,13 +2,36 @@ package integration
import (
"os"
+ "strconv"
"strings"
. "github.com/containers/podman/v2/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
+ "github.com/syndtr/gocapability/capability"
)
+// helper function for confirming that container capabilities are equal
+// to those of the host, but only to the extent of caps we (podman)
+// know about at compile time. That is: the kernel may have more caps
+// available than we are aware of, leading to host=FFF... and ctr=3FF...
+// because the latter is all we request. Accept that.
+func containerCapMatchesHost(ctr_cap string, host_cap string) {
+ ctr_cap_n, err := strconv.ParseUint(ctr_cap, 16, 64)
+ Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", ctr_cap)
+
+ host_cap_n, err := strconv.ParseUint(host_cap, 16, 64)
+ Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", host_cap)
+
+ // host caps can never be zero (except rootless, which we don't test).
+ // and host caps must always be a superset (inclusive) of container
+ Expect(host_cap_n).To(BeNumerically(">", 0), "host cap %q should be nonzero", host_cap)
+ Expect(host_cap_n).To(BeNumerically(">=", ctr_cap_n), "host cap %q should never be less than container cap %q", host_cap, ctr_cap)
+
+ host_cap_masked := host_cap_n & (1<<len(capability.List()) - 1)
+ Expect(ctr_cap_n).To(Equal(host_cap_masked), "container cap %q is not a subset of host cap %q", ctr_cap, host_cap)
+}
+
var _ = Describe("Podman privileged container tests", func() {
var (
tempdir string
@@ -44,24 +67,27 @@ var _ = Describe("Podman privileged container tests", func() {
It("podman privileged CapEff", func() {
SkipIfRootless()
- cap := SystemExec("grep", []string{"CapEff", "/proc/self/status"})
- Expect(cap.ExitCode()).To(Equal(0))
+ host_cap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+ Expect(host_cap.ExitCode()).To(Equal(0))
- session := podmanTest.Podman([]string{"run", "--privileged", "busybox", "grep", "CapEff", "/proc/self/status"})
+ session := podmanTest.Podman([]string{"run", "--privileged", "busybox", "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(Equal(cap.OutputToString()))
+
+ containerCapMatchesHost(session.OutputToString(), host_cap.OutputToString())
})
It("podman cap-add CapEff", func() {
SkipIfRootless()
- cap := SystemExec("grep", []string{"CapEff", "/proc/self/status"})
- Expect(cap.ExitCode()).To(Equal(0))
+ // Get caps of current process
+ host_cap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+ Expect(host_cap.ExitCode()).To(Equal(0))
- session := podmanTest.Podman([]string{"run", "--cap-add", "all", "busybox", "grep", "CapEff", "/proc/self/status"})
+ session := podmanTest.Podman([]string{"run", "--cap-add", "all", "busybox", "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(Equal(cap.OutputToString()))
+
+ containerCapMatchesHost(session.OutputToString(), host_cap.OutputToString())
})
It("podman cap-drop CapEff", func() {
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 1ac753201..a67f7df92 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -325,10 +325,10 @@ USER bin`
Expect(session.ExitCode()).To(Equal(0))
}
- session = podmanTest.Podman([]string{"run", "--rm", "--oom-score-adj=100", fedoraMinimal, "cat", "/proc/self/oom_score_adj"})
+ session = podmanTest.Podman([]string{"run", "--rm", "--oom-score-adj=111", fedoraMinimal, "cat", "/proc/self/oom_score_adj"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("100"))
+ Expect(session.OutputToString()).To(Equal("111"))
})
It("podman run limits host test", func() {
diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go
index 25f8d0d15..8d860cfc3 100644
--- a/test/e2e/run_userns_test.go
+++ b/test/e2e/run_userns_test.go
@@ -277,6 +277,13 @@ var _ = Describe("Podman UserNS support", func() {
ok, _ := session.GrepString("4998")
Expect(ok).To(BeTrue())
+
+ session = podmanTest.Podman([]string{"run", "--rm", "--userns=container:" + ctrName, "--net=container:" + ctrName, "alpine", "cat", "/proc/self/uid_map"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ ok, _ = session.GrepString("4998")
+ Expect(ok).To(BeTrue())
})
It("podman --user with volume", func() {
diff --git a/test/e2e/runlabel_test.go b/test/e2e/runlabel_test.go
index de79b2b98..0eb679fbf 100644
--- a/test/e2e/runlabel_test.go
+++ b/test/e2e/runlabel_test.go
@@ -29,6 +29,8 @@ var _ = Describe("podman container runlabel", func() {
)
BeforeEach(func() {
+ // runlabel is not supported for remote connections
+ SkipIfRemote()
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
@@ -46,7 +48,6 @@ var _ = Describe("podman container runlabel", func() {
})
It("podman container runlabel (podman --version)", func() {
- SkipIfRemote()
image := "podman-runlabel-test:podman"
podmanTest.BuildImage(PodmanDockerfile, image, "false")
@@ -60,7 +61,6 @@ var _ = Describe("podman container runlabel", func() {
})
It("podman container runlabel (ls -la)", func() {
- SkipIfRemote()
image := "podman-runlabel-test:ls"
podmanTest.BuildImage(LsDockerfile, image, "false")
@@ -72,6 +72,19 @@ var _ = Describe("podman container runlabel", func() {
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
})
+ It("podman container runlabel --display", func() {
+ image := "podman-runlabel-test:ls"
+ podmanTest.BuildImage(LsDockerfile, image, "false")
+
+ result := podmanTest.Podman([]string{"container", "runlabel", "--display", "RUN", image})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.OutputToString()).To(ContainSubstring(podmanTest.PodmanBinary + " -la"))
+
+ result = podmanTest.Podman([]string{"rmi", image})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ })
It("podman container runlabel bogus label should result in non-zero exit code", func() {
result := podmanTest.Podman([]string{"container", "runlabel", "RUN", ALPINE})
result.WaitWithDefaultTimeout()
@@ -100,7 +113,6 @@ var _ = Describe("podman container runlabel", func() {
})
It("runlabel should fail with nonexist authfile", func() {
- SkipIfRemote()
image := "podman-runlabel-test:podman"
podmanTest.BuildImage(PodmanDockerfile, image, "false")
diff --git a/test/e2e/save_test.go b/test/e2e/save_test.go
index e1396f1b2..1f1258be3 100644
--- a/test/e2e/save_test.go
+++ b/test/e2e/save_test.go
@@ -128,4 +128,51 @@ var _ = Describe("Podman save", func() {
save.WaitWithDefaultTimeout()
Expect(save.ExitCode()).To(Equal(0))
})
+
+ It("podman save --multi-image-archive (tagged images)", func() {
+ multiImageSave(podmanTest, RESTORE_IMAGES)
+ })
+
+ It("podman save --multi-image-archive (untagged images)", func() {
+ // Refer to images via ID instead of tag.
+ session := podmanTest.PodmanNoCache([]string{"images", "--format", "{{.ID}}"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ ids := session.OutputToStringArray()
+
+ Expect(len(RESTORE_IMAGES), len(ids))
+ multiImageSave(podmanTest, ids)
+ })
})
+
+// Create a multi-image archive, remove all images, load it and
+// make sure that all images are (again) present.
+func multiImageSave(podmanTest *PodmanTestIntegration, images []string) {
+ // Create the archive.
+ outfile := filepath.Join(podmanTest.TempDir, "temp.tar")
+ session := podmanTest.PodmanNoCache(append([]string{"save", "-o", outfile, "--multi-image-archive"}, images...))
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // Remove all images.
+ session = podmanTest.PodmanNoCache([]string{"rmi", "-af"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // Now load the archive.
+ session = podmanTest.PodmanNoCache([]string{"load", "-i", outfile})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ // Grep for each image in the `podman load` output.
+ for _, image := range images {
+ found, _ := session.GrepString(image)
+ Expect(found).Should(BeTrue())
+ }
+
+ // Make sure that each image has really been loaded.
+ for _, image := range images {
+ session = podmanTest.PodmanNoCache([]string{"image", "exists", image})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ }
+}
diff --git a/test/e2e/testdata/image b/test/e2e/testdata/image
new file mode 120000
index 000000000..a9e67bf9a
--- /dev/null
+++ b/test/e2e/testdata/image
@@ -0,0 +1 @@
+../../../libpod/image/testdata/ \ No newline at end of file
diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats
index a5a3324fb..1d5eb066b 100644
--- a/test/system/001-basic.bats
+++ b/test/system/001-basic.bats
@@ -69,6 +69,17 @@ function setup() {
is "$output" "Error: unknown flag: --remote" "podman version --remote"
}
+# Check that just calling "podman-remote" prints the usage message even
+# without a running endpoint. Use "podman --remote" for this as this works the same.
+@test "podman-remote: check for command usage message without a running endpoint" {
+ if is_remote; then
+ skip "only applicable on a local run since this requires no endpoint"
+ fi
+
+ run_podman 125 --remote
+ is "$output" "Error: missing command 'podman COMMAND'" "podman remote show usage message without running endpoint"
+}
+
# This is for development only; it's intended to make sure our timeout
# in run_podman continues to work. This test should never run in production
# because it will, by definition, fail.
diff --git a/test/system/010-images.bats b/test/system/010-images.bats
index 7fd731ca0..c0a8936e3 100644
--- a/test/system/010-images.bats
+++ b/test/system/010-images.bats
@@ -14,6 +14,8 @@ load helpers
--format {{.ID}} | [0-9a-f]\\\{12\\\}
--format {{.ID}} --no-trunc | sha256:[0-9a-f]\\\{64\\\}
--format {{.Repository}}:{{.Tag}} | $PODMAN_TEST_IMAGE_FQN
+--format {{.Labels.created_by}} | test/system/build-testimage
+--format {{.Labels.created_at}} | 20[0-9-]\\\+T[0-9:]\\\+Z
"
parse_table "$tests" | while read fmt expect; do
@@ -27,11 +29,13 @@ load helpers
@test "podman images - json" {
# 'created': podman includes fractional seconds, podman-remote does not
tests="
-Names[0] | $PODMAN_TEST_IMAGE_FQN
-Id | [0-9a-f]\\\{64\\\}
-Digest | sha256:[0-9a-f]\\\{64\\\}
-CreatedAt | [0-9-]\\\+T[0-9:.]\\\+Z
-Size | [0-9]\\\+
+Names[0] | $PODMAN_TEST_IMAGE_FQN
+Id | [0-9a-f]\\\{64\\\}
+Digest | sha256:[0-9a-f]\\\{64\\\}
+CreatedAt | [0-9-]\\\+T[0-9:.]\\\+Z
+Size | [0-9]\\\+
+Labels.created_by | test/system/build-testimage
+Labels.created_at | 20[0-9-]\\\+T[0-9:]\\\+Z
"
run_podman images -a --format json
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index 5491dcc82..518d902a7 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -140,24 +140,29 @@ echo $rand | 0 | $rand
run_podman run --pull=never $IMAGE true
is "$output" "" "--pull=never [present]: no output"
- # Now test with busybox, which we don't have present
- run_podman 125 run --pull=never busybox true
- is "$output" "Error: unable to find a name and tag match for busybox in repotags: no such image" "--pull=never [busybox/missing]: error"
+ # Now test with a remote image which we don't have present (the 00 tag)
+ NONLOCAL_IMAGE="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:00000000"
- run_podman run --pull=missing busybox true
- is "$output" "Trying to pull .*" "--pull=missing [busybox/missing]: fetches"
+ run_podman 125 run --pull=never $NONLOCAL_IMAGE true
+ is "$output" "Error: unable to find a name and tag match for $NONLOCAL_IMAGE in repotags: no such image" "--pull=never [with image not present]: error"
- run_podman run --pull=always busybox true
- is "$output" "Trying to pull .*" "--pull=always [busybox/present]: fetches"
+ run_podman run --pull=missing $NONLOCAL_IMAGE true
+ is "$output" "Trying to pull .*" "--pull=missing [with image NOT PRESENT]: fetches"
+
+ run_podman run --pull=missing $NONLOCAL_IMAGE true
+ is "$output" "" "--pull=missing [with image PRESENT]: does not re-fetch"
+
+ run_podman run --pull=always $NONLOCAL_IMAGE true
+ is "$output" "Trying to pull .*" "--pull=always [with image PRESENT]: re-fetches"
run_podman rm -a
- run_podman rmi busybox
+ run_podman rmi $NONLOCAL_IMAGE
}
# 'run --rmi' deletes the image in the end unless it's used by another container
@test "podman run --rmi" {
# Name of a nonlocal image. It should be pulled in by the first 'run'
- NONLOCAL_IMAGE=busybox
+ NONLOCAL_IMAGE="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:00000000"
run_podman 1 image exists $NONLOCAL_IMAGE
# Run a container, without --rm; this should block subsequent --rmi
@@ -190,9 +195,19 @@ echo $rand | 0 | $rand
is "$(< $cidfile)" "$cid" "contents of cidfile == container ID"
- conmon_pid=$(< $pidfile)
- is "$(readlink /proc/$conmon_pid/exe)" ".*/conmon" \
- "conmon pidfile (= PID $conmon_pid) points to conmon process"
+ # Cross-check --conmon-pidfile against 'podman inspect'
+ local conmon_pid_from_file=$(< $pidfile)
+ run_podman inspect --format '{{.State.ConmonPid}}' $cid
+ local conmon_pid_from_inspect="$output"
+ is "$conmon_pid_from_file" "$conmon_pid_from_inspect" \
+ "Conmon pid in pidfile matches what 'podman inspect' claims"
+
+ # /proc/PID/exe should be a symlink to a conmon executable
+ # FIXME: 'echo' and 'ls' are to help debug #7580, a CI flake
+ echo "conmon pid = $conmon_pid_from_file"
+ ls -l /proc/$conmon_pid_from_file
+ is "$(readlink /proc/$conmon_pid_from_file/exe)" ".*/conmon" \
+ "conmon pidfile (= PID $conmon_pid_from_file) points to conmon process"
# All OK. Kill container.
run_podman rm -f $cid
@@ -205,7 +220,7 @@ echo $rand | 0 | $rand
}
@test "podman run docker-archive" {
- skip_if_remote "FIXME: pending #7116"
+ skip_if_remote "podman-remote does not support docker-archive (#7116)"
# Create an image that, when run, outputs a random magic string
expect=$(random_string 20)
diff --git a/test/system/055-rm.bats b/test/system/055-rm.bats
index 478ba0f20..c8475c3e9 100644
--- a/test/system/055-rm.bats
+++ b/test/system/055-rm.bats
@@ -44,8 +44,6 @@ load helpers
#
# See https://github.com/containers/podman/issues/3795
@test "podman rm -f" {
- skip_if_remote "FIXME: pending #7117"
-
rand=$(random_string 30)
( sleep 3; run_podman rm -f $rand ) &
run_podman 137 run --name $rand $IMAGE sleep 30
diff --git a/test/system/110-history.bats b/test/system/110-history.bats
index 5dc221d61..75c15b088 100644
--- a/test/system/110-history.bats
+++ b/test/system/110-history.bats
@@ -22,9 +22,10 @@ load helpers
}
@test "podman history - json" {
+ # Sigh. Timestamp in .created can be '...Z' or '...-06:00'
tests="
id | [0-9a-f]\\\{64\\\}
-created | [0-9-]\\\+T[0-9:.]\\\+Z
+created | [0-9-]\\\+T[0-9:.]\\\+[Z0-9:+-]\\\+
size | -\\\?[0-9]\\\+
"
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index 86b396c4a..d7aa16d95 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -27,25 +27,43 @@ verify_iid_and_name() {
}
@test "podman save to pipe and load" {
- get_iid_and_name
+ # Generate a random name and tag (must be lower-case)
+ local random_name=x$(random_string 12 | tr A-Z a-z)
+ local random_tag=t$(random_string 7 | tr A-Z a-z)
+ local fqin=localhost/$random_name:$random_tag
+ run_podman tag $IMAGE $fqin
+
+ archive=$PODMAN_TMPDIR/myimage-$(random_string 8).tar
# We can't use run_podman because that uses the BATS 'run' function
# which redirects stdout and stderr. Here we need to guarantee
# that podman's stdout is a pipe, not any other form of redirection
- $PODMAN save --format oci-archive $IMAGE | cat >$archive
+ $PODMAN save --format oci-archive $fqin | cat >$archive
if [ "$status" -ne 0 ]; then
die "Command failed: podman save ... | cat"
fi
# Make sure we can reload it
- # FIXME: when/if 7337 gets fixed, add a random tag instead of rmi'ing
- # FIXME: when/if 7371 gets fixed, use verify_iid_and_name()
- run_podman rmi $iid
+ run_podman rmi $fqin
run_podman load -i $archive
- # FIXME: cannot compare IID, see #7371
- run_podman images -a --format '{{.Repository}}:{{.Tag}}'
- is "$output" "$IMAGE" "image preserves name across save/load"
+ # FIXME: cannot compare IID, see #7371, so we check only the tag
+ run_podman images $fqin --format '{{.Repository}}:{{.Tag}}'
+ is "$output" "$fqin" "image preserves name across save/load"
+
+ # FIXME: when/if 7337 gets fixed, load with a new tag
+ if false; then
+ local new_name=x$(random_string 14 | tr A-Z a-z)
+ local new_tag=t$(random_string 6 | tr A-Z a-z)
+ run_podman rmi $fqin
+ fqin=localhost/$new_name:$new_tag
+ run_podman load -i $archive $fqin
+ run_podman images $fqin --format '{{.Repository}}:{{.Tag}}'
+ is "$output" "$fqin" "image can be loaded with new name:tag"
+ fi
+
+ # Clean up
+ run_podman rmi $fqin
}
diff --git a/test/system/130-kill.bats b/test/system/130-kill.bats
index 05090f852..c16e64c58 100644
--- a/test/system/130-kill.bats
+++ b/test/system/130-kill.bats
@@ -6,8 +6,6 @@
load helpers
@test "podman kill - test signal handling in containers" {
- skip_if_remote "FIXME: pending #7135"
-
# podman-remote and crun interact poorly in f31: crun seems to gobble up
# some signals.
# Workaround: run 'env --default-signal sh' instead of just 'sh' in
diff --git a/test/system/150-login.bats b/test/system/150-login.bats
index 00c60ca95..5151ab0e1 100644
--- a/test/system/150-login.bats
+++ b/test/system/150-login.bats
@@ -56,14 +56,17 @@ function setup() {
AUTHDIR=${PODMAN_LOGIN_WORKDIR}/auth
mkdir -p $AUTHDIR
+ # Registry image; copy of docker.io, but on our own registry
+ local REGISTRY_IMAGE="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/registry:2.7"
+
# Pull registry image, but into a separate container storage
mkdir -p ${PODMAN_LOGIN_WORKDIR}/root
mkdir -p ${PODMAN_LOGIN_WORKDIR}/runroot
PODMAN_LOGIN_ARGS="--root ${PODMAN_LOGIN_WORKDIR}/root --runroot ${PODMAN_LOGIN_WORKDIR}/runroot"
# Give it three tries, to compensate for flakes
- run_podman ${PODMAN_LOGIN_ARGS} pull registry:2.6 ||
- run_podman ${PODMAN_LOGIN_ARGS} pull registry:2.6 ||
- run_podman ${PODMAN_LOGIN_ARGS} pull registry:2.6
+ run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE ||
+ run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE ||
+ run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE
# Registry image needs a cert. Self-signed is good enough.
CERT=$AUTHDIR/domain.crt
@@ -76,10 +79,8 @@ function setup() {
# Store credentials where container will see them
if [ ! -e $AUTHDIR/htpasswd ]; then
- run_podman ${PODMAN_LOGIN_ARGS} run --rm \
- --entrypoint htpasswd registry:2.6 \
- -Bbn ${PODMAN_LOGIN_USER} ${PODMAN_LOGIN_PASS} \
- > $AUTHDIR/htpasswd
+ htpasswd -Bbn ${PODMAN_LOGIN_USER} ${PODMAN_LOGIN_PASS} \
+ > $AUTHDIR/htpasswd
# In case $PODMAN_TEST_KEEP_LOGIN_REGISTRY is set, for testing later
echo "${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}" \
@@ -97,7 +98,7 @@ function setup() {
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/auth/domain.key \
- registry:2.6
+ $REGISTRY_IMAGE
}
# END first "test" - start a registry for use by other tests
@@ -189,38 +190,26 @@ EOF
}
@test "podman push ok" {
- # ARGH! We can't push $IMAGE (alpine_labels) to this registry; error is:
- #
- # Writing manifest to image destination
- # Error: Error copying image to the remote destination: Error writing manifest: Error uploading manifest latest to localhost:${PODMAN_LOGIN_REGISTRY_PORT}/okpush: received unexpected HTTP status: 500 Internal Server Error
- #
- # Root cause: something to do with v1/v2 s1/s2:
- #
- # https://github.com/containers/skopeo/issues/651
- #
-
- run_podman pull busybox
-
- # Preserve its ID for later comparison against push/pulled image
- run_podman inspect --format '{{.Id}}' busybox
- id_busybox=$output
+ # Preserve image ID for later comparison against push/pulled image
+ run_podman inspect --format '{{.Id}}' $IMAGE
+ iid=$output
destname=ok-$(random_string 10 | tr A-Z a-z)-ok
# Use command-line credentials
run_podman push --tls-verify=false \
--creds ${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS} \
- busybox localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
+ $IMAGE localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
# Yay! Pull it back
run_podman pull --tls-verify=false \
--creds ${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS} \
localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
- # Compare to original busybox
+ # Compare to original image
run_podman inspect --format '{{.Id}}' $destname
- is "$output" "$id_busybox" "Image ID of pulled image == busybox"
+ is "$output" "$iid" "Image ID of pulled image == original IID"
- run_podman rmi busybox $destname
+ run_podman rmi $destname
}
# END primary podman login/push/pull tests
diff --git a/test/system/260-sdnotify.bats b/test/system/260-sdnotify.bats
index 62d3c1497..06aa3bba7 100644
--- a/test/system/260-sdnotify.bats
+++ b/test/system/260-sdnotify.bats
@@ -115,9 +115,10 @@ function _assert_mainpid_is_conmon() {
@test "sdnotify : container" {
# Sigh... we need to pull a humongous image because it has systemd-notify.
+ # (IMPORTANT: fedora:32 and above silently removed systemd-notify; this
+ # caused CI to hang. That's why we explicitly require fedora:31)
# FIXME: is there a smaller image we could use?
- _FEDORA=registry.fedoraproject.org/fedora:31
-
+ local _FEDORA="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/fedora:31"
# Pull that image. Retry in case of flakes.
run_podman pull $_FEDORA || \
run_podman pull $_FEDORA || \
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index 0fae3dcd3..39de8ad54 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -12,7 +12,7 @@ load helpers
random_2=$(random_string 30)
HOST_PORT=8080
- SERVER=http://localhost:$HOST_PORT
+ SERVER=http://127.0.0.1:$HOST_PORT
# Create a test file with random content
INDEX1=$PODMAN_TMPDIR/hello.txt
@@ -22,7 +22,7 @@ load helpers
run_podman run -d --name myweb -p "$HOST_PORT:80" \
-v $INDEX1:/var/www/index.txt \
-w /var/www \
- busybox httpd -f -p 80
+ $IMAGE /bin/busybox-extras httpd -f -p 80
cid=$output
# In that container, create a second file, using exec and redirection
@@ -33,14 +33,14 @@ load helpers
# Verify http contents: curl from localhost
run curl -s $SERVER/index.txt
- is "$output" "$random_1" "curl localhost:/index.txt"
+ is "$output" "$random_1" "curl 127.0.0.1:/index.txt"
run curl -s $SERVER/index2.txt
- is "$output" "$random_2" "curl localhost:/index2.txt"
+ is "$output" "$random_2" "curl 127.0.0.1:/index2.txt"
# Verify http contents: wget from a second container
- run_podman run --rm --net=host busybox wget -qO - $SERVER/index.txt
+ run_podman run --rm --net=host $IMAGE wget -qO - $SERVER/index.txt
is "$output" "$random_1" "podman wget /index.txt"
- run_podman run --rm --net=host busybox wget -qO - $SERVER/index2.txt
+ run_podman run --rm --net=host $IMAGE wget -qO - $SERVER/index2.txt
is "$output" "$random_2" "podman wget /index2.txt"
# Tests #4889 - two-argument form of "podman ports" was broken
@@ -57,7 +57,6 @@ load helpers
# Clean up
run_podman stop -t 1 myweb
run_podman rm myweb
- run_podman rmi busybox
}
# Issue #5466 - port-forwarding doesn't work with this option and -d
diff --git a/test/system/build-testimage b/test/system/build-testimage
new file mode 100755
index 000000000..64aa46337
--- /dev/null
+++ b/test/system/build-testimage
@@ -0,0 +1,59 @@
+#!/bin/bash
+#
+# build-testimage - script for producing a test image for podman CI
+#
+# The idea is to have a small multi-purpose image that can be pulled once
+# by system tests and used for as many tests as possible. This image
+# should live on quay.io, should be small in size, and should include
+# as many components as needed by system tests so they don't have to
+# pull other images.
+#
+# Unfortunately, "small" is incompatible with "systemd" so tests
+# still need a fedora image for that.
+#
+
+# Tag for this new image
+YMD=$(date +%Y%m%d)
+
+# git-relative path to this script
+create_script=$(cd $(dirname $0) && git ls-files --full-name $(basename $0))
+if [ -z "$create_script" ]; then
+ create_script=$0
+fi
+
+# Creation timestamp, Zulu time
+create_time_z=$(env TZ=UTC date +'%Y-%m-%dT%H:%M:%SZ')
+
+set -ex
+
+# Please document the reason for all flags, apk's, and anything non-obvious
+#
+# --squash-all : needed by 'tree' test in 070-build.bats
+# busybox-extras : provides httpd needed in 500-networking.bats
+#
+podman rmi -f testimage &> /dev/null || true
+podman build --squash-all -t testimage - <<EOF
+FROM docker.io/library/alpine:3.12.0
+RUN apk add busybox-extras
+LABEL created_by=$create_script
+LABEL created_at=$create_time_z
+CMD ["/bin/echo", "This container is intended for podman CI testing"]
+EOF
+
+# Tag and push to quay.
+podman tag testimage quay.io/edsantiago/testimage:$YMD
+podman push quay.io/edsantiago/testimage:$YMD
+
+# Side note: there should always be a testimage tagged ':00000000'
+# (eight zeroes) in the same location; this is used by tests which
+# need to pull a non-locally-cached image. This image will rarely
+# if ever need to change, nor in fact does it even have to be a
+# copy of this testimage since all we use it for is 'true'.
+#
+# As of 2020-09-02 it is simply busybox, because it is super small:
+#
+# podman pull docker.io/library/busybox:1.32.0
+# podman tag docker.io/library/busybox:1.32.0 \
+# quay.io/edsantiago/testimage:00000000
+# podman push quay.io/edsantiago/testimage:00000000
+#
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index a6414344e..514ba249e 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -6,8 +6,8 @@ PODMAN=${PODMAN:-podman}
# Standard image to use for most tests
PODMAN_TEST_IMAGE_REGISTRY=${PODMAN_TEST_IMAGE_REGISTRY:-"quay.io"}
PODMAN_TEST_IMAGE_USER=${PODMAN_TEST_IMAGE_USER:-"libpod"}
-PODMAN_TEST_IMAGE_NAME=${PODMAN_TEST_IMAGE_NAME:-"alpine_labels"}
-PODMAN_TEST_IMAGE_TAG=${PODMAN_TEST_IMAGE_TAG:-"latest"}
+PODMAN_TEST_IMAGE_NAME=${PODMAN_TEST_IMAGE_NAME:-"testimage"}
+PODMAN_TEST_IMAGE_TAG=${PODMAN_TEST_IMAGE_TAG:-"20200902"}
PODMAN_TEST_IMAGE_FQN="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG"
# Because who wants to spell that out each time?
@@ -67,7 +67,7 @@ function basic_teardown() {
run_podman '?' pod rm --all --force
run_podman '?' rm --all --force
- /bin/rm -rf $PODMAN_TMPDIR
+ command rm -rf $PODMAN_TMPDIR
}