mirror of
https://github.com/containers/podman.git
synced 2025-10-25 18:25:59 +08:00
It qemu cannot be compiled anyway so make sure we do not try to compile parts where the typechecker complains about on windows. Also all the e2e test files are only used on linux as well. pkg/machine/wsl also reports some error but to many for me to fix them now. One minor problem was fixed in pkg/machine/machine_windows.go. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
761 lines
32 KiB
Go
761 lines
32 KiB
Go
//go:build linux || freebsd
|
|
|
|
package integration
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/containers/common/libimage/define"
|
|
podmanRegistry "github.com/containers/podman/v5/hack/podman-registry-go"
|
|
. "github.com/containers/podman/v5/test/utils"
|
|
"github.com/containers/storage/pkg/archive"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
. "github.com/onsi/gomega/gexec"
|
|
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
|
)
|
|
|
|
// validateManifestHasAllArchs checks that the specified manifest has all
|
|
// the archs in `imageList`
|
|
func validateManifestHasAllArchs(path string) error {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var result struct {
|
|
Manifests []struct {
|
|
Platform struct {
|
|
Architecture string
|
|
}
|
|
}
|
|
}
|
|
if err := json.Unmarshal(data, &result); err != nil {
|
|
return err
|
|
}
|
|
archs := map[string]bool{
|
|
"amd64": false,
|
|
"arm64": false,
|
|
"ppc64le": false,
|
|
"s390x": false,
|
|
}
|
|
for _, m := range result.Manifests {
|
|
archs[m.Platform.Architecture] = true
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Internal function to verify instance compression
|
|
func verifyInstanceCompression(descriptor []imgspecv1.Descriptor, compression string, arch string) bool {
|
|
for _, instance := range descriptor {
|
|
if instance.Platform.Architecture != arch {
|
|
continue
|
|
}
|
|
if compression == "zstd" {
|
|
// if compression is zstd annotations must contain
|
|
val, ok := instance.Annotations["io.github.containers.compression.zstd"]
|
|
if ok && val == "true" {
|
|
return true
|
|
}
|
|
} else if len(instance.Annotations) == 0 {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
var _ = Describe("Podman manifest", func() {
|
|
|
|
const (
|
|
imageList = "docker://quay.io/libpod/testimage:00000004"
|
|
imageListInstance = "docker://quay.io/libpod/testimage@sha256:1385ce282f3a959d0d6baf45636efe686c1e14c3e7240eb31907436f7bc531fa"
|
|
imageListARM64InstanceDigest = "sha256:1385ce282f3a959d0d6baf45636efe686c1e14c3e7240eb31907436f7bc531fa"
|
|
imageListAMD64InstanceDigest = "sha256:1462c8e885d567d534d82004656c764263f98deda813eb379689729658a133fb"
|
|
imageListPPC64LEInstanceDigest = "sha256:9b7c3300f5f7cfe94e3101a28d1f0a28728f8dbc854fb16dd545b7e5aa351785"
|
|
imageListS390XInstanceDigest = "sha256:cb68b7bfd2f4f7d36006efbe3bef04b57a343e0839588476ca336d9ff9240dbf"
|
|
)
|
|
|
|
It("create w/o image and attempt push w/o dest", func() {
|
|
for _, amend := range []string{"--amend", "-a"} {
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).To(ExitWithError(125, `image name "localhost/foo:latest" is already associated with image `))
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "push", "--all", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
// Push should actually fail since it's not valid registry
|
|
Expect(session).To(ExitWithError(125, "requested access to the resource is denied"))
|
|
Expect(session.OutputToString()).To(Not(ContainSubstring("accepts 2 arg(s), received 1")))
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "create", amend, "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "rm", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
}
|
|
})
|
|
|
|
It("create w/ image", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
})
|
|
|
|
It("inspect", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "inspect", BB})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "quay.io/libpod/busybox"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
// inspect manifest of single image
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "quay.io/libpod/busybox@sha256:6655df04a3df853b029a5fac8836035ac4fab117800c9a6c4b69341bb5306c3d"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(Exit(0))
|
|
// yet another warning message that is not seen by remote client
|
|
stderr := session.ErrorToString()
|
|
if IsRemote() {
|
|
Expect(stderr).Should(Equal(""))
|
|
} else {
|
|
Expect(stderr).Should(ContainSubstring("The manifest type application/vnd.docker.distribution.manifest.v2+json is not a manifest list but a single image."))
|
|
}
|
|
})
|
|
|
|
It("add w/ inspect", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
id := strings.TrimSpace(string(session.Out.Contents()))
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", id})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "add", "--arch=arm64", "foo", imageListInstance})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(session.OutputToString()).To(ContainSubstring(imageListARM64InstanceDigest))
|
|
})
|
|
|
|
It("add with new version", func() {
|
|
// Following test must pass for both podman and podman-remote
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
id := strings.TrimSpace(string(session.Out.Contents()))
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", id})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "add", "--os-version", "7.7.7", "foo", imageListInstance})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(session.OutputToString()).To(ContainSubstring("7.7.7"))
|
|
})
|
|
|
|
It("tag", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foobar"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "foobar", "quay.io/libpod/busybox"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"tag", "foobar", "foobar2"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "foobar"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session2 := podmanTest.Podman([]string{"manifest", "inspect", "foobar2"})
|
|
session2.WaitWithDefaultTimeout()
|
|
Expect(session2).Should(ExitCleanly())
|
|
Expect(session2.OutputToString()).To(Equal(session.OutputToString()))
|
|
})
|
|
|
|
It("push with --add-compression and --force-compression", func() {
|
|
if podmanTest.Host.Arch == "ppc64le" {
|
|
Skip("No registry image for ppc64le")
|
|
}
|
|
if isRootless() {
|
|
err := podmanTest.RestoreArtifact(REGISTRY_IMAGE)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
}
|
|
lock := GetPortLock("5007")
|
|
defer lock.Unlock()
|
|
session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5007:5000", REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
|
|
Skip("Cannot start docker registry.")
|
|
}
|
|
|
|
session = podmanTest.Podman([]string{"build", "-q", "--platform", "linux/amd64", "-t", "imageone", "build/basicalpine"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"build", "-q", "--platform", "linux/arm64", "-t", "imagetwo", "build/basicalpine"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "create", "foobar"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "foobar", "containers-storage:localhost/imageone:latest"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "foobar", "containers-storage:localhost/imagetwo:latest"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
push := podmanTest.Podman([]string{"manifest", "push", "--all", "--compression-format", "gzip", "--add-compression", "zstd", "--tls-verify=false", "--remove-signatures", "foobar", "localhost:5007/list"})
|
|
push.WaitWithDefaultTimeout()
|
|
Expect(push).Should(Exit(0))
|
|
output := push.ErrorToString()
|
|
// 4 images must be pushed two for gzip and two for zstd
|
|
Expect(output).To(ContainSubstring("Copying 4 images generated from 2 images in list"))
|
|
|
|
skopeo := SystemExec("skopeo", []string{"inspect", "--tls-verify=false", "--raw", "docker://localhost:5007/list:latest"})
|
|
Expect(skopeo).Should(ExitCleanly())
|
|
inspectData := []byte(skopeo.OutputToString())
|
|
var index imgspecv1.Index
|
|
err = json.Unmarshal(inspectData, &index)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
Expect(verifyInstanceCompression(index.Manifests, "zstd", "amd64")).Should(BeTrue())
|
|
Expect(verifyInstanceCompression(index.Manifests, "zstd", "arm64")).Should(BeTrue())
|
|
Expect(verifyInstanceCompression(index.Manifests, "gzip", "arm64")).Should(BeTrue())
|
|
Expect(verifyInstanceCompression(index.Manifests, "gzip", "amd64")).Should(BeTrue())
|
|
|
|
// Note: Pushing again with --force-compression should produce the correct response the since blobs will be correctly force-pushed again.
|
|
push = podmanTest.Podman([]string{"manifest", "push", "--all", "--add-compression", "zstd", "--tls-verify=false", "--compression-format", "gzip", "--force-compression", "--remove-signatures", "foobar", "localhost:5007/list"})
|
|
push.WaitWithDefaultTimeout()
|
|
Expect(push).Should(Exit(0))
|
|
output = push.ErrorToString()
|
|
// 4 images must be pushed two for gzip and two for zstd
|
|
Expect(output).To(ContainSubstring("Copying 4 images generated from 2 images in list"))
|
|
|
|
skopeo = SystemExec("skopeo", []string{"inspect", "--tls-verify=false", "--raw", "docker://localhost:5007/list:latest"})
|
|
Expect(skopeo).Should(ExitCleanly())
|
|
inspectData = []byte(skopeo.OutputToString())
|
|
err = json.Unmarshal(inspectData, &index)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
Expect(verifyInstanceCompression(index.Manifests, "zstd", "amd64")).Should(BeTrue())
|
|
Expect(verifyInstanceCompression(index.Manifests, "zstd", "arm64")).Should(BeTrue())
|
|
Expect(verifyInstanceCompression(index.Manifests, "gzip", "arm64")).Should(BeTrue())
|
|
Expect(verifyInstanceCompression(index.Manifests, "gzip", "amd64")).Should(BeTrue())
|
|
|
|
// same thing with add_compression from config file should work and without --add-compression flag in CLI
|
|
confFile := filepath.Join(podmanTest.TempDir, "containers.conf")
|
|
err = os.WriteFile(confFile, []byte(`[engine]
|
|
add_compression = ["zstd"]`), 0o644)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
os.Setenv("CONTAINERS_CONF", confFile)
|
|
|
|
push = podmanTest.Podman([]string{"manifest", "push", "--all", "--tls-verify=false", "--compression-format", "gzip", "--force-compression", "--remove-signatures", "foobar", "localhost:5007/list"})
|
|
push.WaitWithDefaultTimeout()
|
|
Expect(push).Should(Exit(0))
|
|
output = push.ErrorToString()
|
|
// 4 images must be pushed two for gzip and two for zstd
|
|
Expect(output).To(ContainSubstring("Copying 4 images generated from 2 images in list"))
|
|
|
|
skopeo = SystemExec("skopeo", []string{"inspect", "--tls-verify=false", "--raw", "docker://localhost:5007/list:latest"})
|
|
Expect(skopeo).Should(ExitCleanly())
|
|
inspectData = []byte(skopeo.OutputToString())
|
|
err = json.Unmarshal(inspectData, &index)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
Expect(verifyInstanceCompression(index.Manifests, "zstd", "amd64")).Should(BeTrue())
|
|
Expect(verifyInstanceCompression(index.Manifests, "zstd", "arm64")).Should(BeTrue())
|
|
Expect(verifyInstanceCompression(index.Manifests, "gzip", "arm64")).Should(BeTrue())
|
|
Expect(verifyInstanceCompression(index.Manifests, "gzip", "amd64")).Should(BeTrue())
|
|
|
|
// Note: Pushing again with --force-compression=false should produce in-correct/wrong result since blobs are already present in registry so they will be reused
|
|
// ignoring our compression priority ( this is expected behaviour of c/image and --force-compression is introduced to mitigate this behaviour ).
|
|
push = podmanTest.Podman([]string{"manifest", "push", "--all", "--add-compression", "zstd", "--force-compression=false", "--tls-verify=false", "--remove-signatures", "foobar", "localhost:5007/list"})
|
|
push.WaitWithDefaultTimeout()
|
|
Expect(push).Should(Exit(0))
|
|
output = push.ErrorToString()
|
|
// 4 images must be pushed two for gzip and two for zstd
|
|
Expect(output).To(ContainSubstring("Copying 4 images generated from 2 images in list"))
|
|
|
|
skopeo = SystemExec("skopeo", []string{"inspect", "--tls-verify=false", "--raw", "docker://localhost:5007/list:latest"})
|
|
Expect(skopeo).Should(ExitCleanly())
|
|
inspectData = []byte(skopeo.OutputToString())
|
|
err = json.Unmarshal(inspectData, &index)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
Expect(verifyInstanceCompression(index.Manifests, "zstd", "amd64")).Should(BeTrue())
|
|
Expect(verifyInstanceCompression(index.Manifests, "zstd", "arm64")).Should(BeTrue())
|
|
// blobs of zstd will be wrongly reused for gzip instances without --force-compression
|
|
Expect(verifyInstanceCompression(index.Manifests, "gzip", "arm64")).Should(BeFalse())
|
|
// blobs of zstd will be wrongly reused for gzip instances without --force-compression
|
|
Expect(verifyInstanceCompression(index.Manifests, "gzip", "amd64")).Should(BeFalse())
|
|
})
|
|
|
|
It("add --all", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "--all", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(session.OutputToString()).To(
|
|
And(
|
|
ContainSubstring(imageListAMD64InstanceDigest),
|
|
ContainSubstring(imageListARM64InstanceDigest),
|
|
ContainSubstring(imageListPPC64LEInstanceDigest),
|
|
ContainSubstring(imageListS390XInstanceDigest),
|
|
))
|
|
})
|
|
|
|
It("add --annotation", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "--annotation", "hoge", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitWithError(125, "no value given for annotation"))
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "add", "--annotation", "hoge=fuga", "--annotation", "key=val,withcomma", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
var inspect define.ManifestListData
|
|
err := json.Unmarshal(session.Out.Contents(), &inspect)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(inspect.Manifests[0].Annotations).To(Equal(map[string]string{"hoge": "fuga", "key": "val,withcomma"}))
|
|
})
|
|
|
|
It("add --os", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "--os", "bar", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(session.OutputToString()).To(ContainSubstring(`"os": "bar"`))
|
|
})
|
|
|
|
It("annotate", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "foo", imageListInstance})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "annotate", "--annotation", "hello=world,withcomma", "--arch", "bar", "foo", imageListARM64InstanceDigest})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(session.OutputToString()).To(ContainSubstring(`"architecture": "bar"`))
|
|
// Check added annotation
|
|
Expect(session.OutputToString()).To(ContainSubstring(`"hello": "world,withcomma"`))
|
|
})
|
|
|
|
It("remove digest", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "--all", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(session.OutputToString()).To(ContainSubstring(imageListARM64InstanceDigest))
|
|
session = podmanTest.Podman([]string{"manifest", "remove", "foo", imageListARM64InstanceDigest})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "inspect", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(session.OutputToString()).To(
|
|
And(
|
|
ContainSubstring(imageListAMD64InstanceDigest),
|
|
ContainSubstring(imageListPPC64LEInstanceDigest),
|
|
ContainSubstring(imageListS390XInstanceDigest),
|
|
Not(
|
|
ContainSubstring(imageListARM64InstanceDigest)),
|
|
))
|
|
})
|
|
|
|
It("remove not-found", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
bogusID := "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
|
session = podmanTest.Podman([]string{"manifest", "remove", "foo", bogusID})
|
|
session.WaitWithDefaultTimeout()
|
|
|
|
// FIXME-someday: figure out why message differs in podman-remote
|
|
expectMessage := "removing from manifest list foo: "
|
|
if IsRemote() {
|
|
expectMessage += "removing from manifest foo"
|
|
} else {
|
|
expectMessage += fmt.Sprintf(`no instance matching digest %q found in manifest list: file does not exist`, bogusID)
|
|
}
|
|
Expect(session).To(ExitWithError(125, expectMessage))
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "rm", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
})
|
|
|
|
It("push --all", func() {
|
|
SkipIfRemote("manifest push to dir not supported in remote mode")
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "--all", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
dest := filepath.Join(podmanTest.TempDir, "pushed")
|
|
err := os.MkdirAll(dest, os.ModePerm)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
defer func() {
|
|
os.RemoveAll(dest)
|
|
}()
|
|
session = podmanTest.Podman([]string{"manifest", "push", "-q", "--all", "foo", "dir:" + dest})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
err = validateManifestHasAllArchs(filepath.Join(dest, "manifest.json"))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
It("push", func() {
|
|
SkipIfRemote("manifest push to dir not supported in remote mode")
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "--all", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
dest := filepath.Join(podmanTest.TempDir, "pushed")
|
|
err := os.MkdirAll(dest, os.ModePerm)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
defer func() {
|
|
os.RemoveAll(dest)
|
|
}()
|
|
session = podmanTest.Podman([]string{"push", "-q", "foo", "dir:" + dest})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
err = validateManifestHasAllArchs(filepath.Join(dest, "manifest.json"))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
It("push with compression-format and compression-level", func() {
|
|
SkipIfRemote("manifest push to dir not supported in remote mode")
|
|
dockerfile := `FROM ` + CITEST_IMAGE + `
|
|
RUN touch /file
|
|
`
|
|
podmanTest.BuildImage(dockerfile, "localhost/test", "false")
|
|
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "add", "foo", "containers-storage:localhost/test"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
// Invalid compression format specified, it must fail
|
|
tmpDir := filepath.Join(podmanTest.TempDir, "wrong-compression")
|
|
session = podmanTest.Podman([]string{"manifest", "push", "--compression-format", "gzip", "--compression-level", "50", "foo", "oci:" + tmpDir})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitWithError(125, "invalid compression level"))
|
|
|
|
dest := filepath.Join(podmanTest.TempDir, "pushed")
|
|
err := os.MkdirAll(dest, os.ModePerm)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
defer func() {
|
|
os.RemoveAll(dest)
|
|
}()
|
|
session = podmanTest.Podman([]string{"push", "-q", "--compression-format=zstd", "foo", "oci:" + dest})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
foundZstdFile := false
|
|
|
|
blobsDir := filepath.Join(dest, "blobs", "sha256")
|
|
|
|
blobs, err := os.ReadDir(blobsDir)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
for _, f := range blobs {
|
|
blobPath := filepath.Join(blobsDir, f.Name())
|
|
|
|
sourceFile, err := os.ReadFile(blobPath)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
compressionType := archive.DetectCompression(sourceFile)
|
|
if compressionType == archive.Zstd {
|
|
foundZstdFile = true
|
|
break
|
|
}
|
|
}
|
|
Expect(foundZstdFile).To(BeTrue(), "found zstd file")
|
|
})
|
|
|
|
It("push progress", func() {
|
|
SkipIfRemote("manifest push to dir not supported in remote mode")
|
|
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
dest := filepath.Join(podmanTest.TempDir, "pushed")
|
|
err := os.MkdirAll(dest, os.ModePerm)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
defer func() {
|
|
os.RemoveAll(dest)
|
|
}()
|
|
|
|
session = podmanTest.Podman([]string{"push", "foo", "-q", "dir:" + dest})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(session.ErrorToString()).To(BeEmpty())
|
|
|
|
session = podmanTest.Podman([]string{"push", "foo", "dir:" + dest})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(Exit(0))
|
|
output := session.ErrorToString()
|
|
Expect(output).To(ContainSubstring("Writing manifest list to image destination"))
|
|
Expect(output).To(ContainSubstring("Storing list signatures"))
|
|
})
|
|
|
|
It("push must retry", func() {
|
|
SkipIfRemote("warning is not relayed in remote setup")
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
push := podmanTest.Podman([]string{"manifest", "push", "--all", "--tls-verify=false", "--remove-signatures", "foo", "localhost:7000/bogus"})
|
|
push.WaitWithDefaultTimeout()
|
|
Expect(push).Should(ExitWithError(125, "Failed, retrying in 1s ... (1/3)"))
|
|
Expect(push.ErrorToString()).To(MatchRegexp("Copying blob.*Failed, retrying in 1s \\.\\.\\. \\(1/3\\).*Copying blob.*Failed, retrying in 2s"))
|
|
})
|
|
|
|
It("authenticated push", func() {
|
|
registryOptions := &podmanRegistry.Options{
|
|
PodmanPath: podmanTest.PodmanBinary,
|
|
PodmanArgs: podmanTest.MakeOptions(nil, false, false),
|
|
Image: "docker-archive:" + imageTarPath(REGISTRY_IMAGE),
|
|
}
|
|
|
|
// Special case for remote: invoke local podman, with all
|
|
// network/storage/other args
|
|
if IsRemote() {
|
|
registryOptions.PodmanArgs = getRemoteOptions(podmanTest, nil)
|
|
}
|
|
registry, err := podmanRegistry.StartWithOptions(registryOptions)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
defer func() {
|
|
err := registry.Stop()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
}()
|
|
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"tag", CITEST_IMAGE, "localhost:" + registry.Port + "/citest:latest"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
push := podmanTest.Podman([]string{"push", "-q", "--tls-verify=false", "--creds=" + registry.User + ":" + registry.Password, "--format=v2s2", "localhost:" + registry.Port + "/citest:latest"})
|
|
push.WaitWithDefaultTimeout()
|
|
// Cannot ExitCleanly() because this sometimes warns "Failed, retrying in 1s"
|
|
Expect(push).Should(Exit(0))
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "add", "--tls-verify=false", "--creds=" + registry.User + ":" + registry.Password, "foo", "localhost:" + registry.Port + "/citest:latest"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
push = podmanTest.Podman([]string{"manifest", "push", "--tls-verify=false", "--creds=" + registry.User + ":" + registry.Password, "foo", "localhost:" + registry.Port + "/credstest"})
|
|
push.WaitWithDefaultTimeout()
|
|
Expect(push).Should(Exit(0))
|
|
output := push.ErrorToString()
|
|
Expect(output).To(ContainSubstring("Copying blob "))
|
|
Expect(output).To(ContainSubstring("Copying config "))
|
|
Expect(output).To(ContainSubstring("Writing manifest to image destination"))
|
|
|
|
push = podmanTest.Podman([]string{"manifest", "push", "--compression-format=gzip", "--compression-level=2", "--tls-verify=false", "--creds=podmantest:wrongpasswd", "foo", "localhost:" + registry.Port + "/credstest"})
|
|
push.WaitWithDefaultTimeout()
|
|
Expect(push).To(ExitWithError(125, ": authentication required"))
|
|
|
|
// push --rm after pull image (#15033)
|
|
push = podmanTest.Podman([]string{"manifest", "push", "-q", "--rm", "--tls-verify=false", "--creds=" + registry.User + ":" + registry.Password, "foo", "localhost:" + registry.Port + "/rmtest"})
|
|
push.WaitWithDefaultTimeout()
|
|
Expect(push).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"images", "-q", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
|
})
|
|
|
|
It("push with error", func() {
|
|
session := podmanTest.Podman([]string{"manifest", "push", "badsrcvalue", "baddestvalue"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitWithError(125, "retrieving local image from image name badsrcvalue: badsrcvalue: image not known"))
|
|
})
|
|
|
|
It("push --rm to local directory", func() {
|
|
SkipIfRemote("manifest push to dir not supported in remote mode")
|
|
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "foo", imageList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
dest := filepath.Join(podmanTest.TempDir, "pushed")
|
|
err := os.MkdirAll(dest, os.ModePerm)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
defer func() {
|
|
os.RemoveAll(dest)
|
|
}()
|
|
session = podmanTest.Podman([]string{"manifest", "push", "-q", "--purge", "foo", "dir:" + dest})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "push", "-p", "foo", "dir:" + dest})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitWithError(125, "retrieving local image from image name foo: foo: image not known"))
|
|
|
|
session = podmanTest.Podman([]string{"images", "-q", "foo"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
|
|
|
// push --rm after pull image (#15033)
|
|
session = podmanTest.Podman([]string{"pull", "-q", "quay.io/libpod/testdigest_v2s2"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "create", "bar"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "add", "bar", "quay.io/libpod/testdigest_v2s2"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"manifest", "push", "-q", "--rm", "bar", "dir:" + dest})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
session = podmanTest.Podman([]string{"images", "-q", "bar"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "rm", "foo", "bar"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitWithError(1, " 2 errors occurred:"))
|
|
Expect(session.ErrorToString()).To(ContainSubstring("* foo: image not known"))
|
|
Expect(session.ErrorToString()).To(ContainSubstring("* bar: image not known"))
|
|
})
|
|
|
|
It("exists", func() {
|
|
manifestList := "manifest-list"
|
|
session := podmanTest.Podman([]string{"manifest", "create", manifestList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "exists", manifestList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "exists", "no-manifest"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitWithError(1, ""))
|
|
})
|
|
|
|
It("rm should not remove referenced images", func() {
|
|
manifestList := "manifestlist"
|
|
imageName := "quay.io/libpod/busybox"
|
|
|
|
session := podmanTest.Podman([]string{"pull", "-q", imageName})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "create", manifestList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "add", manifestList, imageName})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
session = podmanTest.Podman([]string{"manifest", "rm", manifestList})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
// image should still show up
|
|
session = podmanTest.Podman([]string{"image", "exists", imageName})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
})
|
|
|
|
It("manifest rm should not remove image and should be able to remove tagged manifest list", func() {
|
|
// manifest rm should fail with `image is not a manifest list`
|
|
session := podmanTest.Podman([]string{"manifest", "rm", ALPINE})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitWithError(125, "image is not a manifest list"))
|
|
|
|
manifestName := "testmanifest:sometag"
|
|
session = podmanTest.Podman([]string{"manifest", "create", manifestName})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
// verify if manifest exists
|
|
session = podmanTest.Podman([]string{"manifest", "exists", manifestName})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
// manifest rm should be able to remove tagged manifest list
|
|
session = podmanTest.Podman([]string{"manifest", "rm", manifestName})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitCleanly())
|
|
|
|
// verify that manifest should not exist
|
|
session = podmanTest.Podman([]string{"manifest", "exists", manifestName})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).Should(ExitWithError(1, ""))
|
|
})
|
|
})
|