system_routes.go 5.9 KB

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