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