github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/test/e2e/search_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"regexp"
     9  	"strconv"
    10  	"text/template"
    11  
    12  	. "github.com/containers/podman/v2/test/utils"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  type endpoint struct {
    18  	Host string
    19  	Port string
    20  }
    21  
    22  func (e *endpoint) Address() string {
    23  	return fmt.Sprintf("%s:%s", e.Host, e.Port)
    24  }
    25  
    26  var _ = Describe("Podman search", func() {
    27  	var (
    28  		tempdir    string
    29  		err        error
    30  		podmanTest *PodmanTestIntegration
    31  	)
    32  
    33  	var registryEndpoints = []endpoint{
    34  		{"localhost", "5001"},
    35  		{"localhost", "5002"},
    36  		{"localhost", "5003"},
    37  		{"localhost", "5004"},
    38  		{"localhost", "5005"},
    39  		{"localhost", "5006"},
    40  		{"localhost", "5007"},
    41  		{"localhost", "5008"},
    42  		{"localhost", "5009"},
    43  	}
    44  
    45  	const regFileContents = `
    46  [registries.search]
    47  registries = ['{{.Host}}:{{.Port}}']
    48  
    49  [registries.insecure]
    50  registries = ['{{.Host}}:{{.Port}}']`
    51  	registryFileTmpl := template.Must(template.New("registryFile").Parse(regFileContents))
    52  
    53  	const badRegFileContents = `
    54  [registries.search]
    55  registries = ['{{.Host}}:{{.Port}}']
    56  # empty
    57  [registries.insecure]
    58  registries = []`
    59  	registryFileBadTmpl := template.Must(template.New("registryFileBad").Parse(badRegFileContents))
    60  
    61  	const regFileContents2 = `
    62  [registries.search]
    63  registries = ['{{.Host}}:{{.Port}}', '{{.Host}}:6000']
    64  
    65  [registries.insecure]
    66  registries = ['{{.Host}}:{{.Port}}']`
    67  	registryFileTwoTmpl := template.Must(template.New("registryFileTwo").Parse(regFileContents2))
    68  
    69  	BeforeEach(func() {
    70  		tempdir, err = CreateTempDirInTempDir()
    71  		if err != nil {
    72  			os.Exit(1)
    73  		}
    74  
    75  		podmanTest = PodmanTestCreate(tempdir)
    76  		podmanTest.Setup()
    77  		podmanTest.SeedImages()
    78  
    79  	})
    80  
    81  	AfterEach(func() {
    82  		podmanTest.Cleanup()
    83  		f := CurrentGinkgoTestDescription()
    84  		processTestResult(f)
    85  	})
    86  
    87  	It("podman search", func() {
    88  		search := podmanTest.Podman([]string{"search", "alpine"})
    89  		search.WaitWithDefaultTimeout()
    90  		Expect(search.ExitCode()).To(Equal(0))
    91  		Expect(len(search.OutputToStringArray())).To(BeNumerically(">", 1))
    92  		Expect(search.LineInOutputContains("docker.io/library/alpine")).To(BeTrue())
    93  	})
    94  
    95  	It("podman search single registry flag", func() {
    96  		search := podmanTest.Podman([]string{"search", "quay.io/skopeo/stable:latest"})
    97  		search.WaitWithDefaultTimeout()
    98  		Expect(search.ExitCode()).To(Equal(0))
    99  		Expect(search.LineInOutputContains("quay.io/skopeo/stable")).To(BeTrue())
   100  	})
   101  
   102  	It("podman search image with description", func() {
   103  		search := podmanTest.Podman([]string{"search", "quay.io/libpod/whalesay"})
   104  		search.WaitWithDefaultTimeout()
   105  		Expect(search.ExitCode()).To(Equal(0))
   106  		output := string(search.Out.Contents())
   107  		match, _ := regexp.MatchString(`(?m)^quay.io\s+quay.io/libpod/whalesay\s+Static image used for automated testing.+$`, output)
   108  		Expect(match).To(BeTrue())
   109  	})
   110  
   111  	It("podman search format flag", func() {
   112  		search := podmanTest.Podman([]string{"search", "--format", "table {{.Index}} {{.Name}}", "alpine"})
   113  		search.WaitWithDefaultTimeout()
   114  		Expect(search.ExitCode()).To(Equal(0))
   115  		Expect(len(search.OutputToStringArray())).To(BeNumerically(">", 1))
   116  		Expect(search.LineInOutputContains("docker.io/library/alpine")).To(BeTrue())
   117  	})
   118  
   119  	It("podman search format json", func() {
   120  		search := podmanTest.Podman([]string{"search", "--format", "json", "alpine"})
   121  		search.WaitWithDefaultTimeout()
   122  		Expect(search.ExitCode()).To(Equal(0))
   123  		Expect(search.IsJSONOutputValid()).To(BeTrue())
   124  		Expect(search.OutputToString()).To(ContainSubstring("docker.io/library/alpine"))
   125  	})
   126  
   127  	It("podman search no-trunc flag", func() {
   128  		search := podmanTest.Podman([]string{"search", "--no-trunc", "alpine"})
   129  		search.WaitWithDefaultTimeout()
   130  		Expect(search.ExitCode()).To(Equal(0))
   131  		Expect(len(search.OutputToStringArray())).To(BeNumerically(">", 1))
   132  		Expect(search.LineInOutputContains("docker.io/library/alpine")).To(BeTrue())
   133  		Expect(search.LineInOutputContains("...")).To(BeFalse())
   134  	})
   135  
   136  	It("podman search limit flag", func() {
   137  		search := podmanTest.Podman([]string{"search", "docker.io/alpine"})
   138  		search.WaitWithDefaultTimeout()
   139  		Expect(search.ExitCode()).To(Equal(0))
   140  		Expect(len(search.OutputToStringArray())).To(Equal(26))
   141  
   142  		search = podmanTest.Podman([]string{"search", "--limit", "3", "docker.io/alpine"})
   143  		search.WaitWithDefaultTimeout()
   144  		Expect(search.ExitCode()).To(Equal(0))
   145  		Expect(len(search.OutputToStringArray())).To(Equal(4))
   146  
   147  		search = podmanTest.Podman([]string{"search", "--limit", "30", "docker.io/alpine"})
   148  		search.WaitWithDefaultTimeout()
   149  		Expect(search.ExitCode()).To(Equal(0))
   150  		Expect(len(search.OutputToStringArray())).To(Equal(31))
   151  	})
   152  
   153  	It("podman search with filter stars", func() {
   154  		search := podmanTest.Podman([]string{"search", "--filter", "stars=10", "--format", "{{.Stars}}", "alpine"})
   155  		search.WaitWithDefaultTimeout()
   156  		Expect(search.ExitCode()).To(Equal(0))
   157  		output := search.OutputToStringArray()
   158  		for i := 0; i < len(output); i++ {
   159  			Expect(strconv.Atoi(output[i])).To(BeNumerically(">=", 10))
   160  		}
   161  	})
   162  
   163  	It("podman search with filter is-official", func() {
   164  		search := podmanTest.Podman([]string{"search", "--filter", "is-official", "--format", "{{.Official}}", "alpine"})
   165  		search.WaitWithDefaultTimeout()
   166  		Expect(search.ExitCode()).To(Equal(0))
   167  		output := search.OutputToStringArray()
   168  		for i := 0; i < len(output); i++ {
   169  			Expect(output[i]).To(Equal("[OK]"))
   170  		}
   171  	})
   172  
   173  	It("podman search with filter is-automated", func() {
   174  		search := podmanTest.Podman([]string{"search", "--filter", "is-automated=false", "--format", "{{.Automated}}", "alpine"})
   175  		search.WaitWithDefaultTimeout()
   176  		Expect(search.ExitCode()).To(Equal(0))
   177  		output := search.OutputToStringArray()
   178  		for i := 0; i < len(output); i++ {
   179  			Expect(output[i]).To(Equal(""))
   180  		}
   181  	})
   182  
   183  	It("podman search attempts HTTP if tls-verify flag is set false", func() {
   184  		if podmanTest.Host.Arch == "ppc64le" {
   185  			Skip("No registry image for ppc64le")
   186  		}
   187  		lock := GetPortLock(registryEndpoints[0].Port)
   188  		defer lock.Unlock()
   189  
   190  		fakereg := podmanTest.Podman([]string{"run", "-d", "--name", "registry",
   191  			"-p", fmt.Sprintf("%s:5000", registryEndpoints[0].Port),
   192  			registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"})
   193  		fakereg.WaitWithDefaultTimeout()
   194  		Expect(fakereg.ExitCode()).To(Equal(0))
   195  
   196  		if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
   197  			Skip("Cannot start docker registry.")
   198  		}
   199  
   200  		search := podmanTest.Podman([]string{"search",
   201  			fmt.Sprintf("%s/fake/image:andtag", registryEndpoints[0].Address()), "--tls-verify=false"})
   202  		search.WaitWithDefaultTimeout()
   203  
   204  		// if this test succeeded, there will be no output (there is no entry named fake/image:andtag in an empty registry)
   205  		// and the exit code will be 0
   206  		Expect(search.ExitCode()).To(Equal(0))
   207  		Expect(search.OutputToString()).Should(BeEmpty())
   208  		Expect(search.ErrorToString()).Should(BeEmpty())
   209  	})
   210  
   211  	It("podman search in local registry", func() {
   212  		if podmanTest.Host.Arch == "ppc64le" {
   213  			Skip("No registry image for ppc64le")
   214  		}
   215  		lock := GetPortLock(registryEndpoints[3].Port)
   216  		defer lock.Unlock()
   217  		registry := podmanTest.Podman([]string{"run", "-d", "--name", "registry3",
   218  			"-p", fmt.Sprintf("%s:5000", registryEndpoints[3].Port), registry,
   219  			"/entrypoint.sh", "/etc/docker/registry/config.yml"})
   220  		registry.WaitWithDefaultTimeout()
   221  		Expect(registry.ExitCode()).To(Equal(0))
   222  
   223  		if !WaitContainerReady(podmanTest, "registry3", "listening on", 20, 1) {
   224  			Skip("Cannot start docker registry.")
   225  		}
   226  
   227  		podmanTest.RestoreArtifact(ALPINE)
   228  		image := fmt.Sprintf("%s/my-alpine", registryEndpoints[3].Address())
   229  		push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image})
   230  		push.WaitWithDefaultTimeout()
   231  		Expect(push.ExitCode()).To(Equal(0))
   232  		search := podmanTest.Podman([]string{"search", image, "--tls-verify=false"})
   233  		search.WaitWithDefaultTimeout()
   234  
   235  		Expect(search.ExitCode()).To(Equal(0))
   236  		Expect(search.OutputToString()).ShouldNot(BeEmpty())
   237  
   238  		// podman search v2 registry with empty query
   239  		searchEmpty := podmanTest.Podman([]string{"search", fmt.Sprintf("%s/", registryEndpoints[3].Address()), "--tls-verify=false"})
   240  		searchEmpty.WaitWithDefaultTimeout()
   241  		Expect(searchEmpty.ExitCode()).To(BeZero())
   242  		Expect(len(searchEmpty.OutputToStringArray())).To(BeNumerically(">=", 1))
   243  		match, _ := search.GrepString("my-alpine")
   244  		Expect(match).Should(BeTrue())
   245  	})
   246  
   247  	It("podman search attempts HTTP if registry is in registries.insecure and force secure is false", func() {
   248  		if podmanTest.Host.Arch == "ppc64le" {
   249  			Skip("No registry image for ppc64le")
   250  		}
   251  
   252  		lock := GetPortLock(registryEndpoints[4].Port)
   253  		defer lock.Unlock()
   254  		registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%s:5000", registryEndpoints[4].Port),
   255  			"--name", "registry4", registry, "/entrypoint.sh", "/etc/docker/registry/config.yml"})
   256  		registry.WaitWithDefaultTimeout()
   257  		Expect(registry.ExitCode()).To(Equal(0))
   258  
   259  		if !WaitContainerReady(podmanTest, "registry4", "listening on", 20, 1) {
   260  			Skip("Cannot start docker registry.")
   261  		}
   262  
   263  		podmanTest.RestoreArtifact(ALPINE)
   264  		image := fmt.Sprintf("%s/my-alpine", registryEndpoints[4].Address())
   265  		push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image})
   266  		push.WaitWithDefaultTimeout()
   267  		Expect(push.ExitCode()).To(Equal(0))
   268  
   269  		// registries.conf set up
   270  		var buffer bytes.Buffer
   271  		registryFileTmpl.Execute(&buffer, registryEndpoints[4])
   272  		podmanTest.setRegistriesConfigEnv(buffer.Bytes())
   273  		ioutil.WriteFile(fmt.Sprintf("%s/registry4.conf", tempdir), buffer.Bytes(), 0644)
   274  		if IsRemote() {
   275  			podmanTest.RestartRemoteService()
   276  			defer podmanTest.RestartRemoteService()
   277  		}
   278  
   279  		search := podmanTest.Podman([]string{"search", image})
   280  		search.WaitWithDefaultTimeout()
   281  
   282  		Expect(search.ExitCode()).To(Equal(0))
   283  		match, _ := search.GrepString("my-alpine")
   284  		Expect(match).Should(BeTrue())
   285  		Expect(search.ErrorToString()).Should(BeEmpty())
   286  
   287  		// cleanup
   288  		resetRegistriesConfigEnv()
   289  	})
   290  
   291  	It("podman search doesn't attempt HTTP if force secure is true", func() {
   292  		SkipIfRemote("FIXME This should work on podman-remote")
   293  		if podmanTest.Host.Arch == "ppc64le" {
   294  			Skip("No registry image for ppc64le")
   295  		}
   296  		lock := GetPortLock(registryEndpoints[5].Port)
   297  		defer lock.Unlock()
   298  		registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%s:5000", registryEndpoints[5].Port),
   299  			"--name", "registry5", registry})
   300  		registry.WaitWithDefaultTimeout()
   301  		Expect(registry.ExitCode()).To(Equal(0))
   302  
   303  		if !WaitContainerReady(podmanTest, "registry5", "listening on", 20, 1) {
   304  			Skip("Cannot start docker registry.")
   305  		}
   306  
   307  		podmanTest.RestoreArtifact(ALPINE)
   308  		image := fmt.Sprintf("%s/my-alpine", registryEndpoints[5].Address())
   309  		push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image})
   310  		push.WaitWithDefaultTimeout()
   311  		Expect(push.ExitCode()).To(Equal(0))
   312  
   313  		var buffer bytes.Buffer
   314  		registryFileTmpl.Execute(&buffer, registryEndpoints[5])
   315  		podmanTest.setRegistriesConfigEnv(buffer.Bytes())
   316  		ioutil.WriteFile(fmt.Sprintf("%s/registry5.conf", tempdir), buffer.Bytes(), 0644)
   317  		if IsRemote() {
   318  			podmanTest.RestartRemoteService()
   319  			defer podmanTest.RestartRemoteService()
   320  		}
   321  
   322  		search := podmanTest.Podman([]string{"search", image, "--tls-verify=true"})
   323  		search.WaitWithDefaultTimeout()
   324  
   325  		Expect(search.ExitCode()).To(Equal(0))
   326  		Expect(search.OutputToString()).Should(BeEmpty())
   327  		match, _ := search.ErrorGrepString("error")
   328  		Expect(match).Should(BeTrue())
   329  
   330  		// cleanup
   331  		resetRegistriesConfigEnv()
   332  	})
   333  
   334  	It("podman search doesn't attempt HTTP if registry is not listed as insecure", func() {
   335  		SkipIfRemote("FIXME This should work on podman-remote")
   336  		if podmanTest.Host.Arch == "ppc64le" {
   337  			Skip("No registry image for ppc64le")
   338  		}
   339  		lock := GetPortLock(registryEndpoints[6].Port)
   340  		defer lock.Unlock()
   341  		registry := podmanTest.Podman([]string{"run", "-d", "-p", fmt.Sprintf("%s:5000", registryEndpoints[6].Port),
   342  			"--name", "registry6", registry})
   343  		registry.WaitWithDefaultTimeout()
   344  		Expect(registry.ExitCode()).To(Equal(0))
   345  
   346  		if !WaitContainerReady(podmanTest, "registry6", "listening on", 20, 1) {
   347  			Skip("Cannot start docker registry.")
   348  		}
   349  
   350  		podmanTest.RestoreArtifact(ALPINE)
   351  		image := fmt.Sprintf("%s/my-alpine", registryEndpoints[6].Address())
   352  		push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, image})
   353  		push.WaitWithDefaultTimeout()
   354  		Expect(push.ExitCode()).To(Equal(0))
   355  
   356  		var buffer bytes.Buffer
   357  		registryFileBadTmpl.Execute(&buffer, registryEndpoints[6])
   358  		podmanTest.setRegistriesConfigEnv(buffer.Bytes())
   359  		ioutil.WriteFile(fmt.Sprintf("%s/registry6.conf", tempdir), buffer.Bytes(), 0644)
   360  
   361  		if IsRemote() {
   362  			podmanTest.RestartRemoteService()
   363  			defer podmanTest.RestartRemoteService()
   364  		}
   365  
   366  		search := podmanTest.Podman([]string{"search", image})
   367  		search.WaitWithDefaultTimeout()
   368  
   369  		Expect(search.ExitCode()).To(Equal(0))
   370  		Expect(search.OutputToString()).Should(BeEmpty())
   371  		match, _ := search.ErrorGrepString("error")
   372  		Expect(match).Should(BeTrue())
   373  
   374  		// cleanup
   375  		resetRegistriesConfigEnv()
   376  	})
   377  
   378  	It("podman search doesn't attempt HTTP if one registry is not listed as insecure", func() {
   379  		SkipIfRemote("FIXME This should work on podman-remote")
   380  		if podmanTest.Host.Arch == "ppc64le" {
   381  			Skip("No registry image for ppc64le")
   382  		}
   383  		lock7 := GetPortLock(registryEndpoints[7].Port)
   384  		defer lock7.Unlock()
   385  		lock8 := GetPortLock("6000")
   386  		defer lock8.Unlock()
   387  
   388  		registryLocal := podmanTest.Podman([]string{"run", "-d", "--net=host", "-p", fmt.Sprintf("%s:5000", registryEndpoints[7].Port),
   389  			"--name", "registry7", registry})
   390  		registryLocal.WaitWithDefaultTimeout()
   391  		Expect(registryLocal.ExitCode()).To(Equal(0))
   392  
   393  		if !WaitContainerReady(podmanTest, "registry7", "listening on", 20, 1) {
   394  			Skip("Cannot start docker registry.")
   395  		}
   396  
   397  		registryLocal = podmanTest.Podman([]string{"run", "-d", "-p", "6000:5000", "--name", "registry8", registry})
   398  		registryLocal.WaitWithDefaultTimeout()
   399  		Expect(registryLocal.ExitCode()).To(Equal(0))
   400  
   401  		if !WaitContainerReady(podmanTest, "registry8", "listening on", 20, 1) {
   402  			Skip("Cannot start docker registry.")
   403  		}
   404  
   405  		podmanTest.RestoreArtifact(ALPINE)
   406  		push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:6000/my-alpine"})
   407  		push.WaitWithDefaultTimeout()
   408  		Expect(push.ExitCode()).To(Equal(0))
   409  
   410  		// registries.conf set up
   411  		var buffer bytes.Buffer
   412  		registryFileTwoTmpl.Execute(&buffer, registryEndpoints[8])
   413  		podmanTest.setRegistriesConfigEnv(buffer.Bytes())
   414  		ioutil.WriteFile(fmt.Sprintf("%s/registry8.conf", tempdir), buffer.Bytes(), 0644)
   415  
   416  		if IsRemote() {
   417  			podmanTest.RestartRemoteService()
   418  			defer podmanTest.RestartRemoteService()
   419  		}
   420  
   421  		search := podmanTest.Podman([]string{"search", "my-alpine"})
   422  		search.WaitWithDefaultTimeout()
   423  
   424  		Expect(search.ExitCode()).To(Equal(0))
   425  		Expect(search.OutputToString()).Should(BeEmpty())
   426  		match, _ := search.ErrorGrepString("error")
   427  		Expect(match).Should(BeTrue())
   428  
   429  		// cleanup
   430  		resetRegistriesConfigEnv()
   431  	})
   432  
   433  	// search should fail with nonexist authfile
   434  	It("podman search fail with nonexist --authfile", func() {
   435  		search := podmanTest.Podman([]string{"search", "--authfile", "/tmp/nonexist", ALPINE})
   436  		search.WaitWithDefaultTimeout()
   437  		Expect(search.ExitCode()).To(Not(Equal(0)))
   438  	})
   439  
   440  	It("podman search with wildcards", func() {
   441  		search := podmanTest.Podman([]string{"search", "--limit", "30", "registry.redhat.io/*"})
   442  		search.WaitWithDefaultTimeout()
   443  		Expect(search.ExitCode()).To(Equal(0))
   444  		Expect(len(search.OutputToStringArray())).To(Equal(31))
   445  
   446  		search = podmanTest.Podman([]string{"search", "registry.redhat.io/*openshift*"})
   447  		search.WaitWithDefaultTimeout()
   448  		Expect(search.ExitCode()).To(Equal(0))
   449  		Expect(len(search.OutputToStringArray()) > 1).To(BeTrue())
   450  	})
   451  
   452  	It("podman search repository tags", func() {
   453  		search := podmanTest.Podman([]string{"search", "--list-tags", "--limit", "30", "docker.io/library/alpine"})
   454  		search.WaitWithDefaultTimeout()
   455  		Expect(search.ExitCode()).To(Equal(0))
   456  		Expect(len(search.OutputToStringArray())).To(Equal(31))
   457  
   458  		search = podmanTest.Podman([]string{"search", "--list-tags", "docker.io/library/alpine"})
   459  		search.WaitWithDefaultTimeout()
   460  		Expect(search.ExitCode()).To(Equal(0))
   461  		Expect(len(search.OutputToStringArray()) > 2).To(BeTrue())
   462  
   463  		search = podmanTest.Podman([]string{"search", "--filter=is-official", "--list-tags", "docker.io/library/alpine"})
   464  		search.WaitWithDefaultTimeout()
   465  		Expect(search.ExitCode()).To(Not(Equal(0)))
   466  
   467  		search = podmanTest.Podman([]string{"search", "--list-tags", "docker.io/library/"})
   468  		search.WaitWithDefaultTimeout()
   469  		Expect(len(search.OutputToStringArray()) == 0).To(BeTrue())
   470  	})
   471  
   472  	It("podman search with limit over 100", func() {
   473  		search := podmanTest.Podman([]string{"search", "--limit", "130", "registry.redhat.io/rhel"})
   474  		search.WaitWithDefaultTimeout()
   475  		Expect(search.ExitCode()).To(Equal(0))
   476  		Expect(len(search.OutputToStringArray())).To(Equal(131))
   477  	})
   478  })