Browse code

Move docker system information to a dedicated router and backend.

Because I like the name `system` better than `local` :)

Signed-off-by: David Calavera <david.calavera@gmail.com>

David Calavera authored on 2015/12/04 03:11:19
Showing 8 changed files
1 1
deleted file mode 100644
... ...
@@ -1,27 +0,0 @@
1
-package local
2
-
3
-import (
4
-	"encoding/json"
5
-	"net/http"
6
-
7
-	"github.com/docker/docker/api/server/httputils"
8
-	"github.com/docker/docker/api/types"
9
-	"github.com/docker/docker/cliconfig"
10
-	"golang.org/x/net/context"
11
-)
12
-
13
-func (s *router) postAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
14
-	var config *cliconfig.AuthConfig
15
-	err := json.NewDecoder(r.Body).Decode(&config)
16
-	r.Body.Close()
17
-	if err != nil {
18
-		return err
19
-	}
20
-	status, err := s.daemon.AuthenticateToRegistry(config)
21
-	if err != nil {
22
-		return err
23
-	}
24
-	return httputils.WriteJSON(w, http.StatusOK, &types.AuthResponse{
25
-		Status: status,
26
-	})
27
-}
28 1
deleted file mode 100644
... ...
@@ -1,126 +0,0 @@
1
-package local
2
-
3
-import (
4
-	"encoding/json"
5
-	"net/http"
6
-	"runtime"
7
-	"time"
8
-
9
-	"github.com/Sirupsen/logrus"
10
-	"github.com/docker/docker/api"
11
-	"github.com/docker/docker/api/server/httputils"
12
-	"github.com/docker/docker/api/types"
13
-	"github.com/docker/docker/dockerversion"
14
-	"github.com/docker/docker/pkg/ioutils"
15
-	"github.com/docker/docker/pkg/jsonmessage"
16
-	"github.com/docker/docker/pkg/parsers/filters"
17
-	"github.com/docker/docker/pkg/parsers/kernel"
18
-	"github.com/docker/docker/pkg/timeutils"
19
-	"github.com/docker/docker/utils"
20
-	"golang.org/x/net/context"
21
-)
22
-
23
-func (s *router) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
24
-	v := &types.Version{
25
-		Version:    dockerversion.Version,
26
-		APIVersion: api.Version,
27
-		GitCommit:  dockerversion.GitCommit,
28
-		GoVersion:  runtime.Version(),
29
-		Os:         runtime.GOOS,
30
-		Arch:       runtime.GOARCH,
31
-		BuildTime:  dockerversion.BuildTime,
32
-	}
33
-
34
-	version := httputils.VersionFromContext(ctx)
35
-
36
-	if version.GreaterThanOrEqualTo("1.19") {
37
-		v.Experimental = utils.ExperimentalBuild()
38
-	}
39
-
40
-	if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
41
-		v.KernelVersion = kernelVersion.String()
42
-	}
43
-
44
-	return httputils.WriteJSON(w, http.StatusOK, v)
45
-}
46
-
47
-func (s *router) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
48
-	info, err := s.daemon.SystemInfo()
49
-	if err != nil {
50
-		return err
51
-	}
52
-
53
-	return httputils.WriteJSON(w, http.StatusOK, info)
54
-}
55
-
56
-func (s *router) getEvents(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
57
-	if err := httputils.ParseForm(r); err != nil {
58
-		return err
59
-	}
60
-	since, sinceNano, err := timeutils.ParseTimestamps(r.Form.Get("since"), -1)
61
-	if err != nil {
62
-		return err
63
-	}
64
-	until, untilNano, err := timeutils.ParseTimestamps(r.Form.Get("until"), -1)
65
-	if err != nil {
66
-		return err
67
-	}
68
-
69
-	timer := time.NewTimer(0)
70
-	timer.Stop()
71
-	if until > 0 || untilNano > 0 {
72
-		dur := time.Unix(until, untilNano).Sub(time.Now())
73
-		timer = time.NewTimer(dur)
74
-	}
75
-
76
-	ef, err := filters.FromParam(r.Form.Get("filters"))
77
-	if err != nil {
78
-		return err
79
-	}
80
-
81
-	w.Header().Set("Content-Type", "application/json")
82
-
83
-	// This is to ensure that the HTTP status code is sent immediately,
84
-	// so that it will not block the receiver.
85
-	w.WriteHeader(http.StatusOK)
86
-	if flusher, ok := w.(http.Flusher); ok {
87
-		flusher.Flush()
88
-	}
89
-
90
-	output := ioutils.NewWriteFlusher(w)
91
-	defer output.Close()
92
-
93
-	enc := json.NewEncoder(output)
94
-
95
-	buffered, l := s.daemon.SubscribeToEvents(since, sinceNano, ef)
96
-	defer s.daemon.UnsubscribeFromEvents(l)
97
-
98
-	for _, ev := range buffered {
99
-		if err := enc.Encode(ev); err != nil {
100
-			return err
101
-		}
102
-	}
103
-
104
-	var closeNotify <-chan bool
105
-	if closeNotifier, ok := w.(http.CloseNotifier); ok {
106
-		closeNotify = closeNotifier.CloseNotify()
107
-	}
108
-
109
-	for {
110
-		select {
111
-		case ev := <-l:
112
-			jev, ok := ev.(*jsonmessage.JSONMessage)
113
-			if !ok {
114
-				continue
115
-			}
116
-			if err := enc.Encode(jev); err != nil {
117
-				return err
118
-			}
119
-		case <-timer.C:
120
-			return nil
121
-		case <-closeNotify:
122
-			logrus.Debug("Client disconnected, stop sending events")
123
-			return nil
124
-		}
125
-	}
126
-}
... ...
@@ -1,10 +1,6 @@
1 1
 package local
