This continues the effort to separate all registry logic from the
deprecated `Server` object.
* 'search' is exposed by `github.com/dotcloud/docker/registry/Service`
* Added proper documentation of Search while I was at it
Docker-DCO-1.1-Signed-off-by: Solomon Hykes <solomon@docker.com> (github: shykes)
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
// following calls: |
| 10 | 10 |
// |
| 11 | 11 |
// 'auth': Authenticate against the public registry |
| 12 |
-// 'search': Search for images on the public registry (TODO) |
|
| 12 |
+// 'search': Search for images on the public registry |
|
| 13 | 13 |
// 'pull': Download images from any registry (TODO) |
| 14 | 14 |
// 'push': Upload images to any registry (TODO) |
| 15 | 15 |
type Service struct {
|
| ... | ... |
@@ -24,6 +24,7 @@ func NewService() *Service {
|
| 24 | 24 |
// Install installs registry capabilities to eng. |
| 25 | 25 |
func (s *Service) Install(eng *engine.Engine) error {
|
| 26 | 26 |
eng.Register("auth", s.Auth)
|
| 27 |
+ eng.Register("search", s.Search)
|
|
| 27 | 28 |
return nil |
| 28 | 29 |
} |
| 29 | 30 |
|
| ... | ... |
@@ -52,3 +53,52 @@ func (s *Service) Auth(job *engine.Job) engine.Status {
|
| 52 | 52 |
job.Printf("%s\n", status)
|
| 53 | 53 |
return engine.StatusOK |
| 54 | 54 |
} |
| 55 |
+ |
|
| 56 |
+// Search queries the public registry for images matching the specified |
|
| 57 |
+// search terms, and returns the results. |
|
| 58 |
+// |
|
| 59 |
+// Argument syntax: search TERM |
|
| 60 |
+// |
|
| 61 |
+// Option environment: |
|
| 62 |
+// 'authConfig': json-encoded credentials to authenticate against the registry. |
|
| 63 |
+// The search extends to images only accessible via the credentials. |
|
| 64 |
+// |
|
| 65 |
+// 'metaHeaders': extra HTTP headers to include in the request to the registry. |
|
| 66 |
+// The headers should be passed as a json-encoded dictionary. |
|
| 67 |
+// |
|
| 68 |
+// Output: |
|
| 69 |
+// Results are sent as a collection of structured messages (using engine.Table). |
|
| 70 |
+// Each result is sent as a separate message. |
|
| 71 |
+// Results are ordered by number of stars on the public registry. |
|
| 72 |
+func (s *Service) Search(job *engine.Job) engine.Status {
|
|
| 73 |
+ if n := len(job.Args); n != 1 {
|
|
| 74 |
+ return job.Errorf("Usage: %s TERM", job.Name)
|
|
| 75 |
+ } |
|
| 76 |
+ var ( |
|
| 77 |
+ term = job.Args[0] |
|
| 78 |
+ metaHeaders = map[string][]string{}
|
|
| 79 |
+ authConfig = &AuthConfig{}
|
|
| 80 |
+ ) |
|
| 81 |
+ job.GetenvJson("authConfig", authConfig)
|
|
| 82 |
+ job.GetenvJson("metaHeaders", metaHeaders)
|
|
| 83 |
+ |
|
| 84 |
+ r, err := NewRegistry(authConfig, HTTPRequestFactory(metaHeaders), IndexServerAddress()) |
|
| 85 |
+ if err != nil {
|
|
| 86 |
+ return job.Error(err) |
|
| 87 |
+ } |
|
| 88 |
+ results, err := r.SearchRepositories(term) |
|
| 89 |
+ if err != nil {
|
|
| 90 |
+ return job.Error(err) |
|
| 91 |
+ } |
|
| 92 |
+ outs := engine.NewTable("star_count", 0)
|
|
| 93 |
+ for _, result := range results.Results {
|
|
| 94 |
+ out := &engine.Env{}
|
|
| 95 |
+ out.Import(result) |
|
| 96 |
+ outs.Add(out) |
|
| 97 |
+ } |
|
| 98 |
+ outs.ReverseSort() |
|
| 99 |
+ if _, err := outs.WriteListTo(job.Stdout); err != nil {
|
|
| 100 |
+ return job.Error(err) |
|
| 101 |
+ } |
|
| 102 |
+ return engine.StatusOK |
|
| 103 |
+} |
| ... | ... |
@@ -126,7 +126,6 @@ func InitServer(job *engine.Job) engine.Status {
|
| 126 | 126 |
"insert": srv.ImageInsert, |
| 127 | 127 |
"attach": srv.ContainerAttach, |
| 128 | 128 |
"logs": srv.ContainerLogs, |
| 129 |
- "search": srv.ImagesSearch, |
|
| 130 | 129 |
"changes": srv.ContainerChanges, |
| 131 | 130 |
"top": srv.ContainerTop, |
| 132 | 131 |
"version": srv.DockerVersion, |
| ... | ... |
@@ -600,39 +599,6 @@ func (srv *Server) recursiveLoad(address, tmpImageDir string) error {
|
| 600 | 600 |
return nil |
| 601 | 601 |
} |
| 602 | 602 |
|
| 603 |
-func (srv *Server) ImagesSearch(job *engine.Job) engine.Status {
|
|
| 604 |
- if n := len(job.Args); n != 1 {
|
|
| 605 |
- return job.Errorf("Usage: %s TERM", job.Name)
|
|
| 606 |
- } |
|
| 607 |
- var ( |
|
| 608 |
- term = job.Args[0] |
|
| 609 |
- metaHeaders = map[string][]string{}
|
|
| 610 |
- authConfig = ®istry.AuthConfig{}
|
|
| 611 |
- ) |
|
| 612 |
- job.GetenvJson("authConfig", authConfig)
|
|
| 613 |
- job.GetenvJson("metaHeaders", metaHeaders)
|
|
| 614 |
- |
|
| 615 |
- r, err := registry.NewRegistry(authConfig, registry.HTTPRequestFactory(metaHeaders), registry.IndexServerAddress()) |
|
| 616 |
- if err != nil {
|
|
| 617 |
- return job.Error(err) |
|
| 618 |
- } |
|
| 619 |
- results, err := r.SearchRepositories(term) |
|
| 620 |
- if err != nil {
|
|
| 621 |
- return job.Error(err) |
|
| 622 |
- } |
|
| 623 |
- outs := engine.NewTable("star_count", 0)
|
|
| 624 |
- for _, result := range results.Results {
|
|
| 625 |
- out := &engine.Env{}
|
|
| 626 |
- out.Import(result) |
|
| 627 |
- outs.Add(out) |
|
| 628 |
- } |
|
| 629 |
- outs.ReverseSort() |
|
| 630 |
- if _, err := outs.WriteListTo(job.Stdout); err != nil {
|
|
| 631 |
- return job.Error(err) |
|
| 632 |
- } |
|
| 633 |
- return engine.StatusOK |
|
| 634 |
-} |
|
| 635 |
- |
|
| 636 | 603 |
// FIXME: 'insert' is deprecated and should be removed in a future version. |
| 637 | 604 |
func (srv *Server) ImageInsert(job *engine.Job) engine.Status {
|
| 638 | 605 |
fmt.Fprintf(job.Stderr, "Warning: '%s' is deprecated and will be removed in a future version. Please use 'build' and 'ADD' instead.\n", job.Name) |