github.com/darren-clark/docker@v1.5.0/registry/service.go (about) 1 package registry 2 3 import ( 4 log "github.com/Sirupsen/logrus" 5 "github.com/docker/docker/engine" 6 ) 7 8 // Service exposes registry capabilities in the standard Engine 9 // interface. Once installed, it extends the engine with the 10 // following calls: 11 // 12 // 'auth': Authenticate against the public registry 13 // 'search': Search for images on the public registry 14 // 'pull': Download images from any registry (TODO) 15 // 'push': Upload images to any registry (TODO) 16 type Service struct { 17 Config *ServiceConfig 18 } 19 20 // NewService returns a new instance of Service ready to be 21 // installed no an engine. 22 func NewService(options *Options) *Service { 23 return &Service{ 24 Config: NewServiceConfig(options), 25 } 26 } 27 28 // Install installs registry capabilities to eng. 29 func (s *Service) Install(eng *engine.Engine) error { 30 eng.Register("auth", s.Auth) 31 eng.Register("search", s.Search) 32 eng.Register("resolve_repository", s.ResolveRepository) 33 eng.Register("resolve_index", s.ResolveIndex) 34 eng.Register("registry_config", s.GetRegistryConfig) 35 return nil 36 } 37 38 // Auth contacts the public registry with the provided credentials, 39 // and returns OK if authentication was sucessful. 40 // It can be used to verify the validity of a client's credentials. 41 func (s *Service) Auth(job *engine.Job) engine.Status { 42 var ( 43 authConfig = new(AuthConfig) 44 endpoint *Endpoint 45 index *IndexInfo 46 status string 47 err error 48 ) 49 50 job.GetenvJson("authConfig", authConfig) 51 52 addr := authConfig.ServerAddress 53 if addr == "" { 54 // Use the official registry address if not specified. 55 addr = IndexServerAddress() 56 } 57 58 if index, err = ResolveIndexInfo(job, addr); err != nil { 59 return job.Error(err) 60 } 61 62 if endpoint, err = NewEndpoint(index); err != nil { 63 log.Errorf("unable to get new registry endpoint: %s", err) 64 return job.Error(err) 65 } 66 67 authConfig.ServerAddress = endpoint.String() 68 69 if status, err = Login(authConfig, endpoint, HTTPRequestFactory(nil)); err != nil { 70 log.Errorf("unable to login against registry endpoint %s: %s", endpoint, err) 71 return job.Error(err) 72 } 73 74 log.Infof("successful registry login for endpoint %s: %s", endpoint, status) 75 job.Printf("%s\n", status) 76 77 return engine.StatusOK 78 } 79 80 // Search queries the public registry for images matching the specified 81 // search terms, and returns the results. 82 // 83 // Argument syntax: search TERM 84 // 85 // Option environment: 86 // 'authConfig': json-encoded credentials to authenticate against the registry. 87 // The search extends to images only accessible via the credentials. 88 // 89 // 'metaHeaders': extra HTTP headers to include in the request to the registry. 90 // The headers should be passed as a json-encoded dictionary. 91 // 92 // Output: 93 // Results are sent as a collection of structured messages (using engine.Table). 94 // Each result is sent as a separate message. 95 // Results are ordered by number of stars on the public registry. 96 func (s *Service) Search(job *engine.Job) engine.Status { 97 if n := len(job.Args); n != 1 { 98 return job.Errorf("Usage: %s TERM", job.Name) 99 } 100 var ( 101 term = job.Args[0] 102 metaHeaders = map[string][]string{} 103 authConfig = &AuthConfig{} 104 ) 105 job.GetenvJson("authConfig", authConfig) 106 job.GetenvJson("metaHeaders", metaHeaders) 107 108 repoInfo, err := ResolveRepositoryInfo(job, term) 109 if err != nil { 110 return job.Error(err) 111 } 112 // *TODO: Search multiple indexes. 113 endpoint, err := repoInfo.GetEndpoint() 114 if err != nil { 115 return job.Error(err) 116 } 117 r, err := NewSession(authConfig, HTTPRequestFactory(metaHeaders), endpoint, true) 118 if err != nil { 119 return job.Error(err) 120 } 121 results, err := r.SearchRepositories(repoInfo.GetSearchTerm()) 122 if err != nil { 123 return job.Error(err) 124 } 125 outs := engine.NewTable("star_count", 0) 126 for _, result := range results.Results { 127 out := &engine.Env{} 128 out.Import(result) 129 outs.Add(out) 130 } 131 outs.ReverseSort() 132 if _, err := outs.WriteListTo(job.Stdout); err != nil { 133 return job.Error(err) 134 } 135 return engine.StatusOK 136 } 137 138 // ResolveRepository splits a repository name into its components 139 // and configuration of the associated registry. 140 func (s *Service) ResolveRepository(job *engine.Job) engine.Status { 141 var ( 142 reposName = job.Args[0] 143 ) 144 145 repoInfo, err := s.Config.NewRepositoryInfo(reposName) 146 if err != nil { 147 return job.Error(err) 148 } 149 150 out := engine.Env{} 151 err = out.SetJson("repository", repoInfo) 152 if err != nil { 153 return job.Error(err) 154 } 155 out.WriteTo(job.Stdout) 156 157 return engine.StatusOK 158 } 159 160 // Convenience wrapper for calling resolve_repository Job from a running job. 161 func ResolveRepositoryInfo(jobContext *engine.Job, reposName string) (*RepositoryInfo, error) { 162 job := jobContext.Eng.Job("resolve_repository", reposName) 163 env, err := job.Stdout.AddEnv() 164 if err != nil { 165 return nil, err 166 } 167 if err := job.Run(); err != nil { 168 return nil, err 169 } 170 info := RepositoryInfo{} 171 if err := env.GetJson("repository", &info); err != nil { 172 return nil, err 173 } 174 return &info, nil 175 } 176 177 // ResolveIndex takes indexName and returns index info 178 func (s *Service) ResolveIndex(job *engine.Job) engine.Status { 179 var ( 180 indexName = job.Args[0] 181 ) 182 183 index, err := s.Config.NewIndexInfo(indexName) 184 if err != nil { 185 return job.Error(err) 186 } 187 188 out := engine.Env{} 189 err = out.SetJson("index", index) 190 if err != nil { 191 return job.Error(err) 192 } 193 out.WriteTo(job.Stdout) 194 195 return engine.StatusOK 196 } 197 198 // Convenience wrapper for calling resolve_index Job from a running job. 199 func ResolveIndexInfo(jobContext *engine.Job, indexName string) (*IndexInfo, error) { 200 job := jobContext.Eng.Job("resolve_index", indexName) 201 env, err := job.Stdout.AddEnv() 202 if err != nil { 203 return nil, err 204 } 205 if err := job.Run(); err != nil { 206 return nil, err 207 } 208 info := IndexInfo{} 209 if err := env.GetJson("index", &info); err != nil { 210 return nil, err 211 } 212 return &info, nil 213 } 214 215 // GetRegistryConfig returns current registry configuration. 216 func (s *Service) GetRegistryConfig(job *engine.Job) engine.Status { 217 out := engine.Env{} 218 err := out.SetJson("config", s.Config) 219 if err != nil { 220 return job.Error(err) 221 } 222 out.WriteTo(job.Stdout) 223 224 return engine.StatusOK 225 }