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  }