2 2
 
3 3
 import (
4
-	"net/http"
5
-
6
-	"golang.org/x/net/context"
7
-
8 4
 	"github.com/docker/docker/api/server/httputils"
9 5
 	dkrouter "github.com/docker/docker/api/server/router"
10 6
 	"github.com/docker/docker/daemon"
... ...
@@ -92,12 +88,7 @@ func (r *router) Routes() []dkrouter.Route {
92 92
 func (r *router) initRoutes() {
93 93
 	r.routes = []dkrouter.Route{
94 94
 		// OPTIONS
95
-		NewOptionsRoute("/", optionsHandler),
96 95
 		// GET
97
-		NewGetRoute("/_ping", pingHandler),
98
-		NewGetRoute("/events", r.getEvents),
99
-		NewGetRoute("/info", r.getInfo),
100
-		NewGetRoute("/version", r.getVersion),
101 96
 		NewGetRoute("/images/json", r.getImagesJSON),
102 97
 		NewGetRoute("/images/search", r.getImagesSearch),
103 98
 		NewGetRoute("/images/get", r.getImagesGet),
... ...
@@ -105,7 +96,6 @@ func (r *router) initRoutes() {
105 105
 		NewGetRoute("/images/{name:.*}/history", r.getImagesHistory),
106 106
 		NewGetRoute("/images/{name:.*}/json", r.getImagesByName),
107 107
 		// POST
108
-		NewPostRoute("/auth", r.postAuth),
109 108
 		NewPostRoute("/commit", r.postCommit),
110 109
 		NewPostRoute("/build", r.postBuild),
111 110
 		NewPostRoute("/images/create", r.postImagesCreate),
... ...
@@ -116,13 +106,3 @@ func (r *router) initRoutes() {
116 116
 		NewDeleteRoute("/images/{name:.*}", r.deleteImages),
117 117
 	}
118 118
 }
119
-
120
-func optionsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
121
-	w.WriteHeader(http.StatusOK)
122
-	return nil
123
-}
124
-
125
-func pingHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
126
-	_, err := w.Write([]byte{'O', 'K'})
127
-	return err
128
-}
129 119
new file mode 100644
... ...
@@ -0,0 +1,18 @@
0
+package system
1
+
2
+import (
3
+	"github.com/docker/docker/api/types"
4
+	"github.com/docker/docker/cliconfig"
5
+	"github.com/docker/docker/pkg/jsonmessage"
6
+	"github.com/docker/docker/pkg/parsers/filters"
7
+)
8
+
9
+// Backend is the methods that need to be implemented to provide
10
+// system specific functionality.
11
+type Backend interface {
12
+	SystemInfo() (*types.Info, error)
13
+	SystemVersion() types.Version
14
+	SubscribeToEvents(since, sinceNano int64, ef filters.Args) ([]*jsonmessage.JSONMessage, chan interface{})
15
+	UnsubscribeFromEvents(chan interface{})
16
+	AuthenticateToRegistry(authConfig *cliconfig.AuthConfig) (string, error)
17
+}
0 18
new file mode 100644
... ...
@@ -0,0 +1,37 @@
0
+package system
1
+
2
+import (
3
+	"github.com/docker/docker/api/server/router"
4
+	"github.com/docker/docker/api/server/router/local"
5
+)
6
+
7
+// systemRouter is a Router that provides information about
8
+// the Docker system overall. It gathers information about
9
+// host, daemon and container events.
10
+type systemRouter struct {
11
+	backend Backend
12
+	routes  []router.Route
13
+}
14
+
15
+// NewRouter initializes a new systemRouter
16
+func NewRouter(b Backend) router.Router {
17
+	r := &systemRouter{
18
+		backend: b,
19
+	}
20
+
21
+	r.routes = []router.Route{
22
+		local.NewOptionsRoute("/", optionsHandler),
23
+		local.NewGetRoute("/_ping", pingHandler),
24
+		local.NewGetRoute("/events", r.getEvents),
25
+		local.NewGetRoute("/info", r.getInfo),
26
+		local.NewGetRoute("/version", r.getVersion),
27
+		local.NewPostRoute("/auth", r.postAuth),
28
+	}
29
+
30
+	return r
31
+}
32
+
33
+// Routes return all the API routes dedicated to the docker system.
34
+func (s *systemRouter) Routes() []router.Route {
35
+	return s.routes
36
+}
0 37
new file mode 100644
... ...
@@ -0,0 +1,132 @@
0
+package system
1
+
2
+import (
3
+	"encoding/json"
4
+	"net/http"
5
+	"time"
6
+
7
+	"github.com/Sirupsen/logrus"
8
+	"github.com/docker/docker/api"
9
+	"github.com/docker/docker/api/server/httputils"
10
+	"github.com/docker/docker/api/types"
11
+	"github.com/docker/docker/cliconfig"
12
+	"github.com/docker/docker/pkg/ioutils"
13
+	"github.com/docker/docker/pkg/jsonmessage"
14
+	"github.com/docker/docker/pkg/parsers/filters"
15
+	"github.com/docker/docker/pkg/timeutils"
16
+	"golang.org/x/net/context"
17
+)
18
+
19
+func optionsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
20
+	w.WriteHeader(http.StatusOK)
21
+	return nil
22
+}
23
+
24
+func pingHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
25
+	_, err := w.Write([]byte{'O', 'K'})
26
+	return err
27
+}
28
+
29
+func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
30
+	info, err := s.backend.SystemInfo()
31
+	if err != nil {
32
+		return err
33
+	}
34
+
35
+	return httputils.WriteJSON(w, http.StatusOK, info)
36
+}
37
+
38
+func (s *systemRouter) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
39
+	info := s.backend.SystemVersion()
40
+	info.APIVersion = api.Version
41
+
42
+	return httputils.WriteJSON(w, http.StatusOK, info)
43
+}
44
+
45
+func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
46
+	if err := httputils.ParseForm(r); err != nil {
47
+		return err
48
+	}
49
+	since, sinceNano, err := timeutils.ParseTimestamps(r.Form.Get("since"), -1)
50
+	if err != nil {
51
+		return err
52
+	}
53
+	until, untilNano, err := timeutils.ParseTimestamps(r.Form.Get("until"), -1)
54
+	if err != nil {
55
+		return err
56
+	}
57
+
58
+	timer := time.NewTimer(0)
59
+	timer.Stop()
60
+	if until > 0 || untilNano > 0 {
61
+		dur := time.Unix(until, untilNano).Sub(time.Now())
62
+		timer = time.NewTimer(dur)
63
+	}
64
+
65
+	ef, err := filters.FromParam(r.Form.Get("filters"))
66
+	if err != nil {
67
+		return err
68
+	}
69
+
70
+	w.Header().Set("Content-Type", "application/json")
71
+
72
+	// This is to ensure that the HTTP status code is sent immediately,
73
+	// so that it will not block the receiver.
74
+	w.WriteHeader(http.StatusOK)
75
+	if flusher, ok := w.(http.Flusher); ok {
76
+		flusher.Flush()
77
+	}
78
+
79
+	output := ioutils.NewWriteFlusher(w)
80
+	defer output.Close()
81
+
82
+	enc := json.NewEncoder(output)
83
+
84
+	buffered, l := s.backend.SubscribeToEvents(since, sinceNano, ef)
85
+	defer s.backend.UnsubscribeFromEvents(l)
86
+
87
+	for _, ev := range buffered {
88
+		if err := enc.Encode(ev); err != nil {
89
+			return err
90
+		}
91
+	}
92
+
93
+	var closeNotify <-chan bool
94
+	if closeNotifier, ok := w.(http.CloseNotifier); ok {
95
+		closeNotify = closeNotifier.CloseNotify()
96
+	}
97
+
98
+	for {
99
+		select {
100
+		case ev := <-l:
101
+			jev, ok := ev.(*jsonmessage.JSONMessage)
102
+			if !ok {
103
+				continue
104
+			}
105
+			if err := enc.Encode(jev); err != nil {
106
+				return err
107
+			}
108
+		case <-timer.C:
109
+			return nil
110
+		case <-closeNotify:
111
+			logrus.Debug("Client disconnected, stop sending events")
112
+			return nil
113
+		}
114
+	}
115
+}
116
+
117
+func (s *systemRouter) postAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
118
+	var config *cliconfig.AuthConfig
119
+	err := json.NewDecoder(r.Body).Decode(&config)
120
+	r.Body.Close()
121
+	if err != nil {
122
+		return err
123
+	}
124
+	status, err := s.backend.AuthenticateToRegistry(config)
125
+	if err != nil {
126
+		return err
127
+	}
128
+	return httputils.WriteJSON(w, http.StatusOK, &types.AuthResponse{
129
+		Status: status,
130
+	})
131
+}
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"github.com/docker/docker/api/server/router/container"
14 14
 	"github.com/docker/docker/api/server/router/local"
