| package system |
| |
| import ( |
| "encoding/json" |
| "fmt" |
| "net/http" |
| "time" |
| |
| "github.com/Sirupsen/logrus" |
| "github.com/docker/docker/api" |
| "github.com/docker/docker/api/errors" |
| "github.com/docker/docker/api/server/httputils" |
| "github.com/docker/docker/api/types" |
| "github.com/docker/docker/api/types/events" |
| "github.com/docker/docker/api/types/filters" |
| "github.com/docker/docker/api/types/registry" |
| timetypes "github.com/docker/docker/api/types/time" |
| "github.com/docker/docker/api/types/versions" |
| "github.com/docker/docker/pkg/ioutils" |
| "golang.org/x/net/context" |
| ) |
| |
| func optionsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| w.WriteHeader(http.StatusOK) |
| return nil |
| } |
| |
| func pingHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| _, err := w.Write([]byte{'O', 'K'}) |
| return err |
| } |
| |
| func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| info, err := s.backend.SystemInfo() |
| if err != nil { |
| return err |
| } |
| if s.clusterProvider != nil { |
| info.Swarm = s.clusterProvider.Info() |
| } |
| |
| if versions.LessThan(httputils.VersionFromContext(ctx), "1.25") { |
| // TODO: handle this conversion in engine-api |
| type oldInfo struct { |
| *types.Info |
| ExecutionDriver string |
| } |
| old := &oldInfo{ |
| Info: info, |
| ExecutionDriver: "<not supported>", |
| } |
| nameOnlySecurityOptions := []string{} |
| kvSecOpts, err := types.DecodeSecurityOptions(old.SecurityOptions) |
| if err != nil { |
| return err |
| } |
| for _, s := range kvSecOpts { |
| nameOnlySecurityOptions = append(nameOnlySecurityOptions, s.Name) |
| } |
| old.SecurityOptions = nameOnlySecurityOptions |
| return httputils.WriteJSON(w, http.StatusOK, old) |
| } |
| return httputils.WriteJSON(w, http.StatusOK, info) |
| } |
| |
| func (s *systemRouter) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| info := s.backend.SystemVersion() |
| info.APIVersion = api.DefaultVersion |
| |
| return httputils.WriteJSON(w, http.StatusOK, info) |
| } |
| |
| func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| du, err := s.backend.SystemDiskUsage() |
| if err != nil { |
| return err |
| } |
| |
| return httputils.WriteJSON(w, http.StatusOK, du) |
| } |
| |
| func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| if err := httputils.ParseForm(r); err != nil { |
| return err |
| } |
| |
| since, err := eventTime(r.Form.Get("since")) |
| if err != nil { |
| return err |
| } |
| until, err := eventTime(r.Form.Get("until")) |
| if err != nil { |
| return err |
| } |
| |
| var ( |
| timeout <-chan time.Time |
| onlyPastEvents bool |
| ) |
| if !until.IsZero() { |
| if until.Before(since) { |
| return errors.NewBadRequestError(fmt.Errorf("`since` time (%s) cannot be after `until` time (%s)", r.Form.Get("since"), r.Form.Get("until"))) |
| } |
| |
| now := time.Now() |
| |
| onlyPastEvents = until.Before(now) |
| |
| if !onlyPastEvents { |
| dur := until.Sub(now) |
| timeout = time.NewTimer(dur).C |
| } |
| } |
| |
| ef, err := filters.FromParam(r.Form.Get("filters")) |
| if err != nil { |
| return err |
| } |
| |
| w.Header().Set("Content-Type", "application/json") |
| output := ioutils.NewWriteFlusher(w) |
| defer output.Close() |
| output.Flush() |
| |
| enc := json.NewEncoder(output) |
| |
| buffered, l := s.backend.SubscribeToEvents(since, until, ef) |
| defer s.backend.UnsubscribeFromEvents(l) |
| |
| for _, ev := range buffered { |
| if err := enc.Encode(ev); err != nil { |
| return err |
| } |
| } |
| |
| if onlyPastEvents { |
| return nil |
| } |
| |
| for { |
| select { |
| case ev := <-l: |
| jev, ok := ev.(events.Message) |
| if !ok { |
| logrus.Warnf("unexpected event message: %q", ev) |
| continue |
| } |
| if err := enc.Encode(jev); err != nil { |
| return err |
| } |
| case <-timeout: |
| return nil |
| case <-ctx.Done(): |
| logrus.Debug("Client context cancelled, stop sending events") |
| return nil |
| } |
| } |
| } |
| |
| func (s *systemRouter) postAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| var config *types.AuthConfig |
| err := json.NewDecoder(r.Body).Decode(&config) |
| r.Body.Close() |
| if err != nil { |
| return err |
| } |
| status, token, err := s.backend.AuthenticateToRegistry(ctx, config) |
| if err != nil { |
| return err |
| } |
| return httputils.WriteJSON(w, http.StatusOK, ®istry.AuthenticateOKBody{ |
| Status: status, |
| IdentityToken: token, |
| }) |
| } |
| |
| func eventTime(formTime string) (time.Time, error) { |
| t, tNano, err := timetypes.ParseTimestamps(formTime, -1) |
| if err != nil { |
| return time.Time{}, err |
| } |
| if t == -1 { |
| return time.Time{}, nil |
| } |
| return time.Unix(t, tNano), nil |
| } |