podman

Форк
0
/
run_test.go 
2238 строк · 94.0 Кб
1
package integration
2

3
import (
4
	"fmt"
5
	"net"
6
	"os"
7
	"path/filepath"
8
	"strconv"
9
	"strings"
10
	"syscall"
11
	"time"
12

13
	"github.com/containers/common/pkg/cgroups"
14
	"github.com/containers/common/pkg/config"
15
	"github.com/containers/podman/v5/libpod/define"
16
	. "github.com/containers/podman/v5/test/utils"
17
	"github.com/containers/storage/pkg/stringid"
18
	. "github.com/onsi/ginkgo/v2"
19
	. "github.com/onsi/gomega"
20
	. "github.com/onsi/gomega/gexec"
21
)
22

23
var _ = Describe("Podman run", func() {
24

25
	It("podman run a container based on local image", func() {
26
		session := podmanTest.Podman([]string{"run", ALPINE, "ls"})
27
		session.WaitWithDefaultTimeout()
28
		Expect(session).Should(ExitCleanly())
29
	})
30

31
	// This test may seem entirely pointless, it is not.  Due to compatibility
32
	// and historical reasons, the container name generator uses a globally
33
	// scoped RNG, seeded from a global state.  An easy way to check if its
34
	// been initialized properly (i.e. pseudo-non-deterministically) is
35
	// checking if the name-generator spits out the same name twice.  Because
36
	// existing containers are checked when generating names, the test must ensure
37
	// the first container is removed before creating a second.
38
	It("podman generates different names for successive containers", func() {
39
		var names [2]string
40

41
		for i := range names {
42
			session := podmanTest.Podman([]string{"create", ALPINE, "true"})
43
			session.WaitWithDefaultTimeout()
44
			Expect(session).Should(ExitCleanly())
45
			cid := session.OutputToString()
46
			Expect(cid).To(Not(Equal("")))
47

48
			session = podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Name}}", cid})
49
			session.WaitWithDefaultTimeout()
50
			Expect(session).Should(ExitCleanly())
51
			names[i] = session.OutputToString()
52
			Expect(names[i]).To(Not(Equal("")))
53

54
			session = podmanTest.Podman([]string{"rm", cid})
55
			session.WaitWithDefaultTimeout()
56
			Expect(session).Should(ExitCleanly())
57
		}
58
		Expect(names[0]).ToNot(Equal(names[1]), "Podman generated duplicate successive container names, has the global RNG been seeded correctly?")
59
	})
60

61
	It("podman run check /run/.containerenv", func() {
62
		session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/run/.containerenv"})
63
		session.WaitWithDefaultTimeout()
64
		Expect(session).Should(ExitCleanly())
65
		Expect(session.OutputToString()).To(Equal(""))
66

67
		session = podmanTest.Podman([]string{"run", "--privileged", "--name=test1", ALPINE, "cat", "/run/.containerenv"})
68
		session.WaitWithDefaultTimeout()
69
		Expect(session).Should(ExitCleanly())
70
		Expect(session.OutputToString()).To(ContainSubstring("name=\"test1\""))
71
		Expect(session.OutputToString()).To(ContainSubstring("image=\"" + ALPINE + "\""))
72

73
		session = podmanTest.Podman([]string{"run", "-v", "/:/host", ALPINE, "cat", "/run/.containerenv"})
74
		session.WaitWithDefaultTimeout()
75
		Expect(session).Should(ExitCleanly())
76
		Expect(session.OutputToString()).To(ContainSubstring("graphRootMounted=1"))
77

78
		session = podmanTest.Podman([]string{"run", "-v", "/:/host", "--privileged", ALPINE, "cat", "/run/.containerenv"})
79
		session.WaitWithDefaultTimeout()
80
		Expect(session).Should(ExitCleanly())
81
		Expect(session.OutputToString()).To(ContainSubstring("graphRootMounted=1"))
82
	})
83

84
	It("podman run from manifest list", func() {
85
		session := podmanTest.Podman([]string{"manifest", "create", "localhost/test:latest"})
86
		session.WaitWithDefaultTimeout()
87
		Expect(session).Should(ExitCleanly())
88

89
		session = podmanTest.Podman([]string{"build", "-q", "-f", "build/Containerfile.with-platform", "--platform", "linux/amd64,linux/arm64", "--manifest", "localhost/test:latest"})
90
		session.WaitWithDefaultTimeout()
91
		Expect(session).Should(ExitCleanly())
92

93
		session = podmanTest.Podman([]string{"run", "--platform", "linux/arm64", "localhost/test", "uname", "-a"})
94
		session.WaitWithDefaultTimeout()
95
		exitCode := session.ExitCode()
96
		// CI could either support requested platform or not, if it supports then output should contain `aarch64`
97
		// if not run should fail with a very specific error i.e `Exec format error` anything other than this should
98
		// be marked as failure of test.
99
		if exitCode == 0 {
100
			Expect(session.OutputToString()).To(ContainSubstring("aarch64"))
101
		} else {
102
			// crun says 'Exec', runc says 'exec'. Handle either.
103
			Expect(session.ErrorToString()).To(ContainSubstring("xec format error"))
104
		}
105
	})
106

107
	It("podman run a container based on a complex local image name", func() {
108
		imageName := strings.TrimPrefix(NGINX_IMAGE, "quay.io/")
109
		session := podmanTest.Podman([]string{"run", imageName, "ls"})
110
		session.WaitWithDefaultTimeout()
111
		Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull"))
112
		Expect(session).Should(ExitCleanly())
113
	})
114

115
	It("podman run --signature-policy", func() {
116
		session := podmanTest.Podman([]string{"run", "--pull=always", "--signature-policy", "/no/such/file", ALPINE})
117
		session.WaitWithDefaultTimeout()
118
		Expect(session).To(ExitWithError())
119

120
		session = podmanTest.Podman([]string{"run", "--pull=always", "--signature-policy", "/etc/containers/policy.json", ALPINE})
121
		session.WaitWithDefaultTimeout()
122
		if IsRemote() {
123
			Expect(session).To(ExitWithError())
124
			Expect(session.ErrorToString()).To(ContainSubstring("unknown flag"))
125
		} else {
126
			Expect(session).Should(Exit(0))
127
			Expect(session.ErrorToString()).To(ContainSubstring("Getting image source signatures"))
128
		}
129
	})
130

131
	It("podman run --rm with --restart", func() {
132
		session := podmanTest.Podman([]string{"run", "--rm", "--restart", "", ALPINE})
133
		session.WaitWithDefaultTimeout()
134
		Expect(session).Should(ExitCleanly())
135

136
		session = podmanTest.Podman([]string{"run", "--rm", "--restart", "no", ALPINE})
137
		session.WaitWithDefaultTimeout()
138
		Expect(session).Should(ExitCleanly())
139

140
		session = podmanTest.Podman([]string{"run", "--rm", "--restart", "on-failure", ALPINE})
141
		session.WaitWithDefaultTimeout()
142
		Expect(session).Should(ExitCleanly())
143

144
		session = podmanTest.Podman([]string{"run", "--rm", "--restart", "always", ALPINE})
145
		session.WaitWithDefaultTimeout()
146
		Expect(session).To(ExitWithError())
147

148
		session = podmanTest.Podman([]string{"run", "--rm", "--restart", "unless-stopped", ALPINE})
149
		session.WaitWithDefaultTimeout()
150
		Expect(session).To(ExitWithError())
151
	})
152

153
	It("podman run a container based on on a short name with localhost", func() {
154
		tag := podmanTest.Podman([]string{"tag", NGINX_IMAGE, "localhost/libpod/alpine_nginx:latest"})
155
		tag.WaitWithDefaultTimeout()
156

157
		rmi := podmanTest.Podman([]string{"rmi", NGINX_IMAGE})
158
		rmi.WaitWithDefaultTimeout()
159

160
		session := podmanTest.Podman([]string{"run", "libpod/alpine_nginx:latest", "ls"})
161
		session.WaitWithDefaultTimeout()
162
		Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull"))
163
		Expect(session).Should(ExitCleanly())
164
	})
165

166
	It("podman container run a container based on on a short name with localhost", func() {
167
		tag := podmanTest.Podman([]string{"image", "tag", NGINX_IMAGE, "localhost/libpod/alpine_nginx:latest"})
168
		tag.WaitWithDefaultTimeout()
169

170
		rmi := podmanTest.Podman([]string{"image", "rm", NGINX_IMAGE})
171
		rmi.WaitWithDefaultTimeout()
172

173
		session := podmanTest.Podman([]string{"container", "run", "libpod/alpine_nginx:latest", "ls"})
174
		session.WaitWithDefaultTimeout()
175
		Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull"))
176
		Expect(session).Should(ExitCleanly())
177
	})
178

179
	It("podman run a container based on local image with short options", func() {
180
		session := podmanTest.Podman([]string{"run", "-dt", ALPINE, "ls"})
181
		session.WaitWithDefaultTimeout()
182
		Expect(session).Should(ExitCleanly())
183
	})
184

185
	It("podman run a container based on local image with short options and args", func() {
186
		// regression test for #714
187
		session := podmanTest.Podman([]string{"run", ALPINE, "find", "/etc", "-name", "hosts"})
188
		session.WaitWithDefaultTimeout()
189
		Expect(session).Should(ExitCleanly())
190
		Expect(session.OutputToString()).To(ContainSubstring("/etc/hosts"))
191
	})
192

193
	It("podman run --name X --hostname Y, both X and Y in /etc/hosts", func() {
194
		name := "test_container"
195
		hostname := "test_hostname"
196
		session := podmanTest.Podman([]string{"run", "--rm", "--name", name, "--hostname", hostname, ALPINE, "cat", "/etc/hosts"})
197
		session.WaitWithDefaultTimeout()
198
		Expect(session).Should(ExitCleanly())
199
		Expect(session.OutputToString()).To(ContainSubstring(name))
200
		Expect(session.OutputToString()).To(ContainSubstring(hostname))
201
	})
202

203
	It("podman run a container based on remote image", func() {
204
		// Pick any image that is not in our cache
205
		session := podmanTest.Podman([]string{"run", "-dt", BB_GLIBC, "ls"})
206
		session.WaitWithDefaultTimeout()
207
		Expect(session).Should(Exit(0))
208
		Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull " + BB_GLIBC))
209
		Expect(session.ErrorToString()).To(ContainSubstring("Writing manifest to image destination"))
210

211
	})
212

213
	It("podman run --tls-verify", func() {
214
		// 5000 is marked insecure in registries.conf, so --tls-verify=false
215
		// is a NOP. Pick any other port.
216
		port := "5050"
217
		lock := GetPortLock(port)
218
		defer lock.Unlock()
219
		session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", port + ":5000", REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"})
220
		session.WaitWithDefaultTimeout()
221
		Expect(session).Should(ExitCleanly())
222

223
		if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
224
			Fail("Cannot start docker registry.")
225
		}
226

227
		pushedImage := "localhost:" + port + "/pushed" + strings.ToLower(RandomString(5)) + ":" + RandomString(8)
228
		push := podmanTest.Podman([]string{"push", "--tls-verify=false", ALPINE, pushedImage})
229
		push.WaitWithDefaultTimeout()
230
		Expect(push).To(Exit(0))
231
		Expect(push.ErrorToString()).To(ContainSubstring("Writing manifest to image destination"))
232

233
		run := podmanTest.Podman([]string{"run", pushedImage, "date"})
234
		run.WaitWithDefaultTimeout()
235
		Expect(run).Should(Exit(125))
236
		Expect(run.ErrorToString()).To(ContainSubstring("pinging container registry localhost:" + port))
237
		Expect(run.ErrorToString()).To(ContainSubstring("http: server gave HTTP response to HTTPS client"))
238

239
		run = podmanTest.Podman([]string{"run", "--tls-verify=false", pushedImage, "echo", "got here"})
240
		run.WaitWithDefaultTimeout()
241
		Expect(run).Should(Exit(0))
242
		Expect(run.OutputToString()).To(Equal("got here"))
243
		Expect(run.ErrorToString()).To(ContainSubstring("Trying to pull " + pushedImage))
244
	})
245

246
	It("podman run a container with a --rootfs", func() {
247
		rootfs := filepath.Join(tempdir, "rootfs")
248
		uls := filepath.Join("/", "usr", "local", "share")
249
		uniqueString := stringid.GenerateRandomID()
250
		testFilePath := filepath.Join(uls, uniqueString)
251
		tarball := filepath.Join(tempdir, "rootfs.tar")
252

253
		err := os.Mkdir(rootfs, 0770)
254
		Expect(err).ShouldNot(HaveOccurred())
255

256
		// Change image in predictable way to validate export
257
		csession := podmanTest.Podman([]string{"run", "--name", uniqueString, ALPINE,
258
			"/bin/sh", "-c", fmt.Sprintf("echo %s > %s", uniqueString, testFilePath)})
259
		csession.WaitWithDefaultTimeout()
260
		Expect(csession).Should(ExitCleanly())
261

262
		// Export from working container image guarantees working root
263
		esession := podmanTest.Podman([]string{"export", "--output", tarball, uniqueString})
264
		esession.WaitWithDefaultTimeout()
265
		Expect(esession).Should(ExitCleanly())
266
		Expect(tarball).Should(BeARegularFile())
267

268
		// N/B: This will lose any extended attributes like SELinux types
269
		GinkgoWriter.Printf("Extracting container root tarball\n")
270
		tarsession := SystemExec("tar", []string{"xf", tarball, "-C", rootfs})
271
		Expect(tarsession).Should(ExitCleanly())
272
		Expect(filepath.Join(rootfs, uls)).Should(BeADirectory())
273

274
		// Other tests confirm SELinux types, just confirm --rootfs is working.
275
		session := podmanTest.Podman([]string{"run", "-i", "--security-opt", "label=disable",
276
			"--rootfs", rootfs, "cat", testFilePath})
277
		session.WaitWithDefaultTimeout()
278
		Expect(session).Should(ExitCleanly())
279

280
		// Validate changes made in original container and export
281
		stdoutLines := session.OutputToStringArray()
282
		Expect(stdoutLines).Should(HaveLen(1))
283
		Expect(stdoutLines[0]).Should(Equal(uniqueString))
284

285
		// The rest of these tests only work locally and not containerized
286
		if IsRemote() || os.Getenv("container") != "" {
287
			GinkgoWriter.Println("Bypassing subsequent tests due to remote or container environment")
288
			return
289
		}
290
		// Test --rootfs with an external overlay
291
		// use --rm to remove container and confirm if we did not leak anything
292
		osession := podmanTest.Podman([]string{"run", "-i", "--rm", "--security-opt", "label=disable",
293
			"--rootfs", rootfs + ":O", "cat", testFilePath})
294
		osession.WaitWithDefaultTimeout()
295
		Expect(osession).Should(ExitCleanly())
296
		Expect(osession.OutputToString()).To(Equal(uniqueString))
297

298
		// Test podman start stop with overlay
299
		osession = podmanTest.Podman([]string{"run", "--name", "overlay-foo", "--security-opt", "label=disable",
300
			"--rootfs", rootfs + ":O", "echo", "hello"})
301
		osession.WaitWithDefaultTimeout()
302
		Expect(osession).Should(ExitCleanly())
303
		Expect(osession.OutputToString()).To(Equal("hello"))
304

305
		podmanTest.StopContainer("overlay-foo")
306

307
		startsession := podmanTest.Podman([]string{"start", "--attach", "overlay-foo"})
308
		startsession.WaitWithDefaultTimeout()
309
		Expect(startsession).Should(ExitCleanly())
310
		Expect(startsession.OutputToString()).To(Equal("hello"))
311

312
		// remove container for above test overlay-foo
313
		osession = podmanTest.Podman([]string{"rm", "overlay-foo"})
314
		osession.WaitWithDefaultTimeout()
315
		Expect(osession).Should(ExitCleanly())
316

317
		// Test --rootfs with an external overlay with --uidmap
318
		osession = podmanTest.Podman([]string{"run", "--uidmap", "0:1234:5678", "--rm", "--security-opt", "label=disable",
319
			"--rootfs", rootfs + ":O", "cat", "/proc/self/uid_map"})
320
		osession.WaitWithDefaultTimeout()
321
		Expect(osession).Should(ExitCleanly())
322
		Expect(osession.OutputToString()).To(Equal("0 1234 5678"))
323
	})
