github.com/sld880311/docker@v0.0.0-20200524143708-d5593973a475/api/server/router/swarm/cluster_routes.go (about)

     1  package swarm
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"strconv"
     8  
     9  	"github.com/Sirupsen/logrus"
    10  	"github.com/docker/docker/api/errors"
    11  	"github.com/docker/docker/api/server/httputils"
    12  	basictypes "github.com/docker/docker/api/types"
    13  	"github.com/docker/docker/api/types/backend"
    14  	"github.com/docker/docker/api/types/filters"
    15  	types "github.com/docker/docker/api/types/swarm"
    16  	"golang.org/x/net/context"
    17  )
    18  
    19  func (sr *swarmRouter) initCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    20  	var req types.InitRequest
    21  	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
    22  		return err
    23  	}
    24  	nodeID, err := sr.backend.Init(req)
    25  	if err != nil {
    26  		logrus.Errorf("Error initializing swarm: %v", err)
    27  		return err
    28  	}
    29  	return httputils.WriteJSON(w, http.StatusOK, nodeID)
    30  }
    31  
    32  func (sr *swarmRouter) joinCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    33  	var req types.JoinRequest
    34  	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
    35  		return err
    36  	}
    37  	return sr.backend.Join(req)
    38  }
    39  
    40  func (sr *swarmRouter) leaveCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    41  	if err := httputils.ParseForm(r); err != nil {
    42  		return err
    43  	}
    44  
    45  	force := httputils.BoolValue(r, "force")
    46  	return sr.backend.Leave(force)
    47  }
    48  
    49  func (sr *swarmRouter) inspectCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    50  	swarm, err := sr.backend.Inspect()
    51  	if err != nil {
    52  		logrus.Errorf("Error getting swarm: %v", err)
    53  		return err
    54  	}
    55  
    56  	return httputils.WriteJSON(w, http.StatusOK, swarm)
    57  }
    58  
    59  func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    60  	var swarm types.Spec
    61  	if err := json.NewDecoder(r.Body).Decode(&swarm); err != nil {
    62  		return err
    63  	}
    64  
    65  	rawVersion := r.URL.Query().Get("version")
    66  	version, err := strconv.ParseUint(rawVersion, 10, 64)
    67  	if err != nil {
    68  		err := fmt.Errorf("invalid swarm version '%s': %v", rawVersion, err)
    69  		return errors.NewBadRequestError(err)
    70  	}
    71  
    72  	var flags types.UpdateFlags
    73  
    74  	if value := r.URL.Query().Get("rotateWorkerToken"); value != "" {
    75  		rot, err := strconv.ParseBool(value)
    76  		if err != nil {
    77  			err := fmt.Errorf("invalid value for rotateWorkerToken: %s", value)
    78  			return errors.NewBadRequestError(err)
    79  		}
    80  
    81  		flags.RotateWorkerToken = rot
    82  	}
    83  
    84  	if value := r.URL.Query().Get("rotateManagerToken"); value != "" {
    85  		rot, err := strconv.ParseBool(value)
    86  		if err != nil {
    87  			err := fmt.Errorf("invalid value for rotateManagerToken: %s", value)
    88  			return errors.NewBadRequestError(err)
    89  		}
    90  
    91  		flags.RotateManagerToken = rot
    92  	}
    93  
    94  	if value := r.URL.Query().Get("rotateManagerUnlockKey"); value != "" {
    95  		rot, err := strconv.ParseBool(value)
    96  		if err != nil {
    97  			return errors.NewBadRequestError(fmt.Errorf("invalid value for rotateManagerUnlockKey: %s", value))
    98  		}
    99  
   100  		flags.RotateManagerUnlockKey = rot
   101  	}
   102  
   103  	if err := sr.backend.Update(version, swarm, flags); err != nil {
   104  		logrus.Errorf("Error configuring swarm: %v", err)
   105  		return err
   106  	}
   107  	return nil
   108  }
   109  
   110  func (sr *swarmRouter) unlockCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   111  	var req types.UnlockRequest
   112  	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
   113  		return err
   114  	}
   115  
   116  	if err := sr.backend.UnlockSwarm(req); err != nil {
   117  		logrus.Errorf("Error unlocking swarm: %v", err)
   118  		return err
   119  	}
   120  	return nil
   121  }
   122  
   123  func (sr *swarmRouter) getUnlockKey(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   124  	unlockKey, err := sr.backend.GetUnlockKey()
   125  	if err != nil {
   126  		logrus.WithError(err).Errorf("Error retrieving swarm unlock key")
   127  		return err
   128  	}
   129  
   130  	return httputils.WriteJSON(w, http.StatusOK, &basictypes.SwarmUnlockKeyResponse{
   131  		UnlockKey: unlockKey,
   132  	})
   133  }
   134  
   135  func (sr *swarmRouter) getServices(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   136  	if err := httputils.ParseForm(r); err != nil {
   137  		return err
   138  	}
   139  	filter, err := filters.FromParam(r.Form.Get("filters"))
   140  	if err != nil {
   141  		return err
   142  	}
   143  
   144  	services, err := sr.backend.GetServices(basictypes.ServiceListOptions{Filters: filter})
   145  	if err != nil {
   146  		logrus.Errorf("Error getting services: %v", err)
   147  		return err
   148  	}
   149  
   150  	return httputils.WriteJSON(w, http.StatusOK, services)
   151  }
   152  
   153  func (sr *swarmRouter) getService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   154  	service, err := sr.backend.GetService(vars["id"])
   155  	if err != nil {
   156  		logrus.Errorf("Error getting service %s: %v", vars["id"], err)
   157  		return err
   158  	}
   159  
   160  	return httputils.WriteJSON(w, http.StatusOK, service)
   161  }
   162  
   163  func (sr *swarmRouter) createService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   164  	var service types.ServiceSpec
   165  	if err := json.NewDecoder(r.Body).Decode(&service); err != nil {
   166  		return err
   167  	}
   168  
   169  	// Get returns "" if the header does not exist
   170  	encodedAuth := r.Header.Get("X-Registry-Auth")
   171  
   172  	resp, err := sr.backend.CreateService(service, encodedAuth)
   173  	if err != nil {
   174  		logrus.Errorf("Error creating service %s: %v", service.Name, err)
   175  		return err
   176  	}
   177  
   178  	return httputils.WriteJSON(w, http.StatusCreated, resp)
   179  }
   180  
   181  func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   182  	var service types.ServiceSpec
   183  	if err := json.NewDecoder(r.Body).Decode(&service); err != nil {
   184  		return err
   185  	}
   186  
   187  	rawVersion := r.URL.Query().Get("version")
   188  	version, err := strconv.ParseUint(rawVersion, 10, 64)
   189  	if err != nil {
   190  		err := fmt.Errorf("invalid service version '%s': %v", rawVersion, err)
   191  		return errors.NewBadRequestError(err)
   192  	}
   193  
   194  	// Get returns "" if the header does not exist
   195  	encodedAuth := r.Header.Get("X-Registry-Auth")
   196  
   197  	registryAuthFrom := r.URL.Query().Get("registryAuthFrom")
   198  
   199  	resp, err := sr.backend.UpdateService(vars["id"], version, service, encodedAuth, registryAuthFrom)
   200  	if err != nil {
   201  		logrus.Errorf("Error updating service %s: %v", vars["id"], err)
   202  		return err
   203  	}
   204  	return httputils.WriteJSON(w, http.StatusOK, resp)
   205  }
   206  
   207  func (sr *swarmRouter) removeService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   208  	if err := sr.backend.RemoveService(vars["id"]); err != nil {
   209  		logrus.Errorf("Error removing service %s: %v", vars["id"], err)
   210  		return err
   211  	}
   212  	return nil
   213  }
   214  
   215  func (sr *swarmRouter) getServiceLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   216  	if err := httputils.ParseForm(r); err != nil {
   217  		return err
   218  	}
   219  
   220  	// Args are validated before the stream starts because when it starts we're
   221  	// sending HTTP 200 by writing an empty chunk of data to tell the client that
   222  	// daemon is going to stream. By sending this initial HTTP 200 we can't report
   223  	// any error after the stream starts (i.e. container not found, wrong parameters)
   224  	// with the appropriate status code.
   225  	stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr")
   226  	if !(stdout || stderr) {
   227  		return fmt.Errorf("Bad parameters: you must choose at least one stream")
   228  	}
   229  
   230  	serviceName := vars["id"]
   231  	logsConfig := &backend.ContainerLogsConfig{
   232  		ContainerLogsOptions: basictypes.ContainerLogsOptions{
   233  			Follow:     httputils.BoolValue(r, "follow"),
   234  			Timestamps: httputils.BoolValue(r, "timestamps"),
   235  			Since:      r.Form.Get("since"),
   236  			Tail:       r.Form.Get("tail"),
   237  			ShowStdout: stdout,
   238  			ShowStderr: stderr,
   239  			Details:    httputils.BoolValue(r, "details"),
   240  		},
   241  		OutStream: w,
   242  	}
   243  
   244  	if logsConfig.Details {
   245  		return fmt.Errorf("Bad parameters: details is not currently supported")
   246  	}
   247  
   248  	chStarted := make(chan struct{})
   249  	if err := sr.backend.ServiceLogs(ctx, serviceName, logsConfig, chStarted); err != nil {
   250  		select {
   251  		case <-chStarted:
   252  			// The client may be expecting all of the data we're sending to
   253  			// be multiplexed, so send it through OutStream, which will
   254  			// have been set up to handle that if needed.
   255  			fmt.Fprintf(logsConfig.OutStream, "Error grabbing service logs: %v\n", err)
   256  		default:
   257  			return err
   258  		}
   259  	}
   260  
   261  	return nil
   262  }
   263  
   264  func (sr *swarmRouter) getNodes(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   265  	if err := httputils.ParseForm(r); err != nil {
   266  		return err
   267  	}
   268  	filter, err := filters.FromParam(r.Form.Get("filters"))
   269  	if err != nil {
   270  		return err
   271  	}
   272  
   273  	nodes, err := sr.backend.GetNodes(basictypes.NodeListOptions{Filters: filter})
   274  	if err != nil {
   275  		logrus.Errorf("Error getting nodes: %v", err)
   276  		return err
   277  	}
   278  
   279  	return httputils.WriteJSON(w, http.StatusOK, nodes)
   280  }
   281  
   282  func (sr *swarmRouter) getNode(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   283  	node, err := sr.backend.GetNode(vars["id"])
   284  	if err != nil {
   285  		logrus.Errorf("Error getting node %s: %v", vars["id"], err)
   286  		return err
   287  	}
   288  
   289  	return httputils.WriteJSON(w, http.StatusOK, node)
   290  }
   291  
   292  func (sr *swarmRouter) updateNode(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   293  	var node types.NodeSpec
   294  	if err := json.NewDecoder(r.Body).Decode(&node); err != nil {
   295  		return err
   296  	}
   297  
   298  	rawVersion := r.URL.Query().Get("version")
   299  	version, err := strconv.ParseUint(rawVersion, 10, 64)
   300  	if err != nil {
   301  		err := fmt.Errorf("invalid node version '%s': %v", rawVersion, err)
   302  		return errors.NewBadRequestError(err)
   303  	}
   304  
   305  	if err := sr.backend.UpdateNode(vars["id"], version, node); err != nil {
   306  		logrus.Errorf("Error updating node %s: %v", vars["id"], err)
   307  		return err
   308  	}
   309  	return nil
   310  }
   311  
   312  func (sr *swarmRouter) removeNode(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   313  	if err := httputils.ParseForm(r); err != nil {
   314  		return err
   315  	}
   316  
   317  	force := httputils.BoolValue(r, "force")
   318  
   319  	if err := sr.backend.RemoveNode(vars["id"], force); err != nil {
   320  		logrus.Errorf("Error removing node %s: %v", vars["id"], err)
   321  		return err
   322  	}
   323  	return nil
   324  }
   325  
   326  func (sr *swarmRouter) getTasks(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   327  	if err := httputils.ParseForm(r); err != nil {
   328  		return err
   329  	}
   330  	filter, err := filters.FromParam(r.Form.Get("filters"))
   331  	if err != nil {
   332  		return err
   333  	}
   334  
   335  	tasks, err := sr.backend.GetTasks(basictypes.TaskListOptions{Filters: filter})
   336  	if err != nil {
   337  		logrus.Errorf("Error getting tasks: %v", err)
   338  		return err
   339  	}
   340  
   341  	return httputils.WriteJSON(w, http.StatusOK, tasks)
   342  }
   343  
   344  func (sr *swarmRouter) getTask(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   345  	task, err := sr.backend.GetTask(vars["id"])
   346  	if err != nil {
   347  		logrus.Errorf("Error getting task %s: %v", vars["id"], err)
   348  		return err
   349  	}
   350  
   351  	return httputils.WriteJSON(w, http.StatusOK, task)
   352  }
   353  
   354  func (sr *swarmRouter) getSecrets(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   355  	if err := httputils.ParseForm(r); err != nil {
   356  		return err
   357  	}
   358  	filters, err := filters.FromParam(r.Form.Get("filters"))
   359  	if err != nil {
   360  		return err
   361  	}
   362  
   363  	secrets, err := sr.backend.GetSecrets(basictypes.SecretListOptions{Filters: filters})
   364  	if err != nil {
   365  		return err
   366  	}
   367  
   368  	return httputils.WriteJSON(w, http.StatusOK, secrets)
   369  }
   370  
   371  func (sr *swarmRouter) createSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   372  	var secret types.SecretSpec
   373  	if err := json.NewDecoder(r.Body).Decode(&secret); err != nil {
   374  		return err
   375  	}
   376  
   377  	id, err := sr.backend.CreateSecret(secret)
   378  	if err != nil {
   379  		return err
   380  	}
   381  
   382  	return httputils.WriteJSON(w, http.StatusCreated, &basictypes.SecretCreateResponse{
   383  		ID: id,
   384  	})
   385  }
   386  
   387  func (sr *swarmRouter) removeSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   388  	if err := sr.backend.RemoveSecret(vars["id"]); err != nil {
   389  		return err
   390  	}
   391  	w.WriteHeader(http.StatusNoContent)
   392  
   393  	return nil
   394  }
   395  
   396  func (sr *swarmRouter) getSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   397  	secret, err := sr.backend.GetSecret(vars["id"])
   398  	if err != nil {
   399  		return err
   400  	}
   401  
   402  	return httputils.WriteJSON(w, http.StatusOK, secret)
   403  }
   404  
   405  func (sr *swarmRouter) updateSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   406  	var secret types.SecretSpec
   407  	if err := json.NewDecoder(r.Body).Decode(&secret); err != nil {
   408  		return errors.NewBadRequestError(err)
   409  	}
   410  
   411  	rawVersion := r.URL.Query().Get("version")
   412  	version, err := strconv.ParseUint(rawVersion, 10, 64)
   413  	if err != nil {
   414  		return errors.NewBadRequestError(fmt.Errorf("invalid secret version"))
   415  	}
   416  
   417  	id := vars["id"]
   418  	if err := sr.backend.UpdateSecret(id, version, secret); err != nil {
   419  		return err
   420  	}
   421  
   422  	return nil
   423  }