15 15
 	"github.com/docker/docker/api/server/router/network"
16
+	"github.com/docker/docker/api/server/router/system"
16 17
 	"github.com/docker/docker/api/server/router/volume"
17 18
 	"github.com/docker/docker/daemon"
18 19
 	"github.com/docker/docker/pkg/sockets"
... ...
@@ -168,10 +169,11 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc {
168 168
 
169 169
 // InitRouters initializes a list of routers for the server.
170 170
 func (s *Server) InitRouters(d *daemon.Daemon) {
171
+	s.addRouter(container.NewRouter(d))
171 172
 	s.addRouter(local.NewRouter(d))
172 173
 	s.addRouter(network.NewRouter(d))
174
+	s.addRouter(system.NewRouter(d))
173 175
 	s.addRouter(volume.NewRouter(d))
174
-	s.addRouter(container.NewRouter(d))
175 176
 }
176 177
 
177 178
 // addRouter adds a new router to the server.
... ...
@@ -113,6 +113,25 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
113 113
 	return v, nil
114 114
 }
115 115
 
116
+// SystemVersion returns version information about the daemon.
117
+func (daemon *Daemon) SystemVersion() types.Version {
118
+	v := types.Version{
119
+		Version:      dockerversion.Version,
120
+		GitCommit:    dockerversion.GitCommit,
121
+		GoVersion:    runtime.Version(),
122
+		Os:           runtime.GOOS,
123
+		Arch:         runtime.GOARCH,
124
+		BuildTime:    dockerversion.BuildTime,
125
+		Experimental: utils.ExperimentalBuild(),
126
+	}
127
+
128
+	if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
129
+		v.KernelVersion = kernelVersion.String()
130
+	}
131
+
132
+	return v
133
+}
134
+
116 135
 func (daemon *Daemon) showPluginsInfo() types.PluginsInfo {
117 136
 	var pluginsInfo types.PluginsInfo
118 137