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, &registry.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  }