github.com/maier/nomad@v0.4.1-0.20161110003312-a9e3d0b8549d/command/agent/agent_test.go (about) 1 package agent 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net" 7 "os" 8 "strings" 9 "testing" 10 "time" 11 12 "github.com/hashicorp/nomad/nomad" 13 sconfig "github.com/hashicorp/nomad/nomad/structs/config" 14 ) 15 16 func getPort() int { 17 addr, err := net.ResolveTCPAddr("tcp", "localhost:0") 18 if err != nil { 19 panic(err) 20 } 21 22 l, err := net.ListenTCP("tcp", addr) 23 if err != nil { 24 panic(err) 25 } 26 defer l.Close() 27 return l.Addr().(*net.TCPAddr).Port 28 } 29 30 func tmpDir(t testing.TB) string { 31 dir, err := ioutil.TempDir("", "nomad") 32 if err != nil { 33 t.Fatalf("err: %v", err) 34 } 35 return dir 36 } 37 38 func makeAgent(t testing.TB, cb func(*Config)) (string, *Agent) { 39 dir := tmpDir(t) 40 conf := DevConfig() 41 42 // Customize the server configuration 43 config := nomad.DefaultConfig() 44 conf.NomadConfig = config 45 46 // Bind and set ports 47 conf.BindAddr = "127.0.0.1" 48 conf.Ports = &Ports{ 49 HTTP: getPort(), 50 RPC: getPort(), 51 Serf: getPort(), 52 } 53 conf.NodeName = fmt.Sprintf("Node %d", conf.Ports.RPC) 54 conf.Consul = sconfig.DefaultConsulConfig() 55 conf.Vault.Enabled = new(bool) 56 57 // Tighten the Serf timing 58 config.SerfConfig.MemberlistConfig.SuspicionMult = 2 59 config.SerfConfig.MemberlistConfig.RetransmitMult = 2 60 config.SerfConfig.MemberlistConfig.ProbeTimeout = 50 * time.Millisecond 61 config.SerfConfig.MemberlistConfig.ProbeInterval = 100 * time.Millisecond 62 config.SerfConfig.MemberlistConfig.GossipInterval = 100 * time.Millisecond 63 64 // Tighten the Raft timing 65 config.RaftConfig.LeaderLeaseTimeout = 20 * time.Millisecond 66 config.RaftConfig.HeartbeatTimeout = 40 * time.Millisecond 67 config.RaftConfig.ElectionTimeout = 40 * time.Millisecond 68 config.RaftConfig.StartAsLeader = true 69 config.RaftTimeout = 500 * time.Millisecond 70 71 if cb != nil { 72 cb(conf) 73 } 74 75 agent, err := NewAgent(conf, os.Stderr) 76 if err != nil { 77 os.RemoveAll(dir) 78 t.Fatalf("err: %v", err) 79 } 80 return dir, agent 81 } 82 83 func TestAgent_RPCPing(t *testing.T) { 84 dir, agent := makeAgent(t, nil) 85 defer os.RemoveAll(dir) 86 defer agent.Shutdown() 87 88 var out struct{} 89 if err := agent.RPC("Status.Ping", struct{}{}, &out); err != nil { 90 t.Fatalf("err: %v", err) 91 } 92 } 93 94 func TestAgent_ServerConfig(t *testing.T) { 95 conf := DefaultConfig() 96 a := &Agent{config: conf} 97 98 // Returns error on bad serf addr 99 conf.AdvertiseAddrs.Serf = "nope" 100 _, err := a.serverConfig() 101 if err == nil || !strings.Contains(err.Error(), "Failed to parse Serf") { 102 t.Fatalf("expected serf address error, got: %#v", err) 103 } 104 conf.AdvertiseAddrs.Serf = "127.0.0.1:4000" 105 106 // Returns error on bad rpc addr 107 conf.AdvertiseAddrs.RPC = "nope" 108 _, err = a.serverConfig() 109 if err == nil || !strings.Contains(err.Error(), "Failed to parse RPC") { 110 t.Fatalf("expected rpc address error, got: %#v", err) 111 } 112 conf.AdvertiseAddrs.RPC = "127.0.0.1:4001" 113 conf.AdvertiseAddrs.HTTP = "10.10.11.1:4005" 114 115 // Parses the advertise addrs correctly 116 out, err := a.serverConfig() 117 if err != nil { 118 t.Fatalf("err: %s", err) 119 } 120 serfAddr := out.SerfConfig.MemberlistConfig.AdvertiseAddr 121 if serfAddr != "127.0.0.1" { 122 t.Fatalf("expect 127.0.0.1, got: %s", serfAddr) 123 } 124 serfPort := out.SerfConfig.MemberlistConfig.AdvertisePort 125 if serfPort != 4000 { 126 t.Fatalf("expected 4000, got: %d", serfPort) 127 } 128 if addr := out.RPCAdvertise; addr.IP.String() != "127.0.0.1" || addr.Port != 4001 { 129 t.Fatalf("bad rpc advertise addr: %#v", addr) 130 } 131 if addr := a.serverHTTPAddr; addr != "10.10.11.1:4005" { 132 t.Fatalf("expect 10.11.11.1:4005, got: %v", addr) 133 } 134 if addr := a.serverRPCAddr; addr != "127.0.0.1:4001" { 135 t.Fatalf("expect 127.0.0.1:4001, got: %v", addr) 136 } 137 138 // Sets up the ports properly 139 conf.Ports.RPC = 4003 140 conf.Ports.Serf = 4004 141 142 out, err = a.serverConfig() 143 if err != nil { 144 t.Fatalf("err: %s", err) 145 } 146 if addr := out.RPCAddr.Port; addr != 4003 { 147 t.Fatalf("expect 4003, got: %d", out.RPCAddr.Port) 148 } 149 if port := out.SerfConfig.MemberlistConfig.BindPort; port != 4004 { 150 t.Fatalf("expect 4004, got: %d", port) 151 } 152 153 // Prefers advertise over bind addr 154 conf.BindAddr = "127.0.0.3" 155 conf.Addresses.RPC = "127.0.0.2" 156 conf.Addresses.Serf = "127.0.0.2" 157 conf.Addresses.HTTP = "127.0.0.2" 158 conf.AdvertiseAddrs.HTTP = "10.0.0.10" 159 conf.AdvertiseAddrs.RPC = "" 160 conf.AdvertiseAddrs.Serf = "10.0.0.12:4004" 161 162 out, err = a.serverConfig() 163 if err != nil { 164 t.Fatalf("err: %s", err) 165 } 166 if addr := out.RPCAddr.IP.String(); addr != "127.0.0.2" { 167 t.Fatalf("expect 127.0.0.2, got: %s", addr) 168 } 169 if addr := out.SerfConfig.MemberlistConfig.BindAddr; addr != "127.0.0.2" { 170 t.Fatalf("expect 127.0.0.2, got: %s", addr) 171 } 172 if addr := a.serverHTTPAddr; addr != "10.0.0.10:4646" { 173 t.Fatalf("expect 10.0.0.10:4646, got: %s", addr) 174 } 175 // NOTE: AdvertiseAddr > Addresses > BindAddr > Defaults 176 if addr := a.serverRPCAddr; addr != "127.0.0.2:4003" { 177 t.Fatalf("expect 127.0.0.2:4003, got: %s", addr) 178 } 179 if addr := a.serverSerfAddr; addr != "10.0.0.12:4004" { 180 t.Fatalf("expect 10.0.0.12:4004, got: %s", addr) 181 } 182 183 // It correctly identifies the bind and advertise address when requested 184 if addr, err := a.selectAddr(a.getHTTPAddr, true); addr != "127.0.0.2:4646" || err != nil { 185 t.Fatalf("expect 127.0.0.2:4646, got: %s", addr) 186 } 187 188 if addr, err := a.selectAddr(a.getHTTPAddr, false); addr != "10.0.0.10:4646" || err != nil { 189 t.Fatalf("expect 10.0.0.10:4646, got: %s", addr) 190 } 191 192 if addr, err := a.selectAddr(a.getRPCAddr, true); addr != "127.0.0.2:4003" || err != nil { 193 t.Fatalf("expect 127.0.0.2:4003, got: %s", addr) 194 } 195 196 if addr, err := a.selectAddr(a.getRPCAddr, false); addr != "127.0.0.2:4003" || err != nil { 197 t.Fatalf("expect 127.0.0.2:4003, got: %s", addr) 198 } 199 200 if addr, err := a.selectAddr(a.getSerfAddr, true); addr != "127.0.0.2:4004" || err != nil { 201 t.Fatalf("expect 127.0.0.2:4004, got: %s", addr) 202 } 203 204 if addr, err := a.selectAddr(a.getSerfAddr, false); addr != "10.0.0.12:4004" || err != nil { 205 t.Fatalf("expect 10.0.0.12:4004, got: %s", addr) 206 } 207 208 // We don't resolve 0.0.0.0 unless we're asking for bind 209 conf.Addresses.HTTP = "0.0.0.0" 210 conf.AdvertiseAddrs.HTTP = "" 211 if addr, err := a.getHTTPAddr(false); addr.IP.String() != "127.0.0.3" || err != nil { 212 t.Fatalf("expect 127.0.0.3, got: %s", addr.IP.String()) 213 } 214 215 // We still get 0.0.0.0 when explicitly asking for bind 216 if addr, err := a.getHTTPAddr(true); addr.IP.String() != "0.0.0.0" || err != nil { 217 t.Fatalf("expect 0.0.0.0, got: %s", addr.IP.String()) 218 } 219 220 // selectAddr does not return 0.0.0.0 with preferBind 221 if addr, err := a.selectAddr(a.getHTTPAddr, true); addr != "127.0.0.3:4646" || err != nil { 222 t.Fatalf("expect 127.0.0.3:4646, got: %s", addr) 223 } 224 225 conf.Server.NodeGCThreshold = "42g" 226 out, err = a.serverConfig() 227 if err == nil || !strings.Contains(err.Error(), "unknown unit") { 228 t.Fatalf("expected unknown unit error, got: %#v", err) 229 } 230 conf.Server.NodeGCThreshold = "10s" 231 out, err = a.serverConfig() 232 if threshold := out.NodeGCThreshold; threshold != time.Second*10 { 233 t.Fatalf("expect 10s, got: %s", threshold) 234 } 235 236 conf.Server.HeartbeatGrace = "42g" 237 out, err = a.serverConfig() 238 if err == nil || !strings.Contains(err.Error(), "unknown unit") { 239 t.Fatalf("expected unknown unit error, got: %#v", err) 240 } 241 conf.Server.HeartbeatGrace = "37s" 242 out, err = a.serverConfig() 243 if threshold := out.HeartbeatGrace; threshold != time.Second*37 { 244 t.Fatalf("expect 37s, got: %s", threshold) 245 } 246 247 // Defaults to the global bind addr 248 conf.Addresses.RPC = "" 249 conf.Addresses.Serf = "" 250 conf.Addresses.HTTP = "" 251 conf.AdvertiseAddrs.RPC = "" 252 conf.AdvertiseAddrs.HTTP = "" 253 conf.AdvertiseAddrs.Serf = "" 254 conf.Ports.HTTP = 4646 255 conf.Ports.RPC = 4647 256 conf.Ports.Serf = 4648 257 out, err = a.serverConfig() 258 if err != nil { 259 t.Fatalf("err: %s", err) 260 } 261 if addr := out.RPCAddr.IP.String(); addr != "127.0.0.3" { 262 t.Fatalf("expect 127.0.0.3, got: %s", addr) 263 } 264 if addr := out.SerfConfig.MemberlistConfig.BindAddr; addr != "127.0.0.3" { 265 t.Fatalf("expect 127.0.0.3, got: %s", addr) 266 } 267 if addr := a.serverHTTPAddr; addr != "127.0.0.3:4646" { 268 t.Fatalf("expect 127.0.0.3:4646, got: %s", addr) 269 } 270 if addr := a.serverRPCAddr; addr != "127.0.0.3:4647" { 271 t.Fatalf("expect 127.0.0.3:4647, got: %s", addr) 272 } 273 if addr := a.serverSerfAddr; addr != "127.0.0.3:4648" { 274 t.Fatalf("expect 127.0.0.3:4648, got: %s", addr) 275 } 276 277 // Properly handles the bootstrap flags 278 conf.Server.BootstrapExpect = 1 279 out, err = a.serverConfig() 280 if err != nil { 281 t.Fatalf("err: %s", err) 282 } 283 if !out.Bootstrap { 284 t.Fatalf("should have set bootstrap mode") 285 } 286 if out.BootstrapExpect != 0 { 287 t.Fatalf("boostrap expect should be 0") 288 } 289 290 conf.Server.BootstrapExpect = 3 291 out, err = a.serverConfig() 292 if err != nil { 293 t.Fatalf("err: %s", err) 294 } 295 if out.Bootstrap { 296 t.Fatalf("bootstrap mode should be disabled") 297 } 298 if out.BootstrapExpect != 3 { 299 t.Fatalf("should have bootstrap-expect = 3") 300 } 301 } 302 303 func TestAgent_ClientConfig(t *testing.T) { 304 conf := DefaultConfig() 305 a := &Agent{config: conf} 306 conf.Client.Enabled = true 307 conf.Addresses.HTTP = "127.0.0.1" 308 conf.Ports.HTTP = 5678 309 310 c, err := a.clientConfig() 311 if err != nil { 312 t.Fatalf("got err: %v", err) 313 } 314 315 expectedHttpAddr := "127.0.0.1:5678" 316 if c.Node.HTTPAddr != expectedHttpAddr { 317 t.Fatalf("Expected http addr: %v, got: %v", expectedHttpAddr, c.Node.HTTPAddr) 318 } 319 320 conf = DefaultConfig() 321 a = &Agent{config: conf} 322 conf.Client.Enabled = true 323 conf.Addresses.HTTP = "127.0.0.1" 324 325 c, err = a.clientConfig() 326 if err != nil { 327 t.Fatalf("got err: %v", err) 328 } 329 330 expectedHttpAddr = "127.0.0.1:4646" 331 if c.Node.HTTPAddr != expectedHttpAddr { 332 t.Fatalf("Expected http addr: %v, got: %v", expectedHttpAddr, c.Node.HTTPAddr) 333 } 334 }