github.com/jrxfive/nomad@v0.6.1-0.20170802162750-1fef470e89bf/nomad/serf_test.go (about) 1 package nomad 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path" 8 "strings" 9 "testing" 10 11 "github.com/hashicorp/nomad/testutil" 12 "github.com/hashicorp/serf/serf" 13 ) 14 15 func TestNomad_JoinPeer(t *testing.T) { 16 t.Parallel() 17 s1 := testServer(t, nil) 18 defer s1.Shutdown() 19 s2 := testServer(t, func(c *Config) { 20 c.Region = "region2" 21 }) 22 defer s2.Shutdown() 23 testJoin(t, s1, s2) 24 25 testutil.WaitForResult(func() (bool, error) { 26 if members := s1.Members(); len(members) != 2 { 27 return false, fmt.Errorf("bad: %#v", members) 28 } 29 if members := s2.Members(); len(members) != 2 { 30 return false, fmt.Errorf("bad: %#v", members) 31 } 32 return true, nil 33 }, func(err error) { 34 t.Fatalf("err: %v", err) 35 }) 36 37 testutil.WaitForResult(func() (bool, error) { 38 if len(s1.peers) != 2 { 39 return false, fmt.Errorf("bad: %#v", s1.peers) 40 } 41 if len(s2.peers) != 2 { 42 return false, fmt.Errorf("bad: %#v", s2.peers) 43 } 44 if len(s1.localPeers) != 1 { 45 return false, fmt.Errorf("bad: %#v", s1.localPeers) 46 } 47 if len(s2.localPeers) != 1 { 48 return false, fmt.Errorf("bad: %#v", s2.localPeers) 49 } 50 return true, nil 51 }, func(err error) { 52 t.Fatalf("err: %v", err) 53 }) 54 } 55 56 func TestNomad_RemovePeer(t *testing.T) { 57 t.Parallel() 58 s1 := testServer(t, nil) 59 defer s1.Shutdown() 60 s2 := testServer(t, func(c *Config) { 61 c.Region = "region2" 62 }) 63 defer s2.Shutdown() 64 testJoin(t, s1, s2) 65 66 testutil.WaitForResult(func() (bool, error) { 67 if members := s1.Members(); len(members) != 2 { 68 return false, fmt.Errorf("bad: %#v", members) 69 } 70 if members := s2.Members(); len(members) != 2 { 71 return false, fmt.Errorf("bad: %#v", members) 72 } 73 return true, nil 74 }, func(err error) { 75 t.Fatalf("err: %v", err) 76 }) 77 78 // Leave immediately 79 s2.Leave() 80 s2.Shutdown() 81 82 testutil.WaitForResult(func() (bool, error) { 83 if len(s1.peers) != 1 { 84 return false, fmt.Errorf("bad: %#v", s1.peers) 85 } 86 if len(s2.peers) != 1 { 87 return false, fmt.Errorf("bad: %#v", s2.peers) 88 } 89 return true, nil 90 }, func(err error) { 91 t.Fatalf("err: %v", err) 92 }) 93 } 94 95 func TestNomad_ReapPeer(t *testing.T) { 96 t.Parallel() 97 dir := tmpDir(t) 98 defer os.RemoveAll(dir) 99 s1 := testServer(t, func(c *Config) { 100 c.BootstrapExpect = 3 101 c.DevMode = false 102 c.DevDisableBootstrap = true 103 c.DataDir = path.Join(dir, "node1") 104 }) 105 defer s1.Shutdown() 106 s2 := testServer(t, func(c *Config) { 107 c.BootstrapExpect = 3 108 c.DevMode = false 109 c.DevDisableBootstrap = true 110 c.DataDir = path.Join(dir, "node2") 111 }) 112 defer s2.Shutdown() 113 s3 := testServer(t, func(c *Config) { 114 c.BootstrapExpect = 3 115 c.DevMode = false 116 c.DevDisableBootstrap = true 117 c.DataDir = path.Join(dir, "node3") 118 }) 119 defer s3.Shutdown() 120 testJoin(t, s1, s2, s3) 121 122 testutil.WaitForResult(func() (bool, error) { 123 if members := s1.Members(); len(members) != 3 { 124 return false, fmt.Errorf("bad: %#v", members) 125 } 126 if members := s2.Members(); len(members) != 3 { 127 return false, fmt.Errorf("bad: %#v", members) 128 } 129 if members := s3.Members(); len(members) != 3 { 130 return false, fmt.Errorf("bad: %#v", members) 131 } 132 return true, nil 133 }, func(err error) { 134 t.Fatalf("err: %v", err) 135 }) 136 137 testutil.WaitForLeader(t, s1.RPC) 138 139 // Simulate a reap 140 mems := s1.Members() 141 var s2mem serf.Member 142 for _, m := range mems { 143 if strings.Contains(m.Name, s2.config.NodeName) { 144 s2mem = m 145 s2mem.Status = StatusReap 146 break 147 } 148 } 149 150 // Shutdown and then send the reap 151 s2.Shutdown() 152 s1.reconcileCh <- s2mem 153 s2.reconcileCh <- s2mem 154 s3.reconcileCh <- s2mem 155 156 testutil.WaitForResult(func() (bool, error) { 157 if len(s1.peers["global"]) != 2 { 158 return false, fmt.Errorf("bad: %#v", s1.peers["global"]) 159 } 160 peers, err := s1.numPeers() 161 if err != nil { 162 return false, fmt.Errorf("numPeers() failed: %v", err) 163 } 164 if peers != 2 { 165 return false, fmt.Errorf("bad: %#v", peers) 166 } 167 168 if len(s3.peers["global"]) != 2 { 169 return false, fmt.Errorf("bad: %#v", s1.peers["global"]) 170 } 171 peers, err = s3.numPeers() 172 if err != nil { 173 return false, fmt.Errorf("numPeers() failed: %v", err) 174 } 175 if peers != 2 { 176 return false, fmt.Errorf("bad: %#v", peers) 177 } 178 return true, nil 179 }, func(err error) { 180 t.Fatalf("err: %v", err) 181 }) 182 } 183 184 func TestNomad_BootstrapExpect(t *testing.T) { 185 t.Parallel() 186 dir := tmpDir(t) 187 defer os.RemoveAll(dir) 188 189 s1 := testServer(t, func(c *Config) { 190 c.BootstrapExpect = 3 191 c.DevMode = false 192 c.DevDisableBootstrap = true 193 c.DataDir = path.Join(dir, "node1") 194 }) 195 defer s1.Shutdown() 196 s2 := testServer(t, func(c *Config) { 197 c.BootstrapExpect = 3 198 c.DevMode = false 199 c.DevDisableBootstrap = true 200 c.DataDir = path.Join(dir, "node2") 201 }) 202 defer s2.Shutdown() 203 s3 := testServer(t, func(c *Config) { 204 c.BootstrapExpect = 3 205 c.DevMode = false 206 c.DevDisableBootstrap = true 207 c.DataDir = path.Join(dir, "node3") 208 }) 209 defer s3.Shutdown() 210 testJoin(t, s1, s2, s3) 211 212 testutil.WaitForResult(func() (bool, error) { 213 peers, err := s1.numPeers() 214 if err != nil { 215 return false, err 216 } 217 if peers != 3 { 218 return false, fmt.Errorf("bad: %#v", peers) 219 } 220 peers, err = s2.numPeers() 221 if err != nil { 222 return false, err 223 } 224 if peers != 3 { 225 return false, fmt.Errorf("bad: %#v", peers) 226 } 227 peers, err = s3.numPeers() 228 if err != nil { 229 return false, err 230 } 231 if peers != 3 { 232 return false, fmt.Errorf("bad: %#v", peers) 233 } 234 if len(s1.localPeers) != 3 { 235 return false, fmt.Errorf("bad: %#v", s1.localPeers) 236 } 237 if len(s2.localPeers) != 3 { 238 return false, fmt.Errorf("bad: %#v", s2.localPeers) 239 } 240 if len(s3.localPeers) != 3 { 241 return false, fmt.Errorf("bad: %#v", s3.localPeers) 242 } 243 return true, nil 244 }, func(err error) { 245 t.Fatalf("err: %v", err) 246 }) 247 248 // Join a fourth server after quorum has already been formed and ensure 249 // there is no election 250 s4 := testServer(t, func(c *Config) { 251 c.BootstrapExpect = 3 252 c.DevMode = false 253 c.DevDisableBootstrap = true 254 c.DataDir = path.Join(dir, "node4") 255 }) 256 defer s4.Shutdown() 257 258 // Make sure a leader is elected, grab the current term and then add in 259 // the fourth server. 260 testutil.WaitForLeader(t, s1.RPC) 261 termBefore := s1.raft.Stats()["last_log_term"] 262 addr := fmt.Sprintf("127.0.0.1:%d", s1.config.SerfConfig.MemberlistConfig.BindPort) 263 if _, err := s4.Join([]string{addr}); err != nil { 264 t.Fatalf("err: %v", err) 265 } 266 267 // Wait for the new server to see itself added to the cluster. 268 var p4 int 269 testutil.WaitForResult(func() (bool, error) { 270 p4, _ = s4.numPeers() 271 return p4 == 4, errors.New(fmt.Sprintf("%d", p4)) 272 }, func(err error) { 273 t.Fatalf("should have 4 peers: %v", err) 274 }) 275 276 // Make sure there's still a leader and that the term didn't change, 277 // so we know an election didn't occur. 278 testutil.WaitForLeader(t, s1.RPC) 279 termAfter := s1.raft.Stats()["last_log_term"] 280 if termAfter != termBefore { 281 t.Fatalf("looks like an election took place") 282 } 283 } 284 285 func TestNomad_BadExpect(t *testing.T) { 286 t.Parallel() 287 s1 := testServer(t, func(c *Config) { 288 c.BootstrapExpect = 2 289 c.DevDisableBootstrap = true 290 }) 291 defer s1.Shutdown() 292 s2 := testServer(t, func(c *Config) { 293 c.BootstrapExpect = 3 294 c.DevDisableBootstrap = true 295 }) 296 defer s2.Shutdown() 297 servers := []*Server{s1, s2} 298 testJoin(t, s1, s2) 299 300 // Serf members should update 301 testutil.WaitForResult(func() (bool, error) { 302 for _, s := range servers { 303 members := s.Members() 304 if len(members) != 2 { 305 return false, fmt.Errorf("%d", len(members)) 306 } 307 } 308 return true, nil 309 }, func(err error) { 310 t.Fatalf("should have 2 peers: %v", err) 311 }) 312 313 // should still have no peers (because s2 is in expect=2 mode) 314 testutil.WaitForResult(func() (bool, error) { 315 for _, s := range servers { 316 p, _ := s.numPeers() 317 if p != 1 { 318 return false, fmt.Errorf("%d", p) 319 } 320 } 321 return true, nil 322 }, func(err error) { 323 t.Fatalf("should have 0 peers: %v", err) 324 }) 325 }