github.com/endophage/docker@v1.4.2-0.20161027011718-242853499895/integration-cli/docker_cli_swarm_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "encoding/json" 7 "fmt" 8 "io/ioutil" 9 "net/http" 10 "net/http/httptest" 11 "os" 12 "strings" 13 "time" 14 15 "github.com/docker/docker/api/types/swarm" 16 "github.com/docker/docker/pkg/integration/checker" 17 "github.com/docker/libnetwork/driverapi" 18 "github.com/docker/libnetwork/ipamapi" 19 remoteipam "github.com/docker/libnetwork/ipams/remote/api" 20 "github.com/go-check/check" 21 "github.com/vishvananda/netlink" 22 ) 23 24 func (s *DockerSwarmSuite) TestSwarmUpdate(c *check.C) { 25 d := s.AddDaemon(c, true, true) 26 27 getSpec := func() swarm.Spec { 28 sw := d.getSwarm(c) 29 return sw.Spec 30 } 31 32 out, err := d.Cmd("swarm", "update", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s") 33 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 34 35 spec := getSpec() 36 c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour) 37 c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, 11*time.Second) 38 39 // setting anything under 30m for cert-expiry is not allowed 40 out, err = d.Cmd("swarm", "update", "--cert-expiry", "15m") 41 c.Assert(err, checker.NotNil) 42 c.Assert(out, checker.Contains, "minimum certificate expiry time") 43 spec = getSpec() 44 c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour) 45 } 46 47 func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) { 48 d := s.AddDaemon(c, false, false) 49 50 getSpec := func() swarm.Spec { 51 sw := d.getSwarm(c) 52 return sw.Spec 53 } 54 55 out, err := d.Cmd("swarm", "init", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s") 56 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 57 58 spec := getSpec() 59 c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour) 60 c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, 11*time.Second) 61 62 c.Assert(d.Leave(true), checker.IsNil) 63 time.Sleep(500 * time.Millisecond) // https://github.com/docker/swarmkit/issues/1421 64 out, err = d.Cmd("swarm", "init") 65 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 66 67 spec = getSpec() 68 c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 90*24*time.Hour) 69 c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, 5*time.Second) 70 } 71 72 func (s *DockerSwarmSuite) TestSwarmInitIPv6(c *check.C) { 73 testRequires(c, IPv6) 74 d1 := s.AddDaemon(c, false, false) 75 out, err := d1.Cmd("swarm", "init", "--listen-addr", "::1") 76 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 77 78 d2 := s.AddDaemon(c, false, false) 79 out, err = d2.Cmd("swarm", "join", "::1") 80 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 81 82 out, err = d2.Cmd("info") 83 c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) 84 c.Assert(out, checker.Contains, "Swarm: active") 85 } 86 87 func (s *DockerSwarmSuite) TestSwarmIncompatibleDaemon(c *check.C) { 88 // init swarm mode and stop a daemon 89 d := s.AddDaemon(c, true, true) 90 info, err := d.info() 91 c.Assert(err, checker.IsNil) 92 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 93 c.Assert(d.Stop(), checker.IsNil) 94 95 // start a daemon with --cluster-store and --cluster-advertise 96 err = d.Start("--cluster-store=consul://consuladdr:consulport/some/path", "--cluster-advertise=1.1.1.1:2375") 97 c.Assert(err, checker.NotNil) 98 content, _ := ioutil.ReadFile(d.logFile.Name()) 99 c.Assert(string(content), checker.Contains, "--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode") 100 101 // start a daemon with --live-restore 102 err = d.Start("--live-restore") 103 c.Assert(err, checker.NotNil) 104 content, _ = ioutil.ReadFile(d.logFile.Name()) 105 c.Assert(string(content), checker.Contains, "--live-restore daemon configuration is incompatible with swarm mode") 106 // restart for teardown 107 c.Assert(d.Start(), checker.IsNil) 108 } 109 110 // Test case for #24090 111 func (s *DockerSwarmSuite) TestSwarmNodeListHostname(c *check.C) { 112 d := s.AddDaemon(c, true, true) 113 114 // The first line should contain "HOSTNAME" 115 out, err := d.Cmd("node", "ls") 116 c.Assert(err, checker.IsNil) 117 c.Assert(strings.Split(out, "\n")[0], checker.Contains, "HOSTNAME") 118 } 119 120 // Test case for #24270 121 func (s *DockerSwarmSuite) TestSwarmServiceListFilter(c *check.C) { 122 d := s.AddDaemon(c, true, true) 123 124 name1 := "redis-cluster-md5" 125 name2 := "redis-cluster" 126 name3 := "other-cluster" 127 out, err := d.Cmd("service", "create", "--name", name1, "busybox", "top") 128 c.Assert(err, checker.IsNil) 129 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 130 131 out, err = d.Cmd("service", "create", "--name", name2, "busybox", "top") 132 c.Assert(err, checker.IsNil) 133 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 134 135 out, err = d.Cmd("service", "create", "--name", name3, "busybox", "top") 136 c.Assert(err, checker.IsNil) 137 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 138 139 filter1 := "name=redis-cluster-md5" 140 filter2 := "name=redis-cluster" 141 142 // We search checker.Contains with `name+" "` to prevent prefix only. 143 out, err = d.Cmd("service", "ls", "--filter", filter1) 144 c.Assert(err, checker.IsNil) 145 c.Assert(out, checker.Contains, name1+" ") 146 c.Assert(out, checker.Not(checker.Contains), name2+" ") 147 c.Assert(out, checker.Not(checker.Contains), name3+" ") 148 149 out, err = d.Cmd("service", "ls", "--filter", filter2) 150 c.Assert(err, checker.IsNil) 151 c.Assert(out, checker.Contains, name1+" ") 152 c.Assert(out, checker.Contains, name2+" ") 153 c.Assert(out, checker.Not(checker.Contains), name3+" ") 154 155 out, err = d.Cmd("service", "ls") 156 c.Assert(err, checker.IsNil) 157 c.Assert(out, checker.Contains, name1+" ") 158 c.Assert(out, checker.Contains, name2+" ") 159 c.Assert(out, checker.Contains, name3+" ") 160 } 161 162 func (s *DockerSwarmSuite) TestSwarmNodeListFilter(c *check.C) { 163 d := s.AddDaemon(c, true, true) 164 165 out, err := d.Cmd("node", "inspect", "--format", "{{ .Description.Hostname }}", "self") 166 c.Assert(err, checker.IsNil) 167 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 168 name := strings.TrimSpace(out) 169 170 filter := "name=" + name[:4] 171 172 out, err = d.Cmd("node", "ls", "--filter", filter) 173 c.Assert(err, checker.IsNil) 174 c.Assert(out, checker.Contains, name) 175 176 out, err = d.Cmd("node", "ls", "--filter", "name=none") 177 c.Assert(err, checker.IsNil) 178 c.Assert(out, checker.Not(checker.Contains), name) 179 } 180 181 func (s *DockerSwarmSuite) TestSwarmNodeTaskListFilter(c *check.C) { 182 d := s.AddDaemon(c, true, true) 183 184 name := "redis-cluster-md5" 185 out, err := d.Cmd("service", "create", "--name", name, "--replicas=3", "busybox", "top") 186 c.Assert(err, checker.IsNil) 187 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 188 189 // make sure task has been deployed. 190 waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 3) 191 192 filter := "name=redis-cluster" 193 194 out, err = d.Cmd("node", "ps", "--filter", filter, "self") 195 c.Assert(err, checker.IsNil) 196 c.Assert(out, checker.Contains, name+".1") 197 c.Assert(out, checker.Contains, name+".2") 198 c.Assert(out, checker.Contains, name+".3") 199 200 out, err = d.Cmd("node", "ps", "--filter", "name=none", "self") 201 c.Assert(err, checker.IsNil) 202 c.Assert(out, checker.Not(checker.Contains), name+".1") 203 c.Assert(out, checker.Not(checker.Contains), name+".2") 204 c.Assert(out, checker.Not(checker.Contains), name+".3") 205 } 206 207 // Test case for #25375 208 func (s *DockerSwarmSuite) TestSwarmPublishAdd(c *check.C) { 209 d := s.AddDaemon(c, true, true) 210 211 name := "top" 212 out, err := d.Cmd("service", "create", "--name", name, "--label", "x=y", "busybox", "top") 213 c.Assert(err, checker.IsNil) 214 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 215 216 out, err = d.Cmd("service", "update", "--publish-add", "80:80", name) 217 c.Assert(err, checker.IsNil) 218 219 out, err = d.cmdRetryOutOfSequence("service", "update", "--publish-add", "80:80", name) 220 c.Assert(err, checker.IsNil) 221 222 out, err = d.cmdRetryOutOfSequence("service", "update", "--publish-add", "80:80", "--publish-add", "80:20", name) 223 c.Assert(err, checker.NotNil) 224 225 out, err = d.cmdRetryOutOfSequence("service", "update", "--publish-add", "80:20", name) 226 c.Assert(err, checker.IsNil) 227 228 out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.EndpointSpec.Ports }}", name) 229 c.Assert(err, checker.IsNil) 230 c.Assert(strings.TrimSpace(out), checker.Equals, "[{ tcp 20 80}]") 231 } 232 233 func (s *DockerSwarmSuite) TestSwarmServiceWithGroup(c *check.C) { 234 d := s.AddDaemon(c, true, true) 235 236 name := "top" 237 out, err := d.Cmd("service", "create", "--name", name, "--user", "root:root", "--group-add", "wheel", "--group-add", "audio", "--group-add", "staff", "--group-add", "777", "busybox", "top") 238 c.Assert(err, checker.IsNil) 239 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 240 241 // make sure task has been deployed. 242 waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 1) 243 244 out, err = d.Cmd("ps", "-q") 245 c.Assert(err, checker.IsNil) 246 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 247 248 container := strings.TrimSpace(out) 249 250 out, err = d.Cmd("exec", container, "id") 251 c.Assert(err, checker.IsNil) 252 c.Assert(strings.TrimSpace(out), checker.Equals, "uid=0(root) gid=0(root) groups=10(wheel),29(audio),50(staff),777") 253 } 254 255 func (s *DockerSwarmSuite) TestSwarmContainerAutoStart(c *check.C) { 256 d := s.AddDaemon(c, true, true) 257 258 out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", "foo") 259 c.Assert(err, checker.IsNil) 260 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 261 262 out, err = d.Cmd("run", "-id", "--restart=always", "--net=foo", "--name=test", "busybox", "top") 263 c.Assert(err, checker.IsNil) 264 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 265 266 out, err = d.Cmd("ps", "-q") 267 c.Assert(err, checker.IsNil) 268 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 269 270 d.Restart() 271 272 out, err = d.Cmd("ps", "-q") 273 c.Assert(err, checker.IsNil) 274 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 275 } 276 277 func (s *DockerSwarmSuite) TestSwarmRemoveInternalNetwork(c *check.C) { 278 d := s.AddDaemon(c, true, true) 279 280 name := "ingress" 281 out, err := d.Cmd("network", "rm", name) 282 c.Assert(err, checker.NotNil) 283 c.Assert(strings.TrimSpace(out), checker.Contains, name) 284 c.Assert(strings.TrimSpace(out), checker.Contains, "is a pre-defined network and cannot be removed") 285 } 286 287 // Test case for #24108, also the case from: 288 // https://github.com/docker/docker/pull/24620#issuecomment-233715656 289 func (s *DockerSwarmSuite) TestSwarmTaskListFilter(c *check.C) { 290 d := s.AddDaemon(c, true, true) 291 292 name := "redis-cluster-md5" 293 out, err := d.Cmd("service", "create", "--name", name, "--replicas=3", "busybox", "top") 294 c.Assert(err, checker.IsNil) 295 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 296 297 filter := "name=redis-cluster" 298 299 checkNumTasks := func(*check.C) (interface{}, check.CommentInterface) { 300 out, err := d.Cmd("service", "ps", "--filter", filter, name) 301 c.Assert(err, checker.IsNil) 302 return len(strings.Split(out, "\n")) - 2, nil // includes header and nl in last line 303 } 304 305 // wait until all tasks have been created 306 waitAndAssert(c, defaultReconciliationTimeout, checkNumTasks, checker.Equals, 3) 307 308 out, err = d.Cmd("service", "ps", "--filter", filter, name) 309 c.Assert(err, checker.IsNil) 310 c.Assert(out, checker.Contains, name+".1") 311 c.Assert(out, checker.Contains, name+".2") 312 c.Assert(out, checker.Contains, name+".3") 313 314 out, err = d.Cmd("service", "ps", "--filter", "name="+name+".1", name) 315 c.Assert(err, checker.IsNil) 316 c.Assert(out, checker.Contains, name+".1") 317 c.Assert(out, checker.Not(checker.Contains), name+".2") 318 c.Assert(out, checker.Not(checker.Contains), name+".3") 319 320 out, err = d.Cmd("service", "ps", "--filter", "name=none", name) 321 c.Assert(err, checker.IsNil) 322 c.Assert(out, checker.Not(checker.Contains), name+".1") 323 c.Assert(out, checker.Not(checker.Contains), name+".2") 324 c.Assert(out, checker.Not(checker.Contains), name+".3") 325 326 name = "redis-cluster-sha1" 327 out, err = d.Cmd("service", "create", "--name", name, "--mode=global", "busybox", "top") 328 c.Assert(err, checker.IsNil) 329 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 330 331 waitAndAssert(c, defaultReconciliationTimeout, checkNumTasks, checker.Equals, 1) 332 333 filter = "name=redis-cluster" 334 out, err = d.Cmd("service", "ps", "--filter", filter, name) 335 c.Assert(err, checker.IsNil) 336 c.Assert(out, checker.Contains, name) 337 338 out, err = d.Cmd("service", "ps", "--filter", "name="+name, name) 339 c.Assert(err, checker.IsNil) 340 c.Assert(out, checker.Contains, name) 341 342 out, err = d.Cmd("service", "ps", "--filter", "name=none", name) 343 c.Assert(err, checker.IsNil) 344 c.Assert(out, checker.Not(checker.Contains), name) 345 } 346 347 func (s *DockerSwarmSuite) TestPsListContainersFilterIsTask(c *check.C) { 348 d := s.AddDaemon(c, true, true) 349 350 // Create a bare container 351 out, err := d.Cmd("run", "-d", "--name=bare-container", "busybox", "top") 352 c.Assert(err, checker.IsNil) 353 bareID := strings.TrimSpace(out)[:12] 354 // Create a service 355 name := "busybox-top" 356 out, err = d.Cmd("service", "create", "--name", name, "busybox", "top") 357 c.Assert(err, checker.IsNil) 358 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 359 360 // make sure task has been deployed. 361 waitAndAssert(c, defaultReconciliationTimeout, d.checkServiceRunningTasks(name), checker.Equals, 1) 362 363 // Filter non-tasks 364 out, err = d.Cmd("ps", "-a", "-q", "--filter=is-task=false") 365 c.Assert(err, checker.IsNil) 366 psOut := strings.TrimSpace(out) 367 c.Assert(psOut, checker.Equals, bareID, check.Commentf("Expected id %s, got %s for is-task label, output %q", bareID, psOut, out)) 368 369 // Filter tasks 370 out, err = d.Cmd("ps", "-a", "-q", "--filter=is-task=true") 371 c.Assert(err, checker.IsNil) 372 lines := strings.Split(strings.Trim(out, "\n "), "\n") 373 c.Assert(lines, checker.HasLen, 1) 374 c.Assert(lines[0], checker.Not(checker.Equals), bareID, check.Commentf("Expected not %s, but got it for is-task label, output %q", bareID, out)) 375 } 376 377 const globalNetworkPlugin = "global-network-plugin" 378 const globalIPAMPlugin = "global-ipam-plugin" 379 380 func (s *DockerSwarmSuite) SetUpSuite(c *check.C) { 381 mux := http.NewServeMux() 382 s.server = httptest.NewServer(mux) 383 c.Assert(s.server, check.NotNil, check.Commentf("Failed to start an HTTP Server")) 384 setupRemoteGlobalNetworkPlugin(c, mux, s.server.URL, globalNetworkPlugin, globalIPAMPlugin) 385 } 386 387 func setupRemoteGlobalNetworkPlugin(c *check.C, mux *http.ServeMux, url, netDrv, ipamDrv string) { 388 389 mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) { 390 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 391 fmt.Fprintf(w, `{"Implements": ["%s", "%s"]}`, driverapi.NetworkPluginEndpointType, ipamapi.PluginEndpointType) 392 }) 393 394 // Network driver implementation 395 mux.HandleFunc(fmt.Sprintf("/%s.GetCapabilities", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 396 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 397 fmt.Fprintf(w, `{"Scope":"global"}`) 398 }) 399 400 mux.HandleFunc(fmt.Sprintf("/%s.AllocateNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 401 err := json.NewDecoder(r.Body).Decode(&remoteDriverNetworkRequest) 402 if err != nil { 403 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 404 return 405 } 406 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 407 fmt.Fprintf(w, "null") 408 }) 409 410 mux.HandleFunc(fmt.Sprintf("/%s.FreeNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 411 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 412 fmt.Fprintf(w, "null") 413 }) 414 415 mux.HandleFunc(fmt.Sprintf("/%s.CreateNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 416 err := json.NewDecoder(r.Body).Decode(&remoteDriverNetworkRequest) 417 if err != nil { 418 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 419 return 420 } 421 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 422 fmt.Fprintf(w, "null") 423 }) 424 425 mux.HandleFunc(fmt.Sprintf("/%s.DeleteNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 426 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 427 fmt.Fprintf(w, "null") 428 }) 429 430 mux.HandleFunc(fmt.Sprintf("/%s.CreateEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 431 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 432 fmt.Fprintf(w, `{"Interface":{"MacAddress":"a0:b1:c2:d3:e4:f5"}}`) 433 }) 434 435 mux.HandleFunc(fmt.Sprintf("/%s.Join", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 436 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 437 438 veth := &netlink.Veth{ 439 LinkAttrs: netlink.LinkAttrs{Name: "randomIfName", TxQLen: 0}, PeerName: "cnt0"} 440 if err := netlink.LinkAdd(veth); err != nil { 441 fmt.Fprintf(w, `{"Error":"failed to add veth pair: `+err.Error()+`"}`) 442 } else { 443 fmt.Fprintf(w, `{"InterfaceName":{ "SrcName":"cnt0", "DstPrefix":"veth"}}`) 444 } 445 }) 446 447 mux.HandleFunc(fmt.Sprintf("/%s.Leave", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 448 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 449 fmt.Fprintf(w, "null") 450 }) 451 452 mux.HandleFunc(fmt.Sprintf("/%s.DeleteEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 453 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 454 if link, err := netlink.LinkByName("cnt0"); err == nil { 455 netlink.LinkDel(link) 456 } 457 fmt.Fprintf(w, "null") 458 }) 459 460 // IPAM Driver implementation 461 var ( 462 poolRequest remoteipam.RequestPoolRequest 463 poolReleaseReq remoteipam.ReleasePoolRequest 464 addressRequest remoteipam.RequestAddressRequest 465 addressReleaseReq remoteipam.ReleaseAddressRequest 466 lAS = "localAS" 467 gAS = "globalAS" 468 pool = "172.28.0.0/16" 469 poolID = lAS + "/" + pool 470 gw = "172.28.255.254/16" 471 ) 472 473 mux.HandleFunc(fmt.Sprintf("/%s.GetDefaultAddressSpaces", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 474 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 475 fmt.Fprintf(w, `{"LocalDefaultAddressSpace":"`+lAS+`", "GlobalDefaultAddressSpace": "`+gAS+`"}`) 476 }) 477 478 mux.HandleFunc(fmt.Sprintf("/%s.RequestPool", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 479 err := json.NewDecoder(r.Body).Decode(&poolRequest) 480 if err != nil { 481 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 482 return 483 } 484 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 485 if poolRequest.AddressSpace != lAS && poolRequest.AddressSpace != gAS { 486 fmt.Fprintf(w, `{"Error":"Unknown address space in pool request: `+poolRequest.AddressSpace+`"}`) 487 } else if poolRequest.Pool != "" && poolRequest.Pool != pool { 488 fmt.Fprintf(w, `{"Error":"Cannot handle explicit pool requests yet"}`) 489 } else { 490 fmt.Fprintf(w, `{"PoolID":"`+poolID+`", "Pool":"`+pool+`"}`) 491 } 492 }) 493 494 mux.HandleFunc(fmt.Sprintf("/%s.RequestAddress", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 495 err := json.NewDecoder(r.Body).Decode(&addressRequest) 496 if err != nil { 497 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 498 return 499 } 500 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 501 // make sure libnetwork is now querying on the expected pool id 502 if addressRequest.PoolID != poolID { 503 fmt.Fprintf(w, `{"Error":"unknown pool id"}`) 504 } else if addressRequest.Address != "" { 505 fmt.Fprintf(w, `{"Error":"Cannot handle explicit address requests yet"}`) 506 } else { 507 fmt.Fprintf(w, `{"Address":"`+gw+`"}`) 508 } 509 }) 510 511 mux.HandleFunc(fmt.Sprintf("/%s.ReleaseAddress", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 512 err := json.NewDecoder(r.Body).Decode(&addressReleaseReq) 513 if err != nil { 514 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 515 return 516 } 517 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 518 // make sure libnetwork is now asking to release the expected address from the expected poolid 519 if addressRequest.PoolID != poolID { 520 fmt.Fprintf(w, `{"Error":"unknown pool id"}`) 521 } else if addressReleaseReq.Address != gw { 522 fmt.Fprintf(w, `{"Error":"unknown address"}`) 523 } else { 524 fmt.Fprintf(w, "null") 525 } 526 }) 527 528 mux.HandleFunc(fmt.Sprintf("/%s.ReleasePool", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) { 529 err := json.NewDecoder(r.Body).Decode(&poolReleaseReq) 530 if err != nil { 531 http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest) 532 return 533 } 534 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json") 535 // make sure libnetwork is now asking to release the expected poolid 536 if addressRequest.PoolID != poolID { 537 fmt.Fprintf(w, `{"Error":"unknown pool id"}`) 538 } else { 539 fmt.Fprintf(w, "null") 540 } 541 }) 542 543 err := os.MkdirAll("/etc/docker/plugins", 0755) 544 c.Assert(err, checker.IsNil) 545 546 fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", netDrv) 547 err = ioutil.WriteFile(fileName, []byte(url), 0644) 548 c.Assert(err, checker.IsNil) 549 550 ipamFileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", ipamDrv) 551 err = ioutil.WriteFile(ipamFileName, []byte(url), 0644) 552 c.Assert(err, checker.IsNil) 553 } 554 555 func (s *DockerSwarmSuite) TestSwarmNetworkPlugin(c *check.C) { 556 d := s.AddDaemon(c, true, true) 557 558 out, err := d.Cmd("network", "create", "-d", globalNetworkPlugin, "foo") 559 c.Assert(err, checker.IsNil) 560 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 561 562 name := "top" 563 out, err = d.Cmd("service", "create", "--name", name, "--network", "foo", "busybox", "top") 564 c.Assert(err, checker.IsNil) 565 c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") 566 567 out, err = d.Cmd("service", "inspect", "--format", "{{range .Spec.Networks}}{{.Target}}{{end}}", name) 568 c.Assert(err, checker.IsNil) 569 c.Assert(strings.TrimSpace(out), checker.Equals, "foo") 570 }