324

325
	It("podman run a container with --init", func() {
326
		session := podmanTest.Podman([]string{"run", "--name", "test", "--init", ALPINE, "ls"})
327
		session.WaitWithDefaultTimeout()
328
		Expect(session).Should(ExitCleanly())
329
		result := podmanTest.Podman([]string{"inspect", "test"})
330
		result.WaitWithDefaultTimeout()
331
		Expect(result).Should(ExitCleanly())
332
		conData := result.InspectContainerToJSON()
333
		Expect(conData[0]).To(HaveField("Path", define.ContainerInitPath))
334
		Expect(conData[0].Config.Annotations).To(HaveKeyWithValue("io.podman.annotations.init", "TRUE"))
335
	})
336

337
	It("podman run a container with --init and --init-path", func() {
338
		// Also bind-mount /dev (#14251).
339
		session := podmanTest.Podman([]string{"run", "-v", "/dev:/dev", "--name", "test", "--init", "--init-path", "/usr/libexec/podman/catatonit", ALPINE, "ls"})
340
		session.WaitWithDefaultTimeout()
341
		Expect(session).Should(ExitCleanly())
342
		result := podmanTest.Podman([]string{"inspect", "test"})
343
		result.WaitWithDefaultTimeout()
344
		Expect(result).Should(ExitCleanly())
345
		conData := result.InspectContainerToJSON()
346
		Expect(conData[0]).To(HaveField("Path", define.ContainerInitPath))
347
		Expect(conData[0].Config.Annotations).To(HaveKeyWithValue("io.podman.annotations.init", "TRUE"))
348
	})
349

350
	It("podman run a container without --init", func() {
351
		session := podmanTest.Podman([]string{"run", "--name", "test", ALPINE, "ls"})
352
		session.WaitWithDefaultTimeout()
353
		Expect(session).Should(ExitCleanly())
354
		result := podmanTest.Podman([]string{"inspect", "test"})
355
		result.WaitWithDefaultTimeout()
356
		Expect(result).Should(ExitCleanly())
357
		conData := result.InspectContainerToJSON()
358
		Expect(conData[0]).To(HaveField("Path", "ls"))
359
		Expect(conData[0].Config.Annotations).To(Not(HaveKey("io.podman.annotations.init")))
360
	})
361

362
	forbidLinkSeccompProfile := func() string {
363
		in := []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"link","action":"SCMP_ACT_ERRNO"}]}`)
364
		jsonFile, err := podmanTest.CreateSeccompJSON(in)
365
		if err != nil {
366
			GinkgoWriter.Println(err)
367
			Skip("Failed to prepare seccomp.json for test.")
368
		}
369
		return jsonFile
370
	}
371

372
	It("podman run default mask test", func() {
373
		session := podmanTest.Podman([]string{"run", "-d", "--name=maskCtr", ALPINE, "sleep", "200"})
374
		session.WaitWithDefaultTimeout()
375
		Expect(session).Should(ExitCleanly())
376
		for _, mask := range config.DefaultMaskedPaths {
377
			if st, err := os.Stat(mask); err == nil {
378
				if st.IsDir() {
379
					session = podmanTest.Podman([]string{"exec", "maskCtr", "ls", mask})
380
					session.WaitWithDefaultTimeout()
381
					Expect(session).Should(ExitCleanly())
382
					Expect(session.OutputToString()).To(BeEmpty())
383
				} else {
384
					session = podmanTest.Podman([]string{"exec", "maskCtr", "cat", mask})
385
					session.WaitWithDefaultTimeout()
386
					// Call can fail with permission denied, ignoring error or Not exist.
387
					// key factor is there is no information leak
388
					Expect(session.OutputToString()).To(BeEmpty())
389
				}
390
			}
391
		}
392
		for _, mask := range config.DefaultReadOnlyPaths {
393
			if _, err := os.Stat(mask); err == nil {
394
				session = podmanTest.Podman([]string{"exec", "maskCtr", "touch", mask})
395
				session.WaitWithDefaultTimeout()
396
				Expect(session).Should(Exit(1))
397
				Expect(session.ErrorToString()).To(Equal(fmt.Sprintf("touch: %s: Read-only file system", mask)))
398
			}
399
		}
400
	})
401

402
	It("podman run mask and unmask path test", func() {
403
		session := podmanTest.Podman([]string{"run", "-d", "--name=maskCtr1", "--security-opt", "unmask=ALL", "--security-opt", "mask=/proc/acpi", ALPINE, "sleep", "200"})
404
		session.WaitWithDefaultTimeout()
405
		Expect(session).Should(ExitCleanly())
406
		session = podmanTest.Podman([]string{"exec", "maskCtr1", "ls", "/sys/firmware"})
407
		session.WaitWithDefaultTimeout()
408
		Expect(session.OutputToString()).To(Not(BeEmpty()))
409
		Expect(session).Should(ExitCleanly())
410
		session = podmanTest.Podman([]string{"exec", "maskCtr1", "ls", "/proc/acpi"})
411
		session.WaitWithDefaultTimeout()
412
		Expect(session.OutputToString()).To(BeEmpty())
413

414
		session = podmanTest.Podman([]string{"run", "-d", "--name=maskCtr2", "--security-opt", "unmask=/proc/acpi:/sys/firmware", ALPINE, "sleep", "200"})
415
		session.WaitWithDefaultTimeout()
416
		Expect(session).Should(ExitCleanly())
417
		session = podmanTest.Podman([]string{"exec", "maskCtr2", "ls", "/sys/firmware"})
418
		session.WaitWithDefaultTimeout()
419
		Expect(session.OutputToString()).To(Not(BeEmpty()))
420
		Expect(session).Should(ExitCleanly())
421
		session = podmanTest.Podman([]string{"exec", "maskCtr2", "ls", "/proc/acpi"})
422
		session.WaitWithDefaultTimeout()
423
		Expect(session.OutputToString()).To(Not(BeEmpty()))
424
		Expect(session).Should(ExitCleanly())
425

426
		session = podmanTest.Podman([]string{"run", "-d", "--name=maskCtr3", "--security-opt", "mask=/sys/power/disk", ALPINE, "sleep", "200"})
427
		session.WaitWithDefaultTimeout()
428
		Expect(session).Should(ExitCleanly())
429
		session = podmanTest.Podman([]string{"exec", "maskCtr3", "cat", "/sys/power/disk"})
430
		session.WaitWithDefaultTimeout()
431
		Expect(session.OutputToString()).To(BeEmpty())
432
		Expect(session).Should(ExitCleanly())
433

434
		session = podmanTest.Podman([]string{"run", "-d", "--name=maskCtr4", "--security-opt", "systempaths=unconfined", ALPINE, "sleep", "200"})
435
		session.WaitWithDefaultTimeout()
436
		Expect(session).Should(ExitCleanly())
437
		session = podmanTest.Podman([]string{"exec", "maskCtr4", "ls", "/sys/firmware"})
438
		session.WaitWithDefaultTimeout()
439
		Expect(session.OutputToString()).To(Not(BeEmpty()))
440
		Expect(session).Should(ExitCleanly())
441

442
		session = podmanTest.Podman([]string{"run", "-d", "--name=maskCtr5", "--security-opt", "systempaths=unconfined", ALPINE, "grep", "/proc", "/proc/self/mounts"})
443
		session.WaitWithDefaultTimeout()
444
		Expect(session).Should(ExitCleanly())
445
		Expect(session.OutputToStringArray()).Should(HaveLen(1))
446

447
		session = podmanTest.Podman([]string{"run", "-d", "--security-opt", "unmask=/proc/*", ALPINE, "grep", "/proc", "/proc/self/mounts"})
448
		session.WaitWithDefaultTimeout()
449
		Expect(session).Should(ExitCleanly())
450
		Expect(session.OutputToStringArray()).Should(HaveLen(1))
451

452
		session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=/proc/a*", ALPINE, "ls", "/proc/acpi"})
453
		session.WaitWithDefaultTimeout()
454
		Expect(session).Should(ExitCleanly())
455
		Expect(session.OutputToString()).To(Not(BeEmpty()))
456
	})
457

458
	It("podman run powercap is masked", func() {
459
		Skip("CI VMs do not have access to powercap")
460

461
		testCtr1 := "testctr"
462
		run := podmanTest.Podman([]string{"run", "-d", "--name", testCtr1, ALPINE, "top"})
463
		run.WaitWithDefaultTimeout()
464
		Expect(run).Should(ExitCleanly())
465

466
		exec := podmanTest.Podman([]string{"exec", "-ti", testCtr1, "ls", "/sys/devices/virtual/powercap"})
467
		exec.WaitWithDefaultTimeout()
468
		Expect(exec).To(ExitWithError())
469

470
		testCtr2 := "testctr2"
471
		run2 := podmanTest.Podman([]string{"run", "-d", "--privileged", "--name", testCtr2, ALPINE, "top"})
472
		run2.WaitWithDefaultTimeout()
473
		Expect(run2).Should(ExitCleanly())
474

475
		exec2 := podmanTest.Podman([]string{"exec", "-ti", testCtr2, "ls", "/sys/devices/virtual/powercap"})
476
		exec2.WaitWithDefaultTimeout()
477
		Expect(exec2).Should(ExitCleanly())
478
		Expect(exec2.OutputToString()).Should(Not(BeEmpty()))
479
	})
480

481
	It("podman run security-opt unmask on /sys/fs/cgroup", func() {
482

483
		SkipIfCgroupV1("podman umask on /sys/fs/cgroup will fail with cgroups V1")
484
		SkipIfRootless("/sys/fs/cgroup rw access is needed")
485
		rwOnCgroups := "/sys/fs/cgroup cgroup2 rw"
486
		session := podmanTest.Podman([]string{"run", "--security-opt", "unmask=ALL", "--security-opt", "mask=/sys/fs/cgroup", ALPINE, "cat", "/proc/mounts"})
487
		session.WaitWithDefaultTimeout()
488
		Expect(session).Should(ExitCleanly())
489
		Expect(session.OutputToString()).To(ContainSubstring(rwOnCgroups))
490

491
		session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=/sys/fs/cgroup", ALPINE, "cat", "/proc/mounts"})
492
		session.WaitWithDefaultTimeout()
493
		Expect(session).Should(ExitCleanly())
494
		Expect(session.OutputToString()).To(ContainSubstring(rwOnCgroups))
495

496
		session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=/sys/fs/cgroup///", ALPINE, "cat", "/proc/mounts"})
497
		session.WaitWithDefaultTimeout()
498
		Expect(session).Should(ExitCleanly())
499
		Expect(session.OutputToString()).To(ContainSubstring(rwOnCgroups))
500

501
		session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=ALL", ALPINE, "cat", "/proc/mounts"})
502
		session.WaitWithDefaultTimeout()
503
		Expect(session).Should(ExitCleanly())
504
		Expect(session.OutputToString()).To(ContainSubstring(rwOnCgroups))
505

506
		session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=/sys/fs/cgroup", "--security-opt", "mask=/sys/fs/cgroup", ALPINE, "cat", "/proc/mounts"})
507
		session.WaitWithDefaultTimeout()
508
		Expect(session).Should(ExitCleanly())
509
		Expect(session.OutputToString()).To(ContainSubstring(rwOnCgroups))
510

511
		session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=/sys/fs/cgroup", ALPINE, "ls", "/sys/fs/cgroup"})
512
		session.WaitWithDefaultTimeout()
513
		Expect(session).Should(ExitCleanly())
514
		Expect(session.OutputToString()).ToNot(BeEmpty())
515
	})
516

517
	It("podman run seccomp test", func() {
518
		secOpts := []string{"--security-opt", strings.Join([]string{"seccomp=", forbidLinkSeccompProfile()}, "")}
519
		cmd := []string{ALPINE, "ln", "/etc/motd", "/linkNotAllowed"}
520

521
		// Without seccomp, this should succeed
522
		session := podmanTest.Podman(append([]string{"run"}, cmd...))
523
		session.WaitWithDefaultTimeout()
524
		Expect(session).To(ExitCleanly())
525

526
		// With link syscall blocked, should fail
527
		cmd = append(secOpts, cmd...)
528
		session = podmanTest.Podman(append([]string{"run"}, cmd...))
529
		session.WaitWithDefaultTimeout()
530
		Expect(session).To(Exit(1))
531
		Expect(session.ErrorToString()).To(ContainSubstring("ln: /linkNotAllowed: Operation not permitted"))
532

533
		// ...even with --privileged
534
		cmd = append([]string{"--privileged"}, cmd...)
535
		session = podmanTest.Podman(append([]string{"run"}, cmd...))
536
		session.WaitWithDefaultTimeout()
537
		Expect(session).To(Exit(1))
538
		Expect(session.ErrorToString()).To(ContainSubstring("ln: /linkNotAllowed: Operation not permitted"))
539
	})
540

541
	It("podman run seccomp test --privileged no profile should be unconfined", func() {
542
		session := podmanTest.Podman([]string{"run", "--privileged", ALPINE, "grep", "Seccomp", "/proc/self/status"})
543
		session.WaitWithDefaultTimeout()
544
		Expect(session.OutputToString()).To(ContainSubstring("0"))
545
		Expect(session).Should(ExitCleanly())
546
	})
547

548
	It("podman run seccomp test no profile should be default", func() {
549
		session := podmanTest.Podman([]string{"run", ALPINE, "grep", "Seccomp", "/proc/self/status"})
550
		session.WaitWithDefaultTimeout()
551
		Expect(session.OutputToString()).To(ContainSubstring("2"))
552
		Expect(session).Should(ExitCleanly())
553
	})
554

555
	It("podman run capabilities test", func() {
556
		session := podmanTest.Podman([]string{"run", "--rm", "--cap-add", "all", ALPINE, "cat", "/proc/self/status"})
557
		session.WaitWithDefaultTimeout()
558
		Expect(session).Should(ExitCleanly())
559

560
		session = podmanTest.Podman([]string{"run", "--rm", "--cap-add", "sys_admin", ALPINE, "cat", "/proc/self/status"})
561
		session.WaitWithDefaultTimeout()
562
		Expect(session).Should(ExitCleanly())
563

564
		session = podmanTest.Podman([]string{"run", "--rm", "--cap-drop", "all", ALPINE, "cat", "/proc/self/status"})
565
		session.WaitWithDefaultTimeout()
566
		Expect(session).Should(ExitCleanly())
567

568
		session = podmanTest.Podman([]string{"run", "--rm", "--cap-drop", "setuid", ALPINE, "cat", "/proc/self/status"})
569
		session.WaitWithDefaultTimeout()
570
		Expect(session).Should(ExitCleanly())
571
	})
572

573
	It("podman run user capabilities test", func() {
574
		// We need to ignore the containers.conf on the test distribution for this test
575
		os.Setenv("CONTAINERS_CONF", "/dev/null")
576
		if IsRemote() {
577
			podmanTest.RestartRemoteService()
578
		}
579
		session := podmanTest.Podman([]string{"run", "--rm", "--user", "bin", ALPINE, "grep", "CapBnd", "/proc/self/status"})
580
		session.WaitWithDefaultTimeout()
581
		Expect(session).Should(ExitCleanly())
582
		Expect(session.OutputToString()).To(ContainSubstring("00000000800405fb"))
583

584
		session = podmanTest.Podman([]string{"run", "--rm", "--user", "bin", ALPINE, "grep", "CapEff", "/proc/self/status"})
585
		session.WaitWithDefaultTimeout()
586
		Expect(session).Should(ExitCleanly())
587
		Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
588

589
		session = podmanTest.Podman([]string{"run", "--rm", "--user", "bin", ALPINE, "grep", "CapInh", "/proc/self/status"})
590
		session.WaitWithDefaultTimeout()
591
		Expect(session).Should(ExitCleanly())
592
		Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
593

594
		session = podmanTest.Podman([]string{"run", "--rm", "--user", "root", ALPINE, "grep", "CapBnd", "/proc/self/status"})
595
		session.WaitWithDefaultTimeout()
596
		Expect(session).Should(ExitCleanly())
597
		Expect(session.OutputToString()).To(ContainSubstring("00000000800405fb"))
598

599
		session = podmanTest.Podman([]string{"run", "--rm", "--user", "root", ALPINE, "grep", "CapEff", "/proc/self/status"})
600
		session.WaitWithDefaultTimeout()
601
		Expect(session).Should(ExitCleanly())
602
		Expect(session.OutputToString()).To(ContainSubstring("00000000800405fb"))
603

604
		session = podmanTest.Podman([]string{"run", "--rm", "--user", "root", ALPINE, "grep", "CapInh", "/proc/self/status"})
605
		session.WaitWithDefaultTimeout()
606
		Expect(session).Should(ExitCleanly())
607
		Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
608

609
		session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "grep", "CapBnd", "/proc/self/status"})
610
		session.WaitWithDefaultTimeout()
611
		Expect(session).Should(ExitCleanly())
612
		Expect(session.OutputToString()).To(ContainSubstring("00000000800405fb"))
613

614
		session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "grep", "CapEff", "/proc/self/status"})
615
		session.WaitWithDefaultTimeout()
616
		Expect(session).Should(ExitCleanly())
617
		Expect(session.OutputToString()).To(ContainSubstring("00000000800405fb"))
618

619
		session = podmanTest.Podman([]string{"run", "--user=1000:1000", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
620
		session.WaitWithDefaultTimeout()
621
		Expect(session).Should(ExitCleanly())
622
		Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
623

624
		session = podmanTest.Podman([]string{"run", "--user=1000:1000", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"})
625
		session.WaitWithDefaultTimeout()
626
		Expect(session).Should(ExitCleanly())
627
		Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
628

629
		session = podmanTest.Podman([]string{"run", "--user=0", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
630
		session.WaitWithDefaultTimeout()
631
		Expect(session).Should(ExitCleanly())
632
		Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
633

634
		session = podmanTest.Podman([]string{"run", "--user=0:0", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
635
		session.WaitWithDefaultTimeout()
636
		Expect(session).Should(ExitCleanly())
637
		Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
638

639
		session = podmanTest.Podman([]string{"run", "--user=0:0", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"})
640
		session.WaitWithDefaultTimeout()
641
		Expect(session).Should(ExitCleanly())
642
		Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
643

644
		session = podmanTest.Podman([]string{"run", "--user=1:1", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapEff", "/proc/self/status"})
645
		session.WaitWithDefaultTimeout()
646
		Expect(session).Should(ExitCleanly())
647
		Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
648

649
		if isRootless() {
650
			if os.Getenv("SKIP_USERNS") != "" {
651
				GinkgoWriter.Println("Bypassing subsequent tests due to $SKIP_USERNS")
652
				return
653
			}
654
			if _, err := os.Stat("/proc/self/uid_map"); err != nil {
655
				GinkgoWriter.Println("Bypassing subsequent tests due to no /proc/self/uid_map")
656
				return
657
			}
658
			session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
659
			session.WaitWithDefaultTimeout()
660
			Expect(session).Should(ExitCleanly())
661
			Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
662

663
			session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--privileged", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"})
664
			session.WaitWithDefaultTimeout()
665
			Expect(session).Should(ExitCleanly())
666
			Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
667

668
			session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapInh", "/proc/self/status"})
669
			session.WaitWithDefaultTimeout()
670
			Expect(session).Should(ExitCleanly())
671
			Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
672
		}
673
	})
674

675
	It("podman run user capabilities test with image", func() {
676
		// We need to ignore the containers.conf on the test distribution for this test
677
		os.Setenv("CONTAINERS_CONF", "/dev/null")
678
		if IsRemote() {
679
			podmanTest.RestartRemoteService()
680
		}
681
		dockerfile := fmt.Sprintf(`FROM %s
