github.com/brahmaroutu/docker@v1.2.1-0.20160809185609-eb28dde01f16/integration-cli/daemon_swarm.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "strings" 8 "time" 9 10 "github.com/docker/docker/pkg/integration/checker" 11 "github.com/docker/engine-api/types" 12 "github.com/docker/engine-api/types/filters" 13 "github.com/docker/engine-api/types/swarm" 14 "github.com/go-check/check" 15 ) 16 17 // SwarmDaemon is a test daemon with helpers for participating in a swarm. 18 type SwarmDaemon struct { 19 *Daemon 20 swarm.Info 21 port int 22 listenAddr string 23 } 24 25 // Init initializes a new swarm cluster. 26 func (d *SwarmDaemon) Init(req swarm.InitRequest) error { 27 if req.ListenAddr == "" { 28 req.ListenAddr = d.listenAddr 29 } 30 status, out, err := d.SockRequest("POST", "/swarm/init", req) 31 if status != http.StatusOK { 32 return fmt.Errorf("initializing swarm: invalid statuscode %v, %q", status, out) 33 } 34 if err != nil { 35 return fmt.Errorf("initializing swarm: %v", err) 36 } 37 info, err := d.info() 38 if err != nil { 39 return err 40 } 41 d.Info = info 42 return nil 43 } 44 45 // Join joins a daemon to an existing cluster. 46 func (d *SwarmDaemon) Join(req swarm.JoinRequest) error { 47 if req.ListenAddr == "" { 48 req.ListenAddr = d.listenAddr 49 } 50 status, out, err := d.SockRequest("POST", "/swarm/join", req) 51 if status != http.StatusOK { 52 return fmt.Errorf("joining swarm: invalid statuscode %v, %q", status, out) 53 } 54 if err != nil { 55 return fmt.Errorf("joining swarm: %v", err) 56 } 57 info, err := d.info() 58 if err != nil { 59 return err 60 } 61 d.Info = info 62 return nil 63 } 64 65 // Leave forces daemon to leave current cluster. 66 func (d *SwarmDaemon) Leave(force bool) error { 67 url := "/swarm/leave" 68 if force { 69 url += "?force=1" 70 } 71 status, out, err := d.SockRequest("POST", url, nil) 72 if status != http.StatusOK { 73 return fmt.Errorf("leaving swarm: invalid statuscode %v, %q", status, out) 74 } 75 if err != nil { 76 err = fmt.Errorf("leaving swarm: %v", err) 77 } 78 return err 79 } 80 81 func (d *SwarmDaemon) info() (swarm.Info, error) { 82 var info struct { 83 Swarm swarm.Info 84 } 85 status, dt, err := d.SockRequest("GET", "/info", nil) 86 if status != http.StatusOK { 87 return info.Swarm, fmt.Errorf("get swarm info: invalid statuscode %v", status) 88 } 89 if err != nil { 90 return info.Swarm, fmt.Errorf("get swarm info: %v", err) 91 } 92 if err := json.Unmarshal(dt, &info); err != nil { 93 return info.Swarm, err 94 } 95 return info.Swarm, nil 96 } 97 98 type serviceConstructor func(*swarm.Service) 99 type nodeConstructor func(*swarm.Node) 100 type specConstructor func(*swarm.Spec) 101 102 func (d *SwarmDaemon) createService(c *check.C, f ...serviceConstructor) string { 103 var service swarm.Service 104 for _, fn := range f { 105 fn(&service) 106 } 107 status, out, err := d.SockRequest("POST", "/services/create", service.Spec) 108 109 c.Assert(err, checker.IsNil) 110 c.Assert(status, checker.Equals, http.StatusCreated, check.Commentf("output: %q", string(out))) 111 112 var scr types.ServiceCreateResponse 113 c.Assert(json.Unmarshal(out, &scr), checker.IsNil) 114 return scr.ID 115 } 116 117 func (d *SwarmDaemon) getService(c *check.C, id string) *swarm.Service { 118 var service swarm.Service 119 status, out, err := d.SockRequest("GET", "/services/"+id, nil) 120 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 121 c.Assert(err, checker.IsNil) 122 c.Assert(json.Unmarshal(out, &service), checker.IsNil) 123 return &service 124 } 125 126 func (d *SwarmDaemon) getServiceTasks(c *check.C, service string) []swarm.Task { 127 var tasks []swarm.Task 128 129 filterArgs := filters.NewArgs() 130 filterArgs.Add("desired-state", "running") 131 filterArgs.Add("service", service) 132 filters, err := filters.ToParam(filterArgs) 133 c.Assert(err, checker.IsNil) 134 135 status, out, err := d.SockRequest("GET", "/tasks?filters="+filters, nil) 136 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 137 c.Assert(err, checker.IsNil, check.Commentf(string(out))) 138 c.Assert(json.Unmarshal(out, &tasks), checker.IsNil) 139 return tasks 140 } 141 142 func (d *SwarmDaemon) checkServiceRunningTasks(c *check.C, service string) func(*check.C) (interface{}, check.CommentInterface) { 143 return func(*check.C) (interface{}, check.CommentInterface) { 144 tasks := d.getServiceTasks(c, service) 145 var runningCount int 146 for _, task := range tasks { 147 if task.Status.State == swarm.TaskStateRunning { 148 runningCount++ 149 } 150 } 151 return runningCount, nil 152 } 153 } 154 155 func (d *SwarmDaemon) checkServiceTasks(c *check.C, service string) func(*check.C) (interface{}, check.CommentInterface) { 156 return func(*check.C) (interface{}, check.CommentInterface) { 157 tasks := d.getServiceTasks(c, service) 158 return len(tasks), nil 159 } 160 } 161 162 func (d *SwarmDaemon) checkRunningTaskImages(c *check.C) (interface{}, check.CommentInterface) { 163 var tasks []swarm.Task 164 165 filterArgs := filters.NewArgs() 166 filterArgs.Add("desired-state", "running") 167 filters, err := filters.ToParam(filterArgs) 168 c.Assert(err, checker.IsNil) 169 170 status, out, err := d.SockRequest("GET", "/tasks?filters="+filters, nil) 171 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 172 c.Assert(err, checker.IsNil, check.Commentf(string(out))) 173 c.Assert(json.Unmarshal(out, &tasks), checker.IsNil) 174 175 result := make(map[string]int) 176 for _, task := range tasks { 177 if task.Status.State == swarm.TaskStateRunning { 178 result[task.Spec.ContainerSpec.Image]++ 179 } 180 } 181 return result, nil 182 } 183 184 func (d *SwarmDaemon) checkNodeReadyCount(c *check.C) (interface{}, check.CommentInterface) { 185 nodes := d.listNodes(c) 186 var readyCount int 187 for _, node := range nodes { 188 if node.Status.State == swarm.NodeStateReady { 189 readyCount++ 190 } 191 } 192 return readyCount, nil 193 } 194 195 func (d *SwarmDaemon) getTask(c *check.C, id string) swarm.Task { 196 var task swarm.Task 197 198 status, out, err := d.SockRequest("GET", "/tasks/"+id, nil) 199 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 200 c.Assert(err, checker.IsNil, check.Commentf(string(out))) 201 c.Assert(json.Unmarshal(out, &task), checker.IsNil) 202 return task 203 } 204 205 func (d *SwarmDaemon) updateService(c *check.C, service *swarm.Service, f ...serviceConstructor) { 206 for _, fn := range f { 207 fn(service) 208 } 209 url := fmt.Sprintf("/services/%s/update?version=%d", service.ID, service.Version.Index) 210 status, out, err := d.SockRequest("POST", url, service.Spec) 211 c.Assert(err, checker.IsNil) 212 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 213 } 214 215 func (d *SwarmDaemon) removeService(c *check.C, id string) { 216 status, out, err := d.SockRequest("DELETE", "/services/"+id, nil) 217 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 218 c.Assert(err, checker.IsNil) 219 } 220 221 func (d *SwarmDaemon) getNode(c *check.C, id string) *swarm.Node { 222 var node swarm.Node 223 status, out, err := d.SockRequest("GET", "/nodes/"+id, nil) 224 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 225 c.Assert(err, checker.IsNil) 226 c.Assert(json.Unmarshal(out, &node), checker.IsNil) 227 c.Assert(node.ID, checker.Equals, id) 228 return &node 229 } 230 231 func (d *SwarmDaemon) removeNode(c *check.C, id string, force bool) { 232 url := "/nodes/" + id 233 if force { 234 url += "?force=1" 235 } 236 237 status, out, err := d.SockRequest("DELETE", url, nil) 238 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 239 c.Assert(err, checker.IsNil) 240 } 241 242 func (d *SwarmDaemon) updateNode(c *check.C, id string, f ...nodeConstructor) { 243 for i := 0; ; i++ { 244 node := d.getNode(c, id) 245 for _, fn := range f { 246 fn(node) 247 } 248 url := fmt.Sprintf("/nodes/%s/update?version=%d", node.ID, node.Version.Index) 249 status, out, err := d.SockRequest("POST", url, node.Spec) 250 if i < 10 && strings.Contains(string(out), "update out of sequence") { 251 time.Sleep(100 * time.Millisecond) 252 continue 253 } 254 c.Assert(err, checker.IsNil) 255 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 256 return 257 } 258 } 259 260 func (d *SwarmDaemon) listNodes(c *check.C) []swarm.Node { 261 status, out, err := d.SockRequest("GET", "/nodes", nil) 262 c.Assert(err, checker.IsNil) 263 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 264 265 nodes := []swarm.Node{} 266 c.Assert(json.Unmarshal(out, &nodes), checker.IsNil) 267 return nodes 268 } 269 270 func (d *SwarmDaemon) listServices(c *check.C) []swarm.Service { 271 status, out, err := d.SockRequest("GET", "/services", nil) 272 c.Assert(err, checker.IsNil) 273 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 274 275 services := []swarm.Service{} 276 c.Assert(json.Unmarshal(out, &services), checker.IsNil) 277 return services 278 } 279 280 func (d *SwarmDaemon) getSwarm(c *check.C) swarm.Swarm { 281 var sw swarm.Swarm 282 status, out, err := d.SockRequest("GET", "/swarm", nil) 283 c.Assert(err, checker.IsNil) 284 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 285 c.Assert(json.Unmarshal(out, &sw), checker.IsNil) 286 return sw 287 } 288 289 func (d *SwarmDaemon) updateSwarm(c *check.C, f ...specConstructor) { 290 sw := d.getSwarm(c) 291 for _, fn := range f { 292 fn(&sw.Spec) 293 } 294 url := fmt.Sprintf("/swarm/update?version=%d", sw.Version.Index) 295 status, out, err := d.SockRequest("POST", url, sw.Spec) 296 c.Assert(err, checker.IsNil) 297 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 298 } 299 300 func (d *SwarmDaemon) rotateTokens(c *check.C) { 301 var sw swarm.Swarm 302 status, out, err := d.SockRequest("GET", "/swarm", nil) 303 c.Assert(err, checker.IsNil) 304 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 305 c.Assert(json.Unmarshal(out, &sw), checker.IsNil) 306 307 url := fmt.Sprintf("/swarm/update?version=%d&rotateWorkerToken=true&rotateManagerToken=true", sw.Version.Index) 308 status, out, err = d.SockRequest("POST", url, sw.Spec) 309 c.Assert(err, checker.IsNil) 310 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 311 } 312 313 func (d *SwarmDaemon) joinTokens(c *check.C) swarm.JoinTokens { 314 var sw swarm.Swarm 315 status, out, err := d.SockRequest("GET", "/swarm", nil) 316 c.Assert(err, checker.IsNil) 317 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 318 c.Assert(json.Unmarshal(out, &sw), checker.IsNil) 319 return sw.JoinTokens 320 } 321 322 func (d *SwarmDaemon) checkLocalNodeState(c *check.C) (interface{}, check.CommentInterface) { 323 info, err := d.info() 324 c.Assert(err, checker.IsNil) 325 return info.LocalNodeState, nil 326 } 327 328 func (d *SwarmDaemon) checkControlAvailable(c *check.C) (interface{}, check.CommentInterface) { 329 info, err := d.info() 330 c.Assert(err, checker.IsNil) 331 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 332 return info.ControlAvailable, nil 333 } 334 335 func (d *SwarmDaemon) checkLeader(c *check.C) (interface{}, check.CommentInterface) { 336 errList := check.Commentf("could not get node list") 337 status, out, err := d.SockRequest("GET", "/nodes", nil) 338 if err != nil { 339 return err, errList 340 } 341 if status != http.StatusOK { 342 return fmt.Errorf("expected http status OK, got: %d", status), errList 343 } 344 345 var ls []swarm.Node 346 if err := json.Unmarshal(out, &ls); err != nil { 347 return err, errList 348 } 349 350 for _, node := range ls { 351 if node.ManagerStatus != nil && node.ManagerStatus.Leader { 352 return nil, nil 353 } 354 } 355 return fmt.Errorf("no leader"), check.Commentf("could not find leader") 356 }