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 })