682
USER bin`, BB)
683
		podmanTest.BuildImage(dockerfile, "test", "false")
684
		session := podmanTest.Podman([]string{"run", "--rm", "--user", "bin", "test", "grep", "CapBnd", "/proc/self/status"})
685
		session.WaitWithDefaultTimeout()
686
		Expect(session).Should(ExitCleanly())
687
		Expect(session.OutputToString()).To(ContainSubstring("00000000800405fb"))
688

689
		session = podmanTest.Podman([]string{"run", "--rm", "--user", "bin", "test", "grep", "CapEff", "/proc/self/status"})
690
		session.WaitWithDefaultTimeout()
691
		Expect(session).Should(ExitCleanly())
692
		Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
693
	})
694

695
	It("podman run limits test", func() {
696
		SkipIfRootlessCgroupsV1("Setting limits not supported on cgroupv1 for rootless users")
697

698
		if !isRootless() {
699
			session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "rtprio=99", "--cap-add=sys_nice", fedoraMinimal, "cat", "/proc/self/sched"})
700
			session.WaitWithDefaultTimeout()
701
			Expect(session).Should(ExitCleanly())
702
		}
703

704
		session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "nofile=2048:2048", fedoraMinimal, "ulimit", "-n"})
705
		session.WaitWithDefaultTimeout()
706
		Expect(session).Should(ExitCleanly())
707
		Expect(session.OutputToString()).To(ContainSubstring("2048"))
708

709
		session = podmanTest.Podman([]string{"run", "--rm", "--ulimit", "nofile=1024:1028", fedoraMinimal, "ulimit", "-n"})
710
		session.WaitWithDefaultTimeout()
711
		Expect(session).Should(ExitCleanly())
712
		Expect(session.OutputToString()).To(ContainSubstring("1024"))
713

714
		if !CGROUPSV2 {
715
			// --oom-kill-disable not supported on cgroups v2.
716
			session = podmanTest.Podman([]string{"run", "--rm", "--oom-kill-disable=true", fedoraMinimal, "echo", "memory-hog"})
717
			session.WaitWithDefaultTimeout()
718
			Expect(session).Should(ExitCleanly())
719
		}
720

721
		session = podmanTest.Podman([]string{"run", "--rm", "--oom-score-adj=111", fedoraMinimal, "cat", "/proc/self/oom_score_adj"})
722
		session.WaitWithDefaultTimeout()
723
		Expect(session).Should(ExitCleanly())
724
		Expect(session.OutputToString()).To(Equal("111"))
725

726
		currentOOMScoreAdj, err := os.ReadFile("/proc/self/oom_score_adj")
727
		Expect(err).ToNot(HaveOccurred())
728
		name := "ctr-with-oom-score"
729
		session = podmanTest.Podman([]string{"create", "--name", name, fedoraMinimal, "cat", "/proc/self/oom_score_adj"})
730
		session.WaitWithDefaultTimeout()
731
		Expect(session).Should(ExitCleanly())
732

733
		for i := 0; i < 2; i++ {
734
			session = podmanTest.Podman([]string{"start", "-a", name})
735
			session.WaitWithDefaultTimeout()
736
			Expect(session).Should(ExitCleanly())
737
			Expect(session.OutputToString()).To(Equal(strings.TrimRight(string(currentOOMScoreAdj), "\n")))
738
		}
739
	})
740

741
	It("podman run limits host test", func() {
742
		SkipIfRemote("This can only be used for local tests")
743

744
		var l syscall.Rlimit
745

746
		err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
747
		Expect(err).ToNot(HaveOccurred())
748

749
		session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "host", fedoraMinimal, "ulimit", "-Hn"})
750
		session.WaitWithDefaultTimeout()
751
		Expect(session).Should(ExitCleanly())
752

753
		ulimitCtrStr := strings.TrimSpace(session.OutputToString())
754
		ulimitCtr, err := strconv.ParseUint(ulimitCtrStr, 10, 0)
755
		Expect(err).ToNot(HaveOccurred())
756

757
		Expect(ulimitCtr).Should(BeNumerically(">=", l.Max))
758
	})
759

760
	It("podman run with cidfile", func() {
761
		cidFile := filepath.Join(tempdir, "cidfile")
762
		session := podmanTest.Podman([]string{"run", "--name", "cidtest", "--cidfile", cidFile, CITEST_IMAGE, "ls"})
763
		session.WaitWithDefaultTimeout()
764
		Expect(session).Should(ExitCleanly())
765

766
		cidFromFile, err := os.ReadFile(cidFile)
767
		Expect(err).ToNot(HaveOccurred())
768

769
		session = podmanTest.Podman([]string{"inspect", "--format", "{{.Id}}", "cidtest"})
770
		session.WaitWithDefaultTimeout()
771
		Expect(session).Should(ExitCleanly())
772

773
		Expect(string(cidFromFile)).To(Equal(session.OutputToString()), "CID from cidfile == CID from podman inspect")
774
	})
775

776
	It("podman run sysctl test", func() {
777
		SkipIfRootless("Network sysctls are not available root rootless")
778
		session := podmanTest.Podman([]string{"run", "--rm", "--sysctl", "net.core.somaxconn=65535", ALPINE, "sysctl", "net.core.somaxconn"})
779
		session.WaitWithDefaultTimeout()
780
		Expect(session).Should(ExitCleanly())
781
		Expect(session.OutputToString()).To(ContainSubstring("net.core.somaxconn = 65535"))
782

783
		// network sysctls should fail if --net=host is set
784
		session = podmanTest.Podman([]string{"run", "--net", "host", "--rm", "--sysctl", "net.core.somaxconn=65535", ALPINE, "sysctl", "net.core.somaxconn"})
785
		session.WaitWithDefaultTimeout()
786
		Expect(session).Should(Exit(125))
787
	})
788

789
	It("podman run blkio-weight test", func() {
790
		SkipIfRootlessCgroupsV1("Setting blkio-weight not supported on cgroupv1 for rootless users")
791
		SkipIfRootless("By default systemd doesn't delegate io to rootless users")
792
		if CGROUPSV2 {
793
			if _, err := os.Stat("/sys/fs/cgroup/io.stat"); os.IsNotExist(err) {
794
				Skip("Kernel does not have io.stat")
795
			}
796
			if _, err := os.Stat("/sys/fs/cgroup/system.slice/io.bfq.weight"); os.IsNotExist(err) {
797
				Skip("Kernel does not support BFQ IO scheduler")
798
			}
799
			session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/io.bfq.weight"})
800
			session.WaitWithDefaultTimeout()
801
			Expect(session).Should(ExitCleanly())
802
			// there was a documentation issue in the kernel that reported a different range [1-10000] for the io controller.
803
			// older versions of crun/runc used it.  For the time being allow both versions to pass the test.
804
			// FIXME: drop "|51" once all the runtimes we test have the fix in place.
805
			Expect(strings.Replace(session.OutputToString(), "default ", "", 1)).To(MatchRegexp("15|51"))
806
		} else {
807
			if _, err := os.Stat("/sys/fs/cgroup/blkio/blkio.weight"); os.IsNotExist(err) {
808
				Skip("Kernel does not support blkio.weight")
809
			}
810
			session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.weight"})
811
			session.WaitWithDefaultTimeout()
812
			Expect(session).Should(ExitCleanly())
813
			Expect(session.OutputToString()).To(ContainSubstring("15"))
814
		}
815
	})
816

817
	It("podman run device-read-bps test", func() {
818
		SkipIfRootless("Setting device-read-bps not supported for rootless users")
819

820
		var session *PodmanSessionIntegration
821

822
		if CGROUPSV2 {
823
			session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
824
		} else {
825
			session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"})
826
		}
827

828
		session.WaitWithDefaultTimeout()
829
		Expect(session).Should(ExitCleanly())
830
		if !CGROUPSV2 { // TODO: Test Simplification.  For now, we only care about exit(0) w/ cgroupsv2
831
			Expect(session.OutputToString()).To(ContainSubstring("1048576"))
832
		}
833
	})
834

835
	It("podman run device-write-bps test", func() {
836
		SkipIfRootless("Setting device-write-bps not supported for rootless users")
837

838
		var session *PodmanSessionIntegration
839

840
		if CGROUPSV2 {
841
			session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
842
		} else {
843
			session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_bps_device"})
844
		}
845
		session.WaitWithDefaultTimeout()
846
		Expect(session).Should(ExitCleanly())
847
		if !CGROUPSV2 { // TODO: Test Simplification.  For now, we only care about exit(0) w/ cgroupsv2
848
			Expect(session.OutputToString()).To(ContainSubstring("1048576"))
849
		}
850
	})
851

852
	It("podman run device-read-iops test", func() {
853
		SkipIfRootless("Setting device-read-iops not supported for rootless users")
854
		var session *PodmanSessionIntegration
855

856
		if CGROUPSV2 {
857
			session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
858
		} else {
859
			session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_iops_device"})
860
		}
861

862
		session.WaitWithDefaultTimeout()
863
		Expect(session).Should(ExitCleanly())
864
		if !CGROUPSV2 { // TODO: Test Simplification.  For now, we only care about exit(0) w/ cgroupsv2
865
			Expect(session.OutputToString()).To(ContainSubstring("100"))
866
		}
867
	})
868

869
	It("podman run device-write-iops test", func() {
870
		SkipIfRootless("Setting device-write-iops not supported for rootless users")
871
		var session *PodmanSessionIntegration
872

873
		if CGROUPSV2 {
874
			session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"})
875
		} else {
876
			session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_iops_device"})
877
		}
878

879
		session.WaitWithDefaultTimeout()
880
		Expect(session).Should(ExitCleanly())
881
		if !CGROUPSV2 { // TODO: Test Simplification.  For now, we only care about exit(0) w/ cgroupsv2
882
			Expect(session.OutputToString()).To(ContainSubstring("100"))
883
		}
884
	})
885

886
	It("podman run notify_socket", func() {
887
		SkipIfRemote("This can only be used for local tests")
888

889
		host := GetHostDistributionInfo()
890
		if host.Distribution != "rhel" && host.Distribution != "centos" && host.Distribution != "fedora" {
891
			Skip("this test requires a working runc")
892
		}
893
		sock := filepath.Join(podmanTest.TempDir, "notify")
894
		addr := net.UnixAddr{
895
			Name: sock,
896
			Net:  "unixgram",
897
		}
898
		socket, err := net.ListenUnixgram("unixgram", &addr)
899
		Expect(err).ToNot(HaveOccurred())
900
		defer os.Remove(sock)
901
		defer socket.Close()
902

903
		os.Setenv("NOTIFY_SOCKET", sock)
904
		defer os.Unsetenv("NOTIFY_SOCKET")
905

906
		session := podmanTest.Podman([]string{"run", ALPINE, "printenv", "NOTIFY_SOCKET"})
907
		session.WaitWithDefaultTimeout()
908
		Expect(session).Should(ExitCleanly())
909
		Expect(session.OutputToStringArray()).ToNot(BeEmpty())
910
	})
911

912
	It("podman run log-opt", func() {
913
		log := filepath.Join(podmanTest.TempDir, "/container.log")
914
		session := podmanTest.Podman([]string{"run", "--rm", "--log-driver", "k8s-file", "--log-opt", fmt.Sprintf("path=%s", log), ALPINE, "ls"})
915
		session.WaitWithDefaultTimeout()
916
		Expect(session).Should(ExitCleanly())
917
		_, err := os.Stat(log)
918
		Expect(err).ToNot(HaveOccurred())
919
		_ = os.Remove(log)
920
	})
921

922
	It("podman run tagged image", func() {
923
		podmanTest.AddImageToRWStore(BB)
924
		tag := podmanTest.Podman([]string{"tag", BB, "bb"})
925
		tag.WaitWithDefaultTimeout()
926
		Expect(tag).Should(ExitCleanly())
927

928
		session := podmanTest.Podman([]string{"run", "--rm", "bb", "ls"})
929
		session.WaitWithDefaultTimeout()
930
		Expect(session).Should(ExitCleanly())
931
	})
932

933
	It("podman test hooks", func() {
934
		SkipIfRemote("--hooks-dir does not work with remote")
935
		hooksDir := filepath.Join(tempdir, "hooks,withcomma")
936
		err := os.Mkdir(hooksDir, 0755)
937
		Expect(err).ToNot(HaveOccurred())
938
		hookJSONPath := filepath.Join(hooksDir, "checkhooks.json")
939
		hookScriptPath := filepath.Join(hooksDir, "checkhooks.sh")
940
		targetFile := filepath.Join(hooksDir, "target")
941

942
		hookJSON := fmt.Sprintf(`{
943
	"cmd" : [".*"],
944
	"hook" : "%s",
945
	"stage" : [ "prestart" ]
946
}
947
`, hookScriptPath)
948
		err = os.WriteFile(hookJSONPath, []byte(hookJSON), 0644)
949
		Expect(err).ToNot(HaveOccurred())
950

951
		random := stringid.GenerateRandomID()
952

953
		hookScript := fmt.Sprintf(`#!/bin/sh
