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