2015-12-03 13:11:19 -05:00
|
|
|
package system
|
2015-07-28 14:35:24 -04:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2016-04-11 14:52:34 -04:00
|
|
|
"fmt"
|
2015-07-28 14:35:24 -04:00
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
|
|
"github.com/docker/docker/api"
|
2016-09-15 13:15:57 -04:00
|
|
|
"github.com/docker/docker/api/errors"
|
2015-09-23 19:42:08 -04:00
|
|
|
"github.com/docker/docker/api/server/httputils"
|
2016-09-06 14:46:37 -04:00
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
"github.com/docker/docker/api/types/events"
|
|
|
|
"github.com/docker/docker/api/types/filters"
|
2016-10-18 20:52:46 -04:00
|
|
|
"github.com/docker/docker/api/types/registry"
|
2016-09-06 14:46:37 -04:00
|
|
|
timetypes "github.com/docker/docker/api/types/time"
|
|
|
|
"github.com/docker/docker/api/types/versions"
|
2015-07-28 14:35:24 -04:00
|
|
|
"github.com/docker/docker/pkg/ioutils"
|
2015-09-29 17:32:07 -04:00
|
|
|
"golang.org/x/net/context"
|
2015-07-28 14:35:24 -04:00
|
|
|
)
|
|
|
|
|
2015-12-03 13:11:19 -05:00
|
|
|
func optionsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
return nil
|
|
|
|
}
|
2015-07-28 14:35:24 -04:00
|
|
|
|
2015-12-03 13:11:19 -05:00
|
|
|
func pingHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
|
|
_, err := w.Write([]byte{'O', 'K'})
|
|
|
|
return err
|
2015-07-28 14:35:24 -04:00
|
|
|
}
|
|
|
|
|
2015-12-03 13:11:19 -05:00
|
|
|
func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
|
|
info, err := s.backend.SystemInfo()
|
2015-07-28 14:35:24 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-12-26 07:53:13 -05:00
|
|
|
if s.cluster != nil {
|
|
|
|
info.Swarm = s.cluster.Info()
|
2016-06-13 22:52:49 -04:00
|
|
|
}
|
2015-07-28 14:35:24 -04:00
|
|
|
|
2016-10-21 05:43:00 -04:00
|
|
|
if versions.LessThan(httputils.VersionFromContext(ctx), "1.25") {
|
2016-08-15 12:13:18 -04:00
|
|
|
// TODO: handle this conversion in engine-api
|
2016-11-16 16:30:29 -05:00
|
|
|
type oldInfo struct {
|
|
|
|
*types.Info
|
|
|
|
ExecutionDriver string
|
|
|
|
}
|
|
|
|
old := &oldInfo{
|
|
|
|
Info: info,
|
2016-09-02 09:20:54 -04:00
|
|
|
ExecutionDriver: "<not supported>",
|
|
|
|
}
|
2016-11-16 16:30:29 -05:00
|
|
|
nameOnlySecurityOptions := []string{}
|
|
|
|
kvSecOpts, err := types.DecodeSecurityOptions(old.SecurityOptions)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for _, s := range kvSecOpts {
|
|
|
|
nameOnlySecurityOptions = append(nameOnlySecurityOptions, s.Name)
|
2016-09-02 09:20:54 -04:00
|
|
|
}
|
2016-11-16 16:30:29 -05:00
|
|
|
old.SecurityOptions = nameOnlySecurityOptions
|
|
|
|
return httputils.WriteJSON(w, http.StatusOK, old)
|
2016-08-15 12:13:18 -04:00
|
|
|
}
|
2015-09-23 19:42:08 -04:00
|
|
|
return httputils.WriteJSON(w, http.StatusOK, info)
|
2015-07-28 14:35:24 -04:00
|
|
|
}
|
|
|
|
|
2015-12-03 13:11:19 -05:00
|
|
|
func (s *systemRouter) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
|
|
info := s.backend.SystemVersion()
|
2016-04-19 10:56:54 -04:00
|
|
|
info.APIVersion = api.DefaultVersion
|
2015-12-03 13:11:19 -05:00
|
|
|
|
|
|
|
return httputils.WriteJSON(w, http.StatusOK, info)
|
|
|
|
}
|
|
|
|
|
2016-08-23 19:24:15 -04:00
|
|
|
func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
2017-04-12 16:59:31 -04:00
|
|
|
du, err := s.backend.SystemDiskUsage(ctx)
|
2016-08-23 19:24:15 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return httputils.WriteJSON(w, http.StatusOK, du)
|
|
|
|
}
|
|
|
|
|
2015-12-03 13:11:19 -05:00
|
|
|
func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
2015-09-23 19:42:08 -04:00
|
|
|
if err := httputils.ParseForm(r); err != nil {
|
2015-07-28 14:35:24 -04:00
|
|
|
return err
|
|
|
|
}
|
2016-04-11 14:52:34 -04:00
|
|
|
|
|
|
|
since, err := eventTime(r.Form.Get("since"))
|
2015-09-23 14:51:43 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2015-07-28 14:35:24 -04:00
|
|
|
}
|
2016-04-11 14:52:34 -04:00
|
|
|
until, err := eventTime(r.Form.Get("until"))
|
2015-09-23 14:51:43 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2015-07-28 14:35:24 -04:00
|
|
|
}
|
|
|
|
|
2016-04-11 14:52:34 -04:00
|
|
|
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
|
|
|
|
}
|
2015-07-28 14:35:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
ef, err := filters.FromParam(r.Form.Get("filters"))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-11-02 19:11:28 -05:00
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
output := ioutils.NewWriteFlusher(w)
|
|
|
|
defer output.Close()
|
2015-12-19 09:43:10 -05:00
|
|
|
output.Flush()
|
2015-11-02 19:11:28 -05:00
|
|
|
|
|
|
|
enc := json.NewEncoder(output)
|
2015-07-28 14:35:24 -04:00
|
|
|
|
2016-04-11 14:52:34 -04:00
|
|
|
buffered, l := s.backend.SubscribeToEvents(since, until, ef)
|
2015-12-03 13:11:19 -05:00
|
|
|
defer s.backend.UnsubscribeFromEvents(l)
|
2015-10-12 14:54:46 -04:00
|
|
|
|
2015-11-25 21:03:10 -05:00
|
|
|
for _, ev := range buffered {
|
|
|
|
if err := enc.Encode(ev); err != nil {
|
2015-07-28 14:35:24 -04:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-11 14:52:34 -04:00
|
|
|
if onlyPastEvents {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-07-28 14:35:24 -04:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case ev := <-l:
|
2015-12-21 17:55:23 -05:00
|
|
|
jev, ok := ev.(events.Message)
|
2015-07-28 14:35:24 -04:00
|
|
|
if !ok {
|
2015-12-21 17:55:23 -05:00
|
|
|
logrus.Warnf("unexpected event message: %q", ev)
|
2015-07-28 14:35:24 -04:00
|
|
|
continue
|
|
|
|
}
|
2015-11-25 21:03:10 -05:00
|
|
|
if err := enc.Encode(jev); err != nil {
|
2015-07-28 14:35:24 -04:00
|
|
|
return err
|
|
|
|
}
|
2016-03-31 12:48:20 -04:00
|
|
|
case <-timeout:
|
2015-07-28 14:35:24 -04:00
|
|
|
return nil
|
2016-03-25 14:33:54 -04:00
|
|
|
case <-ctx.Done():
|
|
|
|
logrus.Debug("Client context cancelled, stop sending events")
|
2015-07-28 14:35:24 -04:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-12-03 13:11:19 -05:00
|
|
|
|
|
|
|
func (s *systemRouter) postAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
2015-12-11 23:11:42 -05:00
|
|
|
var config *types.AuthConfig
|
2015-12-03 13:11:19 -05:00
|
|
|
err := json.NewDecoder(r.Body).Decode(&config)
|
|
|
|
r.Body.Close()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-03-18 17:42:40 -04:00
|
|
|
status, token, err := s.backend.AuthenticateToRegistry(ctx, config)
|
2015-12-03 13:11:19 -05:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-10-18 20:52:46 -04:00
|
|
|
return httputils.WriteJSON(w, http.StatusOK, ®istry.AuthenticateOKBody{
|
2016-02-23 18:18:04 -05:00
|
|
|
Status: status,
|
|
|
|
IdentityToken: token,
|
2015-12-03 13:11:19 -05:00
|
|
|
})
|
|
|
|
}
|
2016-04-11 14:52:34 -04:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|