954
echo -n %s >%s
955
`, random, targetFile)
956
		err = os.WriteFile(hookScriptPath, []byte(hookScript), 0755)
957
		Expect(err).ToNot(HaveOccurred())
958

959
		session := podmanTest.Podman([]string{"--hooks-dir", hooksDir, "run", ALPINE, "ls"})
960
		session.Wait(10)
961
		Expect(session).Should(ExitCleanly())
962

963
		b, err := os.ReadFile(targetFile)
964
		Expect(err).ToNot(HaveOccurred())
965
		Expect(string(b)).To(Equal(random))
966
	})
967

968
	It("podman run with subscription secrets", func() {
969
		SkipIfRemote("--default-mount-file option is not supported in podman-remote")
970
		containersDir := filepath.Join(podmanTest.TempDir, "containers")
971
		err := os.MkdirAll(containersDir, 0755)
972
		Expect(err).ToNot(HaveOccurred())
973

974
		secretsDir := filepath.Join(podmanTest.TempDir, "rhel", "secrets")
975
		err = os.MkdirAll(secretsDir, 0755)
976
		Expect(err).ToNot(HaveOccurred())
977

978
		mountsFile := filepath.Join(containersDir, "mounts.conf")
979
		mountString := secretsDir + ":/run/secrets"
980
		err = os.WriteFile(mountsFile, []byte(mountString), 0755)
981
		Expect(err).ToNot(HaveOccurred())
982

983
		secretsFile := filepath.Join(secretsDir, "test.txt")
984
		secretsString := "Testing secrets mount. I am mounted!"
985
		err = os.WriteFile(secretsFile, []byte(secretsString), 0755)
986
		Expect(err).ToNot(HaveOccurred())
987

988
		targetDir := filepath.Join(tempdir, "symlink/target")
989
		err = os.MkdirAll(targetDir, 0755)
990
		Expect(err).ToNot(HaveOccurred())
991
		keyFile := filepath.Join(targetDir, "key.pem")
992
		err = os.WriteFile(keyFile, []byte(mountString), 0755)
993
		Expect(err).ToNot(HaveOccurred())
994
		execSession := SystemExec("ln", []string{"-s", targetDir, filepath.Join(secretsDir, "mysymlink")})
995
		Expect(execSession).Should(ExitCleanly())
996

997
		session := podmanTest.Podman([]string{"--default-mounts-file=" + mountsFile, "run", "--rm", ALPINE, "cat", "/run/secrets/test.txt"})
998
		session.WaitWithDefaultTimeout()
999
		Expect(session).Should(ExitCleanly())
1000
		Expect(session.OutputToString()).To(Equal(secretsString))
1001

1002
		session = podmanTest.Podman([]string{"--default-mounts-file=" + mountsFile, "run", "--rm", ALPINE, "ls", "/run/secrets/mysymlink"})
1003
		session.WaitWithDefaultTimeout()
1004
		Expect(session).Should(ExitCleanly())
1005
		Expect(session.OutputToString()).To(ContainSubstring("key.pem"))
1006
	})
1007

1008
	It("podman run with FIPS mode secrets", func() {
1009
		SkipIfRootless("rootless can not manipulate system-fips file")
1010
		fipsFile := "/etc/system-fips"
1011
		err = os.WriteFile(fipsFile, []byte{}, 0755)
1012
		Expect(err).ToNot(HaveOccurred())
1013

1014
		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "ls", "/run/secrets"})
1015
		session.WaitWithDefaultTimeout()
1016
		Expect(session).Should(ExitCleanly())
1017
		Expect(session.OutputToString()).To(ContainSubstring("system-fips"))
1018

1019
		err = os.Remove(fipsFile)
1020
		Expect(err).ToNot(HaveOccurred())
1021
	})
1022

1023
	It("podman run without group-add", func() {
1024
		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "id"})
1025
		session.WaitWithDefaultTimeout()
1026
		Expect(session).Should(ExitCleanly())
1027
		Expect(session.OutputToString()).To(Not(ContainSubstring("27(video),777,65533(nogroup)")))
1028
	})
1029

1030
	It("podman run with group-add", func() {
1031
		session := podmanTest.Podman([]string{"run", "--rm", "--group-add=audio", "--group-add=nogroup", "--group-add=777", ALPINE, "id"})
1032
		session.WaitWithDefaultTimeout()
1033
		Expect(session).Should(ExitCleanly())
1034
		Expect(session.OutputToString()).To(ContainSubstring("777,65533(nogroup)"))
1035
	})
1036

1037
	It("podman run with user (default)", func() {
1038
		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "id"})
1039
		session.WaitWithDefaultTimeout()
1040
		Expect(session).Should(ExitCleanly())
1041
		Expect(session.OutputToString()).To(ContainSubstring("uid=0(root) gid=0(root)"))
1042
	})
1043

1044
	It("podman run with user (integer, not in /etc/passwd)", func() {
1045
		session := podmanTest.Podman([]string{"run", "--rm", "--user=1234", ALPINE, "id"})
1046
		session.WaitWithDefaultTimeout()
1047
		Expect(session).Should(ExitCleanly())
1048
		Expect(session.OutputToString()).To(Equal("uid=1234(1234) gid=0(root) groups=0(root)"))
1049
	})
1050

1051
	It("podman run with user (integer, in /etc/passwd)", func() {
1052
		session := podmanTest.Podman([]string{"run", "--rm", "--user=8", ALPINE, "id"})
1053
		session.WaitWithDefaultTimeout()
1054
		Expect(session).Should(ExitCleanly())
1055
		Expect(session.OutputToString()).To(ContainSubstring("uid=8(mail) gid=12(mail)"))
1056
	})
1057

1058
	It("podman run with user (username)", func() {
1059
		session := podmanTest.Podman([]string{"run", "--rm", "--user=mail", ALPINE, "id"})
1060
		session.WaitWithDefaultTimeout()
1061
		Expect(session).Should(ExitCleanly())
1062
		Expect(session.OutputToString()).To(ContainSubstring("uid=8(mail) gid=12(mail)"))
1063
	})
1064

1065
	It("podman run with user:group (username:integer)", func() {
1066
		session := podmanTest.Podman([]string{"run", "--rm", "--user=mail:21", ALPINE, "id"})
1067
		session.WaitWithDefaultTimeout()
1068
		Expect(session).Should(ExitCleanly())
1069
		Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=21(ftp) groups=21(ftp)"))
1070
	})
1071

1072
	It("podman run with user:group (integer:groupname)", func() {
1073
		session := podmanTest.Podman([]string{"run", "--rm", "--user=8:ftp", ALPINE, "id"})
1074
		session.WaitWithDefaultTimeout()
1075
		Expect(session).Should(ExitCleanly())
1076
		Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=21(ftp) groups=21(ftp)"))
1077
	})
1078

1079
	It("podman run with user, verify caps dropped", func() {
1080
		session := podmanTest.Podman([]string{"run", "--rm", "--user=1234", ALPINE, "grep", "CapEff", "/proc/self/status"})
1081
		session.WaitWithDefaultTimeout()
1082
		Expect(session).Should(ExitCleanly())
1083
		capEff := strings.Split(session.OutputToString(), " ")
1084
		Expect("0000000000000000").To(Equal(capEff[1]))
1085
	})
1086

1087
	It("podman run with user, verify group added", func() {
1088
		session := podmanTest.Podman([]string{"run", "--rm", "--user=1000:1000", ALPINE, "grep", "Groups:", "/proc/self/status"})
1089
		session.WaitWithDefaultTimeout()
1090
		Expect(session).Should(ExitCleanly())
1091
		groups := strings.Split(session.OutputToString(), " ")[1]
1092
		Expect("1000").To(Equal(groups))
1093
	})
1094

1095
	It("podman run with attach stdin outputs container ID", func() {
1096
		session := podmanTest.Podman([]string{"run", "--attach", "stdin", ALPINE, "printenv"})
1097
		session.WaitWithDefaultTimeout()
1098
		Expect(session).Should(ExitCleanly())
1099
		ps := podmanTest.Podman([]string{"ps", "-aq", "--no-trunc"})
1100
		ps.WaitWithDefaultTimeout()
1101
		Expect(ps).Should(ExitCleanly())
1102
		Expect(ps.OutputToString()).To(ContainSubstring(session.OutputToString()))
1103
	})
1104

1105
	It("podman run with attach stdout does not print stderr", func() {
1106
		session := podmanTest.Podman([]string{"run", "--rm", "--attach", "stdout", ALPINE, "ls", "/doesnotexist"})
1107
		session.WaitWithDefaultTimeout()
1108
		Expect(session.OutputToString()).To(Equal(""))
1109
	})
1110

1111
	It("podman run with attach stderr does not print stdout", func() {
1112
		session := podmanTest.Podman([]string{"run", "--rm", "--attach", "stderr", ALPINE, "ls", "/"})
1113
		session.WaitWithDefaultTimeout()
1114
		Expect(session).Should(ExitCleanly())
1115
		Expect(session.OutputToString()).To(Equal(""))
1116
	})
1117

1118
	It("podman run attach nonsense errors", func() {
1119
		session := podmanTest.Podman([]string{"run", "--rm", "--attach", "asdfasdf", ALPINE, "ls", "/"})
1120
		session.WaitWithDefaultTimeout()
1121
		Expect(session).Should(Exit(125))
1122
	})
1123

1124
	It("podman run exit code on failure to exec", func() {
1125
		session := podmanTest.Podman([]string{"run", ALPINE, "/etc"})
1126
		session.WaitWithDefaultTimeout()
1127
		Expect(session).Should(Exit(126))
1128
	})
1129

1130
	It("podman run error on exec", func() {
1131
		session := podmanTest.Podman([]string{"run", ALPINE, "sh", "-c", "exit 100"})
1132
		session.WaitWithDefaultTimeout()
1133
		Expect(session).Should(Exit(100))
1134
	})
1135

1136
	It("podman run with named volume", func() {
1137
		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "stat", "-c", "%a %Y", "/var/tmp"})
1138
		session.WaitWithDefaultTimeout()
1139
		Expect(session).Should(ExitCleanly())
1140
		perms := session.OutputToString()
1141

1142
		session = podmanTest.Podman([]string{"run", "--rm", "-v", "test:/var/tmp", ALPINE, "stat", "-c", "%a %Y", "/var/tmp"})
1143
		session.WaitWithDefaultTimeout()
1144
		Expect(session).Should(ExitCleanly())
1145
		Expect(session.OutputToString()).To(Equal(perms))
1146
	})
1147

1148
	It("podman run with built-in volume image", func() {
1149
		session := podmanTest.Podman([]string{"run", "--rm", REDIS_IMAGE, "ls"})
1150
		session.WaitWithDefaultTimeout()
1151
		Expect(session).Should(ExitCleanly())
1152

1153
		dockerfile := fmt.Sprintf(`FROM %s
