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