zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/pkg/cli/client/search_cmd_test.go (about) 1 //go:build search 2 // +build search 3 4 package client_test 5 6 import ( 7 "bytes" 8 "fmt" 9 "os" 10 "regexp" 11 "strings" 12 "testing" 13 "time" 14 15 ispec "github.com/opencontainers/image-spec/specs-go/v1" 16 . "github.com/smartystreets/goconvey/convey" 17 18 "zotregistry.dev/zot/pkg/api" 19 "zotregistry.dev/zot/pkg/api/config" 20 "zotregistry.dev/zot/pkg/cli/client" 21 extconf "zotregistry.dev/zot/pkg/extensions/config" 22 test "zotregistry.dev/zot/pkg/test/common" 23 . "zotregistry.dev/zot/pkg/test/image-utils" 24 ociutils "zotregistry.dev/zot/pkg/test/oci-utils" 25 ) 26 27 const ( 28 customArtTypeV1 = "application/custom.art.type.v1" 29 customArtTypeV2 = "application/custom.art.type.v2" 30 repoName = "repo" 31 ) 32 33 func TestReferrerCLI(t *testing.T) { 34 Convey("Test GQL", t, func() { 35 rootDir := t.TempDir() 36 37 port := test.GetFreePort() 38 baseURL := test.GetBaseURL(port) 39 conf := config.New() 40 conf.HTTP.Port = port 41 conf.Storage.GC = false 42 defaultVal := true 43 conf.Extensions = &extconf.ExtensionConfig{ 44 Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}}, 45 } 46 ctlr := api.NewController(conf) 47 ctlr.Config.Storage.RootDirectory = rootDir 48 cm := test.NewControllerManager(ctlr) 49 cm.StartAndWait(conf.HTTP.Port) 50 defer cm.StopServer() 51 52 repo := repoName 53 image := CreateRandomImage() 54 55 err := UploadImage(image, baseURL, repo, "tag") 56 So(err, ShouldBeNil) 57 58 ref1 := CreateImageWith(). 59 RandomLayers(1, 10). 60 RandomConfig(). 61 Subject(image.DescriptorRef()).Build() 62 63 ref2 := CreateImageWith(). 64 RandomLayers(1, 10). 65 ArtifactConfig(customArtTypeV1). 66 Subject(image.DescriptorRef()).Build() 67 68 ref3 := CreateImageWith(). 69 RandomLayers(1, 10). 70 RandomConfig(). 71 ArtifactType(customArtTypeV2). 72 Subject(image.DescriptorRef()).Build() 73 74 err = UploadImage(ref1, baseURL, repo, ref1.DigestStr()) 75 So(err, ShouldBeNil) 76 77 err = UploadImage(ref2, baseURL, repo, ref2.DigestStr()) 78 So(err, ShouldBeNil) 79 80 err = UploadImage(ref3, baseURL, repo, ref3.DigestStr()) 81 So(err, ShouldBeNil) 82 83 args := []string{"subject", repo + "@" + image.DigestStr(), "--config", "reftest"} 84 85 configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`, 86 baseURL)) 87 defer os.Remove(configPath) 88 89 cmd := client.NewSearchCommand(client.NewSearchService()) 90 91 buff := &bytes.Buffer{} 92 cmd.SetOut(buff) 93 cmd.SetErr(buff) 94 cmd.SetArgs(args) 95 err = cmd.Execute() 96 So(err, ShouldBeNil) 97 space := regexp.MustCompile(`\s+`) 98 str := strings.TrimSpace(space.ReplaceAllString(buff.String(), " ")) 99 So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST") 100 So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr()) 101 So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr()) 102 So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr()) 103 104 fmt.Println(buff.String()) 105 106 os.Remove(configPath) 107 108 args = []string{"subject", repo + ":" + "tag", "--config", "reftest"} 109 110 configPath = makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`, 111 baseURL)) 112 defer os.Remove(configPath) 113 114 cmd = client.NewSearchCommand(client.NewSearchService()) 115 116 buff = &bytes.Buffer{} 117 cmd.SetOut(buff) 118 cmd.SetErr(buff) 119 cmd.SetArgs(args) 120 err = cmd.Execute() 121 So(err, ShouldBeNil) 122 str = strings.TrimSpace(space.ReplaceAllString(buff.String(), " ")) 123 So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST") 124 So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr()) 125 So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr()) 126 So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr()) 127 128 fmt.Println(buff.String()) 129 }) 130 131 Convey("Test REST", t, func() { 132 rootDir := t.TempDir() 133 134 port := test.GetFreePort() 135 baseURL := test.GetBaseURL(port) 136 conf := config.New() 137 conf.HTTP.Port = port 138 conf.Storage.GC = false 139 defaultVal := false 140 conf.Extensions = &extconf.ExtensionConfig{ 141 Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}}, 142 } 143 ctlr := api.NewController(conf) 144 ctlr.Config.Storage.RootDirectory = rootDir 145 cm := test.NewControllerManager(ctlr) 146 cm.StartAndWait(conf.HTTP.Port) 147 defer cm.StopServer() 148 149 repo := repoName 150 image := CreateRandomImage() 151 152 err := UploadImage(image, baseURL, repo, "tag") 153 So(err, ShouldBeNil) 154 155 ref1 := CreateImageWith(). 156 RandomLayers(1, 10). 157 RandomConfig(). 158 Subject(image.DescriptorRef()).Build() 159 160 ref2 := CreateImageWith(). 161 RandomLayers(1, 10). 162 ArtifactConfig(customArtTypeV1). 163 Subject(image.DescriptorRef()).Build() 164 165 ref3 := CreateImageWith(). 166 RandomLayers(1, 10). 167 RandomConfig(). 168 ArtifactType(customArtTypeV2). 169 Subject(image.DescriptorRef()).Build() 170 171 err = UploadImage(ref1, baseURL, repo, ref1.DigestStr()) 172 So(err, ShouldBeNil) 173 174 err = UploadImage(ref2, baseURL, repo, ref2.DigestStr()) 175 So(err, ShouldBeNil) 176 177 err = UploadImage(ref3, baseURL, repo, ref3.DigestStr()) 178 So(err, ShouldBeNil) 179 180 // get referrers by digest 181 args := []string{"subject", repo + "@" + image.DigestStr(), "--config", "reftest"} 182 183 configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`, 184 baseURL)) 185 186 cmd := client.NewSearchCommand(client.NewSearchService()) 187 188 buff := &bytes.Buffer{} 189 cmd.SetOut(buff) 190 cmd.SetErr(buff) 191 cmd.SetArgs(args) 192 err = cmd.Execute() 193 So(err, ShouldBeNil) 194 space := regexp.MustCompile(`\s+`) 195 str := strings.TrimSpace(space.ReplaceAllString(buff.String(), " ")) 196 So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST") 197 So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr()) 198 So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr()) 199 So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr()) 200 fmt.Println(buff.String()) 201 202 os.Remove(configPath) 203 204 args = []string{"subject", repo + ":" + "tag", "--config", "reftest"} 205 206 configPath = makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`, 207 baseURL)) 208 defer os.Remove(configPath) 209 210 buff = &bytes.Buffer{} 211 cmd.SetOut(buff) 212 cmd.SetErr(buff) 213 cmd.SetArgs(args) 214 err = cmd.Execute() 215 So(err, ShouldBeNil) 216 str = strings.TrimSpace(space.ReplaceAllString(buff.String(), " ")) 217 So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST") 218 So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr()) 219 So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr()) 220 So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr()) 221 fmt.Println(buff.String()) 222 }) 223 } 224 225 func TestFormatsReferrersCLI(t *testing.T) { 226 Convey("Create server", t, func() { 227 rootDir := t.TempDir() 228 229 port := test.GetFreePort() 230 baseURL := test.GetBaseURL(port) 231 conf := config.New() 232 conf.HTTP.Port = port 233 conf.Storage.GC = false 234 defaultVal := false 235 conf.Extensions = &extconf.ExtensionConfig{ 236 Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}}, 237 } 238 ctlr := api.NewController(conf) 239 ctlr.Config.Storage.RootDirectory = rootDir 240 cm := test.NewControllerManager(ctlr) 241 cm.StartAndWait(conf.HTTP.Port) 242 defer cm.StopServer() 243 244 repo := repoName 245 image := CreateRandomImage() 246 247 err := UploadImage(image, baseURL, repo, "tag") 248 So(err, ShouldBeNil) 249 250 // add referrers 251 ref1 := CreateImageWith(). 252 RandomLayers(1, 10). 253 RandomConfig(). 254 Subject(image.DescriptorRef()).Build() 255 256 ref2 := CreateImageWith(). 257 RandomLayers(1, 10). 258 ArtifactConfig(customArtTypeV1). 259 Subject(image.DescriptorRef()).Build() 260 261 ref3 := CreateImageWith(). 262 RandomLayers(1, 10). 263 RandomConfig(). 264 ArtifactType(customArtTypeV2). 265 Subject(image.DescriptorRef()).Build() 266 267 err = UploadImage(ref1, baseURL, repo, ref1.DigestStr()) 268 So(err, ShouldBeNil) 269 270 err = UploadImage(ref2, baseURL, repo, ref2.DigestStr()) 271 So(err, ShouldBeNil) 272 273 err = UploadImage(ref3, baseURL, repo, ref3.DigestStr()) 274 So(err, ShouldBeNil) 275 276 Convey("JSON format", func() { 277 args := []string{"subject", repo + "@" + image.DigestStr(), "--format", "json", "--config", "reftest"} 278 279 configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`, 280 baseURL)) 281 282 defer os.Remove(configPath) 283 284 cmd := client.NewSearchCommand(client.NewSearchService()) 285 286 buff := &bytes.Buffer{} 287 cmd.SetOut(buff) 288 cmd.SetErr(buff) 289 cmd.SetArgs(args) 290 err = cmd.Execute() 291 So(err, ShouldBeNil) 292 fmt.Println(buff.String()) 293 }) 294 Convey("YAML format", func() { 295 args := []string{"subject", repo + "@" + image.DigestStr(), "--format", "yaml", "--config", "reftest"} 296 297 configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`, 298 baseURL)) 299 300 defer os.Remove(configPath) 301 302 cmd := client.NewSearchCommand(client.NewSearchService()) 303 304 buff := &bytes.Buffer{} 305 cmd.SetOut(buff) 306 cmd.SetErr(buff) 307 cmd.SetArgs(args) 308 err = cmd.Execute() 309 So(err, ShouldBeNil) 310 fmt.Println(buff.String()) 311 }) 312 Convey("Invalid format", func() { 313 args := []string{"subject", repo + "@" + image.DigestStr(), "--format", "invalid_format", "--config", "reftest"} 314 315 configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`, 316 baseURL)) 317 318 defer os.Remove(configPath) 319 320 cmd := client.NewSearchCommand(client.NewSearchService()) 321 322 buff := &bytes.Buffer{} 323 cmd.SetOut(buff) 324 cmd.SetErr(buff) 325 cmd.SetArgs(args) 326 err = cmd.Execute() 327 So(err, ShouldNotBeNil) 328 }) 329 }) 330 } 331 332 func TestReferrersCLIErrors(t *testing.T) { 333 Convey("Errors", t, func() { 334 cmd := client.NewSearchCommand(client.NewSearchService()) 335 336 Convey("no url provided", func() { 337 args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "reftest"} 338 339 configPath := makeConfigFile(`{"configs":[{"_name":"reftest","showspinner":false}]}`) 340 341 defer os.Remove(configPath) 342 343 buff := &bytes.Buffer{} 344 cmd.SetOut(buff) 345 cmd.SetErr(buff) 346 cmd.SetArgs(args) 347 err := cmd.Execute() 348 So(err, ShouldNotBeNil) 349 }) 350 351 Convey("getConfigValue", func() { 352 args := []string{"subject", "repo/alpine", "--config", "reftest"} 353 354 configPath := makeConfigFile(`bad-json`) 355 356 defer os.Remove(configPath) 357 358 buff := &bytes.Buffer{} 359 cmd.SetOut(buff) 360 cmd.SetErr(buff) 361 cmd.SetArgs(args) 362 err := cmd.Execute() 363 So(err, ShouldNotBeNil) 364 }) 365 366 Convey("bad showspinnerConfig ", func() { 367 args := []string{"query", "repo", "--config", "reftest"} 368 369 configPath := makeConfigFile(`{"configs":[{"_name":"reftest", "url":"http://127.0.0.1:8080", "showspinner":"bad"}]}`) 370 371 defer os.Remove(configPath) 372 373 buff := &bytes.Buffer{} 374 cmd.SetOut(buff) 375 cmd.SetErr(buff) 376 cmd.SetArgs(args) 377 err := cmd.Execute() 378 So(err, ShouldNotBeNil) 379 }) 380 381 Convey("bad verifyTLSConfig ", func() { 382 args := []string{"query", "repo", "reftest"} 383 384 configPath := makeConfigFile( 385 `{"configs":[{"_name":"reftest", "url":"http://127.0.0.1:8080", "showspinner":false, "verify-tls": "bad"}]}`) 386 387 defer os.Remove(configPath) 388 389 buff := &bytes.Buffer{} 390 cmd.SetOut(buff) 391 cmd.SetErr(buff) 392 cmd.SetArgs(args) 393 err := cmd.Execute() 394 So(err, ShouldNotBeNil) 395 }) 396 397 Convey("url from config is empty", func() { 398 args := []string{"subject", "repo/alpine", "--config", "reftest"} 399 400 configPath := makeConfigFile(`{"configs":[{"_name":"reftest", "url":"", "showspinner":false}]}`) 401 402 defer os.Remove(configPath) 403 404 buff := &bytes.Buffer{} 405 cmd.SetOut(buff) 406 cmd.SetErr(buff) 407 cmd.SetArgs(args) 408 err := cmd.Execute() 409 So(err, ShouldNotBeNil) 410 }) 411 412 Convey("bad params combination", func() { 413 args := []string{"query", "repo", "reftest"} 414 415 configPath := makeConfigFile(`{"configs":[{"_name":"reftest", "url":"http://127.0.0.1:8080", "showspinner":false}]}`) 416 417 defer os.Remove(configPath) 418 419 buff := &bytes.Buffer{} 420 cmd.SetOut(buff) 421 cmd.SetErr(buff) 422 cmd.SetArgs(args) 423 err := cmd.Execute() 424 So(err, ShouldNotBeNil) 425 }) 426 }) 427 } 428 429 func TestSearchCLI(t *testing.T) { 430 Convey("Test GQL", t, func() { 431 rootDir := t.TempDir() 432 433 port := test.GetFreePort() 434 baseURL := test.GetBaseURL(port) 435 conf := config.New() 436 conf.HTTP.Port = port 437 conf.Storage.GC = false 438 defaultVal := true 439 conf.Extensions = &extconf.ExtensionConfig{ 440 Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}}, 441 } 442 ctlr := api.NewController(conf) 443 ctlr.Config.Storage.RootDirectory = rootDir 444 cm := test.NewControllerManager(ctlr) 445 cm.StartAndWait(conf.HTTP.Port) 446 defer cm.StopServer() 447 448 const ( 449 repo1 = "repo" 450 r1tag1 = "repo1tag1" 451 r1tag2 = "repo1tag2" 452 453 repo2 = "repo/alpine" 454 r2tag1 = "repo2tag1" 455 r2tag2 = "repo2tag2" 456 457 repo3 = "repo/test/alpine" 458 r3tag1 = "repo3tag1" 459 r3tag2 = "repo3tag2" 460 ) 461 462 image1 := CreateImageWith(). 463 RandomLayers(1, 10). 464 ImageConfig(ispec.Image{ 465 Created: DefaultTimeRef(), 466 Platform: ispec.Platform{OS: "Os", Architecture: "Arch"}, 467 }). 468 Build() 469 formatterDigest1 := image1.Digest().Encoded()[:8] 470 471 image2 := CreateImageWith(). 472 RandomLayers(1, 10). 473 DefaultConfig(). 474 Build() 475 formatterDigest2 := image2.Digest().Encoded()[:8] 476 477 err := UploadImage(image1, baseURL, repo1, r1tag1) 478 So(err, ShouldBeNil) 479 err = UploadImage(image2, baseURL, repo1, r1tag2) 480 So(err, ShouldBeNil) 481 482 err = UploadImage(image1, baseURL, repo2, r2tag1) 483 So(err, ShouldBeNil) 484 err = UploadImage(image2, baseURL, repo2, r2tag2) 485 So(err, ShouldBeNil) 486 487 err = UploadImage(image1, baseURL, repo3, r3tag1) 488 So(err, ShouldBeNil) 489 err = UploadImage(image2, baseURL, repo3, r3tag2) 490 So(err, ShouldBeNil) 491 492 // search by repos 493 494 args := []string{"query", "test/alpin", "--verbose", "--config", "searchtest"} 495 496 configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`, 497 baseURL)) 498 defer os.Remove(configPath) 499 500 cmd := client.NewSearchCommand(client.NewSearchService()) 501 502 buff := &bytes.Buffer{} 503 cmd.SetOut(buff) 504 cmd.SetErr(buff) 505 cmd.SetArgs(args) 506 err = cmd.Execute() 507 So(err, ShouldBeNil) 508 space := regexp.MustCompile(`\s+`) 509 str := strings.TrimSpace(space.ReplaceAllString(buff.String(), " ")) 510 So(str, ShouldContainSubstring, "NAME SIZE LAST UPDATED DOWNLOADS STARS PLATFORMS") 511 So(str, ShouldContainSubstring, "repo/test/alpine 1.1kB 2010-01-01 01:01:01 +0000 UTC 0 0") 512 So(str, ShouldContainSubstring, "Os/Arch") 513 So(str, ShouldContainSubstring, "linux/amd64") 514 515 fmt.Println("\n", buff.String()) 516 517 os.Remove(configPath) 518 519 cmd = client.NewSearchCommand(client.NewSearchService()) 520 521 args = []string{"query", "repo/alpine:", "--config", "searchtest"} 522 523 configPath = makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`, 524 baseURL)) 525 526 defer os.Remove(configPath) 527 528 buff = &bytes.Buffer{} 529 cmd.SetOut(buff) 530 cmd.SetErr(buff) 531 cmd.SetArgs(args) 532 err = cmd.Execute() 533 So(err, ShouldBeNil) 534 str = strings.TrimSpace(space.ReplaceAllString(buff.String(), " ")) 535 So(str, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") 536 So(str, ShouldContainSubstring, "repo/alpine repo2tag1 Os/Arch "+formatterDigest1+" false 525B") 537 So(str, ShouldContainSubstring, "repo/alpine repo2tag2 linux/amd64 "+formatterDigest2+" false 552B") 538 539 fmt.Println("\n", buff.String()) 540 }) 541 } 542 543 func TestFormatsSearchCLI(t *testing.T) { 544 Convey("", t, func() { 545 rootDir := t.TempDir() 546 547 port := test.GetFreePort() 548 baseURL := test.GetBaseURL(port) 549 conf := config.New() 550 conf.HTTP.Port = port 551 conf.Storage.GC = false 552 defaultVal := true 553 conf.Extensions = &extconf.ExtensionConfig{ 554 Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}}, 555 } 556 ctlr := api.NewController(conf) 557 ctlr.Config.Storage.RootDirectory = rootDir 558 cm := test.NewControllerManager(ctlr) 559 cm.StartAndWait(conf.HTTP.Port) 560 defer cm.StopServer() 561 562 const ( 563 repo1 = "repo" 564 r1tag1 = "repo1tag1" 565 r1tag2 = "repo1tag2" 566 567 repo2 = "repo/alpine" 568 r2tag1 = "repo2tag1" 569 r2tag2 = "repo2tag2" 570 571 repo3 = "repo/test/alpine" 572 r3tag1 = "repo3tag1" 573 r3tag2 = "repo3tag2" 574 ) 575 576 image1 := CreateImageWith().RandomLayers(1, 10).DefaultConfig().Build() 577 image2 := CreateImageWith().RandomLayers(1, 10).DefaultConfig().Build() 578 579 err := UploadImage(image1, baseURL, repo1, r1tag1) 580 So(err, ShouldBeNil) 581 err = UploadImage(image2, baseURL, repo1, r1tag2) 582 So(err, ShouldBeNil) 583 584 err = UploadImage(image1, baseURL, repo2, r2tag1) 585 So(err, ShouldBeNil) 586 err = UploadImage(image2, baseURL, repo2, r2tag2) 587 So(err, ShouldBeNil) 588 589 err = UploadImage(image1, baseURL, repo3, r3tag1) 590 So(err, ShouldBeNil) 591 err = UploadImage(image2, baseURL, repo3, r3tag2) 592 So(err, ShouldBeNil) 593 594 cmd := client.NewSearchCommand(client.NewSearchService()) 595 596 Convey("JSON format", func() { 597 args := []string{"query", "repo/alpine", "--format", "json", "--config", "searchtest"} 598 599 configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`, 600 baseURL)) 601 602 defer os.Remove(configPath) 603 604 buff := &bytes.Buffer{} 605 cmd.SetOut(buff) 606 cmd.SetErr(buff) 607 cmd.SetArgs(args) 608 err = cmd.Execute() 609 So(err, ShouldBeNil) 610 fmt.Println(buff.String()) 611 }) 612 613 Convey("YAML format", func() { 614 args := []string{"query", "repo/alpine", "--format", "yaml", "--config", "searchtest"} 615 616 configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`, 617 baseURL)) 618 619 defer os.Remove(configPath) 620 621 buff := &bytes.Buffer{} 622 cmd.SetOut(buff) 623 cmd.SetErr(buff) 624 cmd.SetArgs(args) 625 err = cmd.Execute() 626 So(err, ShouldBeNil) 627 fmt.Println(buff.String()) 628 }) 629 630 Convey("Invalid format", func() { 631 args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"} 632 633 configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`, 634 baseURL)) 635 636 defer os.Remove(configPath) 637 638 buff := &bytes.Buffer{} 639 cmd.SetOut(buff) 640 cmd.SetErr(buff) 641 cmd.SetArgs(args) 642 err = cmd.Execute() 643 So(err, ShouldNotBeNil) 644 }) 645 }) 646 } 647 648 func TestSearchCLIErrors(t *testing.T) { 649 Convey("Errors", t, func() { 650 cmd := client.NewSearchCommand(client.NewSearchService()) 651 652 Convey("no url provided", func() { 653 args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"} 654 655 configPath := makeConfigFile(`{"configs":[{"_name":"searchtest","showspinner":false}]}`) 656 657 defer os.Remove(configPath) 658 659 buff := &bytes.Buffer{} 660 cmd.SetOut(buff) 661 cmd.SetErr(buff) 662 cmd.SetArgs(args) 663 err := cmd.Execute() 664 So(err, ShouldNotBeNil) 665 }) 666 667 Convey("getConfigValue", func() { 668 args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"} 669 670 configPath := makeConfigFile(`bad-json`) 671 672 defer os.Remove(configPath) 673 674 buff := &bytes.Buffer{} 675 cmd.SetOut(buff) 676 cmd.SetErr(buff) 677 cmd.SetArgs(args) 678 err := cmd.Execute() 679 So(err, ShouldNotBeNil) 680 }) 681 682 Convey("bad showspinnerConfig ", func() { 683 args := []string{"query", "repo/alpine", "--config", "searchtest"} 684 685 configPath := makeConfigFile( 686 `{"configs":[{"_name":"searchtest", "url":"http://127.0.0.1:8080", "showspinner":"bad"}]}`) 687 688 defer os.Remove(configPath) 689 690 buff := &bytes.Buffer{} 691 cmd.SetOut(buff) 692 cmd.SetErr(buff) 693 cmd.SetArgs(args) 694 err := cmd.Execute() 695 So(err, ShouldNotBeNil) 696 }) 697 698 Convey("bad verifyTLSConfig ", func() { 699 args := []string{"query", "repo/alpine", "--config", "searchtest"} 700 701 configPath := makeConfigFile( 702 `{"configs":[{"_name":"searchtest", "url":"http://127.0.0.1:8080", "showspinner":false, "verify-tls": "bad"}]}`) 703 704 defer os.Remove(configPath) 705 706 buff := &bytes.Buffer{} 707 cmd.SetOut(buff) 708 cmd.SetErr(buff) 709 cmd.SetArgs(args) 710 err := cmd.Execute() 711 So(err, ShouldNotBeNil) 712 }) 713 714 Convey("url from config is empty", func() { 715 args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"} 716 717 configPath := makeConfigFile(`{"configs":[{"_name":"searchtest", "url":"", "showspinner":false}]}`) 718 719 defer os.Remove(configPath) 720 721 buff := &bytes.Buffer{} 722 cmd.SetOut(buff) 723 cmd.SetErr(buff) 724 cmd.SetArgs(args) 725 err := cmd.Execute() 726 So(err, ShouldNotBeNil) 727 }) 728 }) 729 } 730 731 func TestSearchSort(t *testing.T) { 732 rootDir := t.TempDir() 733 port := test.GetFreePort() 734 baseURL := test.GetBaseURL(port) 735 conf := config.New() 736 conf.HTTP.Port = port 737 738 defaultVal := true 739 conf.Extensions = &extconf.ExtensionConfig{ 740 Search: &extconf.SearchConfig{ 741 BaseConfig: extconf.BaseConfig{Enable: &defaultVal}, 742 CVE: nil, 743 }, 744 } 745 ctlr := api.NewController(conf) 746 ctlr.Config.Storage.RootDirectory = rootDir 747 748 image1 := CreateImageWith().DefaultLayers(). 749 ImageConfig(ispec.Image{Created: DateRef(2010, 1, 1, 1, 1, 1, 0, time.UTC)}). 750 Build() 751 752 image2 := CreateImageWith().DefaultLayers(). 753 ImageConfig(ispec.Image{Created: DateRef(2020, 1, 1, 1, 1, 1, 0, time.UTC)}). 754 Build() 755 756 storeController := ociutils.GetDefaultStoreController(rootDir, ctlr.Log) 757 758 err := WriteImageToFileSystem(image1, "b-repo", "tag2", storeController) 759 if err != nil { 760 t.FailNow() 761 } 762 763 err = WriteImageToFileSystem(image2, "a-test-repo", "tag2", storeController) 764 if err != nil { 765 t.FailNow() 766 } 767 768 cm := test.NewControllerManager(ctlr) 769 cm.StartAndWait(conf.HTTP.Port) 770 771 defer cm.StopServer() 772 773 Convey("test sorting", t, func() { 774 args := []string{"query", "repo", "--sort-by", "relevance", "--url", baseURL} 775 cmd := client.NewSearchCommand(client.NewSearchService()) 776 buff := bytes.NewBufferString("") 777 cmd.SetOut(buff) 778 cmd.SetErr(buff) 779 cmd.SetArgs(args) 780 err := cmd.Execute() 781 So(err, ShouldBeNil) 782 str := buff.String() 783 So(strings.Index(str, "b-repo"), ShouldBeLessThan, strings.Index(str, "a-test-repo")) 784 785 args = []string{"query", "repo", "--sort-by", "alpha-asc", "--url", baseURL} 786 cmd = client.NewSearchCommand(client.NewSearchService()) 787 buff = bytes.NewBufferString("") 788 cmd.SetOut(buff) 789 cmd.SetErr(buff) 790 cmd.SetArgs(args) 791 err = cmd.Execute() 792 So(err, ShouldBeNil) 793 str = buff.String() 794 So(strings.Index(str, "a-test-repo"), ShouldBeLessThan, strings.Index(str, "b-repo")) 795 }) 796 }