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