github.com/smintz/nomad@v0.8.3/command/agent/agent_test.go (about)

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