github.com/noxiouz/docker@v0.7.3-0.20160629055221-3d231c78e8c5/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/swarm" 13 "github.com/go-check/check" 14 ) 15 16 // SwarmDaemon is a test daemon with helpers for participating in a swarm. 17 type SwarmDaemon struct { 18 *Daemon 19 swarm.Info 20 port int 21 listenAddr string 22 } 23 24 // Init initializes a new swarm cluster. 25 func (d *SwarmDaemon) Init(autoAccept map[string]bool, secret string) error { 26 req := swarm.InitRequest{ 27 ListenAddr: d.listenAddr, 28 } 29 for _, role := range []swarm.NodeRole{swarm.NodeRoleManager, swarm.NodeRoleWorker} { 30 policy := swarm.Policy{ 31 Role: role, 32 Autoaccept: autoAccept[strings.ToLower(string(role))], 33 } 34 35 if secret != "" { 36 policy.Secret = &secret 37 } 38 39 req.Spec.AcceptancePolicy.Policies = append(req.Spec.AcceptancePolicy.Policies, policy) 40 } 41 status, out, err := d.SockRequest("POST", "/swarm/init", req) 42 if status != http.StatusOK { 43 return fmt.Errorf("initializing swarm: invalid statuscode %v, %q", status, out) 44 } 45 if err != nil { 46 return fmt.Errorf("initializing swarm: %v", err) 47 } 48 info, err := d.info() 49 if err != nil { 50 return err 51 } 52 d.Info = info 53 return nil 54 } 55 56 // Join joins a current daemon with existing cluster. 57 func (d *SwarmDaemon) Join(remoteAddr, secret, cahash string, manager bool) error { 58 req := swarm.JoinRequest{ 59 ListenAddr: d.listenAddr, 60 RemoteAddrs: []string{remoteAddr}, 61 Manager: manager, 62 CACertHash: cahash, 63 } 64 65 if secret != "" { 66 req.Secret = secret 67 } 68 status, out, err := d.SockRequest("POST", "/swarm/join", req) 69 if status != http.StatusOK { 70 return fmt.Errorf("joining swarm: invalid statuscode %v, %q", status, out) 71 } 72 if err != nil { 73 return fmt.Errorf("joining swarm: %v", err) 74 } 75 info, err := d.info() 76 if err != nil { 77 return err 78 } 79 d.Info = info 80 return nil 81 } 82 83 // Leave forces daemon to leave current cluster. 84 func (d *SwarmDaemon) Leave(force bool) error { 85 url := "/swarm/leave" 86 if force { 87 url += "?force=1" 88 } 89 status, out, err := d.SockRequest("POST", url, nil) 90 if status != http.StatusOK { 91 return fmt.Errorf("leaving swarm: invalid statuscode %v, %q", status, out) 92 } 93 if err != nil { 94 err = fmt.Errorf("leaving swarm: %v", err) 95 } 96 return err 97 } 98 99 func (d *SwarmDaemon) info() (swarm.Info, error) { 100 var info struct { 101 Swarm swarm.Info 102 } 103 status, dt, err := d.SockRequest("GET", "/info", nil) 104 if status != http.StatusOK { 105 return info.Swarm, fmt.Errorf("get swarm info: invalid statuscode %v", status) 106 } 107 if err != nil { 108 return info.Swarm, fmt.Errorf("get swarm info: %v", err) 109 } 110 if err := json.Unmarshal(dt, &info); err != nil { 111 return info.Swarm, err 112 } 113 return info.Swarm, nil 114 } 115 116 type serviceConstructor func(*swarm.Service) 117 type nodeConstructor func(*swarm.Node) 118 type specConstructor func(*swarm.Spec) 119 120 func (d *SwarmDaemon) createService(c *check.C, f ...serviceConstructor) string { 121 var service swarm.Service 122 for _, fn := range f { 123 fn(&service) 124 } 125 status, out, err := d.SockRequest("POST", "/services/create", service.Spec) 126 127 c.Assert(err, checker.IsNil) 128 c.Assert(status, checker.Equals, http.StatusCreated, check.Commentf("output: %q", string(out))) 129 130 var scr types.ServiceCreateResponse 131 c.Assert(json.Unmarshal(out, &scr), checker.IsNil) 132 return scr.ID 133 } 134 135 func (d *SwarmDaemon) getService(c *check.C, id string) *swarm.Service { 136 var service swarm.Service 137 status, out, err := d.SockRequest("GET", "/services/"+id, nil) 138 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 139 c.Assert(err, checker.IsNil) 140 c.Assert(json.Unmarshal(out, &service), checker.IsNil) 141 c.Assert(service.ID, checker.Equals, id) 142 return &service 143 } 144 145 func (d *SwarmDaemon) updateService(c *check.C, service *swarm.Service, f ...serviceConstructor) { 146 for _, fn := range f { 147 fn(service) 148 } 149 url := fmt.Sprintf("/services/%s/update?version=%d", service.ID, service.Version.Index) 150 status, out, err := d.SockRequest("POST", url, service.Spec) 151 c.Assert(err, checker.IsNil) 152 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 153 } 154 155 func (d *SwarmDaemon) removeService(c *check.C, id string) { 156 status, out, err := d.SockRequest("DELETE", "/services/"+id, nil) 157 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 158 c.Assert(err, checker.IsNil) 159 } 160 161 func (d *SwarmDaemon) getNode(c *check.C, id string) *swarm.Node { 162 var node swarm.Node 163 status, out, err := d.SockRequest("GET", "/nodes/"+id, nil) 164 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 165 c.Assert(err, checker.IsNil) 166 c.Assert(json.Unmarshal(out, &node), checker.IsNil) 167 c.Assert(node.ID, checker.Equals, id) 168 return &node 169 } 170 171 func (d *SwarmDaemon) updateNode(c *check.C, id string, f ...nodeConstructor) { 172 for i := 0; ; i++ { 173 node := d.getNode(c, id) 174 for _, fn := range f { 175 fn(node) 176 } 177 url := fmt.Sprintf("/nodes/%s/update?version=%d", node.ID, node.Version.Index) 178 status, out, err := d.SockRequest("POST", url, node.Spec) 179 if i < 10 && strings.Contains(string(out), "update out of sequence") { 180 time.Sleep(100 * time.Millisecond) 181 continue 182 } 183 c.Assert(err, checker.IsNil) 184 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 185 return 186 } 187 } 188 189 func (d *SwarmDaemon) listNodes(c *check.C) []swarm.Node { 190 status, out, err := d.SockRequest("GET", "/nodes", nil) 191 c.Assert(err, checker.IsNil) 192 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 193 194 nodes := []swarm.Node{} 195 c.Assert(json.Unmarshal(out, &nodes), checker.IsNil) 196 return nodes 197 } 198 199 func (d *SwarmDaemon) updateSwarm(c *check.C, f ...specConstructor) { 200 var sw swarm.Swarm 201 status, out, err := d.SockRequest("GET", "/swarm", nil) 202 c.Assert(err, checker.IsNil) 203 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 204 c.Assert(json.Unmarshal(out, &sw), checker.IsNil) 205 206 for _, fn := range f { 207 fn(&sw.Spec) 208 } 209 url := fmt.Sprintf("/swarm/update?version=%d", sw.Version.Index) 210 status, out, err = d.SockRequest("POST", url, sw.Spec) 211 c.Assert(err, checker.IsNil) 212 c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) 213 }