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  }