github.com/rumpl/bof@v23.0.0-rc.2+incompatible/api/server/router/swarm/cluster_routes.go (about)

     1  package swarm // import "github.com/docker/docker/api/server/router/swarm"
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  	"strconv"
     8  
     9  	"github.com/docker/docker/api/server/httputils"
    10  	basictypes "github.com/docker/docker/api/types"
    11  	"github.com/docker/docker/api/types/backend"
    12  	"github.com/docker/docker/api/types/filters"
    13  	types "github.com/docker/docker/api/types/swarm"
    14  	"github.com/docker/docker/api/types/versions"
    15  	"github.com/docker/docker/errdefs"
    16  	"github.com/pkg/errors"
    17  	"github.com/sirupsen/logrus"
    18  )
    19  
    20  func (sr *swarmRouter) initCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    21  	var req types.InitRequest
    22  	if err := httputils.ReadJSON(r, &req); err != nil {
    23  		return err
    24  	}
    25  	version := httputils.VersionFromContext(ctx)
    26  
    27  	// DefaultAddrPool and SubnetSize were added in API 1.39. Ignore on older API versions.
    28  	if versions.LessThan(version, "1.39") {
    29  		req.DefaultAddrPool = nil
    30  		req.SubnetSize = 0
    31  	}
    32  	// DataPathPort was added in API 1.40. Ignore this option on older API versions.
    33  	if versions.LessThan(version, "1.40") {
    34  		req.DataPathPort = 0
    35  	}
    36  	nodeID, err := sr.backend.Init(req)
    37  	if err != nil {
    38  		logrus.Errorf("Error initializing swarm: %v", err)
    39  		return err
    40  	}
    41  	return httputils.WriteJSON(w, http.StatusOK, nodeID)
    42  }
    43  
    44  func (sr *swarmRouter) joinCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    45  	var req types.JoinRequest
    46  	if err := httputils.ReadJSON(r, &req); err != nil {
    47  		return err
    48  	}
    49  	return sr.backend.Join(req)
    50  }
    51  
    52  func (sr *swarmRouter) leaveCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    53  	if err := httputils.ParseForm(r); err != nil {
    54  		return err
    55  	}
    56  
    57  	force := httputils.BoolValue(r, "force")
    58  	return sr.backend.Leave(force)
    59  }
    60  
    61  func (sr *swarmRouter) inspectCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    62  	swarm, err := sr.backend.Inspect()
    63  	if err != nil {
    64  		logrus.Errorf("Error getting swarm: %v", err)
    65  		return err
    66  	}
    67  
    68  	return httputils.WriteJSON(w, http.StatusOK, swarm)
    69  }
    70  
    71  func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    72  	var swarm types.Spec
    73  	if err := httputils.ReadJSON(r, &swarm); err != nil {
    74  		return err
    75  	}
    76  
    77  	rawVersion := r.URL.Query().Get("version")
    78  	version, err := strconv.ParseUint(rawVersion, 10, 64)
    79  	if err != nil {
    80  		err := fmt.Errorf("invalid swarm version '%s': %v", rawVersion, err)
    81  		return errdefs.InvalidParameter(err)
    82  	}
    83  
    84  	var flags types.UpdateFlags
    85  
    86  	if value := r.URL.Query().Get("rotateWorkerToken"); value != "" {
    87  		rot, err := strconv.ParseBool(value)
    88  		if err != nil {
    89  			err := fmt.Errorf("invalid value for rotateWorkerToken: %s", value)
    90  			return errdefs.InvalidParameter(err)
    91  		}
    92  
    93  		flags.RotateWorkerToken = rot
    94  	}
    95  
    96  	if value := r.URL.Query().Get("rotateManagerToken"); value != "" {
    97  		rot, err := strconv.ParseBool(value)
    98  		if err != nil {
    99  			err := fmt.Errorf("invalid value for rotateManagerToken: %s", value)
   100  			return errdefs.InvalidParameter(err)
   101  		}
   102  
   103  		flags.RotateManagerToken = rot
   104  	}
   105  
   106  	if value := r.URL.Query().Get("rotateManagerUnlockKey"); value != "" {
   107  		rot, err := strconv.ParseBool(value)
   108  		if err != nil {
   109  			return errdefs.InvalidParameter(fmt.Errorf("invalid value for rotateManagerUnlockKey: %s", value))
   110  		}
   111  
   112  		flags.RotateManagerUnlockKey = rot
   113  	}
   114  
   115  	if err := sr.backend.Update(version, swarm, flags); err != nil {
   116  		logrus.Errorf("Error configuring swarm: %v", err)
   117  		return err
   118  	}
   119  	return nil
   120  }
   121  
   122  func (sr *swarmRouter) unlockCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   123  	var req types.UnlockRequest
   124  	if err := httputils.ReadJSON(r, &req); err != nil {
   125  		return err
   126  	}
   127  
   128  	if err := sr.backend.UnlockSwarm(req); err != nil {
   129  		logrus.Errorf("Error unlocking swarm: %v", err)
   130  		return err
   131  	}
   132  	return nil
   133  }
   134  
   135  func (sr *swarmRouter) getUnlockKey(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   136  	unlockKey, err := sr.backend.GetUnlockKey()
   137  	if err != nil {
   138  		logrus.WithError(err).Errorf("Error retrieving swarm unlock key")
   139  		return err
   140  	}
   141  
   142  	return httputils.WriteJSON(w, http.StatusOK, &basictypes.SwarmUnlockKeyResponse{
   143  		UnlockKey: unlockKey,
   144  	})
   145  }
   146  
   147  func (sr *swarmRouter) getServices(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   148  	if err := httputils.ParseForm(r); err != nil {
   149  		return err
   150  	}
   151  	filter, err := filters.FromJSON(r.Form.Get("filters"))
   152  	if err != nil {
   153  		return err
   154  	}
   155  
   156  	// the status query parameter is only support in API versions >= 1.41. If
   157  	// the client is using a lesser version, ignore the parameter.
   158  	cliVersion := httputils.VersionFromContext(ctx)
   159  	var status bool
   160  	if value := r.URL.Query().Get("status"); value != "" && !versions.LessThan(cliVersion, "1.41") {
   161  		var err error
   162  		status, err = strconv.ParseBool(value)
   163  		if err != nil {
   164  			return errors.Wrapf(errdefs.InvalidParameter(err), "invalid value for status: %s", value)
   165  		}
   166  	}
   167  
   168  	services, err := sr.backend.GetServices(basictypes.ServiceListOptions{Filters: filter, Status: status})
   169  	if err != nil {
   170  		logrus.Errorf("Error getting services: %v", err)
   171  		return err
   172  	}
   173  
   174  	return httputils.WriteJSON(w, http.StatusOK, services)
   175  }
   176  
   177  func (sr *swarmRouter) getService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   178  	var insertDefaults bool
   179  
   180  	if value := r.URL.Query().Get("insertDefaults"); value != "" {
   181  		var err error
   182  		insertDefaults, err = strconv.ParseBool(value)
   183  		if err != nil {
   184  			return errors.Wrapf(errdefs.InvalidParameter(err), "invalid value for insertDefaults: %s", value)
   185  		}
   186  	}
   187  
   188  	// you may note that there is no code here to handle the "status" query
   189  	// parameter, as in getServices. the Status field is not supported when
   190  	// retrieving an individual service because the Backend API changes
   191  	// required to accommodate it would be too disruptive, and because that
   192  	// field is so rarely needed as part of an individual service inspection.
   193  
   194  	service, err := sr.backend.GetService(vars["id"], insertDefaults)
   195  	if err != nil {
   196  		logrus.Errorf("Error getting service %s: %v", vars["id"], err)
   197  		return err
   198  	}
   199  
   200  	return httputils.WriteJSON(w, http.StatusOK, service)
   201  }
   202  
   203  func (sr *swarmRouter) createService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   204  	var service types.ServiceSpec
   205  	if err := httputils.ReadJSON(r, &service); err != nil {
   206  		return err
   207  	}
   208  
   209  	// Get returns "" if the header does not exist
   210  	encodedAuth := r.Header.Get("X-Registry-Auth")
   211  	queryRegistry := false
   212  	if v := httputils.VersionFromContext(ctx); v != "" {
   213  		if versions.LessThan(v, "1.30") {
   214  			queryRegistry = true
   215  		}
   216  		adjustForAPIVersion(v, &service)
   217  	}
   218  	resp, err := sr.backend.CreateService(service, encodedAuth, queryRegistry)
   219  	if err != nil {
   220  		logrus.Errorf("Error creating service %s: %v", service.Name, err)
   221  		return err
   222  	}
   223  
   224  	return httputils.WriteJSON(w, http.StatusCreated, resp)
   225  }
   226  
   227  func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   228  	var service types.ServiceSpec
   229  	if err := httputils.ReadJSON(r, &service); err != nil {
   230  		return err
   231  	}
   232  
   233  	rawVersion := r.URL.Query().Get("version")
   234  	version, err := strconv.ParseUint(rawVersion, 10, 64)
   235  	if err != nil {
   236  		err := fmt.Errorf("invalid service version '%s': %v", rawVersion, err)
   237  		return errdefs.InvalidParameter(err)
   238  	}
   239  
   240  	var flags basictypes.ServiceUpdateOptions
   241  
   242  	// Get returns "" if the header does not exist
   243  	flags.EncodedRegistryAuth = r.Header.Get("X-Registry-Auth")
   244  	flags.RegistryAuthFrom = r.URL.Query().Get("registryAuthFrom")
   245  	flags.Rollback = r.URL.Query().Get("rollback")
   246  	queryRegistry := false
   247  	if v := httputils.VersionFromContext(ctx); v != "" {
   248  		if versions.LessThan(v, "1.30") {
   249  			queryRegistry = true
   250  		}
   251  		adjustForAPIVersion(v, &service)
   252  	}
   253  
   254  	resp, err := sr.backend.UpdateService(vars["id"], version, service, flags, queryRegistry)
   255  	if err != nil {
   256  		logrus.Errorf("Error updating service %s: %v", vars["id"], err)
   257  		return err
   258  	}
   259  	return httputils.WriteJSON(w, http.StatusOK, resp)
   260  }
   261  
   262  func (sr *swarmRouter) removeService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   263  	if err := sr.backend.RemoveService(vars["id"]); err != nil {
   264  		logrus.Errorf("Error removing service %s: %v", vars["id"], err)
   265  		return err
   266  	}
   267  	return nil
   268  }
   269  
   270  func (sr *swarmRouter) getTaskLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   271  	if err := httputils.ParseForm(r); err != nil {
   272  		return err
   273  	}
   274  
   275  	// make a selector to pass to the helper function
   276  	selector := &backend.LogSelector{
   277  		Tasks: []string{vars["id"]},
   278  	}
   279  	return sr.swarmLogs(ctx, w, r, selector)
   280  }
   281  
   282  func (sr *swarmRouter) getServiceLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   283  	if err := httputils.ParseForm(r); err != nil {
   284  		return err
   285  	}
   286  
   287  	// make a selector to pass to the helper function
   288  	selector := &backend.LogSelector{
   289  		Services: []string{vars["id"]},
   290  	}
   291  	return sr.swarmLogs(ctx, w, r, selector)
   292  }
   293  
   294  func (sr *swarmRouter) getNodes(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   295  	if err := httputils.ParseForm(r); err != nil {
   296  		return err
   297  	}
   298  	filter, err := filters.FromJSON(r.Form.Get("filters"))
   299  	if err != nil {
   300  		return err
   301  	}
   302  
   303  	nodes, err := sr.backend.GetNodes(basictypes.NodeListOptions{Filters: filter})
   304  	if err != nil {
   305  		logrus.Errorf("Error getting nodes: %v", err)
   306  		return err
   307  	}
   308  
   309  	return httputils.WriteJSON(w, http.StatusOK, nodes)
   310  }
   311  
   312  func (sr *swarmRouter) getNode(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   313  	node, err := sr.backend.GetNode(vars["id"])
   314  	if err != nil {
   315  		logrus.Errorf("Error getting node %s: %v", vars["id"], err)
   316  		return err
   317  	}
   318  
   319  	return httputils.WriteJSON(w, http.StatusOK, node)
   320  }
   321  
   322  func (sr *swarmRouter) updateNode(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   323  	var node types.NodeSpec
   324  	if err := httputils.ReadJSON(r, &node); err != nil {
   325  		return err
   326  	}
   327  
   328  	rawVersion := r.URL.Query().Get("version")
   329  	version, err := strconv.ParseUint(rawVersion, 10, 64)
   330  	if err != nil {
   331  		err := fmt.Errorf("invalid node version '%s': %v", rawVersion, err)
   332  		return errdefs.InvalidParameter(err)
   333  	}
   334  
   335  	if err := sr.backend.UpdateNode(vars["id"], version, node); err != nil {
   336  		logrus.Errorf("Error updating node %s: %v", vars["id"], err)
   337  		return err
   338  	}
   339  	return nil
   340  }
   341  
   342  func (sr *swarmRouter) removeNode(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   343  	if err := httputils.ParseForm(r); err != nil {
   344  		return err
   345  	}
   346  
   347  	force := httputils.BoolValue(r, "force")
   348  
   349  	if err := sr.backend.RemoveNode(vars["id"], force); err != nil {
   350  		logrus.Errorf("Error removing node %s: %v", vars["id"], err)
   351  		return err
   352  	}
   353  	return nil
   354  }
   355  
   356  func (sr *swarmRouter) getTasks(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   357  	if err := httputils.ParseForm(r); err != nil {
   358  		return err
   359  	}
   360  	filter, err := filters.FromJSON(r.Form.Get("filters"))
   361  	if err != nil {
   362  		return err
   363  	}
   364  
   365  	tasks, err := sr.backend.GetTasks(basictypes.TaskListOptions{Filters: filter})
   366  	if err != nil {
   367  		logrus.Errorf("Error getting tasks: %v", err)
   368  		return err
   369  	}
   370  
   371  	return httputils.WriteJSON(w, http.StatusOK, tasks)
   372  }
   373  
   374  func (sr *swarmRouter) getTask(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   375  	task, err := sr.backend.GetTask(vars["id"])
   376  	if err != nil {
   377  		logrus.Errorf("Error getting task %s: %v", vars["id"], err)
   378  		return err
   379  	}
   380  
   381  	return httputils.WriteJSON(w, http.StatusOK, task)
   382  }
   383  
   384  func (sr *swarmRouter) getSecrets(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   385  	if err := httputils.ParseForm(r); err != nil {
   386  		return err
   387  	}
   388  	filters, err := filters.FromJSON(r.Form.Get("filters"))
   389  	if err != nil {
   390  		return err
   391  	}
   392  
   393  	secrets, err := sr.backend.GetSecrets(basictypes.SecretListOptions{Filters: filters})
   394  	if err != nil {
   395  		return err
   396  	}
   397  
   398  	return httputils.WriteJSON(w, http.StatusOK, secrets)
   399  }
   400  
   401  func (sr *swarmRouter) createSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   402  	var secret types.SecretSpec
   403  	if err := httputils.ReadJSON(r, &secret); err != nil {
   404  		return err
   405  	}
   406  	version := httputils.VersionFromContext(ctx)
   407  	if secret.Templating != nil && versions.LessThan(version, "1.37") {
   408  		return errdefs.InvalidParameter(errors.Errorf("secret templating is not supported on the specified API version: %s", version))
   409  	}
   410  
   411  	id, err := sr.backend.CreateSecret(secret)
   412  	if err != nil {
   413  		return err
   414  	}
   415  
   416  	return httputils.WriteJSON(w, http.StatusCreated, &basictypes.SecretCreateResponse{
   417  		ID: id,
   418  	})
   419  }
   420  
   421  func (sr *swarmRouter) removeSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   422  	if err := sr.backend.RemoveSecret(vars["id"]); err != nil {
   423  		return err
   424  	}
   425  	w.WriteHeader(http.StatusNoContent)
   426  
   427  	return nil
   428  }
   429  
   430  func (sr *swarmRouter) getSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   431  	secret, err := sr.backend.GetSecret(vars["id"])
   432  	if err != nil {
   433  		return err
   434  	}
   435  
   436  	return httputils.WriteJSON(w, http.StatusOK, secret)
   437  }
   438  
   439  func (sr *swarmRouter) updateSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   440  	var secret types.SecretSpec
   441  	if err := httputils.ReadJSON(r, &secret); err != nil {
   442  		return err
   443  	}
   444  
   445  	rawVersion := r.URL.Query().Get("version")
   446  	version, err := strconv.ParseUint(rawVersion, 10, 64)
   447  	if err != nil {
   448  		return errdefs.InvalidParameter(fmt.Errorf("invalid secret version"))
   449  	}
   450  
   451  	id := vars["id"]
   452  	return sr.backend.UpdateSecret(id, version, secret)
   453  }
   454  
   455  func (sr *swarmRouter) getConfigs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   456  	if err := httputils.ParseForm(r); err != nil {
   457  		return err
   458  	}
   459  	filters, err := filters.FromJSON(r.Form.Get("filters"))
   460  	if err != nil {
   461  		return err
   462  	}
   463  
   464  	configs, err := sr.backend.GetConfigs(basictypes.ConfigListOptions{Filters: filters})
   465  	if err != nil {
   466  		return err
   467  	}
   468  
   469  	return httputils.WriteJSON(w, http.StatusOK, configs)
   470  }
   471  
   472  func (sr *swarmRouter) createConfig(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   473  	var config types.ConfigSpec
   474  	if err := httputils.ReadJSON(r, &config); err != nil {
   475  		return err
   476  	}
   477  
   478  	version := httputils.VersionFromContext(ctx)
   479  	if config.Templating != nil && versions.LessThan(version, "1.37") {
   480  		return errdefs.InvalidParameter(errors.Errorf("config templating is not supported on the specified API version: %s", version))
   481  	}
   482  
   483  	id, err := sr.backend.CreateConfig(config)
   484  	if err != nil {
   485  		return err
   486  	}
   487  
   488  	return httputils.WriteJSON(w, http.StatusCreated, &basictypes.ConfigCreateResponse{
   489  		ID: id,
   490  	})
   491  }
   492  
   493  func (sr *swarmRouter) removeConfig(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   494  	if err := sr.backend.RemoveConfig(vars["id"]); err != nil {
   495  		return err
   496  	}
   497  	w.WriteHeader(http.StatusNoContent)
   498  
   499  	return nil
   500  }
   501  
   502  func (sr *swarmRouter) getConfig(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   503  	config, err := sr.backend.GetConfig(vars["id"])
   504  	if err != nil {
   505  		return err
   506  	}
   507  
   508  	return httputils.WriteJSON(w, http.StatusOK, config)
   509  }
   510  
   511  func (sr *swarmRouter) updateConfig(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   512  	var config types.ConfigSpec
   513  	if err := httputils.ReadJSON(r, &config); err != nil {
   514  		return err
   515  	}
   516  
   517  	rawVersion := r.URL.Query().Get("version")
   518  	version, err := strconv.ParseUint(rawVersion, 10, 64)
   519  	if err != nil {
   520  		return errdefs.InvalidParameter(fmt.Errorf("invalid config version"))
   521  	}
   522  
   523  	id := vars["id"]
   524  	return sr.backend.UpdateConfig(id, version, config)
   525  }