1154
RUN mkdir -p /myvol/data && chown -R mail.0 /myvol
1155
VOLUME ["/myvol/data"]
1156
USER mail`, BB)
1157

1158
		podmanTest.BuildImage(dockerfile, "test", "false")
1159
		session = podmanTest.Podman([]string{"run", "--rm", "test", "ls", "-al", "/myvol/data"})
1160
		session.WaitWithDefaultTimeout()
1161
		Expect(session).Should(ExitCleanly())
1162
		Expect(session.OutputToString()).To(ContainSubstring("mail root"))
1163
	})
1164

1165
	It("podman run --volumes-from flag", func() {
1166
		vol := filepath.Join(podmanTest.TempDir, "vol-test")
1167
		err := os.MkdirAll(vol, 0755)
1168
		Expect(err).ToNot(HaveOccurred())
1169

1170
		filename := "test.txt"
1171
		volFile := filepath.Join(vol, filename)
1172
		data := "Testing --volumes-from!!!"
1173
		err = os.WriteFile(volFile, []byte(data), 0755)
1174
		Expect(err).ToNot(HaveOccurred())
1175
		mountpoint := "/myvol/"
1176

1177
		session := podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint + ":z", ALPINE, "cat", mountpoint + filename})
1178
		session.WaitWithDefaultTimeout()
1179
		Expect(session).Should(ExitCleanly())
1180
		ctrID := session.OutputToString()
1181

1182
		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "cat", mountpoint + filename})
1183
		session.WaitWithDefaultTimeout()
1184
		Expect(session).Should(ExitCleanly())
1185
		Expect(session.OutputToString()).To(Equal(data))
1186

1187
		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "sh", "-c", "echo test >> " + mountpoint + filename})
1188
		session.WaitWithDefaultTimeout()
1189
		Expect(session).Should(ExitCleanly())
1190

1191
		session = podmanTest.Podman([]string{"start", "--attach", ctrID})
1192
		session.WaitWithDefaultTimeout()
1193
		Expect(session).Should(ExitCleanly())
1194
		Expect(session.OutputToString()).To(Equal(data + "test"))
1195
	})
1196

1197
	It("podman run --volumes-from flag options", func() {
1198
		vol := filepath.Join(podmanTest.TempDir, "vol-test")
1199
		err := os.MkdirAll(vol, 0755)
1200
		Expect(err).ToNot(HaveOccurred())
1201

1202
		filename := "test.txt"
1203
		volFile := filepath.Join(vol, filename)
1204
		data := "Testing --volumes-from!!!"
1205
		err = os.WriteFile(volFile, []byte(data), 0755)
1206
		Expect(err).ToNot(HaveOccurred())
1207
		mountpoint := "/myvol/"
1208

1209
		session := podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint, ALPINE, "cat", mountpoint + filename})
1210
		session.WaitWithDefaultTimeout()
1211
		Expect(session).Should(ExitCleanly())
1212
		ctrID := session.OutputToString()
1213

1214
		// check that the read-only option works
1215
		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro", ALPINE, "touch", mountpoint + "abc.txt"})
1216
		session.WaitWithDefaultTimeout()
1217
		Expect(session).Should(Exit(1))
1218
		Expect(session.ErrorToString()).To(ContainSubstring("Read-only file system"))
1219

1220
		// check that both z and ro options work
1221
		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro,z", ALPINE, "cat", mountpoint + filename})
1222
		session.WaitWithDefaultTimeout()
1223
		Expect(session).Should(ExitCleanly())
1224
		Expect(session.OutputToString()).To(Equal(data))
1225

1226
		// check that multiple ro/rw are not working
1227
		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro,rw", ALPINE, "cat", mountpoint + filename})
1228
		session.WaitWithDefaultTimeout()
1229
		Expect(session).Should(Exit(125))
1230
		Expect(session.ErrorToString()).To(ContainSubstring("cannot set ro or rw options more than once"))
1231

1232
		// check that multiple z options are not working
1233
		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":z,z,ro", ALPINE, "cat", mountpoint + filename})
1234
		session.WaitWithDefaultTimeout()
1235
		Expect(session).Should(Exit(125))
1236
		Expect(session.ErrorToString()).To(ContainSubstring("cannot set :z more than once in mount options"))
1237

1238
		// create new read-only volume
1239
		session = podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint + ":ro", ALPINE, "cat", mountpoint + filename})
1240
		session.WaitWithDefaultTimeout()
1241
		Expect(session).Should(ExitCleanly())
1242
		ctrID = session.OutputToString()
1243

1244
		// check if the original volume was mounted as read-only that --volumes-from also mount it as read-only
1245
		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "touch", mountpoint + "abc.txt"})
1246
		session.WaitWithDefaultTimeout()
1247
		Expect(session).Should(Exit(1))
1248
		Expect(session.ErrorToString()).To(ContainSubstring("Read-only file system"))
1249
	})
1250

1251
	It("podman run --volumes-from flag with built-in volumes", func() {
1252
		session := podmanTest.Podman([]string{"create", REDIS_IMAGE, "sh"})
1253
		session.WaitWithDefaultTimeout()
1254
		Expect(session).Should(ExitCleanly())
1255
		ctrID := session.OutputToString()
1256

1257
		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "ls"})
1258
		session.WaitWithDefaultTimeout()
1259
		Expect(session).Should(ExitCleanly())
1260
		Expect(session.OutputToString()).To(ContainSubstring("data"))
1261
	})
1262

1263
	It("podman run --volumes-from flag mount conflicts with image volume", func() {
1264
		volPathOnHost := filepath.Join(podmanTest.TempDir, "myvol")
1265
		err := os.MkdirAll(volPathOnHost, 0755)
1266
		Expect(err).ToNot(HaveOccurred())
1267

1268
		imgName := "testimg"
1269
		volPath := "/myvol/mypath"
1270
		dockerfile := fmt.Sprintf(`FROM %s
