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  }