github.com/getong/docker@v1.13.1/api/server/router/system/system_routes.go (about) 1 package system 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "time" 8 9 "github.com/Sirupsen/logrus" 10 "github.com/docker/docker/api" 11 "github.com/docker/docker/api/errors" 12 "github.com/docker/docker/api/server/httputils" 13 "github.com/docker/docker/api/types" 14 "github.com/docker/docker/api/types/events" 15 "github.com/docker/docker/api/types/filters" 16 "github.com/docker/docker/api/types/registry" 17 timetypes "github.com/docker/docker/api/types/time" 18 "github.com/docker/docker/api/types/versions" 19 "github.com/docker/docker/pkg/ioutils" 20 "golang.org/x/net/context" 21 ) 22 23 func optionsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 24 w.WriteHeader(http.StatusOK) 25 return nil 26 } 27 28 func pingHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 29 _, err := w.Write([]byte{'O', 'K'}) 30 return err 31 } 32 33 func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 34 info, err := s.backend.SystemInfo() 35 if err != nil { 36 return err 37 } 38 if s.clusterProvider != nil { 39 info.Swarm = s.clusterProvider.Info() 40 } 41 42 if versions.LessThan(httputils.VersionFromContext(ctx), "1.25") { 43 // TODO: handle this conversion in engine-api 44 type oldInfo struct { 45 *types.Info 46 ExecutionDriver string 47 } 48 old := &oldInfo{ 49 Info: info, 50 ExecutionDriver: "<not supported>", 51 } 52 nameOnlySecurityOptions := []string{} 53 kvSecOpts, err := types.DecodeSecurityOptions(old.SecurityOptions) 54 if err != nil { 55 return err 56 } 57 for _, s := range kvSecOpts { 58 nameOnlySecurityOptions = append(nameOnlySecurityOptions, s.Name) 59 } 60 old.SecurityOptions = nameOnlySecurityOptions 61 return httputils.WriteJSON(w, http.StatusOK, old) 62 } 63 return httputils.WriteJSON(w, http.StatusOK, info) 64 } 65 66 func (s *systemRouter) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 67 info := s.backend.SystemVersion() 68 info.APIVersion = api.DefaultVersion 69 70 return httputils.WriteJSON(w, http.StatusOK, info) 71 } 72 73 func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 74 du, err := s.backend.SystemDiskUsage() 75 if err != nil { 76 return err 77 } 78 79 return httputils.WriteJSON(w, http.StatusOK, du) 80 } 81 82 func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 83 if err := httputils.ParseForm(r); err != nil { 84 return err 85 } 86 87 since, err := eventTime(r.Form.Get("since")) 88 if err != nil { 89 return err 90 } 91 until, err := eventTime(r.Form.Get("until")) 92 if err != nil { 93 return err 94 } 95 96 var ( 97 timeout <-chan time.Time 98 onlyPastEvents bool 99 ) 100 if !until.IsZero() { 101 if until.Before(since) { 102 return errors.NewBadRequestError(fmt.Errorf("`since` time (%s) cannot be after `until` time (%s)", r.Form.Get("since"), r.Form.Get("until"))) 103 } 104 105 now := time.Now() 106 107 onlyPastEvents = until.Before(now) 108 109 if !onlyPastEvents { 110 dur := until.Sub(now) 111 timeout = time.NewTimer(dur).C 112 } 113 } 114 115 ef, err := filters.FromParam(r.Form.Get("filters")) 116 if err != nil { 117 return err 118 } 119 120 w.Header().Set("Content-Type", "application/json") 121 output := ioutils.NewWriteFlusher(w) 122 defer output.Close() 123 output.Flush() 124 125 enc := json.NewEncoder(output) 126 127 buffered, l := s.backend.SubscribeToEvents(since, until, ef) 128 defer s.backend.UnsubscribeFromEvents(l) 129 130 for _, ev := range buffered { 131 if err := enc.Encode(ev); err != nil { 132 return err 133 } 134 } 135 136 if onlyPastEvents { 137 return nil 138 } 139 140 for { 141 select { 142 case ev := <-l: 143 jev, ok := ev.(events.Message) 144 if !ok { 145 logrus.Warnf("unexpected event message: %q", ev) 146 continue 147 } 148 if err := enc.Encode(jev); err != nil { 149 return err 150 } 151 case <-timeout: 152 return nil 153 case <-ctx.Done(): 154 logrus.Debug("Client context cancelled, stop sending events") 155 return nil 156 } 157 } 158 } 159 160 func (s *systemRouter) postAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 161 var config *types.AuthConfig 162 err := json.NewDecoder(r.Body).Decode(&config) 163 r.Body.Close() 164 if err != nil { 165 return err 166 } 167 status, token, err := s.backend.AuthenticateToRegistry(ctx, config) 168 if err != nil { 169 return err 170 } 171 return httputils.WriteJSON(w, http.StatusOK, ®istry.AuthenticateOKBody{ 172 Status: status, 173 IdentityToken: token, 174 }) 175 } 176 177 func eventTime(formTime string) (time.Time, error) { 178 t, tNano, err := timetypes.ParseTimestamps(formTime, -1) 179 if err != nil { 180 return time.Time{}, err 181 } 182 if t == -1 { 183 return time.Time{}, nil 184 } 185 return time.Unix(t, tNano), nil 186 }