1271
RUN mkdir -p %s
1272
VOLUME %s`, ALPINE, volPath, volPath)
1273
		podmanTest.BuildImage(dockerfile, imgName, "false")
1274

1275
		ctr1 := "ctr1"
1276
		run1 := podmanTest.Podman([]string{"run", "-d", "-v", fmt.Sprintf("%s:%s:z", volPathOnHost, volPath), "--name", ctr1, ALPINE, "top"})
1277
		run1.WaitWithDefaultTimeout()
1278
		Expect(run1).Should(ExitCleanly())
1279

1280
		testFile := "testfile1"
1281
		ctr1Exec := podmanTest.Podman([]string{"exec", "-t", ctr1, "touch", fmt.Sprintf("%s/%s", volPath, testFile)})
1282
		ctr1Exec.WaitWithDefaultTimeout()
1283
		Expect(ctr1Exec).Should(ExitCleanly())
1284

1285
		run2 := podmanTest.Podman([]string{"run", "--volumes-from", ctr1, imgName, "ls", volPath})
1286
		run2.WaitWithDefaultTimeout()
1287
		Expect(run2).Should(ExitCleanly())
1288
		Expect(run2.OutputToString()).To(Equal(testFile))
1289
	})
1290

1291
	It("podman run --volumes flag with multiple volumes", func() {
1292
		vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
1293
		err := os.MkdirAll(vol1, 0755)
1294
		Expect(err).ToNot(HaveOccurred())
1295
		vol2 := filepath.Join(podmanTest.TempDir, "vol-test2")
1296
		err = os.MkdirAll(vol2, 0755)
1297
		Expect(err).ToNot(HaveOccurred())
1298

1299
		session := podmanTest.Podman([]string{"run", "--volume", vol1 + ":/myvol1:z", "--volume", vol2 + ":/myvol2:z", ALPINE, "touch", "/myvol2/foo.txt"})
1300
		session.WaitWithDefaultTimeout()
1301
		Expect(session).Should(ExitCleanly())
1302
	})
1303

1304
	It("podman run --volumes flag with empty host dir", func() {
1305
		vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
1306
		err := os.MkdirAll(vol1, 0755)
1307
		Expect(err).ToNot(HaveOccurred())
1308

1309
		session := podmanTest.Podman([]string{"run", "--volume", ":/myvol1:z", ALPINE, "touch", "/myvol2/foo.txt"})
1310
		session.WaitWithDefaultTimeout()
1311
		Expect(session).To(ExitWithError())
1312
		Expect(session.ErrorToString()).To(ContainSubstring("directory cannot be empty"))
1313
		session = podmanTest.Podman([]string{"run", "--volume", vol1 + ":", ALPINE, "touch", "/myvol2/foo.txt"})
1314
		session.WaitWithDefaultTimeout()
1315
		Expect(session).To(ExitWithError())
1316
		Expect(session.ErrorToString()).To(ContainSubstring("directory cannot be empty"))
1317
	})
1318

1319
	It("podman run --mount flag with multiple mounts", func() {
1320
		vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
1321
		err := os.MkdirAll(vol1, 0755)
1322
		Expect(err).ToNot(HaveOccurred())
1323
		vol2 := filepath.Join(podmanTest.TempDir, "vol-test2")
1324
		err = os.MkdirAll(vol2, 0755)
1325
		Expect(err).ToNot(HaveOccurred())
1326

1327
		session := podmanTest.Podman([]string{"run", "--mount", "type=bind,src=" + vol1 + ",target=/myvol1,z", "--mount", "type=bind,src=" + vol2 + ",target=/myvol2,z", ALPINE, "touch", "/myvol2/foo.txt"})
1328
		session.WaitWithDefaultTimeout()
1329
		Expect(session).Should(ExitCleanly())
1330
	})
1331

1332
	It("podman run findmnt nothing shared", func() {
1333
		vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
1334
		err := os.MkdirAll(vol1, 0755)
1335
		Expect(err).ToNot(HaveOccurred())
1336
		vol2 := filepath.Join(podmanTest.TempDir, "vol-test2")
1337
		err = os.MkdirAll(vol2, 0755)
1338
		Expect(err).ToNot(HaveOccurred())
1339

1340
		session := podmanTest.Podman([]string{"run", "--volume", vol1 + ":/myvol1:z", "--volume", vol2 + ":/myvol2:z", fedoraMinimal, "findmnt", "-o", "TARGET,PROPAGATION"})
1341
		session.WaitWithDefaultTimeout()
1342
		Expect(session).Should(ExitCleanly())
1343
		Expect(session.OutputToString()).To(Not(ContainSubstring("shared")))
1344
	})
1345

1346
	It("podman run findmnt shared", func() {
1347
		vol := filepath.Join(podmanTest.TempDir, "vol-test")
1348
		err := os.MkdirAll(vol, 0755)
1349
		Expect(err).ToNot(HaveOccurred())
1350

1351
		session := podmanTest.Podman([]string{"run", "--volume", vol + ":/myvol:z", fedoraMinimal, "findmnt", "-no", "PROPAGATION", "/myvol"})
1352
		session.WaitWithDefaultTimeout()
1353
		Expect(session).Should(ExitCleanly())
1354
		Expect(session.OutputToString()).To(Equal("private"))
1355

1356
		session = podmanTest.Podman([]string{"run", "--volume", vol + ":/myvol:shared,z", fedoraMinimal, "findmnt", "-no", "PROPAGATION", "/myvol"})
1357
		session.WaitWithDefaultTimeout()
1358
		Expect(session).Should(ExitCleanly())
1359

1360
		if isRootless() {
1361
			// we need to relax the rootless test because it can be "shared" only when the user owns the outer mount namespace.
1362
			Expect(session.OutputToString()).To(ContainSubstring("shared"))
1363
		} else {
1364
			// make sure it's only shared (and not 'shared,*')
1365
			Expect(session.OutputToString()).To(Equal("shared"))
1366
		}
1367
	})
1368

1369
	It("podman run --security-opts proc-opts=", func() {
1370
		session := podmanTest.Podman([]string{"run", "--security-opt", "proc-opts=nosuid,exec", fedoraMinimal, "findmnt", "-noOPTIONS", "/proc"})
1371
		session.WaitWithDefaultTimeout()
1372
		Expect(session).Should(ExitCleanly())
1373
		output := session.OutputToString()
1374
		Expect(output).To(ContainSubstring("nosuid"))
1375
		Expect(output).To(Not(ContainSubstring("exec")))
1376
	})
1377

1378
	It("podman run --mount type=bind,bind-nonrecursive", func() {
1379
		SkipIfRootless("FIXME: rootless users are not allowed to mount bind-nonrecursive")
1380
		session := podmanTest.Podman([]string{"run", "--mount", "type=bind,bind-nonrecursive,private,src=/sys,target=/host-sys", fedoraMinimal, "findmnt", "-nR", "/host-sys"})
1381
		session.WaitWithDefaultTimeout()
1382
		Expect(session).Should(ExitCleanly())
1383
		Expect(session.OutputToStringArray()).To(HaveLen(1))
1384
	})
1385

1386
	It("podman run --mount type=devpts,target=/foo/bar", func() {
1387
		session := podmanTest.Podman([]string{"run", "--mount", "type=devpts,target=/foo/bar", fedoraMinimal, "stat", "-f", "-c%T", "/foo/bar"})
1388
		session.WaitWithDefaultTimeout()
1389
		Expect(session).Should(ExitCleanly())
1390
		Expect(session.OutputToString()).To(ContainSubstring(define.TypeDevpts))
1391
	})
1392

1393
	It("podman run --mount type=devpts,target=/dev/pts with uid, gid and mode", func() {
1394
		// runc doesn't seem to honor uid= so avoid testing it
1395
		session := podmanTest.Podman([]string{"run", "-t", "--mount", "type=devpts,target=/dev/pts,uid=1000,gid=1001,mode=123", fedoraMinimal, "stat", "-c%g-%a", "/dev/pts/0"})
1396
		session.WaitWithDefaultTimeout()
1397
		Expect(session).Should(ExitCleanly())
1398
		Expect(session.OutputToString()).To(ContainSubstring("1001-123"))
1399
	})
1400

1401
	It("podman run --pod automatically", func() {
1402
		session := podmanTest.Podman([]string{"run", "-d", "--pod", "new:foobar", ALPINE, "nc", "-l", "-p", "8686"})
1403
		session.WaitWithDefaultTimeout()
1404
		Expect(session).Should(ExitCleanly())
1405

1406
		session = podmanTest.Podman([]string{"run", "--pod", "foobar", ALPINE, "/bin/sh", "-c", "echo test | nc -w 1 127.0.0.1 8686"})
1407
		session.WaitWithDefaultTimeout()
1408
		Expect(session).Should(ExitCleanly())
1409

1410
		check := podmanTest.Podman([]string{"pod", "ps", "--no-trunc"})
1411
		check.WaitWithDefaultTimeout()
1412
		Expect(check.OutputToString()).To(ContainSubstring("foobar"))
1413
	})
1414

1415
	It("podman run --pod new with hostname", func() {
1416
		hostname := "abc"
1417
		session := podmanTest.Podman([]string{"run", "--pod", "new:foobar", "--hostname", hostname, ALPINE, "cat", "/etc/hostname"})
1418
		session.WaitWithDefaultTimeout()
1419
		Expect(session).Should(ExitCleanly())
1420
		Expect(session.OutputToString()).To(ContainSubstring(hostname))
1421
	})
1422

1423
	It("podman run --rm should work", func() {
1424
		session := podmanTest.Podman([]string{"run", "--name", "test", "--rm", ALPINE, "ls"})
1425
		session.WaitWithDefaultTimeout()
1426
		Expect(session).Should(ExitCleanly())
1427
		session = podmanTest.Podman([]string{"wait", "test"})
1428
		session.WaitWithDefaultTimeout()
1429
		Expect(session).To(ExitWithError())
1430

1431
		numContainers := podmanTest.NumberOfContainers()
1432
		Expect(numContainers).To(Equal(0))
1433
	})
1434

1435
	It("podman run --rm failed container should delete itself", func() {
1436
		session := podmanTest.Podman([]string{"run", "--name", "test", "--rm", ALPINE, "foo"})
1437
		session.WaitWithDefaultTimeout()
1438
		Expect(session).To(ExitWithError())
1439
		session = podmanTest.Podman([]string{"wait", "test"})
1440
		session.WaitWithDefaultTimeout()
1441
		Expect(session).To(ExitWithError())
1442

1443
		numContainers := podmanTest.NumberOfContainers()
1444
		Expect(numContainers).To(Equal(0))
1445
	})
1446

1447
	It("podman run failed container should NOT delete itself", func() {
1448
		session := podmanTest.Podman([]string{"run", ALPINE, "foo"})
1449
		session.WaitWithDefaultTimeout()
1450
		Expect(session).To(ExitWithError())
1451
		// If remote we could have a race condition
1452
		session = podmanTest.Podman([]string{"wait", "test"})
1453
		session.WaitWithDefaultTimeout()
1454
		Expect(session).To(ExitWithError())
1455

1456
		numContainers := podmanTest.NumberOfContainers()
1457
		Expect(numContainers).To(Equal(1))
1458
	})
1459
	It("podman run readonly container should NOT mount /dev/shm read/only", func() {
1460
		session := podmanTest.Podman([]string{"run", "--read-only", ALPINE, "mount"})
1461
		session.WaitWithDefaultTimeout()
1462
		Expect(session).Should(ExitCleanly())
1463

1464
		Expect(session.OutputToString()).To(Not(ContainSubstring("/dev/shm type tmpfs (ro,")))
1465
	})
1466

1467
	It("podman run readonly container should NOT mount /run noexec", func() {
1468
		session := podmanTest.Podman([]string{"run", "--read-only", ALPINE, "sh", "-c", "mount  | grep \"/run \""})
1469
		session.WaitWithDefaultTimeout()
1470
		Expect(session).Should(ExitCleanly())
1471

1472
		Expect(session.OutputToString()).To(Not(ContainSubstring("noexec")))
1473
	})
1474

1475
	It("podman run with bad healthcheck retries", func() {
1476
		session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "[\"foo\"]", "--health-retries", "0", ALPINE, "top"})
1477
		session.Wait()
1478
		Expect(session).To(ExitWithError())
1479
		Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-retries must be greater than 0"))
1480
	})
1481

1482
	It("podman run with bad healthcheck timeout", func() {
1483
		session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "foo", "--health-timeout", "0s", ALPINE, "top"})
1484
		session.WaitWithDefaultTimeout()
1485
		Expect(session).To(ExitWithError())
1486
		Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-timeout must be at least 1 second"))
1487
	})
1488

1489
	It("podman run with bad healthcheck start-period", func() {
1490
		session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "foo", "--health-start-period", "-1s", ALPINE, "top"})
1491
		session.WaitWithDefaultTimeout()
1492
		Expect(session).To(ExitWithError())
1493
		Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-start-period must be 0 seconds or greater"))
1494
	})
1495

1496
	It("podman run with --add-host and --no-hosts fails", func() {
1497
		session := podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", "--no-hosts", ALPINE, "top"})
1498
		session.WaitWithDefaultTimeout()
1499
		Expect(session).To(ExitWithError())
1500
	})
1501

1502
	It("podman run with restart-policy always restarts containers", func() {
1503
		testDir := filepath.Join(podmanTest.RunRoot, "restart-test")
1504
		err := os.MkdirAll(testDir, 0755)
1505
		Expect(err).ToNot(HaveOccurred())
1506

1507
		aliveFile := filepath.Join(testDir, "running")
1508
		file, err := os.Create(aliveFile)
1509
		Expect(err).ToNot(HaveOccurred())
1510
		file.Close()
1511

1512
		session := podmanTest.Podman([]string{"run", "-dt", "--restart", "always", "-v", fmt.Sprintf("%s:/tmp/runroot:Z", testDir), ALPINE, "sh", "-c", "touch /tmp/runroot/ran && while test -r /tmp/runroot/running; do sleep 0.1s; done"})
1513

1514
		found := false
1515
		testFile := filepath.Join(testDir, "ran")
1516
		for i := 0; i < 30; i++ {
1517
			time.Sleep(1 * time.Second)
1518
			if _, err := os.Stat(testFile); err == nil {
1519
				found = true
1520
				err = os.Remove(testFile)
1521
				Expect(err).ToNot(HaveOccurred())
1522
				break
1523
			}
1524
		}
1525
		Expect(found).To(BeTrue(), "found expected /ran file")
1526

1527
		err = os.Remove(aliveFile)
1528
		Expect(err).ToNot(HaveOccurred())
1529

1530
		session.WaitWithDefaultTimeout()
1531

1532
		// 10 seconds to restart the container
1533
		found = false
1534
		for i := 0; i < 10; i++ {
1535
			time.Sleep(1 * time.Second)
1536
			if _, err := os.Stat(testFile); err == nil {
1537
				found = true
1538
				break
1539
			}
1540
		}
1541
		Expect(found).To(BeTrue(), "found /ran file after restart")
1542
	})
1543

1544
	It("podman run with restart policy does not restart on manual stop", func() {
1545
		ctrName := "testCtr"
1546
		ctr := podmanTest.Podman([]string{"run", "-dt", "--restart=always", "--name", ctrName, ALPINE, "top"})
1547
		ctr.WaitWithDefaultTimeout()
1548
		Expect(ctr).Should(ExitCleanly())
1549

1550
		podmanTest.StopContainer(ctrName)
1551

1552
		// This is ugly, but I don't see a better way
1553
		time.Sleep(10 * time.Second)
1554

1555
		Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
1556
	})
1557

1558
	It("podman run with cgroups=split", func() {
1559
		SkipIfNotSystemd(podmanTest.CgroupManager, "do not test --cgroups=split if not running on systemd")
1560
		SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users")
1561
		SkipIfRemote("--cgroups=split cannot be used in remote mode")
1562

1563
		checkLines := func(lines []string) {
1564
			cgroup := ""
1565
			for _, line := range lines {
1566
				parts := strings.SplitN(line, ":", 3)
1567
				if len(parts) < 2 {
1568
					continue
1569
				}
1570
				if !CGROUPSV2 {
1571
					// ignore unified on cgroup v1.
1572
					// both runc and crun do not set it.
1573
					// crun does not set named hierarchies.
1574
					if parts[1] == "" || strings.Contains(parts[1], "name=") {
1575
						continue
1576
					}
1577
				}
1578
				if parts[2] == "/" {
1579
					continue
1580
				}
1581
				if cgroup == "" {
1582
					cgroup = parts[2]
1583
					continue
1584
				}
1585
				Expect(cgroup).To(Equal(parts[2]))
1586
			}
1587
		}
1588

1589
		container := podmanTest.PodmanSystemdScope([]string{"run", "--rm", "--cgroups=split", ALPINE, "cat", "/proc/self/cgroup"})
1590
		container.WaitWithDefaultTimeout()
1591
		Expect(container).Should(Exit(0))
1592
		checkLines(container.OutputToStringArray())
1593
		Expect(container.ErrorToString()).To(Or(
1594
			ContainSubstring("Running scope as unit: "), // systemd <  255
1595
			ContainSubstring("Running as unit: ")))      // systemd >= 255
1596

1597
		// check that --cgroups=split is honored also when a container runs in a pod
1598
		container = podmanTest.PodmanSystemdScope([]string{"run", "--rm", "--pod", "new:split-test-pod", "--cgroups=split", ALPINE, "cat", "/proc/self/cgroup"})
1599
		container.WaitWithDefaultTimeout()
1600
		Expect(container).Should(Exit(0))
1601
		checkLines(container.OutputToStringArray())
1602
		Expect(container.ErrorToString()).To(Or(
1603
			ContainSubstring("Running scope as unit: "), // systemd <  255
1604
			ContainSubstring("Running as unit: ")))      // systemd >= 255
1605
	})
1606

1607
	It("podman run with cgroups=disabled runs without cgroups", func() {
1608
		SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users")
1609
		// Only works on crun
1610
		if !strings.Contains(podmanTest.OCIRuntime, "crun") {
1611
			Skip("Test only works on crun")
1612
		}
1613

1614
		ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup()
1615
		Expect(err).ShouldNot(HaveOccurred())
1616
		if !ownsCgroup {
1617
			// Podman moves itself to a new cgroup if it doesn't own the current cgroup
1618
			Skip("Test only works when Podman owns the current cgroup")
1619
		}
1620

1621
		trim := func(i string) string {
1622
			return strings.TrimSuffix(i, "\n")
1623
		}
1624

1625
		curCgroupsBytes, err := os.ReadFile("/proc/self/cgroup")
1626
		Expect(err).ShouldNot(HaveOccurred())
1627
		curCgroups := trim(string(curCgroupsBytes))
1628
		GinkgoWriter.Printf("Output:\n%s\n", curCgroups)
1629
		Expect(curCgroups).ToNot(Equal(""))
1630

1631
		container := podmanTest.Podman([]string{"run", "--cgroupns=host", "--cgroups=disabled", ALPINE, "cat", "/proc/self/cgroup"})
1632
		container.WaitWithDefaultTimeout()
1633
		Expect(container).Should(ExitCleanly())
1634

1635
		ctrCgroups := trim(container.OutputToString())
1636
		GinkgoWriter.Printf("Output\n:%s\n", ctrCgroups)
1637

1638
		Expect(ctrCgroups).To(Equal(curCgroups))
1639
	})
1640

1641
	It("podman run with cgroups=enabled makes cgroups", func() {
1642
		SkipIfRootlessCgroupsV1("Enable cgroups not supported on cgroupv1 for rootless users")
1643
		// Only works on crun
1644
		if !strings.Contains(podmanTest.OCIRuntime, "crun") {
1645
			Skip("Test only works on crun")
1646
		}
1647

1648
		curCgroupsBytes, err := os.ReadFile("/proc/self/cgroup")
1649
		Expect(err).ToNot(HaveOccurred())
1650
		var curCgroups = string(curCgroupsBytes)
1651
		GinkgoWriter.Printf("Output:\n%s\n", curCgroups)
1652
		Expect(curCgroups).To(Not(Equal("")))
1653

1654
		ctrName := "testctr"
1655
		container := podmanTest.Podman([]string{"run", "--name", ctrName, "-d", "--cgroups=enabled", ALPINE, "top"})
1656
		container.WaitWithDefaultTimeout()
1657
		Expect(container).Should(ExitCleanly())
1658

1659
		// Get PID and get cgroups of that PID
1660
		inspectOut := podmanTest.InspectContainer(ctrName)
1661
		Expect(inspectOut).To(HaveLen(1))
1662
		pid := inspectOut[0].State.Pid
1663
		Expect(pid).To(Not(Equal(0)))
1664

1665
		ctrCgroupsBytes, err := os.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
1666
		Expect(err).ToNot(HaveOccurred())
1667
		var ctrCgroups = string(ctrCgroupsBytes)
1668
		GinkgoWriter.Printf("Output\n:%s\n", ctrCgroups)
1669
		Expect(curCgroups).To(Not(Equal(ctrCgroups)))
1670
	})
1671

1672
	It("podman run with cgroups=garbage errors", func() {
1673
		session := podmanTest.Podman([]string{"run", "-d", "--cgroups=garbage", ALPINE, "top"})
1674
		session.WaitWithDefaultTimeout()
1675
		Expect(session).To(ExitWithError())
1676
	})
1677

1678
	It("podman run should fail with nonexistent authfile", func() {
1679
		session := podmanTest.Podman([]string{"run", "--authfile", "/tmp/nonexistent", ALPINE, "ls"})
1680
		session.WaitWithDefaultTimeout()
1681
		Expect(session).To(ExitWithError())
1682
	})
1683

1684
	It("podman run --device-cgroup-rule", func() {
1685
		SkipIfRootless("rootless users are not allowed to mknod")
1686
		deviceCgroupRule := "c 42:* rwm"
1687
		session := podmanTest.Podman([]string{"run", "--cap-add", "mknod", "--name", "test", "-d", "--device-cgroup-rule", deviceCgroupRule, ALPINE, "top"})
1688
		session.WaitWithDefaultTimeout()
1689
		Expect(session).Should(ExitCleanly())
1690
		session = podmanTest.Podman([]string{"exec", "test", "mknod", "newDev", "c", "42", "1"})
1691
		session.WaitWithDefaultTimeout()
1692
		Expect(session).Should(ExitCleanly())
1693
	})
1694

1695
	It("podman run --replace", func() {
1696
		// Make sure we error out with --name.
1697
		session := podmanTest.Podman([]string{"create", "--replace", ALPINE, "/bin/sh"})
1698
		session.WaitWithDefaultTimeout()
1699
		Expect(session).Should(Exit(125))
1700
		Expect(session.ErrorToString()).To(ContainSubstring("cannot replace container without --name being set"))
1701

1702
		// Run and replace 5 times in a row the "same" container.
1703
		ctrName := "testCtr"
1704
		for i := 0; i < 5; i++ {
1705
			session := podmanTest.Podman([]string{"run", "--detach", "--replace", "--name", ctrName, ALPINE, "top"})
1706
			session.WaitWithDefaultTimeout()
1707
			// FIXME - #20196: Cannot use ExitCleanly()
1708
			Expect(session).Should(Exit(0))
1709

1710
			// make sure Podman prints only one ID
1711
			Expect(session.OutputToString()).To(HaveLen(64))
1712
		}
1713
	})
1714

1715
	It("podman run --preserve-fds", func() {
1716
		devNull, err := os.Open("/dev/null")
1717
		Expect(err).ToNot(HaveOccurred())
1718
		defer devNull.Close()
1719
		files := []*os.File{
1720
			devNull,
1721
		}
1722
		session := podmanTest.PodmanExtraFiles([]string{"run", "--preserve-fds", "1", ALPINE, "ls"}, files)
1723
		session.WaitWithDefaultTimeout()
1724
		Expect(session).Should(ExitCleanly())
1725
	})
1726

1727
	It("podman run --preserve-fds invalid fd", func() {
1728
		session := podmanTest.Podman([]string{"run", "--preserve-fds", "2", ALPINE})
1729
		session.WaitWithDefaultTimeout()
1730
		Expect(session).To(ExitWithError())
1731
		Expect(session.ErrorToString()).To(ContainSubstring("file descriptor 3 is not available"))
1732
	})
1733

1734
	It("podman run --privileged and --group-add", func() {
1735
		groupName := "mail"
1736
		session := podmanTest.Podman([]string{"run", "--group-add", groupName, "--privileged", fedoraMinimal, "groups"})
1737
		session.WaitWithDefaultTimeout()
1738
		Expect(session).Should(ExitCleanly())
1739
		Expect(session.OutputToString()).To(ContainSubstring(groupName))
1740
	})
1741

1742
	It("podman run --tz", func() {
1743
		testDir := filepath.Join(podmanTest.RunRoot, "tz-test")
1744
		err := os.MkdirAll(testDir, 0755)
1745
		Expect(err).ToNot(HaveOccurred())
1746

1747
		tzFile := filepath.Join(testDir, "tzfile.txt")
1748
		file, err := os.Create(tzFile)
1749
		Expect(err).ToNot(HaveOccurred())
1750
		defer os.Remove(tzFile)
1751

1752
		_, err = file.WriteString("Hello")
1753
		Expect(err).ToNot(HaveOccurred())
1754
		file.Close()
1755

1756
		badTZFile := fmt.Sprintf("../../../%s", tzFile)
1757
		session := podmanTest.Podman([]string{"run", "--tz", badTZFile, "--rm", ALPINE, "date"})
1758
		session.WaitWithDefaultTimeout()
1759
		Expect(session).To(ExitWithError())
1760
		Expect(session.ErrorToString()).To(
1761
			Equal("Error: running container create option: finding timezone: time: invalid location name"))
1762

1763
		session = podmanTest.Podman([]string{"run", "--tz", "Pacific/Honolulu", "--rm", ALPINE, "date", "+'%H %Z'"})
1764
		session.WaitWithDefaultTimeout()
1765
		Expect(session).Should(ExitCleanly())
1766
		Expect(session.OutputToString()).To(ContainSubstring("HST"))
1767

1768
		session = podmanTest.Podman([]string{"run", "--tz", "local", "--rm", ALPINE, "date", "+'%H %Z'"})
1769
		session.WaitWithDefaultTimeout()
1770
		Expect(session).Should(ExitCleanly())
1771
		t := time.Now()
1772
		z, _ := t.Zone()
1773
		h := strconv.Itoa(t.Hour())
1774
		Expect(session.OutputToString()).To(ContainSubstring(z))
1775
		Expect(session.OutputToString()).To(ContainSubstring(h))
1776

1777
	})
1778

1779
	It("podman run verify pids-limit", func() {
1780
		SkipIfCgroupV1("pids-limit not supported on cgroup V1")
1781
		limit := "4321"
1782
		session := podmanTest.Podman([]string{"run", "--pids-limit", limit, "--net=none", "--rm", ALPINE, "cat", "/sys/fs/cgroup/pids.max"})
1783
		session.WaitWithDefaultTimeout()
1784
		Expect(session).Should(ExitCleanly())
1785
		Expect(session.OutputToString()).To(ContainSubstring(limit))
1786
	})
1787

1788
	It("podman run umask", func() {
1789
		if !strings.Contains(podmanTest.OCIRuntime, "crun") {
1790
			Skip("Test only works on crun")
1791
		}
1792

1793
		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "sh", "-c", "umask"})
1794
		session.WaitWithDefaultTimeout()
1795
		Expect(session).Should(ExitCleanly())
1796
		Expect(session.OutputToString()).To(Equal("0022"))
1797

1798
		session = podmanTest.Podman([]string{"run", "--umask", "0002", "--rm", ALPINE, "sh", "-c", "umask"})
1799
		session.WaitWithDefaultTimeout()
1800
		Expect(session).Should(ExitCleanly())
1801
		Expect(session.OutputToString()).To(Equal("0002"))
1802

1803
		session = podmanTest.Podman([]string{"run", "--umask", "0077", "--rm", fedoraMinimal, "umask"})
1804
		session.WaitWithDefaultTimeout()
1805
		Expect(session).Should(ExitCleanly())
1806
		Expect(session.OutputToString()).To(Equal("0077"))
1807

1808
		session = podmanTest.Podman([]string{"run", "--umask", "22", "--rm", ALPINE, "sh", "-c", "umask"})
1809
		session.WaitWithDefaultTimeout()
1810
		Expect(session).Should(ExitCleanly())
1811
		Expect(session.OutputToString()).To(Equal("0022"))
1812

1813
		session = podmanTest.Podman([]string{"run", "--umask", "9999", "--rm", ALPINE, "sh", "-c", "umask"})
1814
		session.WaitWithDefaultTimeout()
1815
		Expect(session).To(ExitWithError())
1816
		Expect(session.ErrorToString()).To(ContainSubstring("invalid umask"))
1817
	})
1818

1819
	It("podman run makes workdir from image", func() {
1820
		// BuildImage does not seem to work remote
1821
		dockerfile := fmt.Sprintf(`FROM %s
1822
WORKDIR /madethis`, BB)
1823
		podmanTest.BuildImage(dockerfile, "test", "false")
1824
		session := podmanTest.Podman([]string{"run", "--rm", "test", "pwd"})
1825
		session.WaitWithDefaultTimeout()
1826
		Expect(session).Should(ExitCleanly())
1827
		Expect(session.OutputToString()).To(ContainSubstring("/madethis"))
1828
	})
1829

1830
	It("podman run --entrypoint does not use image command", func() {
1831
		session := podmanTest.Podman([]string{"run", "--entrypoint", "/bin/echo", ALPINE})
1832
		session.WaitWithDefaultTimeout()
1833
		Expect(session).Should(ExitCleanly())
1834
		// We can't guarantee the output is completely empty, some
1835
		// nonprintables seem to work their way in.
1836
		Expect(session.OutputToString()).To(Not(ContainSubstring("/bin/sh")))
1837
	})
1838

1839
	It("podman run a container with log-level (lower case)", func() {
1840
		session := podmanTest.Podman([]string{"--log-level=info", "run", ALPINE, "ls"})
1841
		session.WaitWithDefaultTimeout()
1842
		Expect(session).Should(Exit(0))
1843
		Expect(session.ErrorToString()).To(ContainSubstring(" level=info "))
1844
	})
1845

1846
	It("podman run a container with log-level (upper case)", func() {
1847
		session := podmanTest.Podman([]string{"--log-level=INFO", "run", ALPINE, "ls"})
1848
		session.WaitWithDefaultTimeout()
1849
		Expect(session).Should(Exit(0))
1850
		Expect(session.ErrorToString()).To(ContainSubstring(" level=info "))
1851
	})
1852

1853
	It("podman run a container with --pull never should fail if no local store", func() {
1854
		session := podmanTest.Podman([]string{"run", "--pull", "never", "docker.io/library/debian:latest", "ls"})
1855
		session.WaitWithDefaultTimeout()
1856
		Expect(session).Should(Exit(125))
1857
	})
1858

1859
	It("podman run container with --pull missing and only pull once", func() {
1860
		session := podmanTest.Podman([]string{"run", "--pull", "missing", CIRROS_IMAGE, "ls"})
1861
		session.WaitWithDefaultTimeout()
1862
		Expect(session).Should(Exit(0))
1863
		Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull"))
1864

1865
		session = podmanTest.Podman([]string{"run", "--pull", "missing", CIRROS_IMAGE, "ls"})
1866
		session.WaitWithDefaultTimeout()
1867
		Expect(session).Should(ExitCleanly())
1868
	})
1869

1870
	It("podman run container with --pull missing should pull image multiple times", func() {
1871
		session := podmanTest.Podman([]string{"run", "--pull", "always", CIRROS_IMAGE, "ls"})
1872
		session.WaitWithDefaultTimeout()
1873
		Expect(session).Should(Exit(0))
1874
		Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull"))
1875

1876
		session = podmanTest.Podman([]string{"run", "--pull", "always", CIRROS_IMAGE, "ls"})
1877
		session.WaitWithDefaultTimeout()
1878
		Expect(session).Should(Exit(0))
1879
		Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull"))
1880
	})
1881

1882
	It("podman run container with hostname and hostname environment variable", func() {
1883
		hostnameEnv := "test123"
1884
		session := podmanTest.Podman([]string{"run", "--hostname", "testctr", "--env", fmt.Sprintf("HOSTNAME=%s", hostnameEnv), ALPINE, "printenv", "HOSTNAME"})
1885
		session.WaitWithDefaultTimeout()
1886
		Expect(session).Should(ExitCleanly())
1887
		Expect(session.OutputToString()).To(ContainSubstring(hostnameEnv))
1888
	})
1889

1890
	It("podman run --secret", func() {
1891
		secretsString := "somesecretdata"
1892
		secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
1893
		err := os.WriteFile(secretFilePath, []byte(secretsString), 0755)
1894
		Expect(err).ToNot(HaveOccurred())
1895

1896
		session := podmanTest.Podman([]string{"secret", "create", "mysecret", secretFilePath})
1897
		session.WaitWithDefaultTimeout()
1898
		Expect(session).Should(ExitCleanly())
1899

1900
		session = podmanTest.Podman([]string{"run", "--secret", "mysecret", "--name", "secr", ALPINE, "cat", "/run/secrets/mysecret"})
1901
		session.WaitWithDefaultTimeout()
1902
		Expect(session).Should(ExitCleanly())
1903
		Expect(session.OutputToString()).To(Equal(secretsString))
1904

1905
		session = podmanTest.Podman([]string{"inspect", "secr", "--format", " {{(index .Config.Secrets 0).Name}}"})
1906
		session.WaitWithDefaultTimeout()
1907
		Expect(session).Should(ExitCleanly())
1908
		Expect(session.OutputToString()).To(ContainSubstring("mysecret"))
1909

1910
	})
1911

1912
	It("podman run --secret source=mysecret,type=mount", func() {
1913
		secretsString := "somesecretdata"
1914
		secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
1915
		err := os.WriteFile(secretFilePath, []byte(secretsString), 0755)
1916
		Expect(err).ToNot(HaveOccurred())
1917

1918
		session := podmanTest.Podman([]string{"secret", "create", "mysecret", secretFilePath})
1919
		session.WaitWithDefaultTimeout()
1920
		Expect(session).Should(ExitCleanly())
1921

1922
		session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=mount", "--name", "secr", ALPINE, "cat", "/run/secrets/mysecret"})
1923
		session.WaitWithDefaultTimeout()
1924
		Expect(session).Should(ExitCleanly())
1925
		Expect(session.OutputToString()).To(Equal(secretsString))
1926

1927
		session = podmanTest.Podman([]string{"inspect", "secr", "--format", " {{(index .Config.Secrets 0).Name}}"})
1928
		session.WaitWithDefaultTimeout()
1929
		Expect(session).Should(ExitCleanly())
1930
		Expect(session.OutputToString()).To(ContainSubstring("mysecret"))
1931

1932
	})
1933

1934
	It("podman run --secret source=mysecret,type=mount with target", func() {
1935
		secretsString := "somesecretdata"
1936
		secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
1937
		err := os.WriteFile(secretFilePath, []byte(secretsString), 0755)
1938
		Expect(err).ToNot(HaveOccurred())
1939

1940
		session := podmanTest.Podman([]string{"secret", "create", "mysecret_target", secretFilePath})
1941
		session.WaitWithDefaultTimeout()
1942
		Expect(session).Should(ExitCleanly())
1943

1944
		session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret_target,type=mount,target=hello", "--name", "secr_target", ALPINE, "cat", "/run/secrets/hello"})
1945
		session.WaitWithDefaultTimeout()
1946
		Expect(session).Should(ExitCleanly())
1947
		Expect(session.OutputToString()).To(Equal(secretsString))
1948

1949
		session = podmanTest.Podman([]string{"inspect", "secr_target", "--format", " {{(index .Config.Secrets 0).Name}}"})
1950
		session.WaitWithDefaultTimeout()
1951
		Expect(session).Should(ExitCleanly())
1952
		Expect(session.OutputToString()).To(ContainSubstring("mysecret_target"))
1953

1954
	})
1955

1956
	It("podman run --secret source=mysecret,type=mount with target at /tmp", func() {
1957
		secretsString := "somesecretdata"
1958
		secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
1959
		err := os.WriteFile(secretFilePath, []byte(secretsString), 0755)
1960
		Expect(err).ToNot(HaveOccurred())
1961

1962
		session := podmanTest.Podman([]string{"secret", "create", "mysecret_target2", secretFilePath})
1963
		session.WaitWithDefaultTimeout()
1964
		Expect(session).Should(ExitCleanly())
1965

1966
		session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret_target2,type=mount,target=/tmp/hello", "--name", "secr_target2", ALPINE, "cat", "/tmp/hello"})
1967
		session.WaitWithDefaultTimeout()
1968
		Expect(session).Should(ExitCleanly())
1969
		Expect(session.OutputToString()).To(Equal(secretsString))
1970

1971
		session = podmanTest.Podman([]string{"inspect", "secr_target2", "--format", " {{(index .Config.Secrets 0).Name}}"})
1972
		session.WaitWithDefaultTimeout()
1973
		Expect(session).Should(ExitCleanly())
1974
		Expect(session.OutputToString()).To(ContainSubstring("mysecret_target2"))
1975

1976
	})
1977

1978
	It("podman run --secret source=mysecret,type=env", func() {
1979
		secretsString := "somesecretdata"
1980
		secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
1981
		err := os.WriteFile(secretFilePath, []byte(secretsString), 0755)
1982
		Expect(err).ToNot(HaveOccurred())
1983

1984
		session := podmanTest.Podman([]string{"secret", "create", "mysecret", secretFilePath})
1985
		session.WaitWithDefaultTimeout()
1986
		Expect(session).Should(ExitCleanly())
1987

1988
		session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=env", "--name", "secr", ALPINE, "printenv", "mysecret"})
1989
		session.WaitWithDefaultTimeout()
1990
		Expect(session).Should(ExitCleanly())
1991
		Expect(session.OutputToString()).To(Equal(secretsString))
1992
	})
1993

1994
	It("podman run --secret target option", func() {
1995
		secretsString := "somesecretdata"
1996
		secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
1997
		err := os.WriteFile(secretFilePath, []byte(secretsString), 0755)
1998
		Expect(err).ToNot(HaveOccurred())
1999

2000
		session := podmanTest.Podman([]string{"secret", "create", "mysecret", secretFilePath})
2001
		session.WaitWithDefaultTimeout()
2002
		Expect(session).Should(ExitCleanly())
2003

2004
		session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=env,target=anotherplace", "--name", "secr", ALPINE, "printenv", "anotherplace"})
2005
		session.WaitWithDefaultTimeout()
2006
		Expect(session).Should(ExitCleanly())
2007
		Expect(session.OutputToString()).To(Equal(secretsString))
2008
	})
2009

2010
	It("podman run --secret mount with uid, gid, mode options", func() {
2011
		secretsString := "somesecretdata"
2012
		secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
2013
		err := os.WriteFile(secretFilePath, []byte(secretsString), 0755)
2014
		Expect(err).ToNot(HaveOccurred())
2015

2016
		session := podmanTest.Podman([]string{"secret", "create", "mysecret", secretFilePath})
2017
		session.WaitWithDefaultTimeout()
2018
		Expect(session).Should(ExitCleanly())
2019

2020
		// check default permissions
2021
		session = podmanTest.Podman([]string{"run", "--secret", "mysecret", "--name", "secr", ALPINE, "ls", "-l", "/run/secrets/mysecret"})
2022
		session.WaitWithDefaultTimeout()
2023
		Expect(session).Should(ExitCleanly())
2024
		output := session.OutputToString()
2025
		Expect(output).To(ContainSubstring("-r--r--r--"))
2026
		Expect(output).To(ContainSubstring("root"))
2027

2028
		session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=mount,uid=1000,gid=1001,mode=777", "--name", "secr2", ALPINE, "ls", "-ln", "/run/secrets/mysecret"})
2029
		session.WaitWithDefaultTimeout()
2030
		Expect(session).Should(ExitCleanly())
2031
		output = session.OutputToString()
2032
		Expect(output).To(ContainSubstring("-rwxrwxrwx"))
2033
		Expect(output).To(ContainSubstring("1000"))
2034
		Expect(output).To(ContainSubstring("1001"))
2035
	})
2036

2037
	It("podman run --secret with --user", func() {
2038
		secretsString := "somesecretdata"
2039
		secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
2040
		err := os.WriteFile(secretFilePath, []byte(secretsString), 0755)
2041
		Expect(err).ToNot(HaveOccurred())
2042

2043
		session := podmanTest.Podman([]string{"secret", "create", "mysecret", secretFilePath})
2044
		session.WaitWithDefaultTimeout()
2045
		Expect(session).Should(ExitCleanly())
2046

2047
		session = podmanTest.Podman([]string{"run", "--secret", "mysecret", "--name", "nonroot", "--user", "200:200", ALPINE, "cat", "/run/secrets/mysecret"})
2048
		session.WaitWithDefaultTimeout()
2049
		Expect(session).Should(ExitCleanly())
2050
		Expect(session.OutputToString()).To(Equal(secretsString))
2051
	})
2052

2053
	It("podman run invalid secret option", func() {
2054
		secretsString := "somesecretdata"
2055
		secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
2056
		err := os.WriteFile(secretFilePath, []byte(secretsString), 0755)
2057
		Expect(err).ToNot(HaveOccurred())
2058

2059
		session := podmanTest.Podman([]string{"secret", "create", "mysecret", secretFilePath})
2060
		session.WaitWithDefaultTimeout()
2061
		Expect(session).Should(ExitCleanly())
2062

2063
		// Invalid type
2064
		session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=other", "--name", "secr", ALPINE, "printenv", "mysecret"})
2065
		session.WaitWithDefaultTimeout()
2066
		Expect(session).To(ExitWithError())
2067

2068
		// Invalid option
2069
		session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,invalid=invalid", "--name", "secr", ALPINE, "printenv", "mysecret"})
2070
		session.WaitWithDefaultTimeout()
2071
		Expect(session).To(ExitWithError())
2072

2073
		// Option syntax not valid
2074
		session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type", "--name", "secr", ALPINE, "printenv", "mysecret"})
2075
		session.WaitWithDefaultTimeout()
2076
		Expect(session).To(ExitWithError())
2077

2078
		// mount option with env type
2079
		session = podmanTest.Podman([]string{"run", "--secret", "source=mysecret,type=env,uid=1000", "--name", "secr", ALPINE, "printenv", "mysecret"})
2080
		session.WaitWithDefaultTimeout()
2081
		Expect(session).To(ExitWithError())
2082

2083
		// No source given
2084
		session = podmanTest.Podman([]string{"run", "--secret", "type=env", "--name", "secr", ALPINE, "printenv", "mysecret"})
2085
		session.WaitWithDefaultTimeout()
2086
		Expect(session).To(ExitWithError())
2087
	})
2088

2089
	It("podman run --requires", func() {
2090
		depName := "ctr1"
2091
		depContainer := podmanTest.Podman([]string{"create", "--name", depName, ALPINE, "top"})
2092
		depContainer.WaitWithDefaultTimeout()
2093
		Expect(depContainer).Should(ExitCleanly())
2094

2095
		mainName := "ctr2"
2096
		mainContainer := podmanTest.Podman([]string{"run", "--name", mainName, "--requires", depName, "-d", ALPINE, "top"})
2097
		mainContainer.WaitWithDefaultTimeout()
2098
		Expect(mainContainer).Should(ExitCleanly())
2099

2100
		podmanTest.StopContainer("--all")
2101

2102
		start := podmanTest.Podman([]string{"start", mainName})
2103
		start.WaitWithDefaultTimeout()
2104
		Expect(start).Should(ExitCleanly())
2105

2106
		running := podmanTest.Podman([]string{"ps", "-q"})
2107
		running.WaitWithDefaultTimeout()
2108
		Expect(running).Should(ExitCleanly())
2109
		Expect(running.OutputToStringArray()).To(HaveLen(2))
2110
	})
2111

2112
	It("podman run with pidfile", func() {
2113
		SkipIfRemote("pidfile not handled by remote")
2114
		pidfile := filepath.Join(tempdir, "pidfile")
2115
		session := podmanTest.Podman([]string{"run", "--pidfile", pidfile, ALPINE, "ls"})
2116
		session.WaitWithDefaultTimeout()
2117
		Expect(session).Should(ExitCleanly())
2118
		readFirstLine := func(path string) string {
2119
			content, err := os.ReadFile(path)
2120
			Expect(err).ToNot(HaveOccurred())
2121
			return strings.Split(string(content), "\n")[0]
2122
		}
2123
		containerPID := readFirstLine(pidfile)
2124
		_, err = strconv.Atoi(containerPID) // Make sure it's a proper integer
2125
		Expect(err).ToNot(HaveOccurred())
2126
	})
2127

2128
	It("podman run check personality support", func() {
2129
		// TODO: Remove this as soon as this is merged and made available in our CI https://github.com/opencontainers/runc/pull/3126.
2130
		if !strings.Contains(podmanTest.OCIRuntime, "crun") {
2131
			Skip("Test only works on crun")
2132
		}
2133
		session := podmanTest.Podman([]string{"run", "--personality=LINUX32", "--name=testpersonality", ALPINE, "uname", "-a"})
2134
		session.WaitWithDefaultTimeout()
2135
		Expect(session).Should(ExitCleanly())
2136
		Expect(session.OutputToString()).To(ContainSubstring("i686"))
2137
	})
2138

2139
	It("podman run /dev/shm has nosuid,noexec,nodev", func() {
2140
		session := podmanTest.Podman([]string{"run", ALPINE, "grep", "/dev/shm", "/proc/self/mountinfo"})
2141
		session.WaitWithDefaultTimeout()
2142
		Expect(session).Should(ExitCleanly())
2143
		output := session.OutputToString()
2144
		Expect(output).To(ContainSubstring("nosuid"))
2145
		Expect(output).To(ContainSubstring("noexec"))
2146
		Expect(output).To(ContainSubstring("nodev"))
2147
	})
2148

2149
	It("podman run and decrypt from local registry", func() {
2150
		SkipIfRemote("Remote run does not support decryption")
2151

2152
		if podmanTest.Host.Arch == "ppc64le" {
2153
			Skip("No registry image for ppc64le")
2154
		}
2155

2156
		podmanTest.AddImageToRWStore(ALPINE)
2157

2158
		lock := GetPortLock("5006")
2159
		defer lock.Unlock()
2160
		session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5006:5000", REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"})
2161
		session.WaitWithDefaultTimeout()
2162
		Expect(session).Should(ExitCleanly())
2163

2164
		if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
2165
			Fail("Cannot start docker registry.")
2166
		}
2167

2168
		bitSize := 1024
2169
		keyFileName := filepath.Join(podmanTest.TempDir, "key,withcomma")
2170
		publicKeyFileName, privateKeyFileName, err := WriteRSAKeyPair(keyFileName, bitSize)
2171
		Expect(err).ToNot(HaveOccurred())
2172

2173
		imgPath := "localhost:5006/my-alpine"
2174
		session = podmanTest.Podman([]string{"push", "--encryption-key", "jwe:" + publicKeyFileName, "--tls-verify=false", "--remove-signatures", ALPINE, imgPath})
2175
		session.WaitWithDefaultTimeout()
2176

2177
		session = podmanTest.Podman([]string{"rmi", ALPINE})
2178
		session.WaitWithDefaultTimeout()
2179
		Expect(session).Should(ExitCleanly())
2180

2181
		// Must fail without --decryption-key
2182
		session = podmanTest.Podman([]string{"run", "--tls-verify=false", imgPath})
2183
		session.WaitWithDefaultTimeout()
2184
		Expect(session).Should(Exit(125))
2185
		Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull " + imgPath))
2186
		Expect(session.ErrorToString()).To(ContainSubstring("invalid tar header"))
2187

2188
		// With
2189
		session = podmanTest.Podman([]string{"run", "--tls-verify=false", "--decryption-key", privateKeyFileName, imgPath})
2190
		session.WaitWithDefaultTimeout()
2191
		Expect(session).Should(Exit(0))
2192
		Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull " + imgPath))
2193
	})
2194

2195
	It("podman run --shm-size-systemd", func() {
2196
		ctrName := "testShmSizeSystemd"
2197
		run := podmanTest.Podman([]string{"run", "--name", ctrName, "--shm-size-systemd", "10mb", "-d", SYSTEMD_IMAGE, "/sbin/init"})
2198
		run.WaitWithDefaultTimeout()
2199
		Expect(run).Should(ExitCleanly())
2200

2201
		logs := podmanTest.Podman([]string{"logs", ctrName})
2202
		logs.WaitWithDefaultTimeout()
2203
		Expect(logs).Should(ExitCleanly())
2204

2205
		mount := podmanTest.Podman([]string{"exec", ctrName, "mount"})
2206
		mount.WaitWithDefaultTimeout()
2207
		Expect(mount).Should(ExitCleanly())
2208
		t, strings := mount.GrepString("tmpfs on /run/lock")
2209
		Expect(t).To(BeTrue(), "found /run/lock")
2210
		Expect(strings[0]).Should(ContainSubstring("size=10240k"))
2211
	})
2212

2213
	It("podman run does not preserve image annotations", func() {
2214
		annoName := "test.annotation.present"
2215
		annoValue := "annovalue"
2216
		imgName := "basicalpine"
2217
		build := podmanTest.Podman([]string{"build", "-f", "build/basicalpine/Containerfile.with_label", "--annotation", fmt.Sprintf("%s=%s", annoName, annoValue), "-t", imgName})
2218
		build.WaitWithDefaultTimeout()
2219
		Expect(build).Should(ExitCleanly())
2220
		Expect(build.ErrorToString()).To(BeEmpty(), "build error logged")
2221

2222
		ctrName := "ctr1"
2223
		run := podmanTest.Podman([]string{"run", "-d", "--name", ctrName, imgName, "top"})
2224
		run.WaitWithDefaultTimeout()
2225
		Expect(run).Should(ExitCleanly())
2226
		Expect(run.ErrorToString()).To(BeEmpty(), "run error logged")
2227

2228
		inspect := podmanTest.Podman([]string{"inspect", ctrName})
2229
		inspect.WaitWithDefaultTimeout()
2230
		Expect(inspect).Should(ExitCleanly())
2231
		Expect(inspect.ErrorToString()).To(BeEmpty(), "inspect error logged")
2232

2233
		inspectData := inspect.InspectContainerToJSON()
2234
		Expect(inspectData).To(HaveLen(1))
2235
		Expect(inspectData[0].Config.Annotations).To(Not(HaveKey(annoName)))
2236
		Expect(inspectData[0].Config.Annotations).To(Not(HaveKey("testlabel")))
2237
	})
2238
})
2239

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.