github.com/nullne/docker@v1.13.0-rc1/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  	id, 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, &basictypes.ServiceCreateResponse{
   176  		ID: id,
   177  	})
   178  }
   179  
   180  func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   181  	var service types.ServiceSpec
   182  	if err := json.NewDecoder(r.Body).Decode(&service); err != nil {
   183  		return err
   184  	}
   185  
   186  	rawVersion := r.URL.Query().Get("version")
   187  	version, err := strconv.ParseUint(rawVersion, 10, 64)
   188  	if err != nil {
   189  		return fmt.Errorf("Invalid service version '%s': %s", rawVersion, err.Error())
   190  	}
   191  
   192  	// Get returns "" if the header does not exist
   193  	encodedAuth := r.Header.Get("X-Registry-Auth")
   194  
   195  	registryAuthFrom := r.URL.Query().Get("registryAuthFrom")
   196  
   197  	if err := sr.backend.UpdateService(vars["id"], version, service, encodedAuth, registryAuthFrom); err != nil {
   198  		logrus.Errorf("Error updating service %s: %v", vars["id"], err)
   199  		return err
   200  	}
   201  	return nil
   202  }
   203  
   204  func (sr *swarmRouter) removeService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   205  	if err := sr.backend.RemoveService(vars["id"]); err != nil {
   206  		logrus.Errorf("Error removing service %s: %v", vars["id"], err)
   207  		return err
   208  	}
   209  	return nil
   210  }
   211  
   212  func (sr *swarmRouter) getServiceLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   213  	if err := httputils.ParseForm(r); err != nil {
   214  		return err
   215  	}
   216  
   217  	// Args are validated before the stream starts because when it starts we're
   218  	// sending HTTP 200 by writing an empty chunk of data to tell the client that
   219  	// daemon is going to stream. By sending this initial HTTP 200 we can't report
   220  	// any error after the stream starts (i.e. container not found, wrong parameters)
   221  	// with the appropriate status code.
   222  	stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr")
   223  	if !(stdout || stderr) {
   224  		return fmt.Errorf("Bad parameters: you must choose at least one stream")
   225  	}
   226  
   227  	serviceName := vars["id"]
   228  	logsConfig := &backend.ContainerLogsConfig{
   229  		ContainerLogsOptions: basictypes.ContainerLogsOptions{
   230  			Follow:     httputils.BoolValue(r, "follow"),
   231  			Timestamps: httputils.BoolValue(r, "timestamps"),
   232  			Since:      r.Form.Get("since"),
   233  			Tail:       r.Form.Get("tail"),
   234  			ShowStdout: stdout,
   235  			ShowStderr: stderr,
   236  			Details:    httputils.BoolValue(r, "details"),
   237  		},
   238  		OutStream: w,
   239  	}
   240  
   241  	if !logsConfig.Follow {
   242  		return fmt.Errorf("Bad parameters: Only follow mode is currently supported")
   243  	}
   244  
   245  	if logsConfig.Details {
   246  		return fmt.Errorf("Bad parameters: details is not currently supported")
   247  	}
   248  
   249  	chStarted := make(chan struct{})
   250  	if err := sr.backend.ServiceLogs(ctx, serviceName, logsConfig, chStarted); err != nil {
   251  		select {
   252  		case <-chStarted:
   253  			// The client may be expecting all of the data we're sending to
   254  			// be multiplexed, so send it through OutStream, which will
   255  			// have been set up to handle that if needed.
   256  			fmt.Fprintf(logsConfig.OutStream, "Error grabbing service logs: %v\n", err)
   257  		default:
   258  			return err
   259  		}
   260  	}
   261  
   262  	return nil
   263  }
   264  
   265  func (sr *swarmRouter) getNodes(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   266  	if err := httputils.ParseForm(r); err != nil {
   267  		return err
   268  	}
   269  	filter, err := filters.FromParam(r.Form.Get("filters"))
   270  	if err != nil {
   271  		return err
   272  	}
   273  
   274  	nodes, err := sr.backend.GetNodes(basictypes.NodeListOptions{Filters: filter})
   275  	if err != nil {
   276  		logrus.Errorf("Error getting nodes: %v", err)
   277  		return err
   278  	}
   279  
   280  	return httputils.WriteJSON(w, http.StatusOK, nodes)
   281  }
   282  
   283  func (sr *swarmRouter) getNode(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   284  	node, err := sr.backend.GetNode(vars["id"])
   285  	if err != nil {
   286  		logrus.Errorf("Error getting node %s: %v", vars["id"], err)
   287  		return err
   288  	}
   289  
   290  	return httputils.WriteJSON(w, http.StatusOK, node)
   291  }
   292  
   293  func (sr *swarmRouter) updateNode(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   294  	var node types.NodeSpec
   295  	if err := json.NewDecoder(r.Body).Decode(&node); err != nil {
   296  		return err
   297  	}
   298  
   299  	rawVersion := r.URL.Query().Get("version")
   300  	version, err := strconv.ParseUint(rawVersion, 10, 64)
   301  	if err != nil {
   302  		return fmt.Errorf("Invalid node version '%s': %s", rawVersion, err.Error())
   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  
   392  	return nil
   393  }
   394  
   395  func (sr *swarmRouter) getSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   396  	secret, err := sr.backend.GetSecret(vars["id"])
   397  	if err != nil {
   398  		return err
   399  	}
   400  
   401  	return httputils.WriteJSON(w, http.StatusOK, secret)
   402  }
   403  
   404  func (sr *swarmRouter) updateSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   405  	var secret types.SecretSpec
   406  	if err := json.NewDecoder(r.Body).Decode(&secret); err != nil {
   407  		return errors.NewBadRequestError(err)
   408  	}
   409  
   410  	rawVersion := r.URL.Query().Get("version")
   411  	version, err := strconv.ParseUint(rawVersion, 10, 64)
   412  	if err != nil {
   413  		return errors.NewBadRequestError(fmt.Errorf("invalid secret version"))
   414  	}
   415  
   416  	id := vars["id"]
   417  	if err := sr.backend.UpdateSecret(id, version, secret); err != nil {
   418  		return err
   419  	}
   420  
   421  	return nil
   422  }