2014-04-27 22:06:09 +00:00
|
|
|
package registry
|
|
|
|
|
|
|
|
import (
|
2014-07-24 22:19:50 +00:00
|
|
|
"github.com/docker/docker/engine"
|
2014-04-27 22:06:09 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Service exposes registry capabilities in the standard Engine
|
|
|
|
// interface. Once installed, it extends the engine with the
|
|
|
|
// following calls:
|
|
|
|
//
|
|
|
|
// 'auth': Authenticate against the public registry
|
2014-04-27 22:21:42 +00:00
|
|
|
// 'search': Search for images on the public registry
|
2014-04-27 22:06:09 +00:00
|
|
|
// 'pull': Download images from any registry (TODO)
|
|
|
|
// 'push': Upload images to any registry (TODO)
|
|
|
|
type Service struct {
|
2014-08-20 15:31:24 +00:00
|
|
|
insecureRegistries []string
|
2014-04-27 22:06:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewService returns a new instance of Service ready to be
|
|
|
|
// installed no an engine.
|
2014-08-20 15:31:24 +00:00
|
|
|
func NewService(insecureRegistries []string) *Service {
|
|
|
|
return &Service{
|
|
|
|
insecureRegistries: insecureRegistries,
|
|
|
|
}
|
2014-04-27 22:06:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Install installs registry capabilities to eng.
|
|
|
|
func (s *Service) Install(eng *engine.Engine) error {
|
|
|
|
eng.Register("auth", s.Auth)
|
2014-04-27 22:21:42 +00:00
|
|
|
eng.Register("search", s.Search)
|
2014-04-27 22:06:09 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Auth contacts the public registry with the provided credentials,
|
|
|
|
// and returns OK if authentication was sucessful.
|
|
|
|
// It can be used to verify the validity of a client's credentials.
|
|
|
|
func (s *Service) Auth(job *engine.Job) engine.Status {
|
2014-08-20 15:31:24 +00:00
|
|
|
var authConfig = new(AuthConfig)
|
2014-04-27 22:06:09 +00:00
|
|
|
|
|
|
|
job.GetenvJson("authConfig", authConfig)
|
2014-08-20 15:31:24 +00:00
|
|
|
|
2014-04-27 22:06:09 +00:00
|
|
|
if addr := authConfig.ServerAddress; addr != "" && addr != IndexServerAddress() {
|
2014-08-20 15:31:24 +00:00
|
|
|
endpoint, err := NewEndpoint(addr, IsSecure(addr, s.insecureRegistries))
|
2014-04-27 22:06:09 +00:00
|
|
|
if err != nil {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
2014-08-26 23:21:04 +00:00
|
|
|
if _, err := endpoint.Ping(); err != nil {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
|
|
|
authConfig.ServerAddress = endpoint.String()
|
2014-04-27 22:06:09 +00:00
|
|
|
}
|
2014-08-20 15:31:24 +00:00
|
|
|
|
|
|
|
if _, err := Login(authConfig, HTTPRequestFactory(nil)); err != nil {
|
2014-04-27 22:06:09 +00:00
|
|
|
return job.Error(err)
|
|
|
|
}
|
2014-08-20 15:31:24 +00:00
|
|
|
|
2014-04-27 22:06:09 +00:00
|
|
|
return engine.StatusOK
|
|
|
|
}
|
2014-04-27 22:21:42 +00:00
|
|
|
|
|
|
|
// Search queries the public registry for images matching the specified
|
|
|
|
// search terms, and returns the results.
|
|
|
|
//
|
|
|
|
// Argument syntax: search TERM
|
|
|
|
//
|
|
|
|
// Option environment:
|
|
|
|
// 'authConfig': json-encoded credentials to authenticate against the registry.
|
|
|
|
// The search extends to images only accessible via the credentials.
|
|
|
|
//
|
|
|
|
// 'metaHeaders': extra HTTP headers to include in the request to the registry.
|
|
|
|
// The headers should be passed as a json-encoded dictionary.
|
|
|
|
//
|
|
|
|
// Output:
|
|
|
|
// Results are sent as a collection of structured messages (using engine.Table).
|
|
|
|
// Each result is sent as a separate message.
|
|
|
|
// Results are ordered by number of stars on the public registry.
|
|
|
|
func (s *Service) Search(job *engine.Job) engine.Status {
|
|
|
|
if n := len(job.Args); n != 1 {
|
|
|
|
return job.Errorf("Usage: %s TERM", job.Name)
|
|
|
|
}
|
|
|
|
var (
|
|
|
|
term = job.Args[0]
|
|
|
|
metaHeaders = map[string][]string{}
|
|
|
|
authConfig = &AuthConfig{}
|
|
|
|
)
|
|
|
|
job.GetenvJson("authConfig", authConfig)
|
|
|
|
job.GetenvJson("metaHeaders", metaHeaders)
|
|
|
|
|
2014-08-09 07:16:54 +00:00
|
|
|
hostname, term, err := ResolveRepositoryName(term)
|
|
|
|
if err != nil {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
2014-10-11 03:22:12 +00:00
|
|
|
|
|
|
|
secure := IsSecure(hostname, s.insecureRegistries)
|
|
|
|
|
|
|
|
endpoint, err := NewEndpoint(hostname, secure)
|
2014-08-09 07:16:54 +00:00
|
|
|
if err != nil {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
2014-08-26 23:21:04 +00:00
|
|
|
r, err := NewSession(authConfig, HTTPRequestFactory(metaHeaders), endpoint, true)
|
2014-04-27 22:21:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
|
|
|
results, err := r.SearchRepositories(term)
|
|
|
|
if err != nil {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
|
|
|
outs := engine.NewTable("star_count", 0)
|
|
|
|
for _, result := range results.Results {
|
|
|
|
out := &engine.Env{}
|
|
|
|
out.Import(result)
|
|
|
|
outs.Add(out)
|
|
|
|
}
|
|
|
|
outs.ReverseSort()
|
|
|
|
if _, err := outs.WriteListTo(job.Stdout); err != nil {
|
|
|
|
return job.Error(err)
|
|
|
|
}
|
|
|
|
return engine.StatusOK
|
|
|
|
}
|