Browse code

Move 'auth' to the registry subsystem

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)

Solomon Hykes authored on 2014/04/28 07:06:09
Showing 4 changed files
... ...
@@ -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 = &registry.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}