9
. "github.com/containers/podman/v5/test/utils"
10
. "github.com/onsi/ginkgo/v2"
11
. "github.com/onsi/gomega"
12
. "github.com/onsi/gomega/gexec"
15
var _ = Describe("Podman pull", func() {
17
It("podman pull multiple images with/without tag/digest", func() {
18
session := podmanTest.Podman([]string{"pull", "-q", "busybox:musl", "alpine", "alpine:latest", "quay.io/libpod/cirros", "quay.io/libpod/testdigest_v2s2@sha256:755f4d90b3716e2bf57060d249e2cd61c9ac089b1233465c5c2cb2d7ee550fdb"})
19
session.WaitWithDefaultTimeout()
20
Expect(session).Should(ExitCleanly())
22
session = podmanTest.Podman([]string{"pull", "busybox:latest", "docker.io/library/ibetthisdoesnotexistfr:random", "alpine"})
23
session.WaitWithDefaultTimeout()
24
Expect(session).Should(Exit(125))
25
expectedError := "initializing source docker://ibetthisdoesnotexistfr:random"
26
Expect(session.ErrorToString()).To(ContainSubstring(expectedError))
28
session = podmanTest.Podman([]string{"rmi", "busybox:musl", "alpine", "quay.io/libpod/cirros", "testdigest_v2s2@sha256:755f4d90b3716e2bf57060d249e2cd61c9ac089b1233465c5c2cb2d7ee550fdb"})
29
session.WaitWithDefaultTimeout()
30
Expect(session).Should(ExitCleanly())
33
It("podman pull bogus image", func() {
34
session := podmanTest.Podman([]string{"pull", "quay.io/libpod/ibetthisdoesntexist:there"})
35
session.WaitWithDefaultTimeout()
36
Expect(session).To(ExitWithError())
37
// "Not authorized", not "Not Found", because that's how registries roll??
38
Expect(session.ErrorToString()).To(ContainSubstring("unauthorized: access to the requested resource is not authorized"))
41
It("podman pull with tag --quiet", func() {
42
session := podmanTest.Podman([]string{"pull", "-q", "quay.io/libpod/testdigest_v2s2:20200210"})
43
session.WaitWithDefaultTimeout()
44
Expect(session).Should(ExitCleanly())
45
quietOutput := session.OutputToString()
47
session = podmanTest.Podman([]string{"inspect", "testdigest_v2s2:20200210", "--format", "{{.ID}}"})
48
session.WaitWithDefaultTimeout()
49
Expect(session).Should(ExitCleanly())
50
Expect(session.OutputToString()).To(Equal(quietOutput))
52
session = podmanTest.Podman([]string{"rmi", "testdigest_v2s2:20200210"})
53
session.WaitWithDefaultTimeout()
54
Expect(session).Should(ExitCleanly())
57
It("podman pull without tag", func() {
58
session := podmanTest.Podman([]string{"pull", "-q", "quay.io/libpod/testdigest_v2s2"})
59
session.WaitWithDefaultTimeout()
60
Expect(session).Should(ExitCleanly())
62
session = podmanTest.Podman([]string{"rmi", "testdigest_v2s2"})
63
session.WaitWithDefaultTimeout()
64
Expect(session).Should(ExitCleanly())
67
It("podman pull and run on split imagestore", func() {
68
SkipIfRemote("podman-remote does not support setting external imagestore")
69
imgName := "splitstoretest"
71
// Make alpine write-able
72
session := podmanTest.Podman([]string{"build", "--pull=never", "--tag", imgName, "build/basicalpine"})
73
session.WaitWithDefaultTimeout()
74
Expect(session).Should(ExitCleanly())
76
tmpDir := filepath.Join(podmanTest.TempDir, "splitstore")
77
outfile := filepath.Join(podmanTest.TempDir, "image.tar")
79
save := podmanTest.Podman([]string{"save", "-q", "-o", outfile, "--format", "oci-archive", imgName})
80
save.WaitWithDefaultTimeout()
81
Expect(save).Should(ExitCleanly())
83
rmi := podmanTest.Podman([]string{"rmi", imgName})
84
rmi.WaitWithDefaultTimeout()
85
Expect(rmi).Should(ExitCleanly())
88
result := podmanTest.Podman([]string{"load", "-q", "--imagestore", tmpDir, "-q", "-i", outfile})
89
result.WaitWithDefaultTimeout()
90
Expect(result).Should(ExitCleanly())
92
// tag busybox to busybox-test in graphroot since we can delete readonly busybox
93
session = podmanTest.Podman([]string{"tag", "quay.io/libpod/busybox:latest", "busybox-test"})
94
session.WaitWithDefaultTimeout()
95
Expect(session).Should(ExitCleanly())
97
session = podmanTest.Podman([]string{"images", "--imagestore", tmpDir})
98
session.WaitWithDefaultTimeout()
99
Expect(session).Should(ExitCleanly())
100
Expect(session.OutputToString()).To(ContainSubstring(imgName))
101
Expect(session.OutputToString()).To(ContainSubstring("busybox-test"))
103
// Test deleting image in graphroot even when `--imagestore` is set
104
session = podmanTest.Podman([]string{"rmi", "--imagestore", tmpDir, "busybox-test"})
105
session.WaitWithDefaultTimeout()
106
Expect(session).Should(ExitCleanly())
108
// Images without --imagestore should not contain alpine
109
session = podmanTest.Podman([]string{"images"})
110
session.WaitWithDefaultTimeout()
111
Expect(session).Should(ExitCleanly())
112
Expect(session.OutputToString()).To(Not(ContainSubstring(imgName)))
114
// Set `imagestore` in `storage.conf` and container should run.
115
configPath := filepath.Join(podmanTest.TempDir, ".config", "containers", "storage.conf")
116
os.Setenv("CONTAINERS_STORAGE_CONF", configPath)
118
os.Unsetenv("CONTAINERS_STORAGE_CONF")
121
err = os.MkdirAll(filepath.Dir(configPath), os.ModePerm)
122
Expect(err).ToNot(HaveOccurred())
123
storageConf := []byte(fmt.Sprintf("[storage]\nimagestore=\"%s\"", tmpDir))
124
err = os.WriteFile(configPath, storageConf, os.ModePerm)
125
Expect(err).ToNot(HaveOccurred())
127
session = podmanTest.Podman([]string{"run", "--name", "test", "--rm",
128
imgName, "echo", "helloworld"})
129
session.WaitWithDefaultTimeout()
130
Expect(session).Should(Exit(0))
131
Expect(session.OutputToString()).To(ContainSubstring("helloworld"))
132
Expect(session.ErrorToString()).To(ContainSubstring("The storage 'driver' option should be set in "))
133
Expect(session.ErrorToString()).To(ContainSubstring("A driver was picked automatically."))
136
It("podman pull by digest", func() {
137
session := podmanTest.Podman([]string{"pull", "-q", "quay.io/libpod/testdigest_v2s2@sha256:755f4d90b3716e2bf57060d249e2cd61c9ac089b1233465c5c2cb2d7ee550fdb"})
138
session.WaitWithDefaultTimeout()
139
Expect(session).Should(ExitCleanly())
141
// Without a tag/digest the input is normalized with the "latest" tag, see #11964
142
session = podmanTest.Podman([]string{"rmi", "testdigest_v2s2"})
143
session.WaitWithDefaultTimeout()
144
Expect(session).Should(Exit(1))
146
session = podmanTest.Podman([]string{"rmi", "testdigest_v2s2@sha256:755f4d90b3716e2bf57060d249e2cd61c9ac089b1233465c5c2cb2d7ee550fdb"})
147
session.WaitWithDefaultTimeout()
148
Expect(session).Should(ExitCleanly())
151
It("podman pull check all tags", func() {
152
session := podmanTest.Podman([]string{"pull", "-q", "--all-tags", "quay.io/libpod/testdigest_v2s2"})
153
session.WaitWithDefaultTimeout()
154
Expect(session).Should(ExitCleanly())
156
session = podmanTest.Podman([]string{"images"})
157
session.WaitWithDefaultTimeout()
158
Expect(session).Should(ExitCleanly())
159
Expect(len(session.OutputToStringArray())).To(BeNumerically(">=", 2), "Expected at least two images")
161
session = podmanTest.Podman([]string{"pull", "-q", "-a", "quay.io/libpod/testdigest_v2s2"})
162
session.WaitWithDefaultTimeout()
163
Expect(session).Should(ExitCleanly())
165
session = podmanTest.Podman([]string{"images"})
166
session.WaitWithDefaultTimeout()
167
Expect(session).Should(ExitCleanly())
168
Expect(len(session.OutputToStringArray())).To(BeNumerically(">=", 2), "Expected at least two images")
171
It("podman pull from docker with nonexistent --authfile", func() {
172
session := podmanTest.Podman([]string{"pull", "-q", "--authfile", "/tmp/nonexistent", ALPINE})
173
session.WaitWithDefaultTimeout()
174
Expect(session).To(ExitWithError())
175
Expect(session.ErrorToString()).To(Equal("Error: credential file is not accessible: faccessat /tmp/nonexistent: no such file or directory"))
178
It("podman pull by digest (image list)", func() {
179
session := podmanTest.Podman([]string{"pull", "-q", "--arch=arm64", ALPINELISTDIGEST})
180
session.WaitWithDefaultTimeout()
181
Expect(session).Should(ExitCleanly())
182
// inspect using the digest of the list
183
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoTags}}", ALPINELISTDIGEST})
184
session.WaitWithDefaultTimeout()
185
Expect(session).Should(ExitCleanly())
186
Expect(string(session.Out.Contents())).To(HavePrefix("[]"))
187
// inspect using the digest of the list
188
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoDigests}}", ALPINELISTDIGEST})
189
session.WaitWithDefaultTimeout()
190
Expect(session).Should(ExitCleanly())
191
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTDIGEST))
192
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
193
// inspect using the digest of the arch-specific image's manifest
194
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoTags}}", ALPINEARM64DIGEST})
195
session.WaitWithDefaultTimeout()
196
Expect(session).Should(ExitCleanly())
197
Expect(string(session.Out.Contents())).To(HavePrefix("[]"))
198
// inspect using the digest of the arch-specific image's manifest
199
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoDigests}}", ALPINEARM64DIGEST})
200
session.WaitWithDefaultTimeout()
201
Expect(session).Should(ExitCleanly())
202
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTDIGEST))
203
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
204
// inspect using the image ID
205
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoTags}}", ALPINEARM64ID})
206
session.WaitWithDefaultTimeout()
207
Expect(session).Should(ExitCleanly())
208
Expect(string(session.Out.Contents())).To(HavePrefix("[]"))
209
// inspect using the image ID
210
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoDigests}}", ALPINEARM64ID})
211
session.WaitWithDefaultTimeout()
212
Expect(session).Should(ExitCleanly())
213
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTDIGEST))
214
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
215
// remove using the digest of the list
216
session = podmanTest.Podman([]string{"rmi", ALPINELISTDIGEST})
217
session.WaitWithDefaultTimeout()
218
Expect(session).Should(ExitCleanly())
221
It("podman pull by instance digest (image list)", func() {
222
session := podmanTest.Podman([]string{"pull", "-q", "--arch=arm64", ALPINEARM64DIGEST})
223
session.WaitWithDefaultTimeout()
224
Expect(session).Should(ExitCleanly())
225
// inspect using the digest of the list
226
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoTags}}", ALPINELISTDIGEST})
227
session.WaitWithDefaultTimeout()
228
Expect(session).To(ExitWithError())
229
// inspect using the digest of the list
230
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoDigests}}", ALPINELISTDIGEST})
231
session.WaitWithDefaultTimeout()
232
Expect(session).To(ExitWithError())
233
// inspect using the digest of the arch-specific image's manifest
234
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoTags}}", ALPINEARM64DIGEST})
235
session.WaitWithDefaultTimeout()
236
Expect(session).Should(ExitCleanly())
237
Expect(string(session.Out.Contents())).To(HavePrefix("[]"))
238
// inspect using the digest of the arch-specific image's manifest
239
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoDigests}}", ALPINEARM64DIGEST})
240
session.WaitWithDefaultTimeout()
241
Expect(session).Should(ExitCleanly())
242
Expect(string(session.Out.Contents())).To(Not(ContainSubstring(ALPINELISTDIGEST)))
243
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
244
// inspect using the image ID
245
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoTags}}", ALPINEARM64ID})
246
session.WaitWithDefaultTimeout()
247
Expect(session).Should(ExitCleanly())
248
Expect(string(session.Out.Contents())).To(HavePrefix("[]"))
249
// inspect using the image ID
250
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoDigests}}", ALPINEARM64ID})
251
session.WaitWithDefaultTimeout()
252
Expect(session).Should(ExitCleanly())
253
Expect(string(session.Out.Contents())).To(Not(ContainSubstring(ALPINELISTDIGEST)))
254
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
255
// remove using the digest of the instance
256
session = podmanTest.Podman([]string{"rmi", ALPINEARM64DIGEST})
257
session.WaitWithDefaultTimeout()
258
Expect(session).Should(ExitCleanly())
261
It("podman pull by tag (image list)", func() {
262
session := podmanTest.Podman([]string{"pull", "-q", "--arch=arm64", ALPINELISTTAG})
263
session.WaitWithDefaultTimeout()
264
Expect(session).Should(ExitCleanly())
265
// inspect using the tag we used for pulling
266
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoTags}}", ALPINELISTTAG})
267
session.WaitWithDefaultTimeout()
268
Expect(session).Should(ExitCleanly())
269
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTTAG))
270
// inspect using the tag we used for pulling
271
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoDigests}}", ALPINELISTTAG})
272
session.WaitWithDefaultTimeout()
273
Expect(session).Should(ExitCleanly())
274
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTDIGEST))
275
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
276
// inspect using the digest of the list
277
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoTags}}", ALPINELISTDIGEST})
278
session.WaitWithDefaultTimeout()
279
Expect(session).Should(ExitCleanly())
280
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTTAG))
281
// inspect using the digest of the list
282
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoDigests}}", ALPINELISTDIGEST})
283
session.WaitWithDefaultTimeout()
284
Expect(session).Should(ExitCleanly())
285
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTDIGEST))
286
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
287
// inspect using the digest of the arch-specific image's manifest
288
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoTags}}", ALPINEARM64DIGEST})
289
session.WaitWithDefaultTimeout()
290
Expect(session).Should(ExitCleanly())
291
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTTAG))
292
// inspect using the digest of the arch-specific image's manifest
293
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoDigests}}", ALPINEARM64DIGEST})
294
session.WaitWithDefaultTimeout()
295
Expect(session).Should(ExitCleanly())
296
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTDIGEST))
297
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
298
// inspect using the image ID
299
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoTags}}", ALPINEARM64ID})
300
session.WaitWithDefaultTimeout()
301
Expect(session).Should(ExitCleanly())
302
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTTAG))
303
// inspect using the image ID
304
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RepoDigests}}", ALPINEARM64ID})
305
session.WaitWithDefaultTimeout()
306
Expect(session).Should(ExitCleanly())
307
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTDIGEST))
308
Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
309
// remove using the tag
310
session = podmanTest.Podman([]string{"rmi", ALPINELISTTAG})
311
session.WaitWithDefaultTimeout()
312
Expect(session).Should(ExitCleanly())
315
It("podman pull from docker-archive", func() {
316
SkipIfRemote("podman-remote does not support pulling from docker-archive")
318
podmanTest.AddImageToRWStore(CIRROS_IMAGE)
319
tarfn := filepath.Join(podmanTest.TempDir, "cirros.tar")
320
session := podmanTest.Podman([]string{"save", "-q", "-o", tarfn, "cirros"})
321
session.WaitWithDefaultTimeout()
323
Expect(session).Should(ExitCleanly())
324
session = podmanTest.Podman([]string{"rmi", "cirros"})
325
session.WaitWithDefaultTimeout()
326
Expect(session).Should(ExitCleanly())
327
session = podmanTest.Podman([]string{"pull", "-q", fmt.Sprintf("docker-archive:%s", tarfn)})
328
session.WaitWithDefaultTimeout()
329
Expect(session).Should(ExitCleanly())
330
session = podmanTest.Podman([]string{"rmi", "cirros"})
331
session.WaitWithDefaultTimeout()
332
Expect(session).Should(ExitCleanly())
334
// Pulling a multi-image archive without further specifying
335
// which image _must_ error out. Pulling is restricted to one
337
session = podmanTest.Podman([]string{"pull", "-q", "docker-archive:./testdata/docker-two-images.tar.xz"})
338
session.WaitWithDefaultTimeout()
339
Expect(session).Should(Exit(125))
340
expectedError := "Unexpected tar manifest.json: expected 1 item, got 2"
341
Expect(session.ErrorToString()).To(ContainSubstring(expectedError))
343
// Now pull _one_ image from a multi-image archive via the name
345
session = podmanTest.Podman([]string{"pull", "-q", "docker-archive:./testdata/docker-two-images.tar.xz:@0"})
346
session.WaitWithDefaultTimeout()
347
Expect(session).Should(ExitCleanly())
349
session = podmanTest.Podman([]string{"pull", "-q", "docker-archive:./testdata/docker-two-images.tar.xz:example.com/empty:latest"})
350
session.WaitWithDefaultTimeout()
351
Expect(session).Should(ExitCleanly())
353
session = podmanTest.Podman([]string{"pull", "-q", "docker-archive:./testdata/docker-two-images.tar.xz:@1"})
354
session.WaitWithDefaultTimeout()
355
Expect(session).Should(ExitCleanly())
357
session = podmanTest.Podman([]string{"pull", "-q", "docker-archive:./testdata/docker-two-images.tar.xz:example.com/empty/but:different"})
358
session.WaitWithDefaultTimeout()
359
Expect(session).Should(ExitCleanly())
361
// Now check for some errors.
362
session = podmanTest.Podman([]string{"pull", "-q", "docker-archive:./testdata/docker-two-images.tar.xz:foo.com/does/not/exist:latest"})
363
session.WaitWithDefaultTimeout()
364
Expect(session).Should(Exit(125))
365
expectedError = "Tag \"foo.com/does/not/exist:latest\" not found"
366
Expect(session.ErrorToString()).To(ContainSubstring(expectedError))
368
session = podmanTest.Podman([]string{"pull", "-q", "docker-archive:./testdata/docker-two-images.tar.xz:@2"})
369
session.WaitWithDefaultTimeout()
370
Expect(session).Should(Exit(125))
371
expectedError = "Invalid source index @2, only 2 manifest items available"
372
Expect(session.ErrorToString()).To(ContainSubstring(expectedError))
375
It("podman pull from oci-archive", func() {
376
SkipIfRemote("podman-remote does not support pulling from oci-archive")
378
podmanTest.AddImageToRWStore(CIRROS_IMAGE)
379
tarfn := filepath.Join(podmanTest.TempDir, "oci-cirrus.tar")
380
session := podmanTest.Podman([]string{"save", "-q", "--format", "oci-archive", "-o", tarfn, "cirros"})
381
session.WaitWithDefaultTimeout()
383
Expect(session).Should(ExitCleanly())
384
session = podmanTest.Podman([]string{"rmi", "cirros"})
385
session.WaitWithDefaultTimeout()
386
Expect(session).Should(ExitCleanly())
387
session = podmanTest.Podman([]string{"pull", "-q", fmt.Sprintf("oci-archive:%s", tarfn)})
388
session.WaitWithDefaultTimeout()
389
Expect(session).Should(ExitCleanly())
390
session = podmanTest.Podman([]string{"rmi", "cirros"})
391
session.WaitWithDefaultTimeout()
392
Expect(session).Should(ExitCleanly())
395
It("podman pull from local directory", func() {
396
SkipIfRemote("podman-remote does not support pulling from local directory")
398
podmanTest.AddImageToRWStore(CIRROS_IMAGE)
399
dirpath := filepath.Join(podmanTest.TempDir, "cirros")
400
err = os.MkdirAll(dirpath, os.ModePerm)
401
Expect(err).ToNot(HaveOccurred())
402
imgPath := fmt.Sprintf("dir:%s", dirpath)
404
session := podmanTest.Podman([]string{"push", "-q", "cirros", imgPath})
405
session.WaitWithDefaultTimeout()
406
Expect(session).Should(ExitCleanly())
407
session = podmanTest.Podman([]string{"rmi", "cirros"})
408
session.WaitWithDefaultTimeout()
409
Expect(session).Should(ExitCleanly())
410
session = podmanTest.Podman([]string{"run", imgPath, "ls"})
411
session.WaitWithDefaultTimeout()
412
Expect(session).Should(Exit(0))
413
Expect(session.ErrorToString()).To(ContainSubstring("Copying blob"), "Image is pulled on run")
415
// Note that reference is not preserved in dir.
416
session = podmanTest.Podman([]string{"image", "exists", "cirros"})
417
session.WaitWithDefaultTimeout()
418
Expect(session).Should(Exit(1))
421
It("podman pull from local OCI directory", func() {
422
SkipIfRemote("podman-remote does not support pulling from OCI directory")
424
podmanTest.AddImageToRWStore(CIRROS_IMAGE)
425
dirpath := filepath.Join(podmanTest.TempDir, "cirros")
426
err = os.MkdirAll(dirpath, os.ModePerm)
427
Expect(err).ToNot(HaveOccurred())
428
imgName := "localhost/name:tag"
429
imgPath := fmt.Sprintf("oci:%s:%s", dirpath, imgName)
431
session := podmanTest.Podman([]string{"push", "-q", "cirros", imgPath})
432
session.WaitWithDefaultTimeout()
433
Expect(session).Should(ExitCleanly())
434
session = podmanTest.Podman([]string{"rmi", "cirros"})
435
session.WaitWithDefaultTimeout()
436
Expect(session).Should(ExitCleanly())
437
session = podmanTest.Podman([]string{"pull", "-q", imgPath})
438
session.WaitWithDefaultTimeout()
439
Expect(session).Should(ExitCleanly())
440
session = podmanTest.Podman([]string{"image", "exists", imgName})
441
session.WaitWithDefaultTimeout()
442
Expect(session).Should(ExitCleanly())
445
It("podman pull + inspect from unqualified-search registry", func() {
446
// Regression test for #6381:
447
// Make sure that `pull shortname` and `inspect shortname`
448
// refer to the same image.
450
// We already tested pulling, so we can save some energy and
451
// just restore local artifacts and tag them.
452
err := podmanTest.RestoreArtifact(ALPINE)
453
Expect(err).ToNot(HaveOccurred())
454
err = podmanTest.RestoreArtifact(BB)
455
Expect(err).ToNot(HaveOccurred())
457
// What we want is at least two images which have the same name
458
// and are prefixed with two different unqualified-search
459
// registries from ../registries.conf.
461
// A `podman inspect $name` must yield the one from the _first_
462
// matching registry in the registries.conf.
463
getID := func(image string) string {
464
setup := podmanTest.Podman([]string{"image", "inspect", image})
465
setup.WaitWithDefaultTimeout()
466
Expect(setup).Should(ExitCleanly())
468
data := setup.InspectImageJSON() // returns []inspect.ImageData
469
Expect(data).To(HaveLen(1))
473
untag := func(image string) {
474
setup := podmanTest.Podman([]string{"untag", image})
475
setup.WaitWithDefaultTimeout()
476
Expect(setup).Should(ExitCleanly())
478
setup = podmanTest.Podman([]string{"image", "inspect", image})
479
setup.WaitWithDefaultTimeout()
480
Expect(setup).Should(ExitCleanly())
482
data := setup.InspectImageJSON() // returns []inspect.ImageData
483
Expect(data).To(HaveLen(1))
484
Expect(data[0].RepoTags).To(BeEmpty())
487
tag := func(image, tag string) {
488
setup := podmanTest.Podman([]string{"tag", image, tag})
489
setup.WaitWithDefaultTimeout()
490
Expect(setup).Should(ExitCleanly())
491
setup = podmanTest.Podman([]string{"image", "exists", tag})
492
setup.WaitWithDefaultTimeout()
493
Expect(setup).Should(ExitCleanly())
496
image1 := getID(ALPINE)
499
// $ head -n2 ../registries.conf
500
// [registries.search]
501
// registries = ['docker.io', 'quay.io', 'registry.fedoraproject.org']
502
registries := []string{"docker.io", "quay.io", "registry.fedoraproject.org"}
503
name := "foo/test:tag"
505
// tag1 has precedence (see list above) over tag2 when
506
// doing an inspect on "test:tag".
510
fmt.Sprintf("%s/%s", registries[0], name),
511
fmt.Sprintf("%s/%s", registries[1], name),
514
fmt.Sprintf("%s/%s", registries[0], name),
515
fmt.Sprintf("%s/%s", registries[2], name),
518
fmt.Sprintf("%s/%s", registries[1], name),
519
fmt.Sprintf("%s/%s", registries[2], name),
523
for _, t := range tests {
524
// 1) untag both images
525
// 2) tag them according to `t`
526
// 3) make sure that an inspect of `name` returns `image1` with `tag1`
532
setup := podmanTest.Podman([]string{"image", "inspect", name})
533
setup.WaitWithDefaultTimeout()
534
Expect(setup).Should(ExitCleanly())
536
data := setup.InspectImageJSON() // returns []inspect.ImageData
537
Expect(data).To(HaveLen(1))
538
Expect(data[0].RepoTags).To(HaveLen(1))
539
Expect(data[0].RepoTags[0]).To(Equal(t.tag1))
540
Expect(data[0]).To(HaveField("ID", image1))
544
It("podman pull --platform", func() {
545
session := podmanTest.Podman([]string{"pull", "-q", "--platform=linux/bogus", ALPINE})
546
session.WaitWithDefaultTimeout()
547
Expect(session).Should(Exit(125))
548
expectedError := "no image found in manifest list for architecture bogus"
549
Expect(session.ErrorToString()).To(ContainSubstring(expectedError))
551
session = podmanTest.Podman([]string{"pull", "-q", "--platform=linux/arm64", "--os", "windows", ALPINE})
552
session.WaitWithDefaultTimeout()
553
Expect(session).Should(Exit(125))
554
expectedError = "--platform option can not be specified with --arch or --os"
555
Expect(session.ErrorToString()).To(ContainSubstring(expectedError))
557
session = podmanTest.Podman([]string{"pull", "-q", "--platform=linux/arm64", ALPINE})
558
session.WaitWithDefaultTimeout()
559
Expect(session).Should(ExitCleanly())
561
setup := podmanTest.Podman([]string{"image", "inspect", session.OutputToString()})
562
setup.WaitWithDefaultTimeout()
563
Expect(setup).Should(ExitCleanly())
565
data := setup.InspectImageJSON() // returns []inspect.ImageData
566
Expect(data).To(HaveLen(1))
567
Expect(data[0]).To(HaveField("Os", runtime.GOOS))
568
Expect(data[0]).To(HaveField("Architecture", "arm64"))
571
It("podman pull --arch", func() {
572
session := podmanTest.Podman([]string{"pull", "-q", "--arch=bogus", ALPINE})
573
session.WaitWithDefaultTimeout()
574
Expect(session).Should(Exit(125))
575
expectedError := "no image found in manifest list for architecture bogus"
576
Expect(session.ErrorToString()).To(ContainSubstring(expectedError))
578
session = podmanTest.Podman([]string{"pull", "-q", "--arch=arm64", "--os", "windows", ALPINE})
579
session.WaitWithDefaultTimeout()
580
Expect(session).Should(Exit(125))
581
expectedError = "no image found in manifest list for architecture"
582
Expect(session.ErrorToString()).To(ContainSubstring(expectedError))
584
session = podmanTest.Podman([]string{"pull", "-q", "--arch=arm64", ALPINE})
585
session.WaitWithDefaultTimeout()
586
Expect(session).Should(ExitCleanly())
588
setup := podmanTest.Podman([]string{"image", "inspect", session.OutputToString()})
589
setup.WaitWithDefaultTimeout()
590
Expect(setup).Should(ExitCleanly())
592
data := setup.InspectImageJSON() // returns []inspect.ImageData
593
Expect(data).To(HaveLen(1))
594
Expect(data[0]).To(HaveField("Os", runtime.GOOS))
595
Expect(data[0]).To(HaveField("Architecture", "arm64"))
598
It("podman pull progress", func() {
599
session := podmanTest.Podman([]string{"pull", ALPINE})
600
session.WaitWithDefaultTimeout()
601
Expect(session).Should(Exit(0))
602
output := session.ErrorToString()
603
Expect(output).To(ContainSubstring("Getting image source signatures"))
604
Expect(output).To(ContainSubstring("Copying blob "))
606
session = podmanTest.Podman([]string{"pull", "-q", ALPINE})
607
session.WaitWithDefaultTimeout()
608
Expect(session).Should(ExitCleanly())
611
Describe("podman pull and decrypt", func() {
613
decryptionTestHelper := func(imgPath string) *PodmanSessionIntegration {
615
keyFileName := filepath.Join(podmanTest.TempDir, "key,withcomma")
616
publicKeyFileName, privateKeyFileName, err := WriteRSAKeyPair(keyFileName, bitSize)
617
Expect(err).ToNot(HaveOccurred())
619
wrongKeyFileName := filepath.Join(podmanTest.TempDir, "wrong_key")
620
_, wrongPrivateKeyFileName, err := WriteRSAKeyPair(wrongKeyFileName, bitSize)
621
Expect(err).ToNot(HaveOccurred())
623
session := podmanTest.Podman([]string{"push", "-q", "--encryption-key", "jwe:" + publicKeyFileName, "--tls-verify=false", "--remove-signatures", ALPINE, imgPath})
624
session.WaitWithDefaultTimeout()
626
session = podmanTest.Podman([]string{"rmi", ALPINE})
627
session.WaitWithDefaultTimeout()
628
Expect(session).Should(ExitCleanly())
630
// Pulling encrypted image without key should fail
631
session = podmanTest.Podman([]string{"pull", imgPath})
632
session.WaitWithDefaultTimeout()
633
Expect(session).Should(Exit(125))
635
// Pulling encrypted image with wrong key should fail
636
session = podmanTest.Podman([]string{"pull", "-q", "--decryption-key", wrongPrivateKeyFileName, "--tls-verify=false", imgPath})
637
session.WaitWithDefaultTimeout()
638
Expect(session).Should(Exit(125))
640
// Pulling encrypted image with correct key should pass
641
session = podmanTest.Podman([]string{"pull", "-q", "--decryption-key", privateKeyFileName, "--tls-verify=false", imgPath})
642
session.WaitWithDefaultTimeout()
643
Expect(session).Should(ExitCleanly())
644
session = podmanTest.Podman([]string{"images"})
645
session.WaitWithDefaultTimeout()
646
Expect(session).Should(ExitCleanly())
651
It("From oci", func() {
652
SkipIfRemote("Remote pull neither supports oci transport, nor decryption")
654
podmanTest.AddImageToRWStore(ALPINE)
656
bbdir := filepath.Join(podmanTest.TempDir, "busybox-oci")
657
imgName := "localhost/name:tag"
658
imgPath := fmt.Sprintf("oci:%s:%s", bbdir, imgName)
660
session := decryptionTestHelper(imgPath)
662
Expect(session.LineInOutputContainsTag("localhost/name", "tag")).To(BeTrue())
665
It("From local registry", func() {
666
SkipIfRemote("Remote pull does not support decryption")
668
if podmanTest.Host.Arch == "ppc64le" {
669
Skip("No registry image for ppc64le")
672
podmanTest.AddImageToRWStore(ALPINE)
675
err := podmanTest.RestoreArtifact(REGISTRY_IMAGE)
676
Expect(err).ToNot(HaveOccurred())
678
lock := GetPortLock("5012")
680
session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5012:5000", REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"})
681
session.WaitWithDefaultTimeout()
682
Expect(session).Should(ExitCleanly())
684
if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
685
Skip("Cannot start docker registry.")
688
imgPath := "localhost:5012/my-alpine"
690
session = decryptionTestHelper(imgPath)
692
Expect(session.LineInOutputContainsTag(imgPath, "latest")).To(BeTrue())