github.com/bigcommerce/nomad@v0.9.3-bc/command/agent/agent_test.go (about)

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