Because I like the name `system` better than `local` :)
Signed-off-by: David Calavera <david.calavera@gmail.com>
| 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 |
|