This is the first step towards separating the registry subsystem from
the deprecated `Server` object.
* New service `github.com/dotcloud/docker/registry/Service`
* The service is installed by default in `builtins`
* The service only exposes `auth` for now...
* ...Soon to be followed by `pull`, `push` and `search`.
Docker-DCO-1.1-Signed-off-by: Solomon Hykes <solomon@docker.com> (github: shykes)
| ... | ... |
@@ -4,12 +4,16 @@ import ( |
| 4 | 4 |
api "github.com/dotcloud/docker/api/server" |
| 5 | 5 |
"github.com/dotcloud/docker/daemon/networkdriver/bridge" |
| 6 | 6 |
"github.com/dotcloud/docker/engine" |
| 7 |
+ "github.com/dotcloud/docker/registry" |
|
| 7 | 8 |
"github.com/dotcloud/docker/server" |
| 8 | 9 |
) |
| 9 | 10 |
|
| 10 | 11 |
func Register(eng *engine.Engine) {
|
| 11 | 12 |
daemon(eng) |
| 12 | 13 |
remote(eng) |
| 14 |
+ // FIXME: engine.Installer.Install can fail. These errors |
|
| 15 |
+ // should be passed up. |
|
| 16 |
+ registry.NewService().Install(eng) |
|
| 13 | 17 |
} |
| 14 | 18 |
|
| 15 | 19 |
// remote: a RESTful api for cross-docker communication |
| ... | ... |
@@ -13,10 +13,12 @@ import ( |
| 13 | 13 |
"net/http/cookiejar" |
| 14 | 14 |
"net/url" |
| 15 | 15 |
"regexp" |
| 16 |
+ "runtime" |
|
| 16 | 17 |
"strconv" |
| 17 | 18 |
"strings" |
| 18 | 19 |
"time" |
| 19 | 20 |
|
| 21 |
+ "github.com/dotcloud/docker/dockerversion" |
|
| 20 | 22 |
"github.com/dotcloud/docker/utils" |
| 21 | 23 |
) |
| 22 | 24 |
|
| ... | ... |
@@ -757,3 +759,40 @@ func NewRegistry(authConfig *AuthConfig, factory *utils.HTTPRequestFactory, inde |
| 757 | 757 |
r.reqFactory = factory |
| 758 | 758 |
return r, nil |
| 759 | 759 |
} |
| 760 |
+ |
|
| 761 |
+func HTTPRequestFactory(metaHeaders map[string][]string) *utils.HTTPRequestFactory {
|
|
| 762 |
+ // FIXME: this replicates the 'info' job. |
|
| 763 |
+ httpVersion := make([]utils.VersionInfo, 0, 4) |
|
| 764 |
+ httpVersion = append(httpVersion, &simpleVersionInfo{"docker", dockerversion.VERSION})
|
|
| 765 |
+ httpVersion = append(httpVersion, &simpleVersionInfo{"go", runtime.Version()})
|
|
| 766 |
+ httpVersion = append(httpVersion, &simpleVersionInfo{"git-commit", dockerversion.GITCOMMIT})
|
|
| 767 |
+ if kernelVersion, err := utils.GetKernelVersion(); err == nil {
|
|
| 768 |
+ httpVersion = append(httpVersion, &simpleVersionInfo{"kernel", kernelVersion.String()})
|
|
| 769 |
+ } |
|
| 770 |
+ httpVersion = append(httpVersion, &simpleVersionInfo{"os", runtime.GOOS})
|
|
| 771 |
+ httpVersion = append(httpVersion, &simpleVersionInfo{"arch", runtime.GOARCH})
|
|
| 772 |
+ ud := utils.NewHTTPUserAgentDecorator(httpVersion...) |
|
| 773 |
+ md := &utils.HTTPMetaHeadersDecorator{
|
|
| 774 |
+ Headers: metaHeaders, |
|
| 775 |
+ } |
|
| 776 |
+ factory := utils.NewHTTPRequestFactory(ud, md) |
|
| 777 |
+ return factory |
|
| 778 |
+} |
|
| 779 |
+ |
|
| 780 |
+// simpleVersionInfo is a simple implementation of |
|
| 781 |
+// the interface VersionInfo, which is used |
|
| 782 |
+// to provide version information for some product, |
|
| 783 |
+// component, etc. It stores the product name and the version |
|
| 784 |
+// in string and returns them on calls to Name() and Version(). |
|
| 785 |
+type simpleVersionInfo struct {
|
|
| 786 |
+ name string |
|
| 787 |
+ version string |
|
| 788 |
+} |
|
| 789 |
+ |
|
| 790 |
+func (v *simpleVersionInfo) Name() string {
|
|
| 791 |
+ return v.name |
|
| 792 |
+} |
|
| 793 |
+ |
|
| 794 |
+func (v *simpleVersionInfo) Version() string {
|
|
| 795 |
+ return v.version |
|
| 796 |
+} |
| 760 | 797 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,54 @@ |
| 0 |
+package registry |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/dotcloud/docker/engine" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+// Service exposes registry capabilities in the standard Engine |
|
| 7 |
+// interface. Once installed, it extends the engine with the |
|
| 8 |
+// following calls: |
|
| 9 |
+// |
|
| 10 |
+// 'auth': Authenticate against the public registry |
|
| 11 |
+// 'search': Search for images on the public registry (TODO) |
|
| 12 |
+// 'pull': Download images from any registry (TODO) |
|
| 13 |
+// 'push': Upload images to any registry (TODO) |
|
| 14 |
+type Service struct {
|
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+// NewService returns a new instance of Service ready to be |
|
| 18 |
+// installed no an engine. |
|
| 19 |
+func NewService() *Service {
|
|
| 20 |
+ return &Service{}
|
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+// Install installs registry capabilities to eng. |
|
| 24 |
+func (s *Service) Install(eng *engine.Engine) error {
|
|
| 25 |
+ eng.Register("auth", s.Auth)
|
|
| 26 |
+ return nil |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+// Auth contacts the public registry with the provided credentials, |
|
| 30 |
+// and returns OK if authentication was sucessful. |
|
| 31 |
+// It can be used to verify the validity of a client's credentials. |
|
| 32 |
+func (s *Service) Auth(job *engine.Job) engine.Status {
|
|
| 33 |
+ var ( |
|
| 34 |
+ err error |
|
| 35 |
+ authConfig = &AuthConfig{}
|
|
| 36 |
+ ) |
|
| 37 |
+ |
|
| 38 |
+ job.GetenvJson("authConfig", authConfig)
|
|
| 39 |
+ // TODO: this is only done here because auth and registry need to be merged into one pkg |
|
| 40 |
+ if addr := authConfig.ServerAddress; addr != "" && addr != IndexServerAddress() {
|
|
| 41 |
+ addr, err = ExpandAndVerifyRegistryUrl(addr) |
|
| 42 |
+ if err != nil {
|
|
| 43 |
+ return job.Error(err) |
|
| 44 |
+ } |
|
| 45 |
+ authConfig.ServerAddress = addr |
|
| 46 |
+ } |
|
| 47 |
+ status, err := Login(authConfig, HTTPRequestFactory(nil)) |
|
| 48 |
+ if err != nil {
|
|
| 49 |
+ return job.Error(err) |
|
| 50 |
+ } |
|
| 51 |
+ job.Printf("%s\n", status)
|
|
| 52 |
+ return engine.StatusOK |
|
| 53 |
+} |
| ... | ... |
@@ -139,7 +139,6 @@ func InitServer(job *engine.Job) engine.Status {
|
| 139 | 139 |
"events": srv.Events, |
| 140 | 140 |
"push": srv.ImagePush, |
| 141 | 141 |
"containers": srv.Containers, |
| 142 |
- "auth": srv.Auth, |
|
| 143 | 142 |
} {
|
| 144 | 143 |
if err := job.Eng.Register(name, handler); err != nil {
|
| 145 | 144 |
return job.Error(err) |
| ... | ... |
@@ -148,24 +147,6 @@ func InitServer(job *engine.Job) engine.Status {
|
| 148 | 148 |
return engine.StatusOK |
| 149 | 149 |
} |
| 150 | 150 |
|
| 151 |
-// simpleVersionInfo is a simple implementation of |
|
| 152 |
-// the interface VersionInfo, which is used |
|
| 153 |
-// to provide version information for some product, |
|
| 154 |
-// component, etc. It stores the product name and the version |
|
| 155 |
-// in string and returns them on calls to Name() and Version(). |
|
| 156 |
-type simpleVersionInfo struct {
|
|
| 157 |
- name string |
|
| 158 |
- version string |
|
| 159 |
-} |
|
| 160 |
- |
|
| 161 |
-func (v *simpleVersionInfo) Name() string {
|
|
| 162 |
- return v.name |
|
| 163 |
-} |
|
| 164 |
- |
|
| 165 |
-func (v *simpleVersionInfo) Version() string {
|
|
| 166 |
- return v.version |
|
| 167 |
-} |
|
| 168 |
- |
|
| 169 | 151 |
// ContainerKill send signal to the container |
| 170 | 152 |
// If no signal is given (sig 0), then Kill with SIGKILL and wait |
| 171 | 153 |
// for the container to exit. |
| ... | ... |
@@ -215,29 +196,6 @@ func (srv *Server) ContainerKill(job *engine.Job) engine.Status {
|
| 215 | 215 |
return engine.StatusOK |
| 216 | 216 |
} |
| 217 | 217 |
|
| 218 |
-func (srv *Server) Auth(job *engine.Job) engine.Status {
|
|
| 219 |
- var ( |
|
| 220 |
- err error |
|
| 221 |
- authConfig = ®istry.AuthConfig{}
|
|
| 222 |
- ) |
|
| 223 |
- |
|
| 224 |
- job.GetenvJson("authConfig", authConfig)
|
|
| 225 |
- // TODO: this is only done here because auth and registry need to be merged into one pkg |
|
| 226 |
- if addr := authConfig.ServerAddress; addr != "" && addr != registry.IndexServerAddress() {
|
|
| 227 |
- addr, err = registry.ExpandAndVerifyRegistryUrl(addr) |
|
| 228 |
- if err != nil {
|
|
| 229 |
- return job.Error(err) |
|
| 230 |
- } |
|
| 231 |
- authConfig.ServerAddress = addr |
|
| 232 |
- } |
|
| 233 |
- status, err := registry.Login(authConfig, srv.HTTPRequestFactory(nil)) |
|
| 234 |
- if err != nil {
|
|
| 235 |
- return job.Error(err) |
|
| 236 |
- } |
|
| 237 |
- job.Printf("%s\n", status)
|
|
| 238 |
- return engine.StatusOK |
|
| 239 |
-} |
|
| 240 |
- |
|
| 241 | 218 |
func (srv *Server) Events(job *engine.Job) engine.Status {
|
| 242 | 219 |
if len(job.Args) != 1 {
|
| 243 | 220 |
return job.Errorf("Usage: %s FROM", job.Name)
|
| ... | ... |
@@ -654,7 +612,7 @@ func (srv *Server) ImagesSearch(job *engine.Job) engine.Status {
|
| 654 | 654 |
job.GetenvJson("authConfig", authConfig)
|
| 655 | 655 |
job.GetenvJson("metaHeaders", metaHeaders)
|
| 656 | 656 |
|
| 657 |
- r, err := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), registry.IndexServerAddress()) |
|
| 657 |
+ r, err := registry.NewRegistry(authConfig, registry.HTTPRequestFactory(metaHeaders), registry.IndexServerAddress()) |
|
| 658 | 658 |
if err != nil {
|
| 659 | 659 |
return job.Error(err) |
| 660 | 660 |
} |
| ... | ... |
@@ -1457,7 +1415,7 @@ func (srv *Server) ImagePull(job *engine.Job) engine.Status {
|
| 1457 | 1457 |
return job.Error(err) |
| 1458 | 1458 |
} |
| 1459 | 1459 |
|
| 1460 |
- r, err := registry.NewRegistry(&authConfig, srv.HTTPRequestFactory(metaHeaders), endpoint) |
|
| 1460 |
+ r, err := registry.NewRegistry(&authConfig, registry.HTTPRequestFactory(metaHeaders), endpoint) |
|
| 1461 | 1461 |
if err != nil {
|
| 1462 | 1462 |
return job.Error(err) |
| 1463 | 1463 |
} |
| ... | ... |
@@ -1680,7 +1638,7 @@ func (srv *Server) ImagePush(job *engine.Job) engine.Status {
|
| 1680 | 1680 |
} |
| 1681 | 1681 |
|
| 1682 | 1682 |
img, err := srv.daemon.Graph().Get(localName) |
| 1683 |
- r, err2 := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), endpoint) |
|
| 1683 |
+ r, err2 := registry.NewRegistry(authConfig, registry.HTTPRequestFactory(metaHeaders), endpoint) |
|
| 1684 | 1684 |
if err2 != nil {
|
| 1685 | 1685 |
return job.Error(err2) |
| 1686 | 1686 |
} |
| ... | ... |
@@ -2558,24 +2516,6 @@ func NewServer(eng *engine.Engine, config *daemonconfig.Config) (*Server, error) |
| 2558 | 2558 |
return srv, nil |
| 2559 | 2559 |
} |
| 2560 | 2560 |
|
| 2561 |
-func (srv *Server) HTTPRequestFactory(metaHeaders map[string][]string) *utils.HTTPRequestFactory {
|
|
| 2562 |
- httpVersion := make([]utils.VersionInfo, 0, 4) |
|
| 2563 |
- httpVersion = append(httpVersion, &simpleVersionInfo{"docker", dockerversion.VERSION})
|
|
| 2564 |
- httpVersion = append(httpVersion, &simpleVersionInfo{"go", goruntime.Version()})
|
|
| 2565 |
- httpVersion = append(httpVersion, &simpleVersionInfo{"git-commit", dockerversion.GITCOMMIT})
|
|
| 2566 |
- if kernelVersion, err := utils.GetKernelVersion(); err == nil {
|
|
| 2567 |
- httpVersion = append(httpVersion, &simpleVersionInfo{"kernel", kernelVersion.String()})
|
|
| 2568 |
- } |
|
| 2569 |
- httpVersion = append(httpVersion, &simpleVersionInfo{"os", goruntime.GOOS})
|
|
| 2570 |
- httpVersion = append(httpVersion, &simpleVersionInfo{"arch", goruntime.GOARCH})
|
|
| 2571 |
- ud := utils.NewHTTPUserAgentDecorator(httpVersion...) |
|
| 2572 |
- md := &utils.HTTPMetaHeadersDecorator{
|
|
| 2573 |
- Headers: metaHeaders, |
|
| 2574 |
- } |
|
| 2575 |
- factory := utils.NewHTTPRequestFactory(ud, md) |
|
| 2576 |
- return factory |
|
| 2577 |
-} |
|
| 2578 |
- |
|
| 2579 | 2561 |
func (srv *Server) LogEvent(action, id, from string) *utils.JSONMessage {
|
| 2580 | 2562 |
now := time.Now().UTC().Unix() |
| 2581 | 2563 |
jm := utils.JSONMessage{Status: action, ID: id, From: from, Time: now}
|