8
. "github.com/containers/podman/v5/test/utils"
9
. "github.com/onsi/ginkgo/v2"
10
. "github.com/onsi/gomega"
11
. "github.com/onsi/gomega/gexec"
14
var pruneImage = fmt.Sprintf(`
16
LABEL RUN podman --version
17
RUN echo hello > /hello
18
RUN echo hello2 > /hello2`, ALPINE)
20
var emptyPruneImage = `
25
var _ = Describe("Podman prune", func() {
27
It("podman container prune containers", func() {
28
top := podmanTest.RunTopContainer("")
29
top.WaitWithDefaultTimeout()
30
Expect(top).Should(ExitCleanly())
32
top = podmanTest.RunTopContainer("")
33
top.WaitWithDefaultTimeout()
34
Expect(top).Should(ExitCleanly())
35
cid := top.OutputToString()
37
podmanTest.StopContainer(cid)
39
prune := podmanTest.Podman([]string{"container", "prune", "-f"})
40
prune.WaitWithDefaultTimeout()
41
Expect(prune).Should(ExitCleanly())
43
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
46
It("podman container prune after create containers", func() {
47
create := podmanTest.Podman([]string{"create", "--name", "test", BB})
48
create.WaitWithDefaultTimeout()
49
Expect(create).Should(ExitCleanly())
51
prune := podmanTest.Podman([]string{"container", "prune", "-f"})
52
prune.WaitWithDefaultTimeout()
53
Expect(prune).Should(ExitCleanly())
55
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
58
It("podman container prune after create & init containers", func() {
59
create := podmanTest.Podman([]string{"create", "--name", "test", BB})
60
create.WaitWithDefaultTimeout()
61
Expect(create).Should(ExitCleanly())
63
init := podmanTest.Podman([]string{"init", "test"})
64
init.WaitWithDefaultTimeout()
65
Expect(init).Should(ExitCleanly())
67
prune := podmanTest.Podman([]string{"container", "prune", "-f"})
68
prune.WaitWithDefaultTimeout()
69
Expect(prune).Should(ExitCleanly())
71
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
74
It("podman image prune - remove only dangling images", func() {
75
session := podmanTest.Podman([]string{"images", "-a"})
76
session.WaitWithDefaultTimeout()
77
Expect(session).Should(ExitCleanly())
78
Expect(session.OutputToString()).To(Not(ContainSubstring("<none>")))
79
numImages := len(session.OutputToStringArray())
82
session = podmanTest.Podman([]string{"image", "prune", "-f"})
83
session.WaitWithDefaultTimeout()
84
Expect(session).Should(ExitCleanly())
85
Expect(session.OutputToStringArray()).To(BeEmpty())
89
session = podmanTest.Podman([]string{"images", "-a"})
90
session.WaitWithDefaultTimeout()
91
Expect(session).Should(ExitCleanly())
92
Expect(session.OutputToStringArray()).To(HaveLen(numImages))
96
podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true")
97
session = podmanTest.Podman([]string{"untag", "alpine_bash:latest"})
98
session.WaitWithDefaultTimeout()
99
Expect(session).Should(ExitCleanly())
101
session = podmanTest.Podman([]string{"images", "-a"})
102
session.WaitWithDefaultTimeout()
103
Expect(session).Should(ExitCleanly())
104
Expect(session.OutputToString()).To(ContainSubstring("<none>"))
105
numImages = len(session.OutputToStringArray())
109
session = podmanTest.Podman([]string{"image", "prune", "-f"})
110
session.WaitWithDefaultTimeout()
111
Expect(session).Should(ExitCleanly())
112
numPrunedImages := len(session.OutputToStringArray())
113
Expect(numPrunedImages).To(BeNumerically(">=", 1), "numPrunedImages")
117
session = podmanTest.Podman([]string{"images", "-a"})
118
session.WaitWithDefaultTimeout()
119
Expect(session).Should(ExitCleanly())
120
Expect(session.OutputToStringArray()).To(HaveLen(numImages - numPrunedImages))
123
It("podman image prune - handle empty images", func() {
126
podmanTest.BuildImage(emptyPruneImage, "empty:scratch", "true")
128
session := podmanTest.Podman([]string{"images", "-a"})
129
session.WaitWithDefaultTimeout()
130
Expect(session).Should(ExitCleanly())
131
Expect(session.OutputToString()).To(ContainSubstring("<none>"))
134
session = podmanTest.Podman([]string{"image", "prune", "-f"})
135
session.WaitWithDefaultTimeout()
136
Expect(session).Should(ExitCleanly())
137
Expect(session.OutputToStringArray()).To(BeEmpty())
141
session = podmanTest.Podman([]string{"untag", "empty:scratch"})
142
session.WaitWithDefaultTimeout()
143
Expect(session).Should(ExitCleanly())
145
session = podmanTest.Podman([]string{"image", "prune", "-f"})
146
session.WaitWithDefaultTimeout()
147
Expect(session).Should(ExitCleanly())
148
Expect(session.OutputToStringArray()).To(HaveLen(2))
151
It("podman image prune dangling images", func() {
152
podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true")
153
podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true")
154
none := podmanTest.Podman([]string{"images", "-a"})
155
none.WaitWithDefaultTimeout()
156
Expect(none).Should(ExitCleanly())
157
hasNone, result := none.GrepString("<none>")
158
Expect(result).To(HaveLen(2))
159
Expect(hasNone).To(BeTrue())
161
prune := podmanTest.Podman([]string{"image", "prune", "-f"})
162
prune.WaitWithDefaultTimeout()
163
Expect(prune).Should(ExitCleanly())
165
after := podmanTest.Podman([]string{"images", "-a"})
166
after.WaitWithDefaultTimeout()
167
Expect(after).Should(ExitCleanly())
168
hasNoneAfter, result := after.GrepString("<none>")
169
Expect(hasNoneAfter).To(BeTrue())
170
Expect(len(after.OutputToStringArray())).To(BeNumerically(">", 1))
171
Expect(result).ToNot(BeEmpty())
174
It("podman image prune unused images", func() {
175
podmanTest.AddImageToRWStore(ALPINE)
176
podmanTest.AddImageToRWStore(BB)
178
images := podmanTest.Podman([]string{"images", "-a"})
179
images.WaitWithDefaultTimeout()
180
Expect(images).Should(ExitCleanly())
182
prune := podmanTest.Podman([]string{"image", "prune", "-af"})
183
prune.WaitWithDefaultTimeout()
184
Expect(prune).Should(ExitCleanly())
186
images = podmanTest.Podman([]string{"images", "-aq"})
187
images.WaitWithDefaultTimeout()
188
Expect(images).Should(ExitCleanly())
190
Expect(images.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES)))
193
It("podman system image prune unused images", func() {
194
useCustomNetworkDir(podmanTest, tempdir)
195
podmanTest.AddImageToRWStore(ALPINE)
196
podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true")
197
prune := podmanTest.Podman([]string{"system", "prune", "-a", "--force"})
198
prune.WaitWithDefaultTimeout()
199
Expect(prune).Should(ExitCleanly())
201
images := podmanTest.Podman([]string{"images", "-aq"})
202
images.WaitWithDefaultTimeout()
204
Expect(images.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES)))
207
It("podman system prune pods", func() {
208
useCustomNetworkDir(podmanTest, tempdir)
209
session := podmanTest.Podman([]string{"pod", "create"})
210
session.WaitWithDefaultTimeout()
211
Expect(session).Should(ExitCleanly())
213
session = podmanTest.Podman([]string{"pod", "create"})
214
session.WaitWithDefaultTimeout()
215
Expect(session).Should(ExitCleanly())
216
podid1 := session.OutputToString()
218
session = podmanTest.Podman([]string{"pod", "start", podid1})
219
session.WaitWithDefaultTimeout()
220
Expect(session).Should(ExitCleanly())
221
podmanTest.StopPod(podid1)
223
pods := podmanTest.Podman([]string{"pod", "ps"})
224
pods.WaitWithDefaultTimeout()
225
Expect(pods).Should(ExitCleanly())
226
Expect(pods.OutputToStringArray()).To(HaveLen(3))
228
prune := podmanTest.Podman([]string{"system", "prune", "-f"})
229
prune.WaitWithDefaultTimeout()
230
Expect(prune).Should(ExitCleanly())
232
pods = podmanTest.Podman([]string{"pod", "ps"})
233
pods.WaitWithDefaultTimeout()
234
Expect(pods).Should(ExitCleanly())
235
Expect(pods.OutputToStringArray()).To(HaveLen(2))
238
It("podman system prune networks", func() {
239
useCustomNetworkDir(podmanTest, tempdir)
241
session := podmanTest.Podman([]string{"network", "create", "test"})
242
session.WaitWithDefaultTimeout()
243
Expect(session).Should(ExitCleanly())
246
session = podmanTest.Podman([]string{"system", "prune", "-f"})
247
session.WaitWithDefaultTimeout()
248
Expect(session).Should(ExitCleanly())
251
session = podmanTest.Podman([]string{"network", "ls", "-q", "--filter", "name=^podman$"})
252
session.WaitWithDefaultTimeout()
253
Expect(session).Should(ExitCleanly())
254
Expect(session.OutputToStringArray()).To(HaveLen(1))
257
session = podmanTest.Podman([]string{"network", "ls", "-q", "--filter", "name=^test$"})
258
session.WaitWithDefaultTimeout()
259
Expect(session).Should(ExitCleanly())
260
Expect(session.OutputToStringArray()).To(BeEmpty())
263
session = podmanTest.Podman([]string{"network", "create", "test1", "--label", "foo"})
264
session.WaitWithDefaultTimeout()
265
Expect(session).Should(ExitCleanly())
268
session = podmanTest.Podman([]string{"system", "prune", "-f", "--filter", "label!=foo"})
269
session.WaitWithDefaultTimeout()
270
Expect(session).Should(ExitCleanly())
271
Expect(session.OutputToString()).Should(Equal("Total reclaimed space: 0B"))
274
session = podmanTest.Podman([]string{"network", "ls", "-q", "--filter", "name=^test1$"})
275
session.WaitWithDefaultTimeout()
276
Expect(session).Should(ExitCleanly())
278
Expect(session.OutputToStringArray()).To(HaveLen(1))
281
It("podman system prune - pod,container stopped", func() {
282
useCustomNetworkDir(podmanTest, tempdir)
283
session := podmanTest.Podman([]string{"pod", "create"})
284
session.WaitWithDefaultTimeout()
285
Expect(session).Should(ExitCleanly())
286
podid1 := session.OutputToString()
289
session = podmanTest.Podman([]string{"pod", "start", podid1})
290
session.WaitWithDefaultTimeout()
291
Expect(session).Should(ExitCleanly())
292
podmanTest.StopPod(podid1)
295
create := podmanTest.Podman([]string{"create", "--name", "test", BB})
296
create.WaitWithDefaultTimeout()
297
Expect(create).Should(ExitCleanly())
299
prune := podmanTest.Podman([]string{"system", "prune", "-f"})
300
prune.WaitWithDefaultTimeout()
301
Expect(prune).Should(ExitCleanly())
303
pods := podmanTest.Podman([]string{"pod", "ps"})
304
pods.WaitWithDefaultTimeout()
305
Expect(pods).Should(ExitCleanly())
306
Expect(podmanTest.NumberOfPods()).To(Equal(0))
308
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
311
It("podman system prune with running, exited pod and volume prune set true", func() {
312
useCustomNetworkDir(podmanTest, tempdir)
314
session := podmanTest.Podman([]string{"pod", "create"})
315
session.WaitWithDefaultTimeout()
316
Expect(session).Should(ExitCleanly())
317
podid1 := session.OutputToString()
319
session = podmanTest.Podman([]string{"pod", "start", podid1})
320
session.WaitWithDefaultTimeout()
321
Expect(session).Should(ExitCleanly())
322
podmanTest.StopPod(podid1)
325
session = podmanTest.Podman([]string{"pod", "create"})
326
session.WaitWithDefaultTimeout()
327
Expect(session).Should(ExitCleanly())
328
podid2 := session.OutputToString()
330
session = podmanTest.Podman([]string{"pod", "start", podid2})
331
session.WaitWithDefaultTimeout()
332
Expect(session).Should(ExitCleanly())
335
Expect(podmanTest.NumberOfPods()).To(Equal(2))
338
_, ec, _ := podmanTest.RunLsContainer("test1")
339
Expect(ec).To(Equal(0))
343
Expect(podmanTest.NumberOfContainers()).To(Equal(3))
346
session = podmanTest.Podman([]string{"images"})
347
session.WaitWithDefaultTimeout()
348
numberOfImages := len(session.OutputToStringArray())
351
session = podmanTest.Podman([]string{"volume", "create"})
352
session.WaitWithDefaultTimeout()
353
Expect(session).Should(ExitCleanly())
355
session = podmanTest.Podman([]string{"create", "-v", "myvol:/myvol", ALPINE, "ls"})
356
session.WaitWithDefaultTimeout()
357
Expect(session).Should(ExitCleanly())
359
session = podmanTest.Podman([]string{"volume", "ls"})
360
session.WaitWithDefaultTimeout()
361
Expect(session).Should(ExitCleanly())
362
Expect(session.OutputToStringArray()).To(HaveLen(3))
364
session = podmanTest.Podman([]string{"system", "prune", "--force", "--volumes"})
365
session.WaitWithDefaultTimeout()
366
Expect(session).Should(ExitCleanly())
369
session = podmanTest.Podman([]string{"volume", "ls"})
370
session.WaitWithDefaultTimeout()
371
Expect(session).Should(ExitCleanly())
372
Expect(session.OutputToStringArray()).To(BeEmpty())
375
Expect(podmanTest.NumberOfPods()).To(Equal(1))
378
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
381
images := podmanTest.Podman([]string{"images"})
382
images.WaitWithDefaultTimeout()
383
Expect(images.OutputToStringArray()).To(HaveLen(numberOfImages))
386
It("podman system prune - with dangling images true", func() {
387
useCustomNetworkDir(podmanTest, tempdir)
388
session := podmanTest.Podman([]string{"pod", "create"})
389
session.WaitWithDefaultTimeout()
390
Expect(session).Should(ExitCleanly())
391
podid1 := session.OutputToString()
394
session = podmanTest.Podman([]string{"pod", "start", podid1})
395
session.WaitWithDefaultTimeout()
396
Expect(session).Should(ExitCleanly())
398
podmanTest.StopPod(podid1)
401
create := podmanTest.Podman([]string{"create", "--name", "test", BB})
402
create.WaitWithDefaultTimeout()
403
Expect(create).Should(ExitCleanly())
406
session = podmanTest.Podman([]string{"volume", "create"})
407
session.WaitWithDefaultTimeout()
408
Expect(session).Should(ExitCleanly())
410
prune := podmanTest.Podman([]string{"system", "prune", "-f", "-a"})
411
prune.WaitWithDefaultTimeout()
412
Expect(prune).Should(ExitCleanly())
414
pods := podmanTest.Podman([]string{"pod", "ps"})
415
pods.WaitWithDefaultTimeout()
416
Expect(pods).Should(ExitCleanly())
417
Expect(podmanTest.NumberOfPods()).To(Equal(0))
419
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
422
session = podmanTest.Podman([]string{"volume", "ls"})
423
session.WaitWithDefaultTimeout()
424
Expect(session).Should(ExitCleanly())
425
Expect(session.OutputToStringArray()).To(HaveLen(2))
427
images := podmanTest.Podman([]string{"images", "-aq"})
428
images.WaitWithDefaultTimeout()
430
Expect(images.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES)))
433
It("podman system prune --volumes --filter", func() {
434
useCustomNetworkDir(podmanTest, tempdir)
435
session := podmanTest.Podman([]string{"volume", "create", "--label", "label1=value1", "myvol1"})
436
session.WaitWithDefaultTimeout()
437
Expect(session).Should(ExitCleanly())
439
session = podmanTest.Podman([]string{"volume", "create", "--label", "sharedlabel1=slv1", "myvol2"})
440
session.WaitWithDefaultTimeout()
441
Expect(session).Should(ExitCleanly())
443
session = podmanTest.Podman([]string{"volume", "create", "--label", "sharedlabel1=slv2", "myvol3"})
444
session.WaitWithDefaultTimeout()
445
Expect(session).Should(ExitCleanly())
447
session = podmanTest.Podman([]string{"volume", "create", "--label", "sharedlabel1", "myvol4"})
448
session.WaitWithDefaultTimeout()
449
Expect(session).Should(ExitCleanly())
451
session = podmanTest.Podman([]string{"create", "-v", "myvol5:/myvol5", ALPINE, "ls"})
452
session.WaitWithDefaultTimeout()
453
Expect(session).Should(ExitCleanly())
455
session = podmanTest.Podman([]string{"create", "-v", "myvol6:/myvol6", ALPINE, "ls"})
456
session.WaitWithDefaultTimeout()
457
Expect(session).Should(ExitCleanly())
459
session = podmanTest.Podman([]string{"volume", "ls"})
460
session.WaitWithDefaultTimeout()
461
Expect(session).Should(ExitCleanly())
462
Expect(session.OutputToStringArray()).To(HaveLen(7))
464
session = podmanTest.Podman([]string{"system", "prune", "--force", "--volumes", "--filter", "label=label1=value1"})
465
session.WaitWithDefaultTimeout()
466
Expect(session).Should(ExitCleanly())
468
session = podmanTest.Podman([]string{"volume", "ls"})
469
session.WaitWithDefaultTimeout()
470
Expect(session).Should(ExitCleanly())
471
Expect(session.OutputToStringArray()).To(HaveLen(6))
473
session = podmanTest.Podman([]string{"system", "prune", "--force", "--volumes", "--filter", "label=sharedlabel1=slv1"})
474
session.WaitWithDefaultTimeout()
475
Expect(session).Should(ExitCleanly())
477
session = podmanTest.Podman([]string{"volume", "ls"})
478
session.WaitWithDefaultTimeout()
479
Expect(session).Should(ExitCleanly())
480
Expect(session.OutputToStringArray()).To(HaveLen(5))
482
session = podmanTest.Podman([]string{"system", "prune", "--force", "--volumes", "--filter", "label=sharedlabel1"})
483
session.WaitWithDefaultTimeout()
484
Expect(session).Should(ExitCleanly())
486
session = podmanTest.Podman([]string{"volume", "ls"})
487
session.WaitWithDefaultTimeout()
488
Expect(session).Should(ExitCleanly())
489
Expect(session.OutputToStringArray()).To(HaveLen(3))
492
It("podman system prune --all --external fails", func() {
493
prune := podmanTest.Podman([]string{"system", "prune", "--all", "--external"})
494
prune.WaitWithDefaultTimeout()
495
Expect(prune).Should(Exit(125))
496
Expect(prune.ErrorToString()).To(ContainSubstring("--external cannot be combined with other options"))
499
It("podman system prune --external leaves referenced containers", func() {
500
useCustomNetworkDir(podmanTest, tempdir)
501
containerStorageDir := filepath.Join(podmanTest.Root, podmanTest.ImageCacheFS+"-containers")
503
create := podmanTest.Podman([]string{"create", "--name", "test", BB})
504
create.WaitWithDefaultTimeout()
505
Expect(create).Should(ExitCleanly())
508
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
511
dirents, err := os.ReadDir(containerStorageDir)
512
Expect(err).ToNot(HaveOccurred())
513
Expect(dirents).To(HaveLen(3))
515
prune := podmanTest.Podman([]string{"system", "prune", "--external", "-f"})
516
prune.WaitWithDefaultTimeout()
517
Expect(prune).Should(ExitCleanly())
520
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
523
dirents, err = os.ReadDir(containerStorageDir)
524
Expect(err).ToNot(HaveOccurred())
525
Expect(dirents).To(HaveLen(3))
529
It("podman system prune --external removes unreferenced containers", func() {
530
SkipIfRemote("Can't drop database while daemon running")
531
useCustomNetworkDir(podmanTest, tempdir)
533
containerStorageDir := filepath.Join(podmanTest.Root, podmanTest.ImageCacheFS+"-containers")
536
create := podmanTest.Podman([]string{"create", "--name", "test", BB})
537
create.WaitWithDefaultTimeout()
538
Expect(create).Should(ExitCleanly())
540
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
543
dirents, err := os.ReadDir(containerStorageDir)
544
Expect(err).ToNot(HaveOccurred())
545
Expect(dirents).To(HaveLen(3))
548
err = os.Remove(filepath.Join(containerStorageDir, "containers.json"))
549
Expect(err).ToNot(HaveOccurred())
551
if podmanTest.DatabaseBackend == "sqlite" {
552
err = os.Remove(filepath.Join(podmanTest.Root, "db.sql"))
553
Expect(err).ToNot(HaveOccurred())
555
dbDir := filepath.Join(podmanTest.Root, "libpod")
556
err = os.RemoveAll(dbDir)
557
Expect(err).ToNot(HaveOccurred())
560
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
563
create = podmanTest.Podman([]string{"create", "--name", "test", BB})
564
create.WaitWithDefaultTimeout()
565
Expect(create).Should(ExitCleanly())
567
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
570
dirents, err = os.ReadDir(containerStorageDir)
571
Expect(err).ToNot(HaveOccurred())
572
Expect(dirents).To(HaveLen(4))
574
prune := podmanTest.Podman([]string{"system", "prune", "--external", "-f"})
575
prune.WaitWithDefaultTimeout()
576
Expect(prune).Should(ExitCleanly())
579
dirents, err = os.ReadDir(containerStorageDir)
580
Expect(err).ToNot(HaveOccurred())
581
Expect(dirents).To(HaveLen(3))