github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/test/e2e/push_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/hanks177/podman/v4/pkg/rootless"
    11  	. "github.com/hanks177/podman/v4/test/utils"
    12  	"github.com/containers/storage/pkg/archive"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  	. "github.com/onsi/gomega/gexec"
    16  )
    17  
    18  var _ = Describe("Podman push", func() {
    19  	var (
    20  		tempdir    string
    21  		err        error
    22  		podmanTest *PodmanTestIntegration
    23  	)
    24  
    25  	BeforeEach(func() {
    26  		tempdir, err = CreateTempDirInTempDir()
    27  		if err != nil {
    28  			os.Exit(1)
    29  		}
    30  		podmanTest = PodmanTestCreate(tempdir)
    31  		podmanTest.Setup()
    32  		podmanTest.AddImageToRWStore(ALPINE)
    33  	})
    34  
    35  	AfterEach(func() {
    36  		podmanTest.Cleanup()
    37  		f := CurrentGinkgoTestDescription()
    38  		processTestResult(f)
    39  
    40  	})
    41  
    42  	It("podman push to containers/storage", func() {
    43  		SkipIfRemote("Remote push does not support containers-storage transport")
    44  		session := podmanTest.Podman([]string{"push", ALPINE, "containers-storage:busybox:test"})
    45  		session.WaitWithDefaultTimeout()
    46  		Expect(session).Should(Exit(0))
    47  
    48  		session = podmanTest.Podman([]string{"rmi", ALPINE})
    49  		session.WaitWithDefaultTimeout()
    50  		Expect(session).Should(Exit(0))
    51  	})
    52  
    53  	It("podman push to dir", func() {
    54  		SkipIfRemote("Remote push does not support dir transport")
    55  		bbdir := filepath.Join(podmanTest.TempDir, "busybox")
    56  		session := podmanTest.Podman([]string{"push", "--remove-signatures", ALPINE,
    57  			fmt.Sprintf("dir:%s", bbdir)})
    58  		session.WaitWithDefaultTimeout()
    59  		Expect(session).Should(Exit(0))
    60  
    61  		bbdir = filepath.Join(podmanTest.TempDir, "busybox")
    62  		session = podmanTest.Podman([]string{"push", "--format", "oci", ALPINE,
    63  			fmt.Sprintf("dir:%s", bbdir)})
    64  		session.WaitWithDefaultTimeout()
    65  		Expect(session).Should(Exit(0))
    66  	})
    67  
    68  	It("podman push to oci with compression-format", func() {
    69  		SkipIfRemote("Remote push does not support dir transport")
    70  		bbdir := filepath.Join(podmanTest.TempDir, "busybox-oci")
    71  		session := podmanTest.Podman([]string{"push", "--compression-format=zstd", "--remove-signatures", ALPINE,
    72  			fmt.Sprintf("oci:%s", bbdir)})
    73  		session.WaitWithDefaultTimeout()
    74  		Expect(session).Should(Exit(0))
    75  
    76  		foundZstdFile := false
    77  
    78  		blobsDir := filepath.Join(bbdir, "blobs/sha256")
    79  
    80  		blobs, err := ioutil.ReadDir(blobsDir)
    81  		Expect(err).To(BeNil())
    82  
    83  		for _, f := range blobs {
    84  			blobPath := filepath.Join(blobsDir, f.Name())
    85  
    86  			sourceFile, err := ioutil.ReadFile(blobPath)
    87  			Expect(err).To(BeNil())
    88  
    89  			compressionType := archive.DetectCompression(sourceFile)
    90  			if compressionType == archive.Zstd {
    91  				foundZstdFile = true
    92  				break
    93  			}
    94  		}
    95  		Expect(foundZstdFile).To(BeTrue())
    96  	})
    97  
    98  	It("podman push to local registry", func() {
    99  		SkipIfRemote("Remote does not support --digestfile or --remove-signatures")
   100  		if podmanTest.Host.Arch == "ppc64le" {
   101  			Skip("No registry image for ppc64le")
   102  		}
   103  		if rootless.IsRootless() {
   104  			err := podmanTest.RestoreArtifact(registry)
   105  			Expect(err).ToNot(HaveOccurred())
   106  		}
   107  		lock := GetPortLock("5000")
   108  		defer lock.Unlock()
   109  		session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", "5000:5000", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"})
   110  		session.WaitWithDefaultTimeout()
   111  		Expect(session).Should(Exit(0))
   112  
   113  		if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
   114  			Skip("Cannot start docker registry.")
   115  		}
   116  
   117  		push := podmanTest.Podman([]string{"push", "-q", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"})
   118  		push.WaitWithDefaultTimeout()
   119  		Expect(push).Should(Exit(0))
   120  
   121  		// Test --digestfile option
   122  		push2 := podmanTest.Podman([]string{"push", "--tls-verify=false", "--digestfile=/tmp/digestfile.txt", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"})
   123  		push2.WaitWithDefaultTimeout()
   124  		fi, err := os.Lstat("/tmp/digestfile.txt")
   125  		Expect(err).To(BeNil())
   126  		Expect(fi.Name()).To(Equal("digestfile.txt"))
   127  		Expect(push2).Should(Exit(0))
   128  	})
   129  
   130  	It("podman push to local registry with authorization", func() {
   131  		SkipIfRootless("volume-mounting a certs.d file N/A over remote")
   132  		if podmanTest.Host.Arch == "ppc64le" {
   133  			Skip("No registry image for ppc64le")
   134  		}
   135  		authPath := filepath.Join(podmanTest.TempDir, "auth")
   136  		err = os.Mkdir(authPath, os.ModePerm)
   137  		Expect(err).ToNot(HaveOccurred())
   138  		err = os.MkdirAll("/etc/containers/certs.d/localhost:5000", os.ModePerm)
   139  		Expect(err).ToNot(HaveOccurred())
   140  		defer os.RemoveAll("/etc/containers/certs.d/localhost:5000")
   141  
   142  		cwd, _ := os.Getwd()
   143  		certPath := filepath.Join(cwd, "../", "certs")
   144  
   145  		if IsCommandAvailable("getenforce") {
   146  			ge := SystemExec("getenforce", []string{})
   147  			Expect(ge).Should(Exit(0))
   148  			if ge.OutputToString() == "Enforcing" {
   149  				se := SystemExec("setenforce", []string{"0"})
   150  				Expect(se).Should(Exit(0))
   151  				defer func() {
   152  					se2 := SystemExec("setenforce", []string{"1"})
   153  					Expect(se2).Should(Exit(0))
   154  				}()
   155  			}
   156  		}
   157  		lock := GetPortLock("5000")
   158  		defer lock.Unlock()
   159  		session := podmanTest.Podman([]string{"run", "--entrypoint", "htpasswd", registry, "-Bbn", "podmantest", "test"})
   160  		session.WaitWithDefaultTimeout()
   161  		Expect(session).Should(Exit(0))
   162  
   163  		f, err := os.Create(filepath.Join(authPath, "htpasswd"))
   164  		Expect(err).ToNot(HaveOccurred())
   165  		defer f.Close()
   166  
   167  		_, err = f.WriteString(session.OutputToString())
   168  		Expect(err).ToNot(HaveOccurred())
   169  		err = f.Sync()
   170  		Expect(err).ToNot(HaveOccurred())
   171  
   172  		session = podmanTest.Podman([]string{"run", "-d", "-p", "5000:5000", "--name", "registry", "-v",
   173  			strings.Join([]string{authPath, "/auth"}, ":"), "-e", "REGISTRY_AUTH=htpasswd", "-e",
   174  			"REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "-e", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd",
   175  			"-v", strings.Join([]string{certPath, "/certs"}, ":"), "-e", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt",
   176  			"-e", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key", registry})
   177  		session.WaitWithDefaultTimeout()
   178  		Expect(session).Should(Exit(0))
   179  
   180  		if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
   181  			Skip("Cannot start docker registry.")
   182  		}
   183  
   184  		session = podmanTest.Podman([]string{"logs", "registry"})
   185  		session.WaitWithDefaultTimeout()
   186  
   187  		push := podmanTest.Podman([]string{"push", "--tls-verify=true", "--format=v2s2", "--creds=podmantest:test", ALPINE, "localhost:5000/tlstest"})
   188  		push.WaitWithDefaultTimeout()
   189  		Expect(push).To(ExitWithError())
   190  
   191  		push = podmanTest.Podman([]string{"push", "--creds=podmantest:test", "--tls-verify=false", ALPINE, "localhost:5000/tlstest"})
   192  		push.WaitWithDefaultTimeout()
   193  		Expect(push).Should(Exit(0))
   194  
   195  		setup := SystemExec("cp", []string{filepath.Join(certPath, "domain.crt"), "/etc/containers/certs.d/localhost:5000/ca.crt"})
   196  		Expect(setup).Should(Exit(0))
   197  
   198  		push = podmanTest.Podman([]string{"push", "--creds=podmantest:wrongpasswd", ALPINE, "localhost:5000/credstest"})
   199  		push.WaitWithDefaultTimeout()
   200  		Expect(push).To(ExitWithError())
   201  
   202  		if !IsRemote() {
   203  			// remote does not support --cert-dir
   204  			push = podmanTest.Podman([]string{"push", "--tls-verify=true", "--creds=podmantest:test", "--cert-dir=fakedir", ALPINE, "localhost:5000/certdirtest"})
   205  			push.WaitWithDefaultTimeout()
   206  			Expect(push).To(ExitWithError())
   207  		}
   208  
   209  		push = podmanTest.Podman([]string{"push", "--creds=podmantest:test", ALPINE, "localhost:5000/defaultflags"})
   210  		push.WaitWithDefaultTimeout()
   211  		Expect(push).Should(Exit(0))
   212  	})
   213  
   214  	It("podman push to docker-archive", func() {
   215  		SkipIfRemote("Remote push does not support docker-archive transport")
   216  		tarfn := filepath.Join(podmanTest.TempDir, "alp.tar")
   217  		session := podmanTest.Podman([]string{"push", ALPINE,
   218  			fmt.Sprintf("docker-archive:%s:latest", tarfn)})
   219  		session.WaitWithDefaultTimeout()
   220  		Expect(session).Should(Exit(0))
   221  	})
   222  
   223  	It("podman push to docker daemon", func() {
   224  		SkipIfRemote("Remote push does not support docker-daemon transport")
   225  		setup := SystemExec("bash", []string{"-c", "systemctl status docker 2>&1"})
   226  
   227  		if setup.LineInOutputContains("Active: inactive") {
   228  			setup = SystemExec("systemctl", []string{"start", "docker"})
   229  			Expect(setup).Should(Exit(0))
   230  			defer func() {
   231  				stop := SystemExec("systemctl", []string{"stop", "docker"})
   232  				Expect(stop).Should(Exit(0))
   233  			}()
   234  		} else if setup.ExitCode() != 0 {
   235  			Skip("Docker is not available")
   236  		}
   237  
   238  		session := podmanTest.Podman([]string{"push", ALPINE, "docker-daemon:alpine:podmantest"})
   239  		session.WaitWithDefaultTimeout()
   240  		Expect(session).Should(Exit(0))
   241  
   242  		check := SystemExec("docker", []string{"images", "--format", "{{.Repository}}:{{.Tag}}"})
   243  		Expect(check).Should(Exit(0))
   244  		Expect(check.OutputToString()).To(ContainSubstring("alpine:podmantest"))
   245  
   246  		clean := SystemExec("docker", []string{"rmi", "alpine:podmantest"})
   247  		Expect(clean).Should(Exit(0))
   248  	})
   249  
   250  	It("podman push to oci-archive", func() {
   251  		SkipIfRemote("Remote push does not support oci-archive transport")
   252  		tarfn := filepath.Join(podmanTest.TempDir, "alp.tar")
   253  		session := podmanTest.Podman([]string{"push", ALPINE,
   254  			fmt.Sprintf("oci-archive:%s:latest", tarfn)})
   255  		session.WaitWithDefaultTimeout()
   256  		Expect(session).Should(Exit(0))
   257  	})
   258  
   259  	It("podman push to docker-archive no reference", func() {
   260  		SkipIfRemote("Remote push does not support docker-archive transport")
   261  		tarfn := filepath.Join(podmanTest.TempDir, "alp.tar")
   262  		session := podmanTest.Podman([]string{"push", ALPINE,
   263  			fmt.Sprintf("docker-archive:%s", tarfn)})
   264  		session.WaitWithDefaultTimeout()
   265  		Expect(session).Should(Exit(0))
   266  	})
   267  
   268  	It("podman push to oci-archive no reference", func() {
   269  		SkipIfRemote("Remote push does not support oci-archive transport")
   270  		ociarc := filepath.Join(podmanTest.TempDir, "alp-oci")
   271  		session := podmanTest.Podman([]string{"push", ALPINE,
   272  			fmt.Sprintf("oci-archive:%s", ociarc)})
   273  
   274  		session.WaitWithDefaultTimeout()
   275  		Expect(session).Should(Exit(0))
   276  	})
   277  
   278  })