github.com/hspak/nomad@v0.7.2-0.20180309000617-bc4ae22a39a5/command/agent/agent_test.go (about)

     1  package agent
     2  
     3  import (
     4  	"encoding/json"
     5  	"io/ioutil"
     6  	"log"
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/hashicorp/nomad/helper"
    13  	sconfig "github.com/hashicorp/nomad/nomad/structs/config"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func tmpDir(t testing.TB) string {
    18  	dir, err := ioutil.TempDir("", "nomad")
    19  	if err != nil {
    20  		t.Fatalf("err: %v", err)
    21  	}
    22  	return dir
    23  }
    24  
    25  func TestAgent_RPC_Ping(t *testing.T) {
    26  	t.Parallel()
    27  	agent := NewTestAgent(t, t.Name(), nil)
    28  	defer agent.Shutdown()
    29  
    30  	var out struct{}
    31  	if err := agent.RPC("Status.Ping", struct{}{}, &out); err != nil {
    32  		t.Fatalf("err: %v", err)
    33  	}
    34  }
    35  
    36  func TestAgent_ServerConfig(t *testing.T) {
    37  	t.Parallel()
    38  	conf := DefaultConfig()
    39  	conf.DevMode = true // allow localhost for advertise addrs
    40  	a := &Agent{config: conf}
    41  
    42  	conf.AdvertiseAddrs.Serf = "127.0.0.1:4000"
    43  	conf.AdvertiseAddrs.RPC = "127.0.0.1:4001"
    44  	conf.AdvertiseAddrs.HTTP = "10.10.11.1:4005"
    45  	conf.ACL.Enabled = true
    46  
    47  	// Parses the advertise addrs correctly
    48  	if err := conf.normalizeAddrs(); err != nil {
    49  		t.Fatalf("error normalizing config: %v", err)
    50  	}
    51  	out, err := a.serverConfig()
    52  	if err != nil {
    53  		t.Fatalf("err: %s", err)
    54  	}
    55  	serfAddr := out.SerfConfig.MemberlistConfig.AdvertiseAddr
    56  	if serfAddr != "127.0.0.1" {
    57  		t.Fatalf("expect 127.0.0.1, got: %s", serfAddr)
    58  	}
    59  	serfPort := out.SerfConfig.MemberlistConfig.AdvertisePort
    60  	if serfPort != 4000 {
    61  		t.Fatalf("expected 4000, got: %d", serfPort)
    62  	}
    63  	if out.AuthoritativeRegion != "global" {
    64  		t.Fatalf("bad: %#v", out.AuthoritativeRegion)
    65  	}
    66  	if !out.ACLEnabled {
    67  		t.Fatalf("ACL not enabled")
    68  	}
    69  
    70  	// Assert addresses weren't changed
    71  	if addr := conf.AdvertiseAddrs.RPC; addr != "127.0.0.1:4001" {
    72  		t.Fatalf("bad rpc advertise addr: %#v", addr)
    73  	}
    74  	if addr := conf.AdvertiseAddrs.HTTP; addr != "10.10.11.1:4005" {
    75  		t.Fatalf("expect 10.11.11.1:4005, got: %v", addr)
    76  	}
    77  	if addr := conf.Addresses.RPC; addr != "0.0.0.0" {
    78  		t.Fatalf("expect 0.0.0.0, got: %v", addr)
    79  	}
    80  
    81  	// Sets up the ports properly
    82  	conf.Addresses.RPC = ""
    83  	conf.Addresses.Serf = ""
    84  	conf.Ports.RPC = 4003
    85  	conf.Ports.Serf = 4004
    86  
    87  	if err := conf.normalizeAddrs(); err != nil {
    88  		t.Fatalf("error normalizing config: %v", err)
    89  	}
    90  	out, err = a.serverConfig()
    91  	if err != nil {
    92  		t.Fatalf("err: %s", err)
    93  	}
    94  	if addr := out.RPCAddr.Port; addr != 4003 {
    95  		t.Fatalf("expect 4003, got: %d", out.RPCAddr.Port)
    96  	}
    97  	if port := out.SerfConfig.MemberlistConfig.BindPort; port != 4004 {
    98  		t.Fatalf("expect 4004, got: %d", port)
    99  	}
   100  
   101  	// Prefers advertise over bind addr
   102  	conf.BindAddr = "127.0.0.3"
   103  	conf.Addresses.HTTP = "127.0.0.2"
   104  	conf.Addresses.RPC = "127.0.0.2"
   105  	conf.Addresses.Serf = "127.0.0.2"
   106  	conf.AdvertiseAddrs.HTTP = "10.0.0.10"
   107  	conf.AdvertiseAddrs.RPC = ""
   108  	conf.AdvertiseAddrs.Serf = "10.0.0.12:4004"
   109  
   110  	if err := conf.normalizeAddrs(); err != nil {
   111  		t.Fatalf("error normalizing config: %v", err)
   112  	}
   113  	out, err = a.serverConfig()
   114  	if err != nil {
   115  		t.Fatalf("err: %s", err)
   116  	}
   117  	if addr := out.RPCAddr.IP.String(); addr != "127.0.0.2" {
   118  		t.Fatalf("expect 127.0.0.2, got: %s", addr)
   119  	}
   120  	if port := out.RPCAddr.Port; port != 4003 {
   121  		t.Fatalf("expect 4647, got: %d", port)
   122  	}
   123  	if addr := out.SerfConfig.MemberlistConfig.BindAddr; addr != "127.0.0.2" {
   124  		t.Fatalf("expect 127.0.0.2, got: %s", addr)
   125  	}
   126  	if port := out.SerfConfig.MemberlistConfig.BindPort; port != 4004 {
   127  		t.Fatalf("expect 4648, got: %d", port)
   128  	}
   129  	if addr := conf.Addresses.HTTP; addr != "127.0.0.2" {
   130  		t.Fatalf("expect 127.0.0.2, got: %s", addr)
   131  	}
   132  	if addr := conf.Addresses.RPC; addr != "127.0.0.2" {
   133  		t.Fatalf("expect 127.0.0.2, got: %s", addr)
   134  	}
   135  	if addr := conf.Addresses.Serf; addr != "127.0.0.2" {
   136  		t.Fatalf("expect 10.0.0.12, got: %s", addr)
   137  	}
   138  	if addr := conf.normalizedAddrs.HTTP; addr != "127.0.0.2:4646" {
   139  		t.Fatalf("expect 127.0.0.2:4646, got: %s", addr)
   140  	}
   141  	if addr := conf.normalizedAddrs.RPC; addr != "127.0.0.2:4003" {
   142  		t.Fatalf("expect 127.0.0.2:4003, got: %s", addr)
   143  	}
   144  	if addr := conf.normalizedAddrs.Serf; addr != "127.0.0.2:4004" {
   145  		t.Fatalf("expect 10.0.0.12:4004, got: %s", addr)
   146  	}
   147  	if addr := conf.AdvertiseAddrs.HTTP; addr != "10.0.0.10:4646" {
   148  		t.Fatalf("expect 10.0.0.10:4646, got: %s", addr)
   149  	}
   150  	if addr := conf.AdvertiseAddrs.RPC; addr != "127.0.0.2:4003" {
   151  		t.Fatalf("expect 127.0.0.2:4003, got: %s", addr)
   152  	}
   153  	if addr := conf.AdvertiseAddrs.Serf; addr != "10.0.0.12:4004" {
   154  		t.Fatalf("expect 10.0.0.12:4004, got: %s", addr)
   155  	}
   156  
   157  	conf.Server.NodeGCThreshold = "42g"
   158  	if err := conf.normalizeAddrs(); err != nil {
   159  		t.Fatalf("error normalizing config: %v", err)
   160  	}
   161  	out, err = a.serverConfig()
   162  	if err == nil || !strings.Contains(err.Error(), "unknown unit") {
   163  		t.Fatalf("expected unknown unit error, got: %#v", err)
   164  	}
   165  
   166  	conf.Server.NodeGCThreshold = "10s"
   167  	if err := conf.normalizeAddrs(); err != nil {
   168  		t.Fatalf("error normalizing config: %v", err)
   169  	}
   170  	out, err = a.serverConfig()
   171  	if threshold := out.NodeGCThreshold; threshold != time.Second*10 {
   172  		t.Fatalf("expect 10s, got: %s", threshold)
   173  	}
   174  
   175  	conf.Server.HeartbeatGrace = 37 * time.Second
   176  	out, err = a.serverConfig()
   177  	if threshold := out.HeartbeatGrace; threshold != time.Second*37 {
   178  		t.Fatalf("expect 37s, got: %s", threshold)
   179  	}
   180  
   181  	conf.Server.MinHeartbeatTTL = 37 * time.Second
   182  	out, err = a.serverConfig()
   183  	if min := out.MinHeartbeatTTL; min != time.Second*37 {
   184  		t.Fatalf("expect 37s, got: %s", min)
   185  	}
   186  
   187  	conf.Server.MaxHeartbeatsPerSecond = 11.0
   188  	out, err = a.serverConfig()
   189  	if max := out.MaxHeartbeatsPerSecond; max != 11.0 {
   190  		t.Fatalf("expect 11, got: %v", max)
   191  	}
   192  
   193  	// Defaults to the global bind addr
   194  	conf.Addresses.RPC = ""
   195  	conf.Addresses.Serf = ""
   196  	conf.Addresses.HTTP = ""
   197  	conf.AdvertiseAddrs.RPC = ""
   198  	conf.AdvertiseAddrs.HTTP = ""
   199  	conf.AdvertiseAddrs.Serf = ""
   200  	conf.Ports.HTTP = 4646
   201  	conf.Ports.RPC = 4647
   202  	conf.Ports.Serf = 4648
   203  	if err := conf.normalizeAddrs(); err != nil {
   204  		t.Fatalf("error normalizing config: %v", err)
   205  	}
   206  	out, err = a.serverConfig()
   207  	if err != nil {
   208  		t.Fatalf("err: %s", err)
   209  	}
   210  	if addr := out.RPCAddr.IP.String(); addr != "127.0.0.3" {
   211  		t.Fatalf("expect 127.0.0.3, got: %s", addr)
   212  	}
   213  	if addr := out.SerfConfig.MemberlistConfig.BindAddr; addr != "127.0.0.3" {
   214  		t.Fatalf("expect 127.0.0.3, got: %s", addr)
   215  	}
   216  	if addr := conf.Addresses.HTTP; addr != "127.0.0.3" {
   217  		t.Fatalf("expect 127.0.0.3, got: %s", addr)
   218  	}
   219  	if addr := conf.Addresses.RPC; addr != "127.0.0.3" {
   220  		t.Fatalf("expect 127.0.0.3, got: %s", addr)
   221  	}
   222  	if addr := conf.Addresses.Serf; addr != "127.0.0.3" {
   223  		t.Fatalf("expect 127.0.0.3, got: %s", addr)
   224  	}
   225  	if addr := conf.normalizedAddrs.HTTP; addr != "127.0.0.3:4646" {
   226  		t.Fatalf("expect 127.0.0.3:4646, got: %s", addr)
   227  	}
   228  	if addr := conf.normalizedAddrs.RPC; addr != "127.0.0.3:4647" {
   229  		t.Fatalf("expect 127.0.0.3:4647, got: %s", addr)
   230  	}
   231  	if addr := conf.normalizedAddrs.Serf; addr != "127.0.0.3:4648" {
   232  		t.Fatalf("expect 127.0.0.3:4648, got: %s", addr)
   233  	}
   234  
   235  	// Properly handles the bootstrap flags
   236  	conf.Server.BootstrapExpect = 1
   237  	out, err = a.serverConfig()
   238  	if err != nil {
   239  		t.Fatalf("err: %s", err)
   240  	}
   241  	if !out.Bootstrap {
   242  		t.Fatalf("should have set bootstrap mode")
   243  	}
   244  	if out.BootstrapExpect != 0 {
   245  		t.Fatalf("boostrap expect should be 0")
   246  	}
   247  
   248  	conf.Server.BootstrapExpect = 3
   249  	out, err = a.serverConfig()
   250  	if err != nil {
   251  		t.Fatalf("err: %s", err)
   252  	}
   253  	if out.Bootstrap {
   254  		t.Fatalf("bootstrap mode should be disabled")
   255  	}
   256  	if out.BootstrapExpect != 3 {
   257  		t.Fatalf("should have bootstrap-expect = 3")
   258  	}
   259  }
   260  
   261  func TestAgent_ClientConfig(t *testing.T) {
   262  	t.Parallel()
   263  	conf := DefaultConfig()
   264  	conf.Client.Enabled = true
   265  
   266  	// For Clients HTTP and RPC must be set (Serf can be skipped)
   267  	conf.Addresses.HTTP = "169.254.0.1"
   268  	conf.Addresses.RPC = "169.254.0.1"
   269  	conf.Ports.HTTP = 5678
   270  	a := &Agent{config: conf}
   271  
   272  	if err := conf.normalizeAddrs(); err != nil {
   273  		t.Fatalf("error normalizing config: %v", err)
   274  	}
   275  	c, err := a.clientConfig()
   276  	if err != nil {
   277  		t.Fatalf("got err: %v", err)
   278  	}
   279  
   280  	expectedHttpAddr := "169.254.0.1:5678"
   281  	if c.Node.HTTPAddr != expectedHttpAddr {
   282  		t.Fatalf("Expected http addr: %v, got: %v", expectedHttpAddr, c.Node.HTTPAddr)
   283  	}
   284  
   285  	conf = DefaultConfig()
   286  	conf.DevMode = true
   287  	a = &Agent{config: conf}
   288  	conf.Client.Enabled = true
   289  	conf.Addresses.HTTP = "169.254.0.1"
   290  
   291  	if err := conf.normalizeAddrs(); err != nil {
   292  		t.Fatalf("error normalizing config: %v", err)
   293  	}
   294  	c, err = a.clientConfig()
   295  	if err != nil {
   296  		t.Fatalf("got err: %v", err)
   297  	}
   298  
   299  	expectedHttpAddr = "169.254.0.1:4646"
   300  	if c.Node.HTTPAddr != expectedHttpAddr {
   301  		t.Fatalf("Expected http addr: %v, got: %v", expectedHttpAddr, c.Node.HTTPAddr)
   302  	}
   303  }
   304  
   305  // Clients should inherit telemetry configuration
   306  func TestAget_Client_TelemetryConfiguration(t *testing.T) {
   307  	assert := assert.New(t)
   308  
   309  	conf := DefaultConfig()
   310  	conf.DevMode = true
   311  	conf.Telemetry.DisableTaggedMetrics = true
   312  	conf.Telemetry.BackwardsCompatibleMetrics = true
   313  
   314  	a := &Agent{config: conf}
   315  
   316  	c, err := a.clientConfig()
   317  	assert.Nil(err)
   318  
   319  	telemetry := conf.Telemetry
   320  
   321  	assert.Equal(c.StatsCollectionInterval, telemetry.collectionInterval)
   322  	assert.Equal(c.PublishNodeMetrics, telemetry.PublishNodeMetrics)
   323  	assert.Equal(c.PublishAllocationMetrics, telemetry.PublishAllocationMetrics)
   324  	assert.Equal(c.DisableTaggedMetrics, telemetry.DisableTaggedMetrics)
   325  	assert.Equal(c.BackwardsCompatibleMetrics, telemetry.BackwardsCompatibleMetrics)
   326  }
   327  
   328  // TestAgent_HTTPCheck asserts Agent.agentHTTPCheck properly alters the HTTP
   329  // API health check depending on configuration.
   330  func TestAgent_HTTPCheck(t *testing.T) {
   331  	t.Parallel()
   332  	logger := log.New(ioutil.Discard, "", 0)
   333  	if testing.Verbose() {
   334  		logger = log.New(os.Stdout, "[TestAgent_HTTPCheck] ", log.Lshortfile)
   335  	}
   336  	agent := func() *Agent {
   337  		return &Agent{
   338  			logger: logger,
   339  			config: &Config{
   340  				AdvertiseAddrs:  &AdvertiseAddrs{HTTP: "advertise:4646"},
   341  				normalizedAddrs: &Addresses{HTTP: "normalized:4646"},
   342  				Consul: &sconfig.ConsulConfig{
   343  					ChecksUseAdvertise: helper.BoolToPtr(false),
   344  				},
   345  				TLSConfig: &sconfig.TLSConfig{EnableHTTP: false},
   346  			},
   347  		}
   348  	}
   349  
   350  	t.Run("Plain HTTP Check", func(t *testing.T) {
   351  		a := agent()
   352  		check := a.agentHTTPCheck(false)
   353  		if check == nil {
   354  			t.Fatalf("expected non-nil check")
   355  		}
   356  		if check.Type != "http" {
   357  			t.Errorf("expected http check not: %q", check.Type)
   358  		}
   359  		if expected := "/v1/agent/health?type=client"; check.Path != expected {
   360  			t.Errorf("expected %q path not: %q", expected, check.Path)
   361  		}
   362  		if check.Protocol != "http" {
   363  			t.Errorf("expected http proto not: %q", check.Protocol)
   364  		}
   365  		if expected := a.config.normalizedAddrs.HTTP; check.PortLabel != expected {
   366  			t.Errorf("expected normalized addr not %q", check.PortLabel)
   367  		}
   368  	})
   369  
   370  	t.Run("Plain HTTP + ChecksUseAdvertise", func(t *testing.T) {
   371  		a := agent()
   372  		a.config.Consul.ChecksUseAdvertise = helper.BoolToPtr(true)
   373  		check := a.agentHTTPCheck(false)
   374  		if check == nil {
   375  			t.Fatalf("expected non-nil check")
   376  		}
   377  		if expected := a.config.AdvertiseAddrs.HTTP; check.PortLabel != expected {
   378  			t.Errorf("expected advertise addr not %q", check.PortLabel)
   379  		}
   380  	})
   381  
   382  	t.Run("HTTPS + consulSupportsTLSSkipVerify", func(t *testing.T) {
   383  		a := agent()
   384  		a.consulSupportsTLSSkipVerify = true
   385  		a.config.TLSConfig.EnableHTTP = true
   386  
   387  		check := a.agentHTTPCheck(false)
   388  		if check == nil {
   389  			t.Fatalf("expected non-nil check")
   390  		}
   391  		if !check.TLSSkipVerify {
   392  			t.Errorf("expected tls skip verify")
   393  		}
   394  		if check.Protocol != "https" {
   395  			t.Errorf("expected https not: %q", check.Protocol)
   396  		}
   397  	})
   398  
   399  	t.Run("HTTPS w/o TLSSkipVerify", func(t *testing.T) {
   400  		a := agent()
   401  		a.consulSupportsTLSSkipVerify = false
   402  		a.config.TLSConfig.EnableHTTP = true
   403  
   404  		if check := a.agentHTTPCheck(false); check != nil {
   405  			t.Fatalf("expected nil check not: %#v", check)
   406  		}
   407  	})
   408  
   409  	t.Run("HTTPS + VerifyHTTPSClient", func(t *testing.T) {
   410  		a := agent()
   411  		a.consulSupportsTLSSkipVerify = true
   412  		a.config.TLSConfig.EnableHTTP = true
   413  		a.config.TLSConfig.VerifyHTTPSClient = true
   414  
   415  		if check := a.agentHTTPCheck(false); check != nil {
   416  			t.Fatalf("expected nil check not: %#v", check)
   417  		}
   418  	})
   419  }
   420  
   421  func TestAgent_ConsulSupportsTLSSkipVerify(t *testing.T) {
   422  	t.Parallel()
   423  	assertSupport := func(expected bool, blob string) {
   424  		self := map[string]map[string]interface{}{}
   425  		if err := json.Unmarshal([]byte("{"+blob+"}"), &self); err != nil {
   426  			t.Fatalf("invalid json: %v", err)
   427  		}
   428  		actual := consulSupportsTLSSkipVerify(self)
   429  		if actual != expected {
   430  			t.Errorf("expected %t but got %t for:\n%s\n", expected, actual, blob)
   431  		}
   432  	}
   433  
   434  	// 0.6.4
   435  	assertSupport(false, `"Member": {
   436          "Addr": "127.0.0.1",
   437          "DelegateCur": 4,
   438          "DelegateMax": 4,
   439          "DelegateMin": 2,
   440          "Name": "rusty",
   441          "Port": 8301,
   442          "ProtocolCur": 2,
   443          "ProtocolMax": 3,
   444          "ProtocolMin": 1,
   445          "Status": 1,
   446          "Tags": {
   447              "build": "0.6.4:26a0ef8c",
   448              "dc": "dc1",
   449              "port": "8300",
   450              "role": "consul",
   451              "vsn": "2",
   452              "vsn_max": "3",
   453              "vsn_min": "1"
   454          }}`)
   455  
   456  	// 0.7.0
   457  	assertSupport(false, `"Member": {
   458          "Addr": "127.0.0.1",
   459          "DelegateCur": 4,
   460          "DelegateMax": 4,
   461          "DelegateMin": 2,
   462          "Name": "rusty",
   463          "Port": 8301,
   464          "ProtocolCur": 2,
   465          "ProtocolMax": 4,
   466          "ProtocolMin": 1,
   467          "Status": 1,
   468          "Tags": {
   469              "build": "0.7.0:'a189091",
   470              "dc": "dc1",
   471              "port": "8300",
   472              "role": "consul",
   473              "vsn": "2",
   474              "vsn_max": "3",
   475              "vsn_min": "2"
   476          }}`)
   477  
   478  	// 0.7.2
   479  	assertSupport(true, `"Member": {
   480          "Addr": "127.0.0.1",
   481          "DelegateCur": 4,
   482          "DelegateMax": 4,
   483          "DelegateMin": 2,
   484          "Name": "rusty",
   485          "Port": 8301,
   486          "ProtocolCur": 2,
   487          "ProtocolMax": 5,
   488          "ProtocolMin": 1,
   489          "Status": 1,
   490          "Tags": {
   491              "build": "0.7.2:'a9afa0c",
   492              "dc": "dc1",
   493              "port": "8300",
   494              "role": "consul",
   495              "vsn": "2",
   496              "vsn_max": "3",
   497              "vsn_min": "2"
   498          }}`)
   499  
   500  	// 0.8.1
   501  	assertSupport(true, `"Member": {
   502          "Addr": "127.0.0.1",
   503          "DelegateCur": 4,
   504          "DelegateMax": 5,
   505          "DelegateMin": 2,
   506          "Name": "rusty",
   507          "Port": 8301,
   508          "ProtocolCur": 2,
   509          "ProtocolMax": 5,
   510          "ProtocolMin": 1,
   511          "Status": 1,
   512          "Tags": {
   513              "build": "0.8.1:'e9ca44d",
   514              "dc": "dc1",
   515              "id": "3ddc1b59-460e-a100-1d5c-ce3972122664",
   516              "port": "8300",
   517              "raft_vsn": "2",
   518              "role": "consul",
   519              "vsn": "2",
   520              "vsn_max": "3",
   521              "vsn_min": "2",
   522              "wan_join_port": "8302"
   523          }}`)
   524  }
   525  
   526  // TestAgent_HTTPCheckPath asserts clients and servers use different endpoints
   527  // for healthchecks.
   528  func TestAgent_HTTPCheckPath(t *testing.T) {
   529  	t.Parallel()
   530  	// Agent.agentHTTPCheck only needs a config and logger
   531  	a := &Agent{
   532  		config: DevConfig(),
   533  		logger: log.New(ioutil.Discard, "", 0),
   534  	}
   535  	if err := a.config.normalizeAddrs(); err != nil {
   536  		t.Fatalf("error normalizing config: %v", err)
   537  	}
   538  	if testing.Verbose() {
   539  		a.logger = log.New(os.Stderr, "", log.LstdFlags)
   540  	}
   541  
   542  	// Assert server check uses /v1/agent/health?type=server
   543  	isServer := true
   544  	check := a.agentHTTPCheck(isServer)
   545  	if expected := "Nomad Server HTTP Check"; check.Name != expected {
   546  		t.Errorf("expected server check name to be %q but found %q", expected, check.Name)
   547  	}
   548  	if expected := "/v1/agent/health?type=server"; check.Path != expected {
   549  		t.Errorf("expected server check path to be %q but found %q", expected, check.Path)
   550  	}
   551  
   552  	// Assert client check uses /v1/agent/health?type=client
   553  	isServer = false
   554  	check = a.agentHTTPCheck(isServer)
   555  	if expected := "Nomad Client HTTP Check"; check.Name != expected {
   556  		t.Errorf("expected client check name to be %q but found %q", expected, check.Name)
   557  	}
   558  	if expected := "/v1/agent/health?type=client"; check.Path != expected {
   559  		t.Errorf("expected client check path to be %q but found %q", expected, check.Path)
   560  	}
   561  }
   562  
   563  // This test asserts that the keyloader embedded in the TLS config is shared
   564  // across the Agent, Server, and Client. This is essential for certificate
   565  // reloading to work.
   566  func TestServer_Reload_TLS_Shared_Keyloader(t *testing.T) {
   567  	t.Parallel()
   568  	assert := assert.New(t)
   569  
   570  	// We will start out with a bad cert and then reload with a good one.
   571  	const (
   572  		cafile   = "../../helper/tlsutil/testdata/ca.pem"
   573  		foocert  = "../../helper/tlsutil/testdata/nomad-bad.pem"
   574  		fookey   = "../../helper/tlsutil/testdata/nomad-bad-key.pem"
   575  		foocert2 = "../../helper/tlsutil/testdata/nomad-foo.pem"
   576  		fookey2  = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
   577  	)
   578  
   579  	agent := NewTestAgent(t, t.Name(), func(c *Config) {
   580  		c.TLSConfig = &sconfig.TLSConfig{
   581  			EnableHTTP:           true,
   582  			EnableRPC:            true,
   583  			VerifyServerHostname: true,
   584  			CAFile:               cafile,
   585  			CertFile:             foocert,
   586  			KeyFile:              fookey,
   587  		}
   588  	})
   589  	defer agent.Shutdown()
   590  
   591  	originalKeyloader := agent.Config.TLSConfig.GetKeyLoader()
   592  	originalCert, err := originalKeyloader.GetOutgoingCertificate(nil)
   593  	assert.NotNil(originalKeyloader)
   594  	if assert.Nil(err) {
   595  		assert.NotNil(originalCert)
   596  	}
   597  
   598  	// Switch to the correct certificates and reload
   599  	newConfig := &Config{
   600  		TLSConfig: &sconfig.TLSConfig{
   601  			EnableHTTP:           true,
   602  			EnableRPC:            true,
   603  			VerifyServerHostname: true,
   604  			CAFile:               cafile,
   605  			CertFile:             foocert2,
   606  			KeyFile:              fookey2,
   607  		},
   608  	}
   609  
   610  	assert.Nil(agent.Reload(newConfig))
   611  	assert.Equal(agent.Config.TLSConfig.CertFile, newConfig.TLSConfig.CertFile)
   612  	assert.Equal(agent.Config.TLSConfig.KeyFile, newConfig.TLSConfig.KeyFile)
   613  	assert.Equal(agent.Config.TLSConfig.GetKeyLoader(), originalKeyloader)
   614  
   615  	// Assert is passed through on the server correctly
   616  	if assert.NotNil(agent.server.GetConfig().TLSConfig) {
   617  		serverKeyloader := agent.server.GetConfig().TLSConfig.GetKeyLoader()
   618  		assert.Equal(serverKeyloader, originalKeyloader)
   619  		newCert, err := serverKeyloader.GetOutgoingCertificate(nil)
   620  		assert.Nil(err)
   621  		assert.NotEqual(originalCert, newCert)
   622  	}
   623  
   624  	// Assert is passed through on the client correctly
   625  	if assert.NotNil(agent.client.GetConfig().TLSConfig) {
   626  		clientKeyloader := agent.client.GetConfig().TLSConfig.GetKeyLoader()
   627  		assert.Equal(clientKeyloader, originalKeyloader)
   628  		newCert, err := clientKeyloader.GetOutgoingCertificate(nil)
   629  		assert.Nil(err)
   630  		assert.NotEqual(originalCert, newCert)
   631  	}
   632  }
   633  
   634  func TestServer_Reload_TLS_Certificate(t *testing.T) {
   635  	t.Parallel()
   636  	assert := assert.New(t)
   637  
   638  	const (
   639  		cafile   = "../../helper/tlsutil/testdata/ca.pem"
   640  		foocert  = "../../helper/tlsutil/testdata/nomad-bad.pem"
   641  		fookey   = "../../helper/tlsutil/testdata/nomad-bad-key.pem"
   642  		foocert2 = "../../helper/tlsutil/testdata/nomad-foo.pem"
   643  		fookey2  = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
   644  	)
   645  
   646  	agentConfig := &Config{
   647  		TLSConfig: &sconfig.TLSConfig{
   648  			EnableHTTP:           true,
   649  			EnableRPC:            true,
   650  			VerifyServerHostname: true,
   651  			CAFile:               cafile,
   652  			CertFile:             foocert,
   653  			KeyFile:              fookey,
   654  		},
   655  	}
   656  
   657  	agent := &Agent{
   658  		config: agentConfig,
   659  	}
   660  
   661  	newConfig := &Config{
   662  		TLSConfig: &sconfig.TLSConfig{
   663  			EnableHTTP:           true,
   664  			EnableRPC:            true,
   665  			VerifyServerHostname: true,
   666  			CAFile:               cafile,
   667  			CertFile:             foocert2,
   668  			KeyFile:              fookey2,
   669  		},
   670  	}
   671  
   672  	originalKeyloader := agentConfig.TLSConfig.GetKeyLoader()
   673  	assert.NotNil(originalKeyloader)
   674  
   675  	err := agent.Reload(newConfig)
   676  	assert.Nil(err)
   677  	assert.Equal(agent.config.TLSConfig.CertFile, newConfig.TLSConfig.CertFile)
   678  	assert.Equal(agent.config.TLSConfig.KeyFile, newConfig.TLSConfig.KeyFile)
   679  	assert.Equal(agent.config.TLSConfig.GetKeyLoader(), originalKeyloader)
   680  }
   681  
   682  func TestServer_Reload_TLS_Certificate_Invalid(t *testing.T) {
   683  	t.Parallel()
   684  	assert := assert.New(t)
   685  
   686  	const (
   687  		cafile   = "../../helper/tlsutil/testdata/ca.pem"
   688  		foocert  = "../../helper/tlsutil/testdata/nomad-bad.pem"
   689  		fookey   = "../../helper/tlsutil/testdata/nomad-bad-key.pem"
   690  		foocert2 = "invalid_cert_path"
   691  		fookey2  = "invalid_key_path"
   692  	)
   693  
   694  	agentConfig := &Config{
   695  		TLSConfig: &sconfig.TLSConfig{
   696  			EnableHTTP:           true,
   697  			EnableRPC:            true,
   698  			VerifyServerHostname: true,
   699  			CAFile:               cafile,
   700  			CertFile:             foocert,
   701  			KeyFile:              fookey,
   702  		},
   703  	}
   704  
   705  	agent := &Agent{
   706  		config: agentConfig,
   707  	}
   708  
   709  	newConfig := &Config{
   710  		TLSConfig: &sconfig.TLSConfig{
   711  			EnableHTTP:           true,
   712  			EnableRPC:            true,
   713  			VerifyServerHostname: true,
   714  			CAFile:               cafile,
   715  			CertFile:             foocert2,
   716  			KeyFile:              fookey2,
   717  		},
   718  	}
   719  
   720  	err := agent.Reload(newConfig)
   721  	assert.NotNil(err)
   722  	assert.NotEqual(agent.config.TLSConfig.CertFile, newConfig.TLSConfig.CertFile)
   723  	assert.NotEqual(agent.config.TLSConfig.KeyFile, newConfig.TLSConfig.KeyFile)
   724  }
   725  
   726  func Test_GetConfig(t *testing.T) {
   727  	assert := assert.New(t)
   728  
   729  	agentConfig := &Config{
   730  		Telemetry:      &Telemetry{},
   731  		Client:         &ClientConfig{},
   732  		Server:         &ServerConfig{},
   733  		ACL:            &ACLConfig{},
   734  		Ports:          &Ports{},
   735  		Addresses:      &Addresses{},
   736  		AdvertiseAddrs: &AdvertiseAddrs{},
   737  		Vault:          &sconfig.VaultConfig{},
   738  		Consul:         &sconfig.ConsulConfig{},
   739  		Sentinel:       &sconfig.SentinelConfig{},
   740  	}
   741  
   742  	agent := &Agent{
   743  		config: agentConfig,
   744  	}
   745  
   746  	actualAgentConfig := agent.GetConfig()
   747  	assert.Equal(actualAgentConfig, agentConfig)
   748  }
   749  
   750  func TestServer_Reload_TLS_WithNilConfiguration(t *testing.T) {
   751  	t.Parallel()
   752  	assert := assert.New(t)
   753  
   754  	logger := log.New(ioutil.Discard, "", 0)
   755  
   756  	agent := &Agent{
   757  		logger: logger,
   758  		config: &Config{},
   759  	}
   760  
   761  	err := agent.Reload(nil)
   762  	assert.NotNil(err)
   763  	assert.Equal(err.Error(), "cannot reload agent with nil configuration")
   764  }
   765  
   766  func TestServer_Reload_TLS_UpgradeToTLS(t *testing.T) {
   767  	t.Parallel()
   768  	assert := assert.New(t)
   769  
   770  	const (
   771  		cafile  = "../../helper/tlsutil/testdata/ca.pem"
   772  		foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
   773  		fookey  = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
   774  	)
   775  	dir := tmpDir(t)
   776  	defer os.RemoveAll(dir)
   777  
   778  	logger := log.New(ioutil.Discard, "", 0)
   779  
   780  	agentConfig := &Config{
   781  		TLSConfig: &sconfig.TLSConfig{},
   782  	}
   783  
   784  	agent := &Agent{
   785  		logger: logger,
   786  		config: agentConfig,
   787  	}
   788  
   789  	newConfig := &Config{
   790  		TLSConfig: &sconfig.TLSConfig{
   791  			EnableHTTP:           true,
   792  			EnableRPC:            true,
   793  			VerifyServerHostname: true,
   794  			CAFile:               cafile,
   795  			CertFile:             foocert,
   796  			KeyFile:              fookey,
   797  		},
   798  	}
   799  
   800  	err := agent.Reload(newConfig)
   801  	assert.Nil(err)
   802  
   803  	assert.Equal(agent.config.TLSConfig.CAFile, newConfig.TLSConfig.CAFile)
   804  	assert.Equal(agent.config.TLSConfig.CertFile, newConfig.TLSConfig.CertFile)
   805  	assert.Equal(agent.config.TLSConfig.KeyFile, newConfig.TLSConfig.KeyFile)
   806  }
   807  
   808  func TestServer_Reload_TLS_DowngradeFromTLS(t *testing.T) {
   809  	t.Parallel()
   810  	assert := assert.New(t)
   811  
   812  	const (
   813  		cafile  = "../../helper/tlsutil/testdata/ca.pem"
   814  		foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
   815  		fookey  = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
   816  	)
   817  	dir := tmpDir(t)
   818  	defer os.RemoveAll(dir)
   819  
   820  	logger := log.New(ioutil.Discard, "", 0)
   821  
   822  	agentConfig := &Config{
   823  		TLSConfig: &sconfig.TLSConfig{
   824  			EnableHTTP:           true,
   825  			EnableRPC:            true,
   826  			VerifyServerHostname: true,
   827  			CAFile:               cafile,
   828  			CertFile:             foocert,
   829  			KeyFile:              fookey,
   830  		},
   831  	}
   832  
   833  	agent := &Agent{
   834  		logger: logger,
   835  		config: agentConfig,
   836  	}
   837  
   838  	newConfig := &Config{
   839  		TLSConfig: &sconfig.TLSConfig{},
   840  	}
   841  
   842  	assert.False(agentConfig.TLSConfig.IsEmpty())
   843  
   844  	err := agent.Reload(newConfig)
   845  	assert.Nil(err)
   846  
   847  	assert.True(agentConfig.TLSConfig.IsEmpty())
   848  }
   849  
   850  func TestServer_ShouldReload_ReturnFalseForNoChanges(t *testing.T) {
   851  	t.Parallel()
   852  	assert := assert.New(t)
   853  
   854  	const (
   855  		cafile  = "../../helper/tlsutil/testdata/ca.pem"
   856  		foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
   857  		fookey  = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
   858  	)
   859  	dir := tmpDir(t)
   860  	defer os.RemoveAll(dir)
   861  
   862  	logger := log.New(ioutil.Discard, "", 0)
   863  
   864  	agentConfig := &Config{
   865  		TLSConfig: &sconfig.TLSConfig{
   866  			EnableHTTP:           true,
   867  			EnableRPC:            true,
   868  			VerifyServerHostname: true,
   869  			CAFile:               cafile,
   870  			CertFile:             foocert,
   871  			KeyFile:              fookey,
   872  		},
   873  	}
   874  
   875  	sameAgentConfig := &Config{
   876  		TLSConfig: &sconfig.TLSConfig{
   877  			EnableHTTP:           true,
   878  			EnableRPC:            true,
   879  			VerifyServerHostname: true,
   880  			CAFile:               cafile,
   881  			CertFile:             foocert,
   882  			KeyFile:              fookey,
   883  		},
   884  	}
   885  
   886  	agent := &Agent{
   887  		logger: logger,
   888  		config: agentConfig,
   889  	}
   890  
   891  	shouldReloadAgent, shouldReloadHTTPServer := agent.ShouldReload(sameAgentConfig)
   892  	assert.False(shouldReloadAgent)
   893  	assert.False(shouldReloadHTTPServer)
   894  }
   895  
   896  func TestServer_ShouldReload_ReturnTrueForConfigChanges(t *testing.T) {
   897  	t.Parallel()
   898  	assert := assert.New(t)
   899  
   900  	const (
   901  		cafile   = "../../helper/tlsutil/testdata/ca.pem"
   902  		foocert  = "../../helper/tlsutil/testdata/nomad-foo.pem"
   903  		fookey   = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
   904  		foocert2 = "any_cert_path"
   905  		fookey2  = "any_key_path"
   906  	)
   907  	dir := tmpDir(t)
   908  	defer os.RemoveAll(dir)
   909  
   910  	logger := log.New(ioutil.Discard, "", 0)
   911  
   912  	agentConfig := &Config{
   913  		TLSConfig: &sconfig.TLSConfig{
   914  			EnableHTTP:           true,
   915  			EnableRPC:            true,
   916  			VerifyServerHostname: true,
   917  			CAFile:               cafile,
   918  			CertFile:             foocert,
   919  			KeyFile:              fookey,
   920  		},
   921  	}
   922  
   923  	newConfig := &Config{
   924  		TLSConfig: &sconfig.TLSConfig{
   925  			EnableHTTP:           true,
   926  			EnableRPC:            true,
   927  			VerifyServerHostname: true,
   928  			CAFile:               cafile,
   929  			CertFile:             foocert2,
   930  			KeyFile:              fookey2,
   931  		},
   932  	}
   933  
   934  	agent := &Agent{
   935  		logger: logger,
   936  		config: agentConfig,
   937  	}
   938  
   939  	shouldReloadAgent, shouldReloadHTTPServer := agent.ShouldReload(newConfig)
   940  	assert.True(shouldReloadAgent)
   941  	assert.True(shouldReloadHTTPServer)
   942  }