github.com/jrxfive/nomad@v0.6.1-0.20170802162750-1fef470e89bf/nomad/server_test.go (about) 1 package nomad 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "log" 7 "math/rand" 8 "net" 9 "os" 10 "path" 11 "sync/atomic" 12 "testing" 13 "time" 14 15 "github.com/hashicorp/nomad/command/agent/consul" 16 "github.com/hashicorp/nomad/nomad/structs" 17 "github.com/hashicorp/nomad/nomad/structs/config" 18 "github.com/hashicorp/nomad/testutil" 19 ) 20 21 var ( 22 nodeNumber uint32 = 0 23 ) 24 25 func getPort() int { 26 return 1030 + int(rand.Int31n(6440)) 27 } 28 29 func testLogger() *log.Logger { 30 return log.New(os.Stderr, "", log.LstdFlags) 31 } 32 33 func tmpDir(t *testing.T) string { 34 dir, err := ioutil.TempDir("", "nomad") 35 if err != nil { 36 t.Fatalf("err: %v", err) 37 } 38 return dir 39 } 40 41 func testServer(t *testing.T, cb func(*Config)) *Server { 42 // Setup the default settings 43 config := DefaultConfig() 44 config.Build = "unittest" 45 config.DevMode = true 46 nodeNum := atomic.AddUint32(&nodeNumber, 1) 47 config.NodeName = fmt.Sprintf("nomad-%03d", nodeNum) 48 49 // Tighten the Serf timing 50 config.SerfConfig.MemberlistConfig.BindAddr = "127.0.0.1" 51 config.SerfConfig.MemberlistConfig.SuspicionMult = 2 52 config.SerfConfig.MemberlistConfig.RetransmitMult = 2 53 config.SerfConfig.MemberlistConfig.ProbeTimeout = 50 * time.Millisecond 54 config.SerfConfig.MemberlistConfig.ProbeInterval = 100 * time.Millisecond 55 config.SerfConfig.MemberlistConfig.GossipInterval = 100 * time.Millisecond 56 57 // Tighten the Raft timing 58 config.RaftConfig.LeaderLeaseTimeout = 50 * time.Millisecond 59 config.RaftConfig.HeartbeatTimeout = 50 * time.Millisecond 60 config.RaftConfig.ElectionTimeout = 50 * time.Millisecond 61 config.RaftTimeout = 500 * time.Millisecond 62 63 // Disable Vault 64 f := false 65 config.VaultConfig.Enabled = &f 66 67 // Squelch output when -v isn't specified 68 if !testing.Verbose() { 69 config.LogOutput = ioutil.Discard 70 } 71 72 // Invoke the callback if any 73 if cb != nil { 74 cb(config) 75 } 76 77 // Enable raft as leader if we have bootstrap on 78 config.RaftConfig.StartAsLeader = !config.DevDisableBootstrap 79 80 logger := log.New(config.LogOutput, fmt.Sprintf("[%s] ", config.NodeName), log.LstdFlags) 81 catalog := consul.NewMockCatalog(logger) 82 83 for i := 10; i >= 0; i-- { 84 // Get random ports 85 config.RPCAddr = &net.TCPAddr{ 86 IP: []byte{127, 0, 0, 1}, 87 Port: getPort(), 88 } 89 config.SerfConfig.MemberlistConfig.BindPort = getPort() 90 91 // Create server 92 server, err := NewServer(config, catalog, logger) 93 if err == nil { 94 return server 95 } else if i == 0 { 96 t.Fatalf("err: %v", err) 97 } else { 98 if server != nil { 99 server.Shutdown() 100 } 101 wait := time.Duration(rand.Int31n(2000)) * time.Millisecond 102 time.Sleep(wait) 103 } 104 } 105 106 return nil 107 } 108 109 func testJoin(t *testing.T, s1 *Server, other ...*Server) { 110 addr := fmt.Sprintf("127.0.0.1:%d", 111 s1.config.SerfConfig.MemberlistConfig.BindPort) 112 for _, s2 := range other { 113 if num, err := s2.Join([]string{addr}); err != nil { 114 t.Fatalf("err: %v", err) 115 } else if num != 1 { 116 t.Fatalf("bad: %d", num) 117 } 118 } 119 } 120 121 func TestServer_RPC(t *testing.T) { 122 t.Parallel() 123 s1 := testServer(t, nil) 124 defer s1.Shutdown() 125 126 var out struct{} 127 if err := s1.RPC("Status.Ping", struct{}{}, &out); err != nil { 128 t.Fatalf("err: %v", err) 129 } 130 } 131 132 func TestServer_RPC_MixedTLS(t *testing.T) { 133 t.Parallel() 134 const ( 135 cafile = "../helper/tlsutil/testdata/ca.pem" 136 foocert = "../helper/tlsutil/testdata/nomad-foo.pem" 137 fookey = "../helper/tlsutil/testdata/nomad-foo-key.pem" 138 ) 139 dir := tmpDir(t) 140 defer os.RemoveAll(dir) 141 s1 := testServer(t, func(c *Config) { 142 c.BootstrapExpect = 3 143 c.DevMode = false 144 c.DevDisableBootstrap = true 145 c.DataDir = path.Join(dir, "node1") 146 c.TLSConfig = &config.TLSConfig{ 147 EnableHTTP: true, 148 EnableRPC: true, 149 VerifyServerHostname: true, 150 CAFile: cafile, 151 CertFile: foocert, 152 KeyFile: fookey, 153 } 154 }) 155 defer s1.Shutdown() 156 157 s2 := testServer(t, func(c *Config) { 158 c.BootstrapExpect = 3 159 c.DevMode = false 160 c.DevDisableBootstrap = true 161 c.DataDir = path.Join(dir, "node2") 162 }) 163 defer s2.Shutdown() 164 s3 := testServer(t, func(c *Config) { 165 c.BootstrapExpect = 3 166 c.DevMode = false 167 c.DevDisableBootstrap = true 168 c.DataDir = path.Join(dir, "node3") 169 }) 170 defer s3.Shutdown() 171 172 testJoin(t, s1, s2, s3) 173 174 l1, l2, l3, shutdown := make(chan error, 1), make(chan error, 1), make(chan error, 1), make(chan struct{}, 1) 175 176 wait := func(done chan error, rpc func(string, interface{}, interface{}) error) { 177 for { 178 select { 179 case <-shutdown: 180 return 181 default: 182 } 183 184 args := &structs.GenericRequest{} 185 var leader string 186 err := rpc("Status.Leader", args, &leader) 187 if err != nil || leader != "" { 188 done <- err 189 } 190 } 191 } 192 193 go wait(l1, s1.RPC) 194 go wait(l2, s2.RPC) 195 go wait(l3, s3.RPC) 196 197 select { 198 case <-time.After(5 * time.Second): 199 case err := <-l1: 200 t.Fatalf("Server 1 has leader or error: %v", err) 201 case err := <-l2: 202 t.Fatalf("Server 2 has leader or error: %v", err) 203 case err := <-l3: 204 t.Fatalf("Server 3 has leader or error: %v", err) 205 } 206 } 207 208 func TestServer_Regions(t *testing.T) { 209 t.Parallel() 210 // Make the servers 211 s1 := testServer(t, func(c *Config) { 212 c.Region = "region1" 213 }) 214 defer s1.Shutdown() 215 216 s2 := testServer(t, func(c *Config) { 217 c.Region = "region2" 218 }) 219 defer s2.Shutdown() 220 221 // Join them together 222 s2Addr := fmt.Sprintf("127.0.0.1:%d", 223 s2.config.SerfConfig.MemberlistConfig.BindPort) 224 if n, err := s1.Join([]string{s2Addr}); err != nil || n != 1 { 225 t.Fatalf("Failed joining: %v (%d joined)", err, n) 226 } 227 228 // Try listing the regions 229 testutil.WaitForResult(func() (bool, error) { 230 out := s1.Regions() 231 if len(out) != 2 || out[0] != "region1" || out[1] != "region2" { 232 return false, fmt.Errorf("unexpected regions: %v", out) 233 } 234 return true, nil 235 }, func(err error) { 236 t.Fatalf("err: %v", err) 237 }) 238 } 239 240 func TestServer_Reload_Vault(t *testing.T) { 241 t.Parallel() 242 s1 := testServer(t, func(c *Config) { 243 c.Region = "region1" 244 }) 245 defer s1.Shutdown() 246 247 if s1.vault.Running() { 248 t.Fatalf("Vault client should not be running") 249 } 250 251 tr := true 252 config := s1.config 253 config.VaultConfig.Enabled = &tr 254 config.VaultConfig.Token = structs.GenerateUUID() 255 256 if err := s1.Reload(config); err != nil { 257 t.Fatalf("Reload failed: %v", err) 258 } 259 260 if !s1.vault.Running() { 261 t.Fatalf("Vault client should be running") 262 } 263 }