github.imxd.top/hashicorp/consul@v1.4.5/agent/agent_test.go (about)

     1  package agent
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"net"
    10  	"net/http"
    11  	"net/http/httptest"
    12  	"os"
    13  	"path/filepath"
    14  	"reflect"
    15  	"strings"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/hashicorp/consul/testrpc"
    20  
    21  	"github.com/hashicorp/consul/agent/checks"
    22  	"github.com/hashicorp/consul/agent/config"
    23  	"github.com/hashicorp/consul/agent/connect"
    24  	"github.com/hashicorp/consul/agent/structs"
    25  	"github.com/hashicorp/consul/api"
    26  	"github.com/hashicorp/consul/testutil"
    27  	"github.com/hashicorp/consul/testutil/retry"
    28  	"github.com/hashicorp/consul/types"
    29  	uuid "github.com/hashicorp/go-uuid"
    30  	"github.com/pascaldekloe/goe/verify"
    31  	"github.com/stretchr/testify/assert"
    32  	"github.com/stretchr/testify/require"
    33  )
    34  
    35  func externalIP() (string, error) {
    36  	addrs, err := net.InterfaceAddrs()
    37  	if err != nil {
    38  		return "", fmt.Errorf("Unable to lookup network interfaces: %v", err)
    39  	}
    40  	for _, a := range addrs {
    41  		if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
    42  			if ipnet.IP.To4() != nil {
    43  				return ipnet.IP.String(), nil
    44  			}
    45  		}
    46  	}
    47  	return "", fmt.Errorf("Unable to find a non-loopback interface")
    48  }
    49  
    50  func TestAgent_MultiStartStop(t *testing.T) {
    51  	for i := 0; i < 10; i++ {
    52  		t.Run("", func(t *testing.T) {
    53  			t.Parallel()
    54  			a := NewTestAgent(t, t.Name(), "")
    55  			time.Sleep(250 * time.Millisecond)
    56  			a.Shutdown()
    57  		})
    58  	}
    59  }
    60  
    61  func TestAgent_ConnectClusterIDConfig(t *testing.T) {
    62  	tests := []struct {
    63  		name          string
    64  		hcl           string
    65  		wantClusterID string
    66  		wantPanic     bool
    67  	}{
    68  		{
    69  			name:          "default TestAgent has fixed cluster id",
    70  			hcl:           "",
    71  			wantClusterID: connect.TestClusterID,
    72  		},
    73  		{
    74  			name:          "no cluster ID specified sets to test ID",
    75  			hcl:           "connect { enabled = true }",
    76  			wantClusterID: connect.TestClusterID,
    77  		},
    78  		{
    79  			name: "non-UUID cluster_id is fatal",
    80  			hcl: `connect {
    81  	   enabled = true
    82  	   ca_config {
    83  	     cluster_id = "fake-id"
    84  	   }
    85  	 }`,
    86  			wantClusterID: "",
    87  			wantPanic:     true,
    88  		},
    89  	}
    90  
    91  	for _, tt := range tests {
    92  		t.Run(tt.name, func(t *testing.T) {
    93  			// Indirection to support panic recovery cleanly
    94  			testFn := func() {
    95  				a := &TestAgent{Name: "test", HCL: tt.hcl}
    96  				a.ExpectConfigError = tt.wantPanic
    97  				a.Start(t)
    98  				defer a.Shutdown()
    99  
   100  				cfg := a.consulConfig()
   101  				assert.Equal(t, tt.wantClusterID, cfg.CAConfig.ClusterID)
   102  			}
   103  
   104  			if tt.wantPanic {
   105  				require.Panics(t, testFn)
   106  			} else {
   107  				testFn()
   108  			}
   109  		})
   110  	}
   111  }
   112  
   113  func TestAgent_StartStop(t *testing.T) {
   114  	t.Parallel()
   115  	a := NewTestAgent(t, t.Name(), "")
   116  	defer a.Shutdown()
   117  
   118  	if err := a.Leave(); err != nil {
   119  		t.Fatalf("err: %v", err)
   120  	}
   121  	if err := a.Shutdown(); err != nil {
   122  		t.Fatalf("err: %v", err)
   123  	}
   124  
   125  	select {
   126  	case <-a.ShutdownCh():
   127  	default:
   128  		t.Fatalf("should be closed")
   129  	}
   130  }
   131  
   132  func TestAgent_RPCPing(t *testing.T) {
   133  	t.Parallel()
   134  	a := NewTestAgent(t, t.Name(), "")
   135  	defer a.Shutdown()
   136  
   137  	var out struct{}
   138  	if err := a.RPC("Status.Ping", struct{}{}, &out); err != nil {
   139  		t.Fatalf("err: %v", err)
   140  	}
   141  }
   142  
   143  func TestAgent_TokenStore(t *testing.T) {
   144  	t.Parallel()
   145  
   146  	a := NewTestAgent(t, t.Name(), `
   147  		acl_token = "user"
   148  		acl_agent_token = "agent"
   149  		acl_agent_master_token = "master"`,
   150  	)
   151  	defer a.Shutdown()
   152  
   153  	if got, want := a.tokens.UserToken(), "user"; got != want {
   154  		t.Fatalf("got %q want %q", got, want)
   155  	}
   156  	if got, want := a.tokens.AgentToken(), "agent"; got != want {
   157  		t.Fatalf("got %q want %q", got, want)
   158  	}
   159  	if got, want := a.tokens.IsAgentMasterToken("master"), true; got != want {
   160  		t.Fatalf("got %v want %v", got, want)
   161  	}
   162  }
   163  
   164  func TestAgent_ReconnectConfigSettings(t *testing.T) {
   165  	t.Parallel()
   166  	func() {
   167  		a := NewTestAgent(t, t.Name(), "")
   168  		defer a.Shutdown()
   169  
   170  		lan := a.consulConfig().SerfLANConfig.ReconnectTimeout
   171  		if lan != 3*24*time.Hour {
   172  			t.Fatalf("bad: %s", lan.String())
   173  		}
   174  
   175  		wan := a.consulConfig().SerfWANConfig.ReconnectTimeout
   176  		if wan != 3*24*time.Hour {
   177  			t.Fatalf("bad: %s", wan.String())
   178  		}
   179  	}()
   180  
   181  	func() {
   182  		a := NewTestAgent(t, t.Name(), `
   183  			reconnect_timeout = "24h"
   184  			reconnect_timeout_wan = "36h"
   185  		`)
   186  		defer a.Shutdown()
   187  
   188  		lan := a.consulConfig().SerfLANConfig.ReconnectTimeout
   189  		if lan != 24*time.Hour {
   190  			t.Fatalf("bad: %s", lan.String())
   191  		}
   192  
   193  		wan := a.consulConfig().SerfWANConfig.ReconnectTimeout
   194  		if wan != 36*time.Hour {
   195  			t.Fatalf("bad: %s", wan.String())
   196  		}
   197  	}()
   198  }
   199  
   200  func TestAgent_ReconnectConfigWanDisabled(t *testing.T) {
   201  	t.Parallel()
   202  
   203  	a := NewTestAgent(t, t.Name(), `
   204  		ports { serf_wan = -1 }
   205  		reconnect_timeout_wan = "36h"
   206  	`)
   207  	defer a.Shutdown()
   208  
   209  	// This is also testing that we dont panic like before #4515
   210  	require.Nil(t, a.consulConfig().SerfWANConfig)
   211  }
   212  
   213  func TestAgent_setupNodeID(t *testing.T) {
   214  	t.Parallel()
   215  	a := NewTestAgent(t, t.Name(), `
   216  		node_id = ""
   217  	`)
   218  	defer a.Shutdown()
   219  
   220  	cfg := a.config
   221  
   222  	// The auto-assigned ID should be valid.
   223  	id := a.consulConfig().NodeID
   224  	if _, err := uuid.ParseUUID(string(id)); err != nil {
   225  		t.Fatalf("err: %v", err)
   226  	}
   227  
   228  	// Running again should get the same ID (persisted in the file).
   229  	cfg.NodeID = ""
   230  	if err := a.setupNodeID(cfg); err != nil {
   231  		t.Fatalf("err: %v", err)
   232  	}
   233  	if newID := a.consulConfig().NodeID; id != newID {
   234  		t.Fatalf("bad: %q vs %q", id, newID)
   235  	}
   236  
   237  	// Set an invalid ID via.Config.
   238  	cfg.NodeID = types.NodeID("nope")
   239  	err := a.setupNodeID(cfg)
   240  	if err == nil || !strings.Contains(err.Error(), "uuid string is wrong length") {
   241  		t.Fatalf("err: %v", err)
   242  	}
   243  
   244  	// Set a valid ID via.Config.
   245  	newID, err := uuid.GenerateUUID()
   246  	if err != nil {
   247  		t.Fatalf("err: %v", err)
   248  	}
   249  	cfg.NodeID = types.NodeID(strings.ToUpper(newID))
   250  	if err := a.setupNodeID(cfg); err != nil {
   251  		t.Fatalf("err: %v", err)
   252  	}
   253  	if id := a.consulConfig().NodeID; string(id) != newID {
   254  		t.Fatalf("bad: %q vs. %q", id, newID)
   255  	}
   256  
   257  	// Set an invalid ID via the file.
   258  	fileID := filepath.Join(cfg.DataDir, "node-id")
   259  	if err := ioutil.WriteFile(fileID, []byte("adf4238a!882b!9ddc!4a9d!5b6758e4159e"), 0600); err != nil {
   260  		t.Fatalf("err: %v", err)
   261  	}
   262  	cfg.NodeID = ""
   263  	err = a.setupNodeID(cfg)
   264  	if err == nil || !strings.Contains(err.Error(), "uuid is improperly formatted") {
   265  		t.Fatalf("err: %v", err)
   266  	}
   267  
   268  	// Set a valid ID via the file.
   269  	if err := ioutil.WriteFile(fileID, []byte("ADF4238a-882b-9ddc-4a9d-5b6758e4159e"), 0600); err != nil {
   270  		t.Fatalf("err: %v", err)
   271  	}
   272  	cfg.NodeID = ""
   273  	if err := a.setupNodeID(cfg); err != nil {
   274  		t.Fatalf("err: %v", err)
   275  	}
   276  	if id := a.consulConfig().NodeID; string(id) != "adf4238a-882b-9ddc-4a9d-5b6758e4159e" {
   277  		t.Fatalf("bad: %q vs. %q", id, newID)
   278  	}
   279  }
   280  
   281  func TestAgent_makeNodeID(t *testing.T) {
   282  	t.Parallel()
   283  	a := NewTestAgent(t, t.Name(), `
   284  		node_id = ""
   285  	`)
   286  	defer a.Shutdown()
   287  
   288  	// We should get a valid host-based ID initially.
   289  	id, err := a.makeNodeID()
   290  	if err != nil {
   291  		t.Fatalf("err: %v", err)
   292  	}
   293  	if _, err := uuid.ParseUUID(string(id)); err != nil {
   294  		t.Fatalf("err: %v", err)
   295  	}
   296  
   297  	// Calling again should yield a random ID by default.
   298  	another, err := a.makeNodeID()
   299  	if err != nil {
   300  		t.Fatalf("err: %v", err)
   301  	}
   302  	if id == another {
   303  		t.Fatalf("bad: %s vs %s", id, another)
   304  	}
   305  
   306  	// Turn on host-based IDs and try again. We should get the same ID
   307  	// each time (and a different one from the random one above).
   308  	a.Config.DisableHostNodeID = false
   309  	id, err = a.makeNodeID()
   310  	if err != nil {
   311  		t.Fatalf("err: %v", err)
   312  	}
   313  	if id == another {
   314  		t.Fatalf("bad: %s vs %s", id, another)
   315  	}
   316  
   317  	// Calling again should yield the host-based ID.
   318  	another, err = a.makeNodeID()
   319  	if err != nil {
   320  		t.Fatalf("err: %v", err)
   321  	}
   322  	if id != another {
   323  		t.Fatalf("bad: %s vs %s", id, another)
   324  	}
   325  }
   326  
   327  func TestAgent_AddService(t *testing.T) {
   328  	t.Parallel()
   329  	a := NewTestAgent(t, t.Name(), `
   330  		node_name = "node1"
   331  	`)
   332  	defer a.Shutdown()
   333  
   334  	tests := []struct {
   335  		desc       string
   336  		srv        *structs.NodeService
   337  		wantSrv    func(ns *structs.NodeService)
   338  		chkTypes   []*structs.CheckType
   339  		healthChks map[string]*structs.HealthCheck
   340  	}{
   341  		{
   342  			"one check",
   343  			&structs.NodeService{
   344  				ID:      "svcid1",
   345  				Service: "svcname1",
   346  				Tags:    []string{"tag1"},
   347  				Weights: nil, // nil weights...
   348  				Port:    8100,
   349  			},
   350  			// ... should be populated to avoid "IsSame" returning true during AE.
   351  			func(ns *structs.NodeService) {
   352  				ns.Weights = &structs.Weights{
   353  					Passing: 1,
   354  					Warning: 1,
   355  				}
   356  			},
   357  			[]*structs.CheckType{
   358  				&structs.CheckType{
   359  					CheckID: "check1",
   360  					Name:    "name1",
   361  					TTL:     time.Minute,
   362  					Notes:   "note1",
   363  				},
   364  			},
   365  			map[string]*structs.HealthCheck{
   366  				"check1": &structs.HealthCheck{
   367  					Node:        "node1",
   368  					CheckID:     "check1",
   369  					Name:        "name1",
   370  					Status:      "critical",
   371  					Notes:       "note1",
   372  					ServiceID:   "svcid1",
   373  					ServiceName: "svcname1",
   374  					ServiceTags: []string{"tag1"},
   375  				},
   376  			},
   377  		},
   378  		{
   379  			"multiple checks",
   380  			&structs.NodeService{
   381  				ID:      "svcid2",
   382  				Service: "svcname2",
   383  				Weights: &structs.Weights{
   384  					Passing: 2,
   385  					Warning: 1,
   386  				},
   387  				Tags: []string{"tag2"},
   388  				Port: 8200,
   389  			},
   390  			nil, // No change expected
   391  			[]*structs.CheckType{
   392  				&structs.CheckType{
   393  					CheckID: "check1",
   394  					Name:    "name1",
   395  					TTL:     time.Minute,
   396  					Notes:   "note1",
   397  				},
   398  				&structs.CheckType{
   399  					CheckID: "check-noname",
   400  					TTL:     time.Minute,
   401  				},
   402  				&structs.CheckType{
   403  					Name: "check-noid",
   404  					TTL:  time.Minute,
   405  				},
   406  				&structs.CheckType{
   407  					TTL: time.Minute,
   408  				},
   409  			},
   410  			map[string]*structs.HealthCheck{
   411  				"check1": &structs.HealthCheck{
   412  					Node:        "node1",
   413  					CheckID:     "check1",
   414  					Name:        "name1",
   415  					Status:      "critical",
   416  					Notes:       "note1",
   417  					ServiceID:   "svcid2",
   418  					ServiceName: "svcname2",
   419  					ServiceTags: []string{"tag2"},
   420  				},
   421  				"check-noname": &structs.HealthCheck{
   422  					Node:        "node1",
   423  					CheckID:     "check-noname",
   424  					Name:        "Service 'svcname2' check",
   425  					Status:      "critical",
   426  					ServiceID:   "svcid2",
   427  					ServiceName: "svcname2",
   428  					ServiceTags: []string{"tag2"},
   429  				},
   430  				"service:svcid2:3": &structs.HealthCheck{
   431  					Node:        "node1",
   432  					CheckID:     "service:svcid2:3",
   433  					Name:        "check-noid",
   434  					Status:      "critical",
   435  					ServiceID:   "svcid2",
   436  					ServiceName: "svcname2",
   437  					ServiceTags: []string{"tag2"},
   438  				},
   439  				"service:svcid2:4": &structs.HealthCheck{
   440  					Node:        "node1",
   441  					CheckID:     "service:svcid2:4",
   442  					Name:        "Service 'svcname2' check",
   443  					Status:      "critical",
   444  					ServiceID:   "svcid2",
   445  					ServiceName: "svcname2",
   446  					ServiceTags: []string{"tag2"},
   447  				},
   448  			},
   449  		},
   450  	}
   451  
   452  	for _, tt := range tests {
   453  		t.Run(tt.desc, func(t *testing.T) {
   454  			// check the service registration
   455  			t.Run(tt.srv.ID, func(t *testing.T) {
   456  				err := a.AddService(tt.srv, tt.chkTypes, false, "", ConfigSourceLocal)
   457  				if err != nil {
   458  					t.Fatalf("err: %v", err)
   459  				}
   460  
   461  				got := a.State.Services()[tt.srv.ID]
   462  				// Make a copy since the tt.srv points to the one in memory in the local
   463  				// state still so changing it is a tautology!
   464  				want := *tt.srv
   465  				if tt.wantSrv != nil {
   466  					tt.wantSrv(&want)
   467  				}
   468  				require.Equal(t, &want, got)
   469  				require.True(t, got.IsSame(&want))
   470  			})
   471  
   472  			// check the health checks
   473  			for k, v := range tt.healthChks {
   474  				t.Run(k, func(t *testing.T) {
   475  					got := a.State.Checks()[types.CheckID(k)]
   476  					require.Equal(t, v, got)
   477  				})
   478  			}
   479  
   480  			// check the ttl checks
   481  			for k := range tt.healthChks {
   482  				t.Run(k+" ttl", func(t *testing.T) {
   483  					chk := a.checkTTLs[types.CheckID(k)]
   484  					if chk == nil {
   485  						t.Fatal("got nil want TTL check")
   486  					}
   487  					if got, want := string(chk.CheckID), k; got != want {
   488  						t.Fatalf("got CheckID %v want %v", got, want)
   489  					}
   490  					if got, want := chk.TTL, time.Minute; got != want {
   491  						t.Fatalf("got TTL %v want %v", got, want)
   492  					}
   493  				})
   494  			}
   495  		})
   496  	}
   497  }
   498  
   499  func TestAgent_AddServiceNoExec(t *testing.T) {
   500  	t.Parallel()
   501  	a := NewTestAgent(t, t.Name(), `
   502  		node_name = "node1"
   503  	`)
   504  	defer a.Shutdown()
   505  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   506  
   507  	srv := &structs.NodeService{
   508  		ID:      "svcid1",
   509  		Service: "svcname1",
   510  		Tags:    []string{"tag1"},
   511  		Port:    8100,
   512  	}
   513  	chk := &structs.CheckType{
   514  		ScriptArgs: []string{"exit", "0"},
   515  		Interval:   15 * time.Second,
   516  	}
   517  
   518  	err := a.AddService(srv, []*structs.CheckType{chk}, false, "", ConfigSourceLocal)
   519  	if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
   520  		t.Fatalf("err: %v", err)
   521  	}
   522  
   523  	err = a.AddService(srv, []*structs.CheckType{chk}, false, "", ConfigSourceRemote)
   524  	if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
   525  		t.Fatalf("err: %v", err)
   526  	}
   527  }
   528  
   529  func TestAgent_AddServiceNoRemoteExec(t *testing.T) {
   530  	t.Parallel()
   531  	a := NewTestAgent(t, t.Name(), `
   532  		node_name = "node1"
   533  		enable_local_script_checks = true
   534  	`)
   535  	defer a.Shutdown()
   536  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   537  
   538  	srv := &structs.NodeService{
   539  		ID:      "svcid1",
   540  		Service: "svcname1",
   541  		Tags:    []string{"tag1"},
   542  		Port:    8100,
   543  	}
   544  	chk := &structs.CheckType{
   545  		ScriptArgs: []string{"exit", "0"},
   546  		Interval:   15 * time.Second,
   547  	}
   548  
   549  	err := a.AddService(srv, []*structs.CheckType{chk}, false, "", ConfigSourceRemote)
   550  	if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
   551  		t.Fatalf("err: %v", err)
   552  	}
   553  }
   554  
   555  func TestAgent_RemoveService(t *testing.T) {
   556  	t.Parallel()
   557  	a := NewTestAgent(t, t.Name(), "")
   558  	defer a.Shutdown()
   559  
   560  	// Remove a service that doesn't exist
   561  	if err := a.RemoveService("redis", false); err != nil {
   562  		t.Fatalf("err: %v", err)
   563  	}
   564  
   565  	// Remove without an ID
   566  	if err := a.RemoveService("", false); err == nil {
   567  		t.Fatalf("should have errored")
   568  	}
   569  
   570  	// Removing a service with a single check works
   571  	{
   572  		srv := &structs.NodeService{
   573  			ID:      "memcache",
   574  			Service: "memcache",
   575  			Port:    8000,
   576  		}
   577  		chkTypes := []*structs.CheckType{&structs.CheckType{TTL: time.Minute}}
   578  
   579  		if err := a.AddService(srv, chkTypes, false, "", ConfigSourceLocal); err != nil {
   580  			t.Fatalf("err: %v", err)
   581  		}
   582  
   583  		// Add a check after the fact with a specific check ID
   584  		check := &structs.CheckDefinition{
   585  			ID:        "check2",
   586  			Name:      "check2",
   587  			ServiceID: "memcache",
   588  			TTL:       time.Minute,
   589  		}
   590  		hc := check.HealthCheck("node1")
   591  		if err := a.AddCheck(hc, check.CheckType(), false, "", ConfigSourceLocal); err != nil {
   592  			t.Fatalf("err: %s", err)
   593  		}
   594  
   595  		if err := a.RemoveService("memcache", false); err != nil {
   596  			t.Fatalf("err: %s", err)
   597  		}
   598  		if _, ok := a.State.Checks()["service:memcache"]; ok {
   599  			t.Fatalf("have memcache check")
   600  		}
   601  		if _, ok := a.State.Checks()["check2"]; ok {
   602  			t.Fatalf("have check2 check")
   603  		}
   604  	}
   605  
   606  	// Removing a service with multiple checks works
   607  	{
   608  		// add a service to remove
   609  		srv := &structs.NodeService{
   610  			ID:      "redis",
   611  			Service: "redis",
   612  			Port:    8000,
   613  		}
   614  		chkTypes := []*structs.CheckType{
   615  			&structs.CheckType{TTL: time.Minute},
   616  			&structs.CheckType{TTL: 30 * time.Second},
   617  		}
   618  		if err := a.AddService(srv, chkTypes, false, "", ConfigSourceLocal); err != nil {
   619  			t.Fatalf("err: %v", err)
   620  		}
   621  
   622  		// add another service that wont be affected
   623  		srv = &structs.NodeService{
   624  			ID:      "mysql",
   625  			Service: "mysql",
   626  			Port:    3306,
   627  		}
   628  		chkTypes = []*structs.CheckType{
   629  			&structs.CheckType{TTL: time.Minute},
   630  			&structs.CheckType{TTL: 30 * time.Second},
   631  		}
   632  		if err := a.AddService(srv, chkTypes, false, "", ConfigSourceLocal); err != nil {
   633  			t.Fatalf("err: %v", err)
   634  		}
   635  
   636  		// Remove the service
   637  		if err := a.RemoveService("redis", false); err != nil {
   638  			t.Fatalf("err: %v", err)
   639  		}
   640  
   641  		// Ensure we have a state mapping
   642  		if _, ok := a.State.Services()["redis"]; ok {
   643  			t.Fatalf("have redis service")
   644  		}
   645  
   646  		// Ensure checks were removed
   647  		if _, ok := a.State.Checks()["service:redis:1"]; ok {
   648  			t.Fatalf("check redis:1 should be removed")
   649  		}
   650  		if _, ok := a.State.Checks()["service:redis:2"]; ok {
   651  			t.Fatalf("check redis:2 should be removed")
   652  		}
   653  
   654  		// Ensure the redis checks are removed
   655  		if _, ok := a.checkTTLs["service:redis:1"]; ok {
   656  			t.Fatalf("check ttl for redis:1 should be removed")
   657  		}
   658  		if check := a.State.Check(types.CheckID("service:redis:1")); check != nil {
   659  			t.Fatalf("check ttl for redis:1 should be removed")
   660  		}
   661  		if _, ok := a.checkTTLs["service:redis:2"]; ok {
   662  			t.Fatalf("check ttl for redis:2 should be removed")
   663  		}
   664  		if check := a.State.Check(types.CheckID("service:redis:2")); check != nil {
   665  			t.Fatalf("check ttl for redis:2 should be removed")
   666  		}
   667  
   668  		// check the mysql service is unnafected
   669  		if _, ok := a.checkTTLs["service:mysql:1"]; !ok {
   670  			t.Fatalf("check ttl for mysql:1 should not be removed")
   671  		}
   672  		if check := a.State.Check(types.CheckID("service:mysql:1")); check == nil {
   673  			t.Fatalf("check ttl for mysql:1 should not be removed")
   674  		}
   675  		if _, ok := a.checkTTLs["service:mysql:2"]; !ok {
   676  			t.Fatalf("check ttl for mysql:2 should not be removed")
   677  		}
   678  		if check := a.State.Check(types.CheckID("service:mysql:2")); check == nil {
   679  			t.Fatalf("check ttl for mysql:2 should not be removed")
   680  		}
   681  	}
   682  }
   683  
   684  func TestAgent_RemoveServiceRemovesAllChecks(t *testing.T) {
   685  	t.Parallel()
   686  	a := NewTestAgent(t, t.Name(), `
   687  		node_name = "node1"
   688  	`)
   689  	defer a.Shutdown()
   690  
   691  	svc := &structs.NodeService{ID: "redis", Service: "redis", Port: 8000}
   692  	chk1 := &structs.CheckType{CheckID: "chk1", Name: "chk1", TTL: time.Minute}
   693  	chk2 := &structs.CheckType{CheckID: "chk2", Name: "chk2", TTL: 2 * time.Minute}
   694  	hchk1 := &structs.HealthCheck{Node: "node1", CheckID: "chk1", Name: "chk1", Status: "critical", ServiceID: "redis", ServiceName: "redis"}
   695  	hchk2 := &structs.HealthCheck{Node: "node1", CheckID: "chk2", Name: "chk2", Status: "critical", ServiceID: "redis", ServiceName: "redis"}
   696  
   697  	// register service with chk1
   698  	if err := a.AddService(svc, []*structs.CheckType{chk1}, false, "", ConfigSourceLocal); err != nil {
   699  		t.Fatal("Failed to register service", err)
   700  	}
   701  
   702  	// verify chk1 exists
   703  	if a.State.Checks()["chk1"] == nil {
   704  		t.Fatal("Could not find health check chk1")
   705  	}
   706  
   707  	// update the service with chk2
   708  	if err := a.AddService(svc, []*structs.CheckType{chk2}, false, "", ConfigSourceLocal); err != nil {
   709  		t.Fatal("Failed to update service", err)
   710  	}
   711  
   712  	// check that both checks are there
   713  	if got, want := a.State.Checks()["chk1"], hchk1; !verify.Values(t, "", got, want) {
   714  		t.FailNow()
   715  	}
   716  	if got, want := a.State.Checks()["chk2"], hchk2; !verify.Values(t, "", got, want) {
   717  		t.FailNow()
   718  	}
   719  
   720  	// Remove service
   721  	if err := a.RemoveService("redis", false); err != nil {
   722  		t.Fatal("Failed to remove service", err)
   723  	}
   724  
   725  	// Check that both checks are gone
   726  	if a.State.Checks()["chk1"] != nil {
   727  		t.Fatal("Found health check chk1 want nil")
   728  	}
   729  	if a.State.Checks()["chk2"] != nil {
   730  		t.Fatal("Found health check chk2 want nil")
   731  	}
   732  }
   733  
   734  // TestAgent_IndexChurn is designed to detect a class of issues where
   735  // we would have unnecessary catalog churn from anti-entropy. See issues
   736  // #3259, #3642, #3845, and #3866.
   737  func TestAgent_IndexChurn(t *testing.T) {
   738  	t.Parallel()
   739  
   740  	t.Run("no tags", func(t *testing.T) {
   741  		verifyIndexChurn(t, nil)
   742  	})
   743  
   744  	t.Run("with tags", func(t *testing.T) {
   745  		verifyIndexChurn(t, []string{"foo", "bar"})
   746  	})
   747  }
   748  
   749  // verifyIndexChurn registers some things and runs anti-entropy a bunch of times
   750  // in a row to make sure there are no index bumps.
   751  func verifyIndexChurn(t *testing.T, tags []string) {
   752  	t.Helper()
   753  
   754  	a := NewTestAgent(t, t.Name(), "")
   755  	defer a.Shutdown()
   756  
   757  	weights := &structs.Weights{
   758  		Passing: 1,
   759  		Warning: 1,
   760  	}
   761  	// Ensure we have a leader before we start adding the services
   762  	testrpc.WaitForLeader(t, a.RPC, "dc1")
   763  
   764  	svc := &structs.NodeService{
   765  		ID:      "redis",
   766  		Service: "redis",
   767  		Port:    8000,
   768  		Tags:    tags,
   769  		Weights: weights,
   770  	}
   771  	if err := a.AddService(svc, nil, true, "", ConfigSourceLocal); err != nil {
   772  		t.Fatalf("err: %v", err)
   773  	}
   774  
   775  	chk := &structs.HealthCheck{
   776  		CheckID:   "redis-check",
   777  		Name:      "Service-level check",
   778  		ServiceID: "redis",
   779  		Status:    api.HealthCritical,
   780  	}
   781  	chkt := &structs.CheckType{
   782  		TTL: time.Hour,
   783  	}
   784  	if err := a.AddCheck(chk, chkt, true, "", ConfigSourceLocal); err != nil {
   785  		t.Fatalf("err: %v", err)
   786  	}
   787  
   788  	chk = &structs.HealthCheck{
   789  		CheckID: "node-check",
   790  		Name:    "Node-level check",
   791  		Status:  api.HealthCritical,
   792  	}
   793  	chkt = &structs.CheckType{
   794  		TTL: time.Hour,
   795  	}
   796  	if err := a.AddCheck(chk, chkt, true, "", ConfigSourceLocal); err != nil {
   797  		t.Fatalf("err: %v", err)
   798  	}
   799  
   800  	if err := a.sync.State.SyncFull(); err != nil {
   801  		t.Fatalf("err: %v", err)
   802  	}
   803  
   804  	args := &structs.ServiceSpecificRequest{
   805  		Datacenter:  "dc1",
   806  		ServiceName: "redis",
   807  	}
   808  	var before structs.IndexedCheckServiceNodes
   809  
   810  	// This sleep is so that the serfHealth check is added to the agent
   811  	// A value of 375ms is sufficient enough time to ensure the serfHealth
   812  	// check is added to an agent. 500ms so that we don't see flakiness ever.
   813  	time.Sleep(500 * time.Millisecond)
   814  
   815  	if err := a.RPC("Health.ServiceNodes", args, &before); err != nil {
   816  		t.Fatalf("err: %v", err)
   817  	}
   818  	for _, name := range before.Nodes[0].Checks {
   819  		a.logger.Println("[DEBUG] Checks Registered: ", name.Name)
   820  	}
   821  	if got, want := len(before.Nodes), 1; got != want {
   822  		t.Fatalf("got %d want %d", got, want)
   823  	}
   824  	if got, want := len(before.Nodes[0].Checks), 3; /* incl. serfHealth */ got != want {
   825  		t.Fatalf("got %d want %d", got, want)
   826  	}
   827  
   828  	for i := 0; i < 10; i++ {
   829  		a.logger.Println("[INFO] # ", i+1, "Sync in progress ")
   830  		if err := a.sync.State.SyncFull(); err != nil {
   831  			t.Fatalf("err: %v", err)
   832  		}
   833  	}
   834  	// If this test fails here this means that the Consul-X-Index
   835  	// has changed for the RPC, which means that idempotent ops
   836  	// are not working as intended.
   837  	var after structs.IndexedCheckServiceNodes
   838  	if err := a.RPC("Health.ServiceNodes", args, &after); err != nil {
   839  		t.Fatalf("err: %v", err)
   840  	}
   841  	verify.Values(t, "", after, before)
   842  }
   843  
   844  func TestAgent_AddCheck(t *testing.T) {
   845  	t.Parallel()
   846  	a := NewTestAgent(t, t.Name(), `
   847  		enable_script_checks = true
   848  	`)
   849  	defer a.Shutdown()
   850  
   851  	health := &structs.HealthCheck{
   852  		Node:    "foo",
   853  		CheckID: "mem",
   854  		Name:    "memory util",
   855  		Status:  api.HealthCritical,
   856  	}
   857  	chk := &structs.CheckType{
   858  		ScriptArgs: []string{"exit", "0"},
   859  		Interval:   15 * time.Second,
   860  	}
   861  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
   862  	if err != nil {
   863  		t.Fatalf("err: %v", err)
   864  	}
   865  
   866  	// Ensure we have a check mapping
   867  	sChk, ok := a.State.Checks()["mem"]
   868  	if !ok {
   869  		t.Fatalf("missing mem check")
   870  	}
   871  
   872  	// Ensure our check is in the right state
   873  	if sChk.Status != api.HealthCritical {
   874  		t.Fatalf("check not critical")
   875  	}
   876  
   877  	// Ensure a TTL is setup
   878  	if _, ok := a.checkMonitors["mem"]; !ok {
   879  		t.Fatalf("missing mem monitor")
   880  	}
   881  }
   882  
   883  func TestAgent_AddCheck_StartPassing(t *testing.T) {
   884  	t.Parallel()
   885  	a := NewTestAgent(t, t.Name(), `
   886  		enable_script_checks = true
   887  	`)
   888  	defer a.Shutdown()
   889  
   890  	health := &structs.HealthCheck{
   891  		Node:    "foo",
   892  		CheckID: "mem",
   893  		Name:    "memory util",
   894  		Status:  api.HealthPassing,
   895  	}
   896  	chk := &structs.CheckType{
   897  		ScriptArgs: []string{"exit", "0"},
   898  		Interval:   15 * time.Second,
   899  	}
   900  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
   901  	if err != nil {
   902  		t.Fatalf("err: %v", err)
   903  	}
   904  
   905  	// Ensure we have a check mapping
   906  	sChk, ok := a.State.Checks()["mem"]
   907  	if !ok {
   908  		t.Fatalf("missing mem check")
   909  	}
   910  
   911  	// Ensure our check is in the right state
   912  	if sChk.Status != api.HealthPassing {
   913  		t.Fatalf("check not passing")
   914  	}
   915  
   916  	// Ensure a TTL is setup
   917  	if _, ok := a.checkMonitors["mem"]; !ok {
   918  		t.Fatalf("missing mem monitor")
   919  	}
   920  }
   921  
   922  func TestAgent_AddCheck_MinInterval(t *testing.T) {
   923  	t.Parallel()
   924  	a := NewTestAgent(t, t.Name(), `
   925  		enable_script_checks = true
   926  	`)
   927  	defer a.Shutdown()
   928  
   929  	health := &structs.HealthCheck{
   930  		Node:    "foo",
   931  		CheckID: "mem",
   932  		Name:    "memory util",
   933  		Status:  api.HealthCritical,
   934  	}
   935  	chk := &structs.CheckType{
   936  		ScriptArgs: []string{"exit", "0"},
   937  		Interval:   time.Microsecond,
   938  	}
   939  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
   940  	if err != nil {
   941  		t.Fatalf("err: %v", err)
   942  	}
   943  
   944  	// Ensure we have a check mapping
   945  	if _, ok := a.State.Checks()["mem"]; !ok {
   946  		t.Fatalf("missing mem check")
   947  	}
   948  
   949  	// Ensure a TTL is setup
   950  	if mon, ok := a.checkMonitors["mem"]; !ok {
   951  		t.Fatalf("missing mem monitor")
   952  	} else if mon.Interval != checks.MinInterval {
   953  		t.Fatalf("bad mem monitor interval")
   954  	}
   955  }
   956  
   957  func TestAgent_AddCheck_MissingService(t *testing.T) {
   958  	t.Parallel()
   959  	a := NewTestAgent(t, t.Name(), `
   960  		enable_script_checks = true
   961  	`)
   962  	defer a.Shutdown()
   963  
   964  	health := &structs.HealthCheck{
   965  		Node:      "foo",
   966  		CheckID:   "baz",
   967  		Name:      "baz check 1",
   968  		ServiceID: "baz",
   969  	}
   970  	chk := &structs.CheckType{
   971  		ScriptArgs: []string{"exit", "0"},
   972  		Interval:   time.Microsecond,
   973  	}
   974  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
   975  	if err == nil || err.Error() != `ServiceID "baz" does not exist` {
   976  		t.Fatalf("expected service id error, got: %v", err)
   977  	}
   978  }
   979  
   980  func TestAgent_AddCheck_RestoreState(t *testing.T) {
   981  	t.Parallel()
   982  	a := NewTestAgent(t, t.Name(), "")
   983  	defer a.Shutdown()
   984  
   985  	// Create some state and persist it
   986  	ttl := &checks.CheckTTL{
   987  		CheckID: "baz",
   988  		TTL:     time.Minute,
   989  	}
   990  	err := a.persistCheckState(ttl, api.HealthPassing, "yup")
   991  	if err != nil {
   992  		t.Fatalf("err: %s", err)
   993  	}
   994  
   995  	// Build and register the check definition and initial state
   996  	health := &structs.HealthCheck{
   997  		Node:    "foo",
   998  		CheckID: "baz",
   999  		Name:    "baz check 1",
  1000  	}
  1001  	chk := &structs.CheckType{
  1002  		TTL: time.Minute,
  1003  	}
  1004  	err = a.AddCheck(health, chk, false, "", ConfigSourceLocal)
  1005  	if err != nil {
  1006  		t.Fatalf("err: %s", err)
  1007  	}
  1008  
  1009  	// Ensure the check status was restored during registration
  1010  	checks := a.State.Checks()
  1011  	check, ok := checks["baz"]
  1012  	if !ok {
  1013  		t.Fatalf("missing check")
  1014  	}
  1015  	if check.Status != api.HealthPassing {
  1016  		t.Fatalf("bad: %#v", check)
  1017  	}
  1018  	if check.Output != "yup" {
  1019  		t.Fatalf("bad: %#v", check)
  1020  	}
  1021  }
  1022  
  1023  func TestAgent_AddCheck_ExecDisable(t *testing.T) {
  1024  	t.Parallel()
  1025  
  1026  	a := NewTestAgent(t, t.Name(), "")
  1027  	defer a.Shutdown()
  1028  
  1029  	health := &structs.HealthCheck{
  1030  		Node:    "foo",
  1031  		CheckID: "mem",
  1032  		Name:    "memory util",
  1033  		Status:  api.HealthCritical,
  1034  	}
  1035  	chk := &structs.CheckType{
  1036  		ScriptArgs: []string{"exit", "0"},
  1037  		Interval:   15 * time.Second,
  1038  	}
  1039  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
  1040  	if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
  1041  		t.Fatalf("err: %v", err)
  1042  	}
  1043  
  1044  	// Ensure we don't have a check mapping
  1045  	if memChk := a.State.Checks()["mem"]; memChk != nil {
  1046  		t.Fatalf("should be missing mem check")
  1047  	}
  1048  
  1049  	err = a.AddCheck(health, chk, false, "", ConfigSourceRemote)
  1050  	if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent") {
  1051  		t.Fatalf("err: %v", err)
  1052  	}
  1053  
  1054  	// Ensure we don't have a check mapping
  1055  	if memChk := a.State.Checks()["mem"]; memChk != nil {
  1056  		t.Fatalf("should be missing mem check")
  1057  	}
  1058  }
  1059  
  1060  func TestAgent_AddCheck_ExecRemoteDisable(t *testing.T) {
  1061  	t.Parallel()
  1062  
  1063  	a := NewTestAgent(t, t.Name(), `
  1064  		enable_local_script_checks = true
  1065  	`)
  1066  	defer a.Shutdown()
  1067  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
  1068  
  1069  	health := &structs.HealthCheck{
  1070  		Node:    "foo",
  1071  		CheckID: "mem",
  1072  		Name:    "memory util",
  1073  		Status:  api.HealthCritical,
  1074  	}
  1075  	chk := &structs.CheckType{
  1076  		ScriptArgs: []string{"exit", "0"},
  1077  		Interval:   15 * time.Second,
  1078  	}
  1079  	err := a.AddCheck(health, chk, false, "", ConfigSourceRemote)
  1080  	if err == nil || !strings.Contains(err.Error(), "Scripts are disabled on this agent from remote calls") {
  1081  		t.Fatalf("err: %v", err)
  1082  	}
  1083  
  1084  	// Ensure we don't have a check mapping
  1085  	if memChk := a.State.Checks()["mem"]; memChk != nil {
  1086  		t.Fatalf("should be missing mem check")
  1087  	}
  1088  }
  1089  
  1090  func TestAgent_AddCheck_GRPC(t *testing.T) {
  1091  	t.Parallel()
  1092  	a := NewTestAgent(t, t.Name(), "")
  1093  	defer a.Shutdown()
  1094  
  1095  	health := &structs.HealthCheck{
  1096  		Node:    "foo",
  1097  		CheckID: "grpchealth",
  1098  		Name:    "grpc health checking protocol",
  1099  		Status:  api.HealthCritical,
  1100  	}
  1101  	chk := &structs.CheckType{
  1102  		GRPC:     "localhost:12345/package.Service",
  1103  		Interval: 15 * time.Second,
  1104  	}
  1105  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
  1106  	if err != nil {
  1107  		t.Fatalf("err: %v", err)
  1108  	}
  1109  
  1110  	// Ensure we have a check mapping
  1111  	sChk, ok := a.State.Checks()["grpchealth"]
  1112  	if !ok {
  1113  		t.Fatalf("missing grpchealth check")
  1114  	}
  1115  
  1116  	// Ensure our check is in the right state
  1117  	if sChk.Status != api.HealthCritical {
  1118  		t.Fatalf("check not critical")
  1119  	}
  1120  
  1121  	// Ensure a check is setup
  1122  	if _, ok := a.checkGRPCs["grpchealth"]; !ok {
  1123  		t.Fatalf("missing grpchealth check")
  1124  	}
  1125  }
  1126  
  1127  func TestAgent_AddCheck_Alias(t *testing.T) {
  1128  	t.Parallel()
  1129  
  1130  	require := require.New(t)
  1131  	a := NewTestAgent(t, t.Name(), "")
  1132  	defer a.Shutdown()
  1133  
  1134  	health := &structs.HealthCheck{
  1135  		Node:    "foo",
  1136  		CheckID: "aliashealth",
  1137  		Name:    "Alias health check",
  1138  		Status:  api.HealthCritical,
  1139  	}
  1140  	chk := &structs.CheckType{
  1141  		AliasService: "foo",
  1142  	}
  1143  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
  1144  	require.NoError(err)
  1145  
  1146  	// Ensure we have a check mapping
  1147  	sChk, ok := a.State.Checks()["aliashealth"]
  1148  	require.True(ok, "missing aliashealth check")
  1149  	require.NotNil(sChk)
  1150  	require.Equal(api.HealthCritical, sChk.Status)
  1151  
  1152  	chkImpl, ok := a.checkAliases["aliashealth"]
  1153  	require.True(ok, "missing aliashealth check")
  1154  	require.Equal("", chkImpl.RPCReq.Token)
  1155  
  1156  	cs := a.State.CheckState("aliashealth")
  1157  	require.NotNil(cs)
  1158  	require.Equal("", cs.Token)
  1159  }
  1160  
  1161  func TestAgent_AddCheck_Alias_setToken(t *testing.T) {
  1162  	t.Parallel()
  1163  
  1164  	require := require.New(t)
  1165  	a := NewTestAgent(t, t.Name(), "")
  1166  	defer a.Shutdown()
  1167  
  1168  	health := &structs.HealthCheck{
  1169  		Node:    "foo",
  1170  		CheckID: "aliashealth",
  1171  		Name:    "Alias health check",
  1172  		Status:  api.HealthCritical,
  1173  	}
  1174  	chk := &structs.CheckType{
  1175  		AliasService: "foo",
  1176  	}
  1177  	err := a.AddCheck(health, chk, false, "foo", ConfigSourceLocal)
  1178  	require.NoError(err)
  1179  
  1180  	cs := a.State.CheckState("aliashealth")
  1181  	require.NotNil(cs)
  1182  	require.Equal("foo", cs.Token)
  1183  
  1184  	chkImpl, ok := a.checkAliases["aliashealth"]
  1185  	require.True(ok, "missing aliashealth check")
  1186  	require.Equal("foo", chkImpl.RPCReq.Token)
  1187  }
  1188  
  1189  func TestAgent_AddCheck_Alias_userToken(t *testing.T) {
  1190  	t.Parallel()
  1191  
  1192  	require := require.New(t)
  1193  	a := NewTestAgent(t, t.Name(), `
  1194  acl_token = "hello"
  1195  	`)
  1196  	defer a.Shutdown()
  1197  
  1198  	health := &structs.HealthCheck{
  1199  		Node:    "foo",
  1200  		CheckID: "aliashealth",
  1201  		Name:    "Alias health check",
  1202  		Status:  api.HealthCritical,
  1203  	}
  1204  	chk := &structs.CheckType{
  1205  		AliasService: "foo",
  1206  	}
  1207  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
  1208  	require.NoError(err)
  1209  
  1210  	cs := a.State.CheckState("aliashealth")
  1211  	require.NotNil(cs)
  1212  	require.Equal("", cs.Token) // State token should still be empty
  1213  
  1214  	chkImpl, ok := a.checkAliases["aliashealth"]
  1215  	require.True(ok, "missing aliashealth check")
  1216  	require.Equal("hello", chkImpl.RPCReq.Token) // Check should use the token
  1217  }
  1218  
  1219  func TestAgent_AddCheck_Alias_userAndSetToken(t *testing.T) {
  1220  	t.Parallel()
  1221  
  1222  	require := require.New(t)
  1223  	a := NewTestAgent(t, t.Name(), `
  1224  acl_token = "hello"
  1225  	`)
  1226  	defer a.Shutdown()
  1227  
  1228  	health := &structs.HealthCheck{
  1229  		Node:    "foo",
  1230  		CheckID: "aliashealth",
  1231  		Name:    "Alias health check",
  1232  		Status:  api.HealthCritical,
  1233  	}
  1234  	chk := &structs.CheckType{
  1235  		AliasService: "foo",
  1236  	}
  1237  	err := a.AddCheck(health, chk, false, "goodbye", ConfigSourceLocal)
  1238  	require.NoError(err)
  1239  
  1240  	cs := a.State.CheckState("aliashealth")
  1241  	require.NotNil(cs)
  1242  	require.Equal("goodbye", cs.Token)
  1243  
  1244  	chkImpl, ok := a.checkAliases["aliashealth"]
  1245  	require.True(ok, "missing aliashealth check")
  1246  	require.Equal("goodbye", chkImpl.RPCReq.Token)
  1247  }
  1248  
  1249  func TestAgent_RemoveCheck(t *testing.T) {
  1250  	t.Parallel()
  1251  	a := NewTestAgent(t, t.Name(), `
  1252  		enable_script_checks = true
  1253  	`)
  1254  	defer a.Shutdown()
  1255  
  1256  	// Remove check that doesn't exist
  1257  	if err := a.RemoveCheck("mem", false); err != nil {
  1258  		t.Fatalf("err: %v", err)
  1259  	}
  1260  
  1261  	// Remove without an ID
  1262  	if err := a.RemoveCheck("", false); err == nil {
  1263  		t.Fatalf("should have errored")
  1264  	}
  1265  
  1266  	health := &structs.HealthCheck{
  1267  		Node:    "foo",
  1268  		CheckID: "mem",
  1269  		Name:    "memory util",
  1270  		Status:  api.HealthCritical,
  1271  	}
  1272  	chk := &structs.CheckType{
  1273  		ScriptArgs: []string{"exit", "0"},
  1274  		Interval:   15 * time.Second,
  1275  	}
  1276  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
  1277  	if err != nil {
  1278  		t.Fatalf("err: %v", err)
  1279  	}
  1280  
  1281  	// Remove check
  1282  	if err := a.RemoveCheck("mem", false); err != nil {
  1283  		t.Fatalf("err: %v", err)
  1284  	}
  1285  
  1286  	// Ensure we have a check mapping
  1287  	if _, ok := a.State.Checks()["mem"]; ok {
  1288  		t.Fatalf("have mem check")
  1289  	}
  1290  
  1291  	// Ensure a TTL is setup
  1292  	if _, ok := a.checkMonitors["mem"]; ok {
  1293  		t.Fatalf("have mem monitor")
  1294  	}
  1295  }
  1296  
  1297  func TestAgent_HTTPCheck_TLSSkipVerify(t *testing.T) {
  1298  	t.Parallel()
  1299  
  1300  	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1301  		fmt.Fprintln(w, "GOOD")
  1302  	})
  1303  	server := httptest.NewTLSServer(handler)
  1304  	defer server.Close()
  1305  
  1306  	a := NewTestAgent(t, t.Name(), "")
  1307  	defer a.Shutdown()
  1308  
  1309  	health := &structs.HealthCheck{
  1310  		Node:    "foo",
  1311  		CheckID: "tls",
  1312  		Name:    "tls check",
  1313  		Status:  api.HealthCritical,
  1314  	}
  1315  	chk := &structs.CheckType{
  1316  		HTTP:          server.URL,
  1317  		Interval:      20 * time.Millisecond,
  1318  		TLSSkipVerify: true,
  1319  	}
  1320  
  1321  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
  1322  	if err != nil {
  1323  		t.Fatalf("err: %v", err)
  1324  	}
  1325  
  1326  	retry.Run(t, func(r *retry.R) {
  1327  		status := a.State.Checks()["tls"]
  1328  		if status.Status != api.HealthPassing {
  1329  			r.Fatalf("bad: %v", status.Status)
  1330  		}
  1331  		if !strings.Contains(status.Output, "GOOD") {
  1332  			r.Fatalf("bad: %v", status.Output)
  1333  		}
  1334  	})
  1335  
  1336  }
  1337  
  1338  func TestAgent_HTTPCheck_EnableAgentTLSForChecks(t *testing.T) {
  1339  	t.Parallel()
  1340  
  1341  	run := func(t *testing.T, ca string) {
  1342  		a := &TestAgent{
  1343  			Name:   t.Name(),
  1344  			UseTLS: true,
  1345  			HCL: `
  1346  				enable_agent_tls_for_checks = true
  1347  
  1348  				verify_incoming = true
  1349  				server_name = "consul.test"
  1350  				key_file = "../test/client_certs/server.key"
  1351  				cert_file = "../test/client_certs/server.crt"
  1352  			` + ca,
  1353  		}
  1354  		a.Start(t)
  1355  		defer a.Shutdown()
  1356  
  1357  		health := &structs.HealthCheck{
  1358  			Node:    "foo",
  1359  			CheckID: "tls",
  1360  			Name:    "tls check",
  1361  			Status:  api.HealthCritical,
  1362  		}
  1363  
  1364  		url := fmt.Sprintf("https://%s/v1/agent/self", a.srv.ln.Addr().String())
  1365  		chk := &structs.CheckType{
  1366  			HTTP:     url,
  1367  			Interval: 20 * time.Millisecond,
  1368  		}
  1369  
  1370  		err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
  1371  		if err != nil {
  1372  			t.Fatalf("err: %v", err)
  1373  		}
  1374  
  1375  		retry.Run(t, func(r *retry.R) {
  1376  			status := a.State.Checks()["tls"]
  1377  			if status.Status != api.HealthPassing {
  1378  				r.Fatalf("bad: %v", status.Status)
  1379  			}
  1380  			if !strings.Contains(status.Output, "200 OK") {
  1381  				r.Fatalf("bad: %v", status.Output)
  1382  			}
  1383  		})
  1384  	}
  1385  
  1386  	// We need to test both methods of passing the CA info to ensure that
  1387  	// we propagate all the fields correctly. All the other fields are
  1388  	// covered by the HCL in the test run function.
  1389  	tests := []struct {
  1390  		desc   string
  1391  		config string
  1392  	}{
  1393  		{"ca_file", `ca_file = "../test/client_certs/rootca.crt"`},
  1394  		{"ca_path", `ca_path = "../test/client_certs/path"`},
  1395  	}
  1396  	for _, tt := range tests {
  1397  		t.Run(tt.desc, func(t *testing.T) {
  1398  			run(t, tt.config)
  1399  		})
  1400  	}
  1401  }
  1402  
  1403  func TestAgent_updateTTLCheck(t *testing.T) {
  1404  	t.Parallel()
  1405  	a := NewTestAgent(t, t.Name(), "")
  1406  	defer a.Shutdown()
  1407  
  1408  	health := &structs.HealthCheck{
  1409  		Node:    "foo",
  1410  		CheckID: "mem",
  1411  		Name:    "memory util",
  1412  		Status:  api.HealthCritical,
  1413  	}
  1414  	chk := &structs.CheckType{
  1415  		TTL: 15 * time.Second,
  1416  	}
  1417  
  1418  	// Add check and update it.
  1419  	err := a.AddCheck(health, chk, false, "", ConfigSourceLocal)
  1420  	if err != nil {
  1421  		t.Fatalf("err: %v", err)
  1422  	}
  1423  	if err := a.updateTTLCheck("mem", api.HealthPassing, "foo"); err != nil {
  1424  		t.Fatalf("err: %v", err)
  1425  	}
  1426  
  1427  	// Ensure we have a check mapping.
  1428  	status := a.State.Checks()["mem"]
  1429  	if status.Status != api.HealthPassing {
  1430  		t.Fatalf("bad: %v", status)
  1431  	}
  1432  	if status.Output != "foo" {
  1433  		t.Fatalf("bad: %v", status)
  1434  	}
  1435  }
  1436  
  1437  func TestAgent_PersistService(t *testing.T) {
  1438  	t.Parallel()
  1439  	dataDir := testutil.TempDir(t, "agent") // we manage the data dir
  1440  	cfg := `
  1441  		server = false
  1442  		bootstrap = false
  1443  		data_dir = "` + dataDir + `"
  1444  	`
  1445  	a := &TestAgent{Name: t.Name(), HCL: cfg, DataDir: dataDir}
  1446  	a.Start(t)
  1447  	defer os.RemoveAll(dataDir)
  1448  	defer a.Shutdown()
  1449  
  1450  	svc := &structs.NodeService{
  1451  		ID:      "redis",
  1452  		Service: "redis",
  1453  		Tags:    []string{"foo"},
  1454  		Port:    8000,
  1455  	}
  1456  
  1457  	file := filepath.Join(a.Config.DataDir, servicesDir, stringHash(svc.ID))
  1458  
  1459  	// Check is not persisted unless requested
  1460  	if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
  1461  		t.Fatalf("err: %v", err)
  1462  	}
  1463  	if _, err := os.Stat(file); err == nil {
  1464  		t.Fatalf("should not persist")
  1465  	}
  1466  
  1467  	// Persists to file if requested
  1468  	if err := a.AddService(svc, nil, true, "mytoken", ConfigSourceLocal); err != nil {
  1469  		t.Fatalf("err: %v", err)
  1470  	}
  1471  	if _, err := os.Stat(file); err != nil {
  1472  		t.Fatalf("err: %s", err)
  1473  	}
  1474  	expected, err := json.Marshal(persistedService{
  1475  		Token:   "mytoken",
  1476  		Service: svc,
  1477  	})
  1478  	if err != nil {
  1479  		t.Fatalf("err: %s", err)
  1480  	}
  1481  	content, err := ioutil.ReadFile(file)
  1482  	if err != nil {
  1483  		t.Fatalf("err: %s", err)
  1484  	}
  1485  	if !bytes.Equal(expected, content) {
  1486  		t.Fatalf("bad: %s", string(content))
  1487  	}
  1488  
  1489  	// Updates service definition on disk
  1490  	svc.Port = 8001
  1491  	if err := a.AddService(svc, nil, true, "mytoken", ConfigSourceLocal); err != nil {
  1492  		t.Fatalf("err: %v", err)
  1493  	}
  1494  	expected, err = json.Marshal(persistedService{
  1495  		Token:   "mytoken",
  1496  		Service: svc,
  1497  	})
  1498  	if err != nil {
  1499  		t.Fatalf("err: %s", err)
  1500  	}
  1501  	content, err = ioutil.ReadFile(file)
  1502  	if err != nil {
  1503  		t.Fatalf("err: %s", err)
  1504  	}
  1505  	if !bytes.Equal(expected, content) {
  1506  		t.Fatalf("bad: %s", string(content))
  1507  	}
  1508  	a.Shutdown()
  1509  
  1510  	// Should load it back during later start
  1511  	a2 := &TestAgent{Name: t.Name(), HCL: cfg, DataDir: dataDir}
  1512  	a2.Start(t)
  1513  	defer a2.Shutdown()
  1514  
  1515  	restored := a2.State.ServiceState(svc.ID)
  1516  	if restored == nil {
  1517  		t.Fatalf("service %q missing", svc.ID)
  1518  	}
  1519  	if got, want := restored.Token, "mytoken"; got != want {
  1520  		t.Fatalf("got token %q want %q", got, want)
  1521  	}
  1522  	if got, want := restored.Service.Port, 8001; got != want {
  1523  		t.Fatalf("got port %d want %d", got, want)
  1524  	}
  1525  }
  1526  
  1527  func TestAgent_persistedService_compat(t *testing.T) {
  1528  	t.Parallel()
  1529  	// Tests backwards compatibility of persisted services from pre-0.5.1
  1530  	a := NewTestAgent(t, t.Name(), "")
  1531  	defer a.Shutdown()
  1532  
  1533  	svc := &structs.NodeService{
  1534  		ID:      "redis",
  1535  		Service: "redis",
  1536  		Tags:    []string{"foo"},
  1537  		Port:    8000,
  1538  		Weights: &structs.Weights{Passing: 1, Warning: 1},
  1539  	}
  1540  
  1541  	// Encode the NodeService directly. This is what previous versions
  1542  	// would serialize to the file (without the wrapper)
  1543  	encoded, err := json.Marshal(svc)
  1544  	if err != nil {
  1545  		t.Fatalf("err: %s", err)
  1546  	}
  1547  
  1548  	// Write the content to the file
  1549  	file := filepath.Join(a.Config.DataDir, servicesDir, stringHash(svc.ID))
  1550  	if err := os.MkdirAll(filepath.Dir(file), 0700); err != nil {
  1551  		t.Fatalf("err: %s", err)
  1552  	}
  1553  	if err := ioutil.WriteFile(file, encoded, 0600); err != nil {
  1554  		t.Fatalf("err: %s", err)
  1555  	}
  1556  
  1557  	// Load the services
  1558  	if err := a.loadServices(a.Config); err != nil {
  1559  		t.Fatalf("err: %s", err)
  1560  	}
  1561  
  1562  	// Ensure the service was restored
  1563  	services := a.State.Services()
  1564  	result, ok := services["redis"]
  1565  	if !ok {
  1566  		t.Fatalf("missing service")
  1567  	}
  1568  	require.Equal(t, svc, result)
  1569  }
  1570  
  1571  func TestAgent_PurgeService(t *testing.T) {
  1572  	t.Parallel()
  1573  	a := NewTestAgent(t, t.Name(), "")
  1574  	defer a.Shutdown()
  1575  
  1576  	svc := &structs.NodeService{
  1577  		ID:      "redis",
  1578  		Service: "redis",
  1579  		Tags:    []string{"foo"},
  1580  		Port:    8000,
  1581  	}
  1582  
  1583  	file := filepath.Join(a.Config.DataDir, servicesDir, stringHash(svc.ID))
  1584  	if err := a.AddService(svc, nil, true, "", ConfigSourceLocal); err != nil {
  1585  		t.Fatalf("err: %v", err)
  1586  	}
  1587  
  1588  	// Not removed
  1589  	if err := a.RemoveService(svc.ID, false); err != nil {
  1590  		t.Fatalf("err: %s", err)
  1591  	}
  1592  	if _, err := os.Stat(file); err != nil {
  1593  		t.Fatalf("err: %s", err)
  1594  	}
  1595  
  1596  	// Re-add the service
  1597  	if err := a.AddService(svc, nil, true, "", ConfigSourceLocal); err != nil {
  1598  		t.Fatalf("err: %v", err)
  1599  	}
  1600  
  1601  	// Removed
  1602  	if err := a.RemoveService(svc.ID, true); err != nil {
  1603  		t.Fatalf("err: %s", err)
  1604  	}
  1605  	if _, err := os.Stat(file); !os.IsNotExist(err) {
  1606  		t.Fatalf("bad: %#v", err)
  1607  	}
  1608  }
  1609  
  1610  func TestAgent_PurgeServiceOnDuplicate(t *testing.T) {
  1611  	t.Parallel()
  1612  	dataDir := testutil.TempDir(t, "agent") // we manage the data dir
  1613  	cfg := `
  1614  		data_dir = "` + dataDir + `"
  1615  		server = false
  1616  		bootstrap = false
  1617  	`
  1618  	a := &TestAgent{Name: t.Name(), HCL: cfg, DataDir: dataDir}
  1619  	a.Start(t)
  1620  	defer a.Shutdown()
  1621  	defer os.RemoveAll(dataDir)
  1622  
  1623  	svc1 := &structs.NodeService{
  1624  		ID:      "redis",
  1625  		Service: "redis",
  1626  		Tags:    []string{"foo"},
  1627  		Port:    8000,
  1628  	}
  1629  
  1630  	// First persist the service
  1631  	if err := a.AddService(svc1, nil, true, "", ConfigSourceLocal); err != nil {
  1632  		t.Fatalf("err: %v", err)
  1633  	}
  1634  	a.Shutdown()
  1635  
  1636  	// Try bringing the agent back up with the service already
  1637  	// existing in the config
  1638  	a2 := &TestAgent{Name: t.Name() + "-a2", HCL: cfg + `
  1639  		service = {
  1640  			id = "redis"
  1641  			name = "redis"
  1642  			tags = ["bar"]
  1643  			port = 9000
  1644  		}
  1645  	`, DataDir: dataDir}
  1646  	a2.Start(t)
  1647  	defer a2.Shutdown()
  1648  
  1649  	file := filepath.Join(a.Config.DataDir, servicesDir, stringHash(svc1.ID))
  1650  	if _, err := os.Stat(file); err == nil {
  1651  		t.Fatalf("should have removed persisted service")
  1652  	}
  1653  	result := a2.State.Service("redis")
  1654  	if result == nil {
  1655  		t.Fatalf("missing service registration")
  1656  	}
  1657  	if !reflect.DeepEqual(result.Tags, []string{"bar"}) || result.Port != 9000 {
  1658  		t.Fatalf("bad: %#v", result)
  1659  	}
  1660  }
  1661  
  1662  func TestAgent_PersistProxy(t *testing.T) {
  1663  	t.Parallel()
  1664  	dataDir := testutil.TempDir(t, "agent") // we manage the data dir
  1665  	cfg := `
  1666  		server = false
  1667  		bootstrap = false
  1668  		data_dir = "` + dataDir + `"
  1669  	`
  1670  	a := &TestAgent{Name: t.Name(), HCL: cfg, DataDir: dataDir}
  1671  	a.Start(t)
  1672  	defer os.RemoveAll(dataDir)
  1673  	defer a.Shutdown()
  1674  
  1675  	require := require.New(t)
  1676  	assert := assert.New(t)
  1677  
  1678  	// Add a service to proxy (precondition for AddProxy)
  1679  	svc1 := &structs.NodeService{
  1680  		ID:      "redis",
  1681  		Service: "redis",
  1682  		Tags:    []string{"foo"},
  1683  		Port:    8000,
  1684  	}
  1685  	require.NoError(a.AddService(svc1, nil, true, "", ConfigSourceLocal))
  1686  
  1687  	// Add a proxy for it
  1688  	proxy := &structs.ConnectManagedProxy{
  1689  		TargetServiceID: svc1.ID,
  1690  		Command:         []string{"/bin/sleep", "3600"},
  1691  	}
  1692  
  1693  	file := filepath.Join(a.Config.DataDir, proxyDir, stringHash("redis-proxy"))
  1694  
  1695  	// Proxy is not persisted unless requested
  1696  	require.NoError(a.AddProxy(proxy, false, false, "", ConfigSourceLocal))
  1697  	_, err := os.Stat(file)
  1698  	require.Error(err, "proxy should not be persisted")
  1699  
  1700  	// Proxy is  persisted if requested
  1701  	require.NoError(a.AddProxy(proxy, true, false, "", ConfigSourceLocal))
  1702  	_, err = os.Stat(file)
  1703  	require.NoError(err, "proxy should be persisted")
  1704  
  1705  	content, err := ioutil.ReadFile(file)
  1706  	require.NoError(err)
  1707  
  1708  	var gotProxy persistedProxy
  1709  	require.NoError(json.Unmarshal(content, &gotProxy))
  1710  	assert.Equal(proxy.Command, gotProxy.Proxy.Command)
  1711  	assert.Len(gotProxy.ProxyToken, 36) // sanity check for UUID
  1712  
  1713  	// Updates service definition on disk
  1714  	proxy.Config = map[string]interface{}{
  1715  		"foo": "bar",
  1716  	}
  1717  	require.NoError(a.AddProxy(proxy, true, false, "", ConfigSourceLocal))
  1718  
  1719  	content, err = ioutil.ReadFile(file)
  1720  	require.NoError(err)
  1721  
  1722  	require.NoError(json.Unmarshal(content, &gotProxy))
  1723  	assert.Equal(gotProxy.Proxy.Command, proxy.Command)
  1724  	assert.Equal(gotProxy.Proxy.Config, proxy.Config)
  1725  	assert.Len(gotProxy.ProxyToken, 36) // sanity check for UUID
  1726  
  1727  	a.Shutdown()
  1728  
  1729  	// Should load it back during later start
  1730  	a2 := &TestAgent{Name: t.Name(), HCL: cfg, DataDir: dataDir}
  1731  	a2.Start(t)
  1732  	defer a2.Shutdown()
  1733  
  1734  	restored := a2.State.Proxy("redis-proxy")
  1735  	require.NotNil(restored)
  1736  	assert.Equal(gotProxy.ProxyToken, restored.ProxyToken)
  1737  	// Ensure the port that was auto picked at random is the same again
  1738  	assert.Equal(gotProxy.Proxy.ProxyService.Port, restored.Proxy.ProxyService.Port)
  1739  	assert.Equal(gotProxy.Proxy.Command, restored.Proxy.Command)
  1740  }
  1741  
  1742  func TestAgent_PurgeProxy(t *testing.T) {
  1743  	t.Parallel()
  1744  	a := NewTestAgent(t, t.Name(), "")
  1745  	defer a.Shutdown()
  1746  
  1747  	require := require.New(t)
  1748  
  1749  	// Add a service to proxy (precondition for AddProxy)
  1750  	svc1 := &structs.NodeService{
  1751  		ID:      "redis",
  1752  		Service: "redis",
  1753  		Tags:    []string{"foo"},
  1754  		Port:    8000,
  1755  	}
  1756  	require.NoError(a.AddService(svc1, nil, true, "", ConfigSourceLocal))
  1757  
  1758  	// Add a proxy for it
  1759  	proxy := &structs.ConnectManagedProxy{
  1760  		TargetServiceID: svc1.ID,
  1761  		Command:         []string{"/bin/sleep", "3600"},
  1762  	}
  1763  	proxyID := "redis-proxy"
  1764  	require.NoError(a.AddProxy(proxy, true, false, "", ConfigSourceLocal))
  1765  
  1766  	file := filepath.Join(a.Config.DataDir, proxyDir, stringHash("redis-proxy"))
  1767  
  1768  	// Not removed
  1769  	require.NoError(a.RemoveProxy(proxyID, false))
  1770  	_, err := os.Stat(file)
  1771  	require.NoError(err, "should not be removed")
  1772  
  1773  	// Re-add the proxy
  1774  	require.NoError(a.AddProxy(proxy, true, false, "", ConfigSourceLocal))
  1775  
  1776  	// Removed
  1777  	require.NoError(a.RemoveProxy(proxyID, true))
  1778  	_, err = os.Stat(file)
  1779  	require.Error(err, "should be removed")
  1780  }
  1781  
  1782  func TestAgent_PurgeProxyOnDuplicate(t *testing.T) {
  1783  	t.Parallel()
  1784  	dataDir := testutil.TempDir(t, "agent") // we manage the data dir
  1785  	cfg := `
  1786  		data_dir = "` + dataDir + `"
  1787  		server = false
  1788  		bootstrap = false
  1789  	`
  1790  	a := &TestAgent{Name: t.Name(), HCL: cfg, DataDir: dataDir}
  1791  	a.Start(t)
  1792  	defer a.Shutdown()
  1793  	defer os.RemoveAll(dataDir)
  1794  
  1795  	require := require.New(t)
  1796  
  1797  	// Add a service to proxy (precondition for AddProxy)
  1798  	svc1 := &structs.NodeService{
  1799  		ID:      "redis",
  1800  		Service: "redis",
  1801  		Tags:    []string{"foo"},
  1802  		Port:    8000,
  1803  	}
  1804  	require.NoError(a.AddService(svc1, nil, true, "", ConfigSourceLocal))
  1805  
  1806  	// Add a proxy for it
  1807  	proxy := &structs.ConnectManagedProxy{
  1808  		TargetServiceID: svc1.ID,
  1809  		Command:         []string{"/bin/sleep", "3600"},
  1810  	}
  1811  	proxyID := "redis-proxy"
  1812  	require.NoError(a.AddProxy(proxy, true, false, "", ConfigSourceLocal))
  1813  
  1814  	a.Shutdown()
  1815  
  1816  	// Try bringing the agent back up with the service already
  1817  	// existing in the config
  1818  	a2 := &TestAgent{Name: t.Name() + "-a2", HCL: cfg + `
  1819  		service = {
  1820  			id = "redis"
  1821  			name = "redis"
  1822  			tags = ["bar"]
  1823  			port = 9000
  1824  			connect {
  1825  				proxy {
  1826  					command = ["/bin/sleep", "3600"]
  1827  				}
  1828  			}
  1829  		}
  1830  	`, DataDir: dataDir}
  1831  	a2.Start(t)
  1832  	defer a2.Shutdown()
  1833  
  1834  	file := filepath.Join(a.Config.DataDir, proxyDir, stringHash(proxyID))
  1835  	_, err := os.Stat(file)
  1836  	require.NoError(err, "Config File based proxies should be persisted too")
  1837  
  1838  	result := a2.State.Proxy(proxyID)
  1839  	require.NotNil(result)
  1840  	require.Equal(proxy.Command, result.Proxy.Command)
  1841  }
  1842  
  1843  func TestAgent_PersistCheck(t *testing.T) {
  1844  	t.Parallel()
  1845  	dataDir := testutil.TempDir(t, "agent") // we manage the data dir
  1846  	cfg := `
  1847  		data_dir = "` + dataDir + `"
  1848  		server = false
  1849  		bootstrap = false
  1850  		enable_script_checks = true
  1851  	`
  1852  	a := &TestAgent{Name: t.Name(), HCL: cfg, DataDir: dataDir}
  1853  	a.Start(t)
  1854  	defer os.RemoveAll(dataDir)
  1855  	defer a.Shutdown()
  1856  
  1857  	check := &structs.HealthCheck{
  1858  		Node:    a.config.NodeName,
  1859  		CheckID: "mem",
  1860  		Name:    "memory check",
  1861  		Status:  api.HealthPassing,
  1862  	}
  1863  	chkType := &structs.CheckType{
  1864  		ScriptArgs: []string{"/bin/true"},
  1865  		Interval:   10 * time.Second,
  1866  	}
  1867  
  1868  	file := filepath.Join(a.Config.DataDir, checksDir, checkIDHash(check.CheckID))
  1869  
  1870  	// Not persisted if not requested
  1871  	if err := a.AddCheck(check, chkType, false, "", ConfigSourceLocal); err != nil {
  1872  		t.Fatalf("err: %v", err)
  1873  	}
  1874  	if _, err := os.Stat(file); err == nil {
  1875  		t.Fatalf("should not persist")
  1876  	}
  1877  
  1878  	// Should persist if requested
  1879  	if err := a.AddCheck(check, chkType, true, "mytoken", ConfigSourceLocal); err != nil {
  1880  		t.Fatalf("err: %v", err)
  1881  	}
  1882  	if _, err := os.Stat(file); err != nil {
  1883  		t.Fatalf("err: %s", err)
  1884  	}
  1885  	expected, err := json.Marshal(persistedCheck{
  1886  		Check:   check,
  1887  		ChkType: chkType,
  1888  		Token:   "mytoken",
  1889  	})
  1890  	if err != nil {
  1891  		t.Fatalf("err: %s", err)
  1892  	}
  1893  	content, err := ioutil.ReadFile(file)
  1894  	if err != nil {
  1895  		t.Fatalf("err: %s", err)
  1896  	}
  1897  	if !bytes.Equal(expected, content) {
  1898  		t.Fatalf("bad: %s != %s", string(content), expected)
  1899  	}
  1900  
  1901  	// Updates the check definition on disk
  1902  	check.Name = "mem1"
  1903  	if err := a.AddCheck(check, chkType, true, "mytoken", ConfigSourceLocal); err != nil {
  1904  		t.Fatalf("err: %v", err)
  1905  	}
  1906  	expected, err = json.Marshal(persistedCheck{
  1907  		Check:   check,
  1908  		ChkType: chkType,
  1909  		Token:   "mytoken",
  1910  	})
  1911  	if err != nil {
  1912  		t.Fatalf("err: %s", err)
  1913  	}
  1914  	content, err = ioutil.ReadFile(file)
  1915  	if err != nil {
  1916  		t.Fatalf("err: %s", err)
  1917  	}
  1918  	if !bytes.Equal(expected, content) {
  1919  		t.Fatalf("bad: %s", string(content))
  1920  	}
  1921  	a.Shutdown()
  1922  
  1923  	// Should load it back during later start
  1924  	a2 := &TestAgent{Name: t.Name() + "-a2", HCL: cfg, DataDir: dataDir}
  1925  	a2.Start(t)
  1926  	defer a2.Shutdown()
  1927  
  1928  	result := a2.State.Check(check.CheckID)
  1929  	if result == nil {
  1930  		t.Fatalf("bad: %#v", a2.State.Checks())
  1931  	}
  1932  	if result.Status != api.HealthCritical {
  1933  		t.Fatalf("bad: %#v", result)
  1934  	}
  1935  	if result.Name != "mem1" {
  1936  		t.Fatalf("bad: %#v", result)
  1937  	}
  1938  
  1939  	// Should have restored the monitor
  1940  	if _, ok := a2.checkMonitors[check.CheckID]; !ok {
  1941  		t.Fatalf("bad: %#v", a2.checkMonitors)
  1942  	}
  1943  	if a2.State.CheckState(check.CheckID).Token != "mytoken" {
  1944  		t.Fatalf("bad: %s", a2.State.CheckState(check.CheckID).Token)
  1945  	}
  1946  }
  1947  
  1948  func TestAgent_PurgeCheck(t *testing.T) {
  1949  	t.Parallel()
  1950  	a := NewTestAgent(t, t.Name(), "")
  1951  	defer a.Shutdown()
  1952  
  1953  	check := &structs.HealthCheck{
  1954  		Node:    a.Config.NodeName,
  1955  		CheckID: "mem",
  1956  		Name:    "memory check",
  1957  		Status:  api.HealthPassing,
  1958  	}
  1959  
  1960  	file := filepath.Join(a.Config.DataDir, checksDir, checkIDHash(check.CheckID))
  1961  	if err := a.AddCheck(check, nil, true, "", ConfigSourceLocal); err != nil {
  1962  		t.Fatalf("err: %v", err)
  1963  	}
  1964  
  1965  	// Not removed
  1966  	if err := a.RemoveCheck(check.CheckID, false); err != nil {
  1967  		t.Fatalf("err: %s", err)
  1968  	}
  1969  	if _, err := os.Stat(file); err != nil {
  1970  		t.Fatalf("err: %s", err)
  1971  	}
  1972  
  1973  	// Removed
  1974  	if err := a.RemoveCheck(check.CheckID, true); err != nil {
  1975  		t.Fatalf("err: %s", err)
  1976  	}
  1977  	if _, err := os.Stat(file); !os.IsNotExist(err) {
  1978  		t.Fatalf("bad: %#v", err)
  1979  	}
  1980  }
  1981  
  1982  func TestAgent_PurgeCheckOnDuplicate(t *testing.T) {
  1983  	t.Parallel()
  1984  	nodeID := NodeID()
  1985  	dataDir := testutil.TempDir(t, "agent")
  1986  	a := NewTestAgent(t, t.Name(), `
  1987  	    node_id = "`+nodeID+`"
  1988  	    node_name = "Node `+nodeID+`"
  1989  		data_dir = "`+dataDir+`"
  1990  		server = false
  1991  		bootstrap = false
  1992  		enable_script_checks = true
  1993  	`)
  1994  	defer os.RemoveAll(dataDir)
  1995  	defer a.Shutdown()
  1996  
  1997  	check1 := &structs.HealthCheck{
  1998  		Node:    a.Config.NodeName,
  1999  		CheckID: "mem",
  2000  		Name:    "memory check",
  2001  		Status:  api.HealthPassing,
  2002  	}
  2003  
  2004  	// First persist the check
  2005  	if err := a.AddCheck(check1, nil, true, "", ConfigSourceLocal); err != nil {
  2006  		t.Fatalf("err: %v", err)
  2007  	}
  2008  	a.Shutdown()
  2009  
  2010  	// Start again with the check registered in config
  2011  	a2 := NewTestAgent(t, t.Name()+"-a2", `
  2012  	    node_id = "`+nodeID+`"
  2013  	    node_name = "Node `+nodeID+`"
  2014  		data_dir = "`+dataDir+`"
  2015  		server = false
  2016  		bootstrap = false
  2017  		enable_script_checks = true
  2018  		check = {
  2019  			id = "mem"
  2020  			name = "memory check"
  2021  			notes = "my cool notes"
  2022  			args = ["/bin/check-redis.py"]
  2023  			interval = "30s"
  2024  		}
  2025  	`)
  2026  	defer a2.Shutdown()
  2027  
  2028  	file := filepath.Join(dataDir, checksDir, checkIDHash(check1.CheckID))
  2029  	if _, err := os.Stat(file); err == nil {
  2030  		t.Fatalf("should have removed persisted check")
  2031  	}
  2032  	result := a2.State.Check("mem")
  2033  	if result == nil {
  2034  		t.Fatalf("missing check registration")
  2035  	}
  2036  	expected := &structs.HealthCheck{
  2037  		Node:    a2.Config.NodeName,
  2038  		CheckID: "mem",
  2039  		Name:    "memory check",
  2040  		Status:  api.HealthCritical,
  2041  		Notes:   "my cool notes",
  2042  	}
  2043  	if got, want := result, expected; !verify.Values(t, "", got, want) {
  2044  		t.FailNow()
  2045  	}
  2046  }
  2047  
  2048  func TestAgent_loadChecks_token(t *testing.T) {
  2049  	t.Parallel()
  2050  	a := NewTestAgent(t, t.Name(), `
  2051  		check = {
  2052  			id = "rabbitmq"
  2053  			name = "rabbitmq"
  2054  			token = "abc123"
  2055  			ttl = "10s"
  2056  		}
  2057  	`)
  2058  	defer a.Shutdown()
  2059  
  2060  	checks := a.State.Checks()
  2061  	if _, ok := checks["rabbitmq"]; !ok {
  2062  		t.Fatalf("missing check")
  2063  	}
  2064  	if token := a.State.CheckToken("rabbitmq"); token != "abc123" {
  2065  		t.Fatalf("bad: %s", token)
  2066  	}
  2067  }
  2068  
  2069  func TestAgent_unloadChecks(t *testing.T) {
  2070  	t.Parallel()
  2071  	a := NewTestAgent(t, t.Name(), "")
  2072  	defer a.Shutdown()
  2073  
  2074  	// First register a service
  2075  	svc := &structs.NodeService{
  2076  		ID:      "redis",
  2077  		Service: "redis",
  2078  		Tags:    []string{"foo"},
  2079  		Port:    8000,
  2080  	}
  2081  	if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
  2082  		t.Fatalf("err: %v", err)
  2083  	}
  2084  
  2085  	// Register a check
  2086  	check1 := &structs.HealthCheck{
  2087  		Node:        a.Config.NodeName,
  2088  		CheckID:     "service:redis",
  2089  		Name:        "redischeck",
  2090  		Status:      api.HealthPassing,
  2091  		ServiceID:   "redis",
  2092  		ServiceName: "redis",
  2093  	}
  2094  	if err := a.AddCheck(check1, nil, false, "", ConfigSourceLocal); err != nil {
  2095  		t.Fatalf("err: %s", err)
  2096  	}
  2097  	found := false
  2098  	for check := range a.State.Checks() {
  2099  		if check == check1.CheckID {
  2100  			found = true
  2101  			break
  2102  		}
  2103  	}
  2104  	if !found {
  2105  		t.Fatalf("check should have been registered")
  2106  	}
  2107  
  2108  	// Unload all of the checks
  2109  	if err := a.unloadChecks(); err != nil {
  2110  		t.Fatalf("err: %s", err)
  2111  	}
  2112  
  2113  	// Make sure it was unloaded
  2114  	for check := range a.State.Checks() {
  2115  		if check == check1.CheckID {
  2116  			t.Fatalf("should have unloaded checks")
  2117  		}
  2118  	}
  2119  }
  2120  
  2121  func TestAgent_loadServices_token(t *testing.T) {
  2122  	t.Parallel()
  2123  	a := NewTestAgent(t, t.Name(), `
  2124  		service = {
  2125  			id = "rabbitmq"
  2126  			name = "rabbitmq"
  2127  			port = 5672
  2128  			token = "abc123"
  2129  		}
  2130  	`)
  2131  	defer a.Shutdown()
  2132  
  2133  	services := a.State.Services()
  2134  	if _, ok := services["rabbitmq"]; !ok {
  2135  		t.Fatalf("missing service")
  2136  	}
  2137  	if token := a.State.ServiceToken("rabbitmq"); token != "abc123" {
  2138  		t.Fatalf("bad: %s", token)
  2139  	}
  2140  }
  2141  
  2142  func TestAgent_loadServices_sidecar(t *testing.T) {
  2143  	t.Parallel()
  2144  	a := NewTestAgent(t, t.Name(), `
  2145  		service = {
  2146  			id = "rabbitmq"
  2147  			name = "rabbitmq"
  2148  			port = 5672
  2149  			token = "abc123"
  2150  			connect = {
  2151  				sidecar_service {}
  2152  			}
  2153  		}
  2154  	`)
  2155  	defer a.Shutdown()
  2156  
  2157  	services := a.State.Services()
  2158  	if _, ok := services["rabbitmq"]; !ok {
  2159  		t.Fatalf("missing service")
  2160  	}
  2161  	if token := a.State.ServiceToken("rabbitmq"); token != "abc123" {
  2162  		t.Fatalf("bad: %s", token)
  2163  	}
  2164  	if _, ok := services["rabbitmq-sidecar-proxy"]; !ok {
  2165  		t.Fatalf("missing service")
  2166  	}
  2167  	if token := a.State.ServiceToken("rabbitmq-sidecar-proxy"); token != "abc123" {
  2168  		t.Fatalf("bad: %s", token)
  2169  	}
  2170  
  2171  	// Sanity check rabbitmq service should NOT have sidecar info in state since
  2172  	// it's done it's job and should be a registration syntax sugar only.
  2173  	assert.Nil(t, services["rabbitmq"].Connect.SidecarService)
  2174  }
  2175  
  2176  func TestAgent_loadServices_sidecarSeparateToken(t *testing.T) {
  2177  	t.Parallel()
  2178  	a := NewTestAgent(t, t.Name(), `
  2179  		service = {
  2180  			id = "rabbitmq"
  2181  			name = "rabbitmq"
  2182  			port = 5672
  2183  			token = "abc123"
  2184  			connect = {
  2185  				sidecar_service {
  2186  					token = "789xyz"
  2187  				}
  2188  			}
  2189  		}
  2190  	`)
  2191  	defer a.Shutdown()
  2192  
  2193  	services := a.State.Services()
  2194  	if _, ok := services["rabbitmq"]; !ok {
  2195  		t.Fatalf("missing service")
  2196  	}
  2197  	if token := a.State.ServiceToken("rabbitmq"); token != "abc123" {
  2198  		t.Fatalf("bad: %s", token)
  2199  	}
  2200  	if _, ok := services["rabbitmq-sidecar-proxy"]; !ok {
  2201  		t.Fatalf("missing service")
  2202  	}
  2203  	if token := a.State.ServiceToken("rabbitmq-sidecar-proxy"); token != "789xyz" {
  2204  		t.Fatalf("bad: %s", token)
  2205  	}
  2206  }
  2207  
  2208  func TestAgent_loadServices_sidecarInheritMeta(t *testing.T) {
  2209  	t.Parallel()
  2210  
  2211  	a := NewTestAgent(t, t.Name(), `
  2212  		service = {
  2213  			id = "rabbitmq"
  2214  			name = "rabbitmq"
  2215  			port = 5672
  2216  			tags = ["a", "b"],
  2217  			meta = {
  2218  				environment = "prod"
  2219  			}
  2220  			connect = {
  2221  				sidecar_service {
  2222  
  2223  				}
  2224  			}
  2225  		}
  2226  	`)
  2227  	defer a.Shutdown()
  2228  
  2229  	services := a.State.Services()
  2230  
  2231  	svc, ok := services["rabbitmq"]
  2232  	require.True(t, ok, "missing service")
  2233  	require.Len(t, svc.Tags, 2)
  2234  	require.Len(t, svc.Meta, 1)
  2235  
  2236  	sidecar, ok := services["rabbitmq-sidecar-proxy"]
  2237  	require.True(t, ok, "missing sidecar service")
  2238  	require.ElementsMatch(t, svc.Tags, sidecar.Tags)
  2239  	require.Len(t, sidecar.Meta, 1)
  2240  	meta, ok := sidecar.Meta["environment"]
  2241  	require.True(t, ok, "missing sidecar service meta")
  2242  	require.Equal(t, "prod", meta)
  2243  }
  2244  
  2245  func TestAgent_loadServices_sidecarOverrideMeta(t *testing.T) {
  2246  	t.Parallel()
  2247  
  2248  	a := NewTestAgent(t, t.Name(), `
  2249  		service = {
  2250  			id = "rabbitmq"
  2251  			name = "rabbitmq"
  2252  			port = 5672
  2253  			tags = ["a", "b"],
  2254  			meta = {
  2255  				environment = "prod"
  2256  			}
  2257  			connect = {
  2258  				sidecar_service {
  2259  					tags = ["foo"],
  2260  					meta = {
  2261  						environment = "qa"
  2262  					}
  2263  				}
  2264  			}
  2265  		}
  2266  	`)
  2267  	defer a.Shutdown()
  2268  
  2269  	services := a.State.Services()
  2270  
  2271  	svc, ok := services["rabbitmq"]
  2272  	require.True(t, ok, "missing service")
  2273  	require.Len(t, svc.Tags, 2)
  2274  	require.Len(t, svc.Meta, 1)
  2275  
  2276  	sidecar, ok := services["rabbitmq-sidecar-proxy"]
  2277  	require.True(t, ok, "missing sidecar service")
  2278  	require.Len(t, sidecar.Tags, 1)
  2279  	require.Equal(t, "foo", sidecar.Tags[0])
  2280  	require.Len(t, sidecar.Meta, 1)
  2281  	meta, ok := sidecar.Meta["environment"]
  2282  	require.True(t, ok, "missing sidecar service meta")
  2283  	require.Equal(t, "qa", meta)
  2284  }
  2285  
  2286  func TestAgent_unloadServices(t *testing.T) {
  2287  	t.Parallel()
  2288  	a := NewTestAgent(t, t.Name(), "")
  2289  	defer a.Shutdown()
  2290  
  2291  	svc := &structs.NodeService{
  2292  		ID:      "redis",
  2293  		Service: "redis",
  2294  		Tags:    []string{"foo"},
  2295  		Port:    8000,
  2296  	}
  2297  
  2298  	// Register the service
  2299  	if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
  2300  		t.Fatalf("err: %v", err)
  2301  	}
  2302  	found := false
  2303  	for id := range a.State.Services() {
  2304  		if id == svc.ID {
  2305  			found = true
  2306  			break
  2307  		}
  2308  	}
  2309  	if !found {
  2310  		t.Fatalf("should have registered service")
  2311  	}
  2312  
  2313  	// Unload all services
  2314  	if err := a.unloadServices(); err != nil {
  2315  		t.Fatalf("err: %s", err)
  2316  	}
  2317  	if len(a.State.Services()) != 0 {
  2318  		t.Fatalf("should have unloaded services")
  2319  	}
  2320  }
  2321  
  2322  func TestAgent_loadProxies(t *testing.T) {
  2323  	t.Parallel()
  2324  	a := NewTestAgent(t, t.Name(), `
  2325  		service = {
  2326  			id = "rabbitmq"
  2327  			name = "rabbitmq"
  2328  			port = 5672
  2329  			token = "abc123"
  2330  			connect {
  2331  				proxy {
  2332  					config {
  2333  						bind_port = 1234
  2334  					}
  2335  				}
  2336  			}
  2337  		}
  2338  	`)
  2339  	defer a.Shutdown()
  2340  
  2341  	services := a.State.Services()
  2342  	if _, ok := services["rabbitmq"]; !ok {
  2343  		t.Fatalf("missing service")
  2344  	}
  2345  	if token := a.State.ServiceToken("rabbitmq"); token != "abc123" {
  2346  		t.Fatalf("bad: %s", token)
  2347  	}
  2348  	if _, ok := services["rabbitmq-proxy"]; !ok {
  2349  		t.Fatalf("missing proxy service")
  2350  	}
  2351  	if token := a.State.ServiceToken("rabbitmq-proxy"); token != "abc123" {
  2352  		t.Fatalf("bad: %s", token)
  2353  	}
  2354  	proxies := a.State.Proxies()
  2355  	if _, ok := proxies["rabbitmq-proxy"]; !ok {
  2356  		t.Fatalf("missing proxy")
  2357  	}
  2358  }
  2359  
  2360  func TestAgent_loadProxies_nilProxy(t *testing.T) {
  2361  	t.Parallel()
  2362  	a := NewTestAgent(t, t.Name(), `
  2363  		service = {
  2364  			id = "rabbitmq"
  2365  			name = "rabbitmq"
  2366  			port = 5672
  2367  			token = "abc123"
  2368  			connect {
  2369  			}
  2370  		}
  2371  	`)
  2372  	defer a.Shutdown()
  2373  
  2374  	services := a.State.Services()
  2375  	require.Contains(t, services, "rabbitmq")
  2376  	require.Equal(t, "abc123", a.State.ServiceToken("rabbitmq"))
  2377  	require.NotContains(t, services, "rabbitme-proxy")
  2378  	require.Empty(t, a.State.Proxies())
  2379  }
  2380  
  2381  func TestAgent_unloadProxies(t *testing.T) {
  2382  	t.Parallel()
  2383  	a := NewTestAgent(t, t.Name(), `
  2384  		service = {
  2385  			id = "rabbitmq"
  2386  			name = "rabbitmq"
  2387  			port = 5672
  2388  			token = "abc123"
  2389  			connect {
  2390  				proxy {
  2391  					config {
  2392  						bind_port = 1234
  2393  					}
  2394  				}
  2395  			}
  2396  		}
  2397  	`)
  2398  	defer a.Shutdown()
  2399  
  2400  	// Sanity check it's there
  2401  	require.NotNil(t, a.State.Proxy("rabbitmq-proxy"))
  2402  
  2403  	// Unload all proxies
  2404  	if err := a.unloadProxies(); err != nil {
  2405  		t.Fatalf("err: %s", err)
  2406  	}
  2407  	if len(a.State.Proxies()) != 0 {
  2408  		t.Fatalf("should have unloaded proxies")
  2409  	}
  2410  }
  2411  
  2412  func TestAgent_Service_MaintenanceMode(t *testing.T) {
  2413  	t.Parallel()
  2414  	a := NewTestAgent(t, t.Name(), "")
  2415  	defer a.Shutdown()
  2416  
  2417  	svc := &structs.NodeService{
  2418  		ID:      "redis",
  2419  		Service: "redis",
  2420  		Tags:    []string{"foo"},
  2421  		Port:    8000,
  2422  	}
  2423  
  2424  	// Register the service
  2425  	if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
  2426  		t.Fatalf("err: %v", err)
  2427  	}
  2428  
  2429  	// Enter maintenance mode for the service
  2430  	if err := a.EnableServiceMaintenance("redis", "broken", "mytoken"); err != nil {
  2431  		t.Fatalf("err: %s", err)
  2432  	}
  2433  
  2434  	// Make sure the critical health check was added
  2435  	checkID := serviceMaintCheckID("redis")
  2436  	check, ok := a.State.Checks()[checkID]
  2437  	if !ok {
  2438  		t.Fatalf("should have registered critical maintenance check")
  2439  	}
  2440  
  2441  	// Check that the token was used to register the check
  2442  	if token := a.State.CheckToken(checkID); token != "mytoken" {
  2443  		t.Fatalf("expected 'mytoken', got: '%s'", token)
  2444  	}
  2445  
  2446  	// Ensure the reason was set in notes
  2447  	if check.Notes != "broken" {
  2448  		t.Fatalf("bad: %#v", check)
  2449  	}
  2450  
  2451  	// Leave maintenance mode
  2452  	if err := a.DisableServiceMaintenance("redis"); err != nil {
  2453  		t.Fatalf("err: %s", err)
  2454  	}
  2455  
  2456  	// Ensure the check was deregistered
  2457  	if _, ok := a.State.Checks()[checkID]; ok {
  2458  		t.Fatalf("should have deregistered maintenance check")
  2459  	}
  2460  
  2461  	// Enter service maintenance mode without providing a reason
  2462  	if err := a.EnableServiceMaintenance("redis", "", ""); err != nil {
  2463  		t.Fatalf("err: %s", err)
  2464  	}
  2465  
  2466  	// Ensure the check was registered with the default notes
  2467  	check, ok = a.State.Checks()[checkID]
  2468  	if !ok {
  2469  		t.Fatalf("should have registered critical check")
  2470  	}
  2471  	if check.Notes != defaultServiceMaintReason {
  2472  		t.Fatalf("bad: %#v", check)
  2473  	}
  2474  }
  2475  
  2476  func TestAgent_Service_Reap(t *testing.T) {
  2477  	// t.Parallel() // timing test. no parallel
  2478  	a := NewTestAgent(t, t.Name(), `
  2479  		check_reap_interval = "50ms"
  2480  		check_deregister_interval_min = "0s"
  2481  	`)
  2482  	defer a.Shutdown()
  2483  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
  2484  
  2485  	svc := &structs.NodeService{
  2486  		ID:      "redis",
  2487  		Service: "redis",
  2488  		Tags:    []string{"foo"},
  2489  		Port:    8000,
  2490  	}
  2491  	chkTypes := []*structs.CheckType{
  2492  		&structs.CheckType{
  2493  			Status:                         api.HealthPassing,
  2494  			TTL:                            25 * time.Millisecond,
  2495  			DeregisterCriticalServiceAfter: 200 * time.Millisecond,
  2496  		},
  2497  	}
  2498  
  2499  	// Register the service.
  2500  	if err := a.AddService(svc, chkTypes, false, "", ConfigSourceLocal); err != nil {
  2501  		t.Fatalf("err: %v", err)
  2502  	}
  2503  
  2504  	// Make sure it's there and there's no critical check yet.
  2505  	if _, ok := a.State.Services()["redis"]; !ok {
  2506  		t.Fatalf("should have redis service")
  2507  	}
  2508  	if checks := a.State.CriticalCheckStates(); len(checks) > 0 {
  2509  		t.Fatalf("should not have critical checks")
  2510  	}
  2511  
  2512  	// Wait for the check TTL to fail but before the check is reaped.
  2513  	time.Sleep(100 * time.Millisecond)
  2514  	if _, ok := a.State.Services()["redis"]; !ok {
  2515  		t.Fatalf("should have redis service")
  2516  	}
  2517  	if checks := a.State.CriticalCheckStates(); len(checks) != 1 {
  2518  		t.Fatalf("should have a critical check")
  2519  	}
  2520  
  2521  	// Pass the TTL.
  2522  	if err := a.updateTTLCheck("service:redis", api.HealthPassing, "foo"); err != nil {
  2523  		t.Fatalf("err: %v", err)
  2524  	}
  2525  	if _, ok := a.State.Services()["redis"]; !ok {
  2526  		t.Fatalf("should have redis service")
  2527  	}
  2528  	if checks := a.State.CriticalCheckStates(); len(checks) > 0 {
  2529  		t.Fatalf("should not have critical checks")
  2530  	}
  2531  
  2532  	// Wait for the check TTL to fail again.
  2533  	time.Sleep(100 * time.Millisecond)
  2534  	if _, ok := a.State.Services()["redis"]; !ok {
  2535  		t.Fatalf("should have redis service")
  2536  	}
  2537  	if checks := a.State.CriticalCheckStates(); len(checks) != 1 {
  2538  		t.Fatalf("should have a critical check")
  2539  	}
  2540  
  2541  	// Wait for the reap.
  2542  	time.Sleep(400 * time.Millisecond)
  2543  	if _, ok := a.State.Services()["redis"]; ok {
  2544  		t.Fatalf("redis service should have been reaped")
  2545  	}
  2546  	if checks := a.State.CriticalCheckStates(); len(checks) > 0 {
  2547  		t.Fatalf("should not have critical checks")
  2548  	}
  2549  }
  2550  
  2551  func TestAgent_Service_NoReap(t *testing.T) {
  2552  	// t.Parallel() // timing test. no parallel
  2553  	a := NewTestAgent(t, t.Name(), `
  2554  		check_reap_interval = "50ms"
  2555  		check_deregister_interval_min = "0s"
  2556  	`)
  2557  	defer a.Shutdown()
  2558  
  2559  	svc := &structs.NodeService{
  2560  		ID:      "redis",
  2561  		Service: "redis",
  2562  		Tags:    []string{"foo"},
  2563  		Port:    8000,
  2564  	}
  2565  	chkTypes := []*structs.CheckType{
  2566  		&structs.CheckType{
  2567  			Status: api.HealthPassing,
  2568  			TTL:    25 * time.Millisecond,
  2569  		},
  2570  	}
  2571  
  2572  	// Register the service.
  2573  	if err := a.AddService(svc, chkTypes, false, "", ConfigSourceLocal); err != nil {
  2574  		t.Fatalf("err: %v", err)
  2575  	}
  2576  
  2577  	// Make sure it's there and there's no critical check yet.
  2578  	if _, ok := a.State.Services()["redis"]; !ok {
  2579  		t.Fatalf("should have redis service")
  2580  	}
  2581  	if checks := a.State.CriticalCheckStates(); len(checks) > 0 {
  2582  		t.Fatalf("should not have critical checks")
  2583  	}
  2584  
  2585  	// Wait for the check TTL to fail.
  2586  	time.Sleep(200 * time.Millisecond)
  2587  	if _, ok := a.State.Services()["redis"]; !ok {
  2588  		t.Fatalf("should have redis service")
  2589  	}
  2590  	if checks := a.State.CriticalCheckStates(); len(checks) != 1 {
  2591  		t.Fatalf("should have a critical check")
  2592  	}
  2593  
  2594  	// Wait a while and make sure it doesn't reap.
  2595  	time.Sleep(200 * time.Millisecond)
  2596  	if _, ok := a.State.Services()["redis"]; !ok {
  2597  		t.Fatalf("should have redis service")
  2598  	}
  2599  	if checks := a.State.CriticalCheckStates(); len(checks) != 1 {
  2600  		t.Fatalf("should have a critical check")
  2601  	}
  2602  }
  2603  
  2604  func TestAgent_AddService_restoresSnapshot(t *testing.T) {
  2605  	t.Parallel()
  2606  	a := NewTestAgent(t, t.Name(), "")
  2607  	defer a.Shutdown()
  2608  
  2609  	// First register a service
  2610  	svc := &structs.NodeService{
  2611  		ID:      "redis",
  2612  		Service: "redis",
  2613  		Tags:    []string{"foo"},
  2614  		Port:    8000,
  2615  	}
  2616  	if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
  2617  		t.Fatalf("err: %v", err)
  2618  	}
  2619  
  2620  	// Register a check
  2621  	check1 := &structs.HealthCheck{
  2622  		Node:        a.Config.NodeName,
  2623  		CheckID:     "service:redis",
  2624  		Name:        "redischeck",
  2625  		Status:      api.HealthPassing,
  2626  		ServiceID:   "redis",
  2627  		ServiceName: "redis",
  2628  	}
  2629  	if err := a.AddCheck(check1, nil, false, "", ConfigSourceLocal); err != nil {
  2630  		t.Fatalf("err: %s", err)
  2631  	}
  2632  
  2633  	// Re-registering the service preserves the state of the check
  2634  	chkTypes := []*structs.CheckType{&structs.CheckType{TTL: 30 * time.Second}}
  2635  	if err := a.AddService(svc, chkTypes, false, "", ConfigSourceLocal); err != nil {
  2636  		t.Fatalf("err: %s", err)
  2637  	}
  2638  	check, ok := a.State.Checks()["service:redis"]
  2639  	if !ok {
  2640  		t.Fatalf("missing check")
  2641  	}
  2642  	if check.Status != api.HealthPassing {
  2643  		t.Fatalf("bad: %s", check.Status)
  2644  	}
  2645  }
  2646  
  2647  func TestAgent_AddCheck_restoresSnapshot(t *testing.T) {
  2648  	t.Parallel()
  2649  	a := NewTestAgent(t, t.Name(), "")
  2650  	defer a.Shutdown()
  2651  
  2652  	// First register a service
  2653  	svc := &structs.NodeService{
  2654  		ID:      "redis",
  2655  		Service: "redis",
  2656  		Tags:    []string{"foo"},
  2657  		Port:    8000,
  2658  	}
  2659  	if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
  2660  		t.Fatalf("err: %v", err)
  2661  	}
  2662  
  2663  	// Register a check
  2664  	check1 := &structs.HealthCheck{
  2665  		Node:        a.Config.NodeName,
  2666  		CheckID:     "service:redis",
  2667  		Name:        "redischeck",
  2668  		Status:      api.HealthPassing,
  2669  		ServiceID:   "redis",
  2670  		ServiceName: "redis",
  2671  	}
  2672  	if err := a.AddCheck(check1, nil, false, "", ConfigSourceLocal); err != nil {
  2673  		t.Fatalf("err: %s", err)
  2674  	}
  2675  
  2676  	// Re-registering the check preserves its state
  2677  	check1.Status = ""
  2678  	if err := a.AddCheck(check1, &structs.CheckType{TTL: 30 * time.Second}, false, "", ConfigSourceLocal); err != nil {
  2679  		t.Fatalf("err: %s", err)
  2680  	}
  2681  	check, ok := a.State.Checks()["service:redis"]
  2682  	if !ok {
  2683  		t.Fatalf("missing check")
  2684  	}
  2685  	if check.Status != api.HealthPassing {
  2686  		t.Fatalf("bad: %s", check.Status)
  2687  	}
  2688  }
  2689  
  2690  func TestAgent_NodeMaintenanceMode(t *testing.T) {
  2691  	t.Parallel()
  2692  	a := NewTestAgent(t, t.Name(), "")
  2693  	defer a.Shutdown()
  2694  
  2695  	// Enter maintenance mode for the node
  2696  	a.EnableNodeMaintenance("broken", "mytoken")
  2697  
  2698  	// Make sure the critical health check was added
  2699  	check, ok := a.State.Checks()[structs.NodeMaint]
  2700  	if !ok {
  2701  		t.Fatalf("should have registered critical node check")
  2702  	}
  2703  
  2704  	// Check that the token was used to register the check
  2705  	if token := a.State.CheckToken(structs.NodeMaint); token != "mytoken" {
  2706  		t.Fatalf("expected 'mytoken', got: '%s'", token)
  2707  	}
  2708  
  2709  	// Ensure the reason was set in notes
  2710  	if check.Notes != "broken" {
  2711  		t.Fatalf("bad: %#v", check)
  2712  	}
  2713  
  2714  	// Leave maintenance mode
  2715  	a.DisableNodeMaintenance()
  2716  
  2717  	// Ensure the check was deregistered
  2718  	if _, ok := a.State.Checks()[structs.NodeMaint]; ok {
  2719  		t.Fatalf("should have deregistered critical node check")
  2720  	}
  2721  
  2722  	// Enter maintenance mode without passing a reason
  2723  	a.EnableNodeMaintenance("", "")
  2724  
  2725  	// Make sure the check was registered with the default note
  2726  	check, ok = a.State.Checks()[structs.NodeMaint]
  2727  	if !ok {
  2728  		t.Fatalf("should have registered critical node check")
  2729  	}
  2730  	if check.Notes != defaultNodeMaintReason {
  2731  		t.Fatalf("bad: %#v", check)
  2732  	}
  2733  }
  2734  
  2735  func TestAgent_checkStateSnapshot(t *testing.T) {
  2736  	t.Parallel()
  2737  	a := NewTestAgent(t, t.Name(), "")
  2738  	defer a.Shutdown()
  2739  
  2740  	// First register a service
  2741  	svc := &structs.NodeService{
  2742  		ID:      "redis",
  2743  		Service: "redis",
  2744  		Tags:    []string{"foo"},
  2745  		Port:    8000,
  2746  	}
  2747  	if err := a.AddService(svc, nil, false, "", ConfigSourceLocal); err != nil {
  2748  		t.Fatalf("err: %v", err)
  2749  	}
  2750  
  2751  	// Register a check
  2752  	check1 := &structs.HealthCheck{
  2753  		Node:        a.Config.NodeName,
  2754  		CheckID:     "service:redis",
  2755  		Name:        "redischeck",
  2756  		Status:      api.HealthPassing,
  2757  		ServiceID:   "redis",
  2758  		ServiceName: "redis",
  2759  	}
  2760  	if err := a.AddCheck(check1, nil, true, "", ConfigSourceLocal); err != nil {
  2761  		t.Fatalf("err: %s", err)
  2762  	}
  2763  
  2764  	// Snapshot the state
  2765  	snap := a.snapshotCheckState()
  2766  
  2767  	// Unload all of the checks
  2768  	if err := a.unloadChecks(); err != nil {
  2769  		t.Fatalf("err: %s", err)
  2770  	}
  2771  
  2772  	// Reload the checks
  2773  	if err := a.loadChecks(a.Config); err != nil {
  2774  		t.Fatalf("err: %s", err)
  2775  	}
  2776  
  2777  	// Restore the state
  2778  	a.restoreCheckState(snap)
  2779  
  2780  	// Search for the check
  2781  	out, ok := a.State.Checks()[check1.CheckID]
  2782  	if !ok {
  2783  		t.Fatalf("check should have been registered")
  2784  	}
  2785  
  2786  	// Make sure state was restored
  2787  	if out.Status != api.HealthPassing {
  2788  		t.Fatalf("should have restored check state")
  2789  	}
  2790  }
  2791  
  2792  func TestAgent_loadChecks_checkFails(t *testing.T) {
  2793  	t.Parallel()
  2794  	a := NewTestAgent(t, t.Name(), "")
  2795  	defer a.Shutdown()
  2796  
  2797  	// Persist a health check with an invalid service ID
  2798  	check := &structs.HealthCheck{
  2799  		Node:      a.Config.NodeName,
  2800  		CheckID:   "service:redis",
  2801  		Name:      "redischeck",
  2802  		Status:    api.HealthPassing,
  2803  		ServiceID: "nope",
  2804  	}
  2805  	if err := a.persistCheck(check, nil); err != nil {
  2806  		t.Fatalf("err: %s", err)
  2807  	}
  2808  
  2809  	// Check to make sure the check was persisted
  2810  	checkHash := checkIDHash(check.CheckID)
  2811  	checkPath := filepath.Join(a.Config.DataDir, checksDir, checkHash)
  2812  	if _, err := os.Stat(checkPath); err != nil {
  2813  		t.Fatalf("err: %s", err)
  2814  	}
  2815  
  2816  	// Try loading the checks from the persisted files
  2817  	if err := a.loadChecks(a.Config); err != nil {
  2818  		t.Fatalf("err: %s", err)
  2819  	}
  2820  
  2821  	// Ensure the erroneous check was purged
  2822  	if _, err := os.Stat(checkPath); err == nil {
  2823  		t.Fatalf("should have purged check")
  2824  	}
  2825  }
  2826  
  2827  func TestAgent_persistCheckState(t *testing.T) {
  2828  	t.Parallel()
  2829  	a := NewTestAgent(t, t.Name(), "")
  2830  	defer a.Shutdown()
  2831  
  2832  	// Create the TTL check to persist
  2833  	check := &checks.CheckTTL{
  2834  		CheckID: "check1",
  2835  		TTL:     10 * time.Minute,
  2836  	}
  2837  
  2838  	// Persist some check state for the check
  2839  	err := a.persistCheckState(check, api.HealthCritical, "nope")
  2840  	if err != nil {
  2841  		t.Fatalf("err: %s", err)
  2842  	}
  2843  
  2844  	// Check the persisted file exists and has the content
  2845  	file := filepath.Join(a.Config.DataDir, checkStateDir, stringHash("check1"))
  2846  	buf, err := ioutil.ReadFile(file)
  2847  	if err != nil {
  2848  		t.Fatalf("err: %s", err)
  2849  	}
  2850  
  2851  	// Decode the state
  2852  	var p persistedCheckState
  2853  	if err := json.Unmarshal(buf, &p); err != nil {
  2854  		t.Fatalf("err: %s", err)
  2855  	}
  2856  
  2857  	// Check the fields
  2858  	if p.CheckID != "check1" {
  2859  		t.Fatalf("bad: %#v", p)
  2860  	}
  2861  	if p.Output != "nope" {
  2862  		t.Fatalf("bad: %#v", p)
  2863  	}
  2864  	if p.Status != api.HealthCritical {
  2865  		t.Fatalf("bad: %#v", p)
  2866  	}
  2867  
  2868  	// Check the expiration time was set
  2869  	if p.Expires < time.Now().Unix() {
  2870  		t.Fatalf("bad: %#v", p)
  2871  	}
  2872  }
  2873  
  2874  func TestAgent_loadCheckState(t *testing.T) {
  2875  	t.Parallel()
  2876  	a := NewTestAgent(t, t.Name(), "")
  2877  	defer a.Shutdown()
  2878  
  2879  	// Create a check whose state will expire immediately
  2880  	check := &checks.CheckTTL{
  2881  		CheckID: "check1",
  2882  		TTL:     0,
  2883  	}
  2884  
  2885  	// Persist the check state
  2886  	err := a.persistCheckState(check, api.HealthPassing, "yup")
  2887  	if err != nil {
  2888  		t.Fatalf("err: %s", err)
  2889  	}
  2890  
  2891  	// Try to load the state
  2892  	health := &structs.HealthCheck{
  2893  		CheckID: "check1",
  2894  		Status:  api.HealthCritical,
  2895  	}
  2896  	if err := a.loadCheckState(health); err != nil {
  2897  		t.Fatalf("err: %s", err)
  2898  	}
  2899  
  2900  	// Should not have restored the status due to expiration
  2901  	if health.Status != api.HealthCritical {
  2902  		t.Fatalf("bad: %#v", health)
  2903  	}
  2904  	if health.Output != "" {
  2905  		t.Fatalf("bad: %#v", health)
  2906  	}
  2907  
  2908  	// Should have purged the state
  2909  	file := filepath.Join(a.Config.DataDir, checksDir, stringHash("check1"))
  2910  	if _, err := os.Stat(file); !os.IsNotExist(err) {
  2911  		t.Fatalf("should have purged state")
  2912  	}
  2913  
  2914  	// Set a TTL which will not expire before we check it
  2915  	check.TTL = time.Minute
  2916  	err = a.persistCheckState(check, api.HealthPassing, "yup")
  2917  	if err != nil {
  2918  		t.Fatalf("err: %s", err)
  2919  	}
  2920  
  2921  	// Try to load
  2922  	if err := a.loadCheckState(health); err != nil {
  2923  		t.Fatalf("err: %s", err)
  2924  	}
  2925  
  2926  	// Should have restored
  2927  	if health.Status != api.HealthPassing {
  2928  		t.Fatalf("bad: %#v", health)
  2929  	}
  2930  	if health.Output != "yup" {
  2931  		t.Fatalf("bad: %#v", health)
  2932  	}
  2933  }
  2934  
  2935  func TestAgent_purgeCheckState(t *testing.T) {
  2936  	t.Parallel()
  2937  	a := NewTestAgent(t, t.Name(), "")
  2938  	defer a.Shutdown()
  2939  
  2940  	// No error if the state does not exist
  2941  	if err := a.purgeCheckState("check1"); err != nil {
  2942  		t.Fatalf("err: %s", err)
  2943  	}
  2944  
  2945  	// Persist some state to the data dir
  2946  	check := &checks.CheckTTL{
  2947  		CheckID: "check1",
  2948  		TTL:     time.Minute,
  2949  	}
  2950  	err := a.persistCheckState(check, api.HealthPassing, "yup")
  2951  	if err != nil {
  2952  		t.Fatalf("err: %s", err)
  2953  	}
  2954  
  2955  	// Purge the check state
  2956  	if err := a.purgeCheckState("check1"); err != nil {
  2957  		t.Fatalf("err: %s", err)
  2958  	}
  2959  
  2960  	// Removed the file
  2961  	file := filepath.Join(a.Config.DataDir, checkStateDir, stringHash("check1"))
  2962  	if _, err := os.Stat(file); !os.IsNotExist(err) {
  2963  		t.Fatalf("should have removed file")
  2964  	}
  2965  }
  2966  
  2967  func TestAgent_GetCoordinate(t *testing.T) {
  2968  	t.Parallel()
  2969  	check := func(server bool) {
  2970  		a := NewTestAgent(t, t.Name(), `
  2971  			server = true
  2972  		`)
  2973  		defer a.Shutdown()
  2974  
  2975  		// This doesn't verify the returned coordinate, but it makes
  2976  		// sure that the agent chooses the correct Serf instance,
  2977  		// depending on how it's configured as a client or a server.
  2978  		// If it chooses the wrong one, this will crash.
  2979  		if _, err := a.GetLANCoordinate(); err != nil {
  2980  			t.Fatalf("err: %s", err)
  2981  		}
  2982  	}
  2983  
  2984  	check(true)
  2985  	check(false)
  2986  }
  2987  
  2988  func TestAgent_reloadWatches(t *testing.T) {
  2989  	t.Parallel()
  2990  	a := NewTestAgent(t, t.Name(), "")
  2991  	defer a.Shutdown()
  2992  
  2993  	// Normal watch with http addr set, should succeed
  2994  	newConf := *a.config
  2995  	newConf.Watches = []map[string]interface{}{
  2996  		{
  2997  			"type": "key",
  2998  			"key":  "asdf",
  2999  			"args": []interface{}{"ls"},
  3000  		},
  3001  	}
  3002  	if err := a.reloadWatches(&newConf); err != nil {
  3003  		t.Fatalf("bad: %s", err)
  3004  	}
  3005  
  3006  	// Should fail to reload with connect watches
  3007  	newConf.Watches = []map[string]interface{}{
  3008  		{
  3009  			"type": "connect_roots",
  3010  			"key":  "asdf",
  3011  			"args": []interface{}{"ls"},
  3012  		},
  3013  	}
  3014  	if err := a.reloadWatches(&newConf); err == nil || !strings.Contains(err.Error(), "not allowed in agent config") {
  3015  		t.Fatalf("bad: %s", err)
  3016  	}
  3017  
  3018  	// Should still succeed with only HTTPS addresses
  3019  	newConf.HTTPSAddrs = newConf.HTTPAddrs
  3020  	newConf.HTTPAddrs = make([]net.Addr, 0)
  3021  	newConf.Watches = []map[string]interface{}{
  3022  		{
  3023  			"type": "key",
  3024  			"key":  "asdf",
  3025  			"args": []interface{}{"ls"},
  3026  		},
  3027  	}
  3028  	if err := a.reloadWatches(&newConf); err != nil {
  3029  		t.Fatalf("bad: %s", err)
  3030  	}
  3031  
  3032  	// Should fail to reload with no http or https addrs
  3033  	newConf.HTTPSAddrs = make([]net.Addr, 0)
  3034  	newConf.Watches = []map[string]interface{}{
  3035  		{
  3036  			"type": "key",
  3037  			"key":  "asdf",
  3038  			"args": []interface{}{"ls"},
  3039  		},
  3040  	}
  3041  	if err := a.reloadWatches(&newConf); err == nil || !strings.Contains(err.Error(), "watch plans require an HTTP or HTTPS endpoint") {
  3042  		t.Fatalf("bad: %s", err)
  3043  	}
  3044  }
  3045  
  3046  func TestAgent_reloadWatchesHTTPS(t *testing.T) {
  3047  	t.Parallel()
  3048  	a := TestAgent{Name: t.Name(), UseTLS: true}
  3049  	a.Start(t)
  3050  	defer a.Shutdown()
  3051  
  3052  	// Normal watch with http addr set, should succeed
  3053  	newConf := *a.config
  3054  	newConf.Watches = []map[string]interface{}{
  3055  		{
  3056  			"type": "key",
  3057  			"key":  "asdf",
  3058  			"args": []interface{}{"ls"},
  3059  		},
  3060  	}
  3061  	if err := a.reloadWatches(&newConf); err != nil {
  3062  		t.Fatalf("bad: %s", err)
  3063  	}
  3064  }
  3065  
  3066  func TestAgent_AddProxy(t *testing.T) {
  3067  	t.Parallel()
  3068  
  3069  	tests := []struct {
  3070  		desc             string
  3071  		proxy, wantProxy *structs.ConnectManagedProxy
  3072  		wantTCPCheck     string
  3073  		wantErr          bool
  3074  	}{
  3075  		{
  3076  			desc: "basic proxy adding, unregistered service",
  3077  			proxy: &structs.ConnectManagedProxy{
  3078  				ExecMode: structs.ProxyExecModeDaemon,
  3079  				Command:  []string{"consul", "connect", "proxy"},
  3080  				Config: map[string]interface{}{
  3081  					"foo": "bar",
  3082  				},
  3083  				TargetServiceID: "db", // non-existent service.
  3084  			},
  3085  			// Target service must be registered.
  3086  			wantErr: true,
  3087  		},
  3088  		{
  3089  			desc: "basic proxy adding, registered service",
  3090  			proxy: &structs.ConnectManagedProxy{
  3091  				ExecMode: structs.ProxyExecModeDaemon,
  3092  				Command:  []string{"consul", "connect", "proxy"},
  3093  				Config: map[string]interface{}{
  3094  					"foo": "bar",
  3095  				},
  3096  				TargetServiceID: "web",
  3097  			},
  3098  			// Proxy will inherit agent's 0.0.0.0 bind address but we can't check that
  3099  			// so we should default to localhost in that case.
  3100  			wantTCPCheck: "127.0.0.1:20000",
  3101  			wantErr:      false,
  3102  		},
  3103  		{
  3104  			desc: "default global exec mode",
  3105  			proxy: &structs.ConnectManagedProxy{
  3106  				Command:         []string{"consul", "connect", "proxy"},
  3107  				TargetServiceID: "web",
  3108  			},
  3109  			wantProxy: &structs.ConnectManagedProxy{
  3110  				ExecMode:        structs.ProxyExecModeScript,
  3111  				Command:         []string{"consul", "connect", "proxy"},
  3112  				TargetServiceID: "web",
  3113  			},
  3114  			wantTCPCheck: "127.0.0.1:20000",
  3115  			wantErr:      false,
  3116  		},
  3117  		{
  3118  			desc: "default daemon command",
  3119  			proxy: &structs.ConnectManagedProxy{
  3120  				ExecMode:        structs.ProxyExecModeDaemon,
  3121  				TargetServiceID: "web",
  3122  			},
  3123  			wantProxy: &structs.ConnectManagedProxy{
  3124  				ExecMode:        structs.ProxyExecModeDaemon,
  3125  				Command:         []string{"foo", "bar"},
  3126  				TargetServiceID: "web",
  3127  			},
  3128  			wantTCPCheck: "127.0.0.1:20000",
  3129  			wantErr:      false,
  3130  		},
  3131  		{
  3132  			desc: "default script command",
  3133  			proxy: &structs.ConnectManagedProxy{
  3134  				ExecMode:        structs.ProxyExecModeScript,
  3135  				TargetServiceID: "web",
  3136  			},
  3137  			wantProxy: &structs.ConnectManagedProxy{
  3138  				ExecMode:        structs.ProxyExecModeScript,
  3139  				Command:         []string{"bar", "foo"},
  3140  				TargetServiceID: "web",
  3141  			},
  3142  			wantTCPCheck: "127.0.0.1:20000",
  3143  			wantErr:      false,
  3144  		},
  3145  		{
  3146  			desc: "managed proxy with custom bind port",
  3147  			proxy: &structs.ConnectManagedProxy{
  3148  				ExecMode: structs.ProxyExecModeDaemon,
  3149  				Command:  []string{"consul", "connect", "proxy"},
  3150  				Config: map[string]interface{}{
  3151  					"foo":          "bar",
  3152  					"bind_address": "127.10.10.10",
  3153  					"bind_port":    1234,
  3154  				},
  3155  				TargetServiceID: "web",
  3156  			},
  3157  			wantTCPCheck: "127.10.10.10:1234",
  3158  			wantErr:      false,
  3159  		},
  3160  		{
  3161  			// This test is necessary since JSON and HCL both will parse
  3162  			// numbers as a float64.
  3163  			desc: "managed proxy with custom bind port (float64)",
  3164  			proxy: &structs.ConnectManagedProxy{
  3165  				ExecMode: structs.ProxyExecModeDaemon,
  3166  				Command:  []string{"consul", "connect", "proxy"},
  3167  				Config: map[string]interface{}{
  3168  					"foo":          "bar",
  3169  					"bind_address": "127.10.10.10",
  3170  					"bind_port":    float64(1234),
  3171  				},
  3172  				TargetServiceID: "web",
  3173  			},
  3174  			wantTCPCheck: "127.10.10.10:1234",
  3175  			wantErr:      false,
  3176  		},
  3177  		{
  3178  			desc: "managed proxy with overridden but unspecified ipv6 bind address",
  3179  			proxy: &structs.ConnectManagedProxy{
  3180  				ExecMode: structs.ProxyExecModeDaemon,
  3181  				Command:  []string{"consul", "connect", "proxy"},
  3182  				Config: map[string]interface{}{
  3183  					"foo":          "bar",
  3184  					"bind_address": "[::]",
  3185  				},
  3186  				TargetServiceID: "web",
  3187  			},
  3188  			wantTCPCheck: "127.0.0.1:20000",
  3189  			wantErr:      false,
  3190  		},
  3191  		{
  3192  			desc: "managed proxy with overridden check address",
  3193  			proxy: &structs.ConnectManagedProxy{
  3194  				ExecMode: structs.ProxyExecModeDaemon,
  3195  				Command:  []string{"consul", "connect", "proxy"},
  3196  				Config: map[string]interface{}{
  3197  					"foo":               "bar",
  3198  					"tcp_check_address": "127.20.20.20",
  3199  				},
  3200  				TargetServiceID: "web",
  3201  			},
  3202  			wantTCPCheck: "127.20.20.20:20000",
  3203  			wantErr:      false,
  3204  		},
  3205  		{
  3206  			desc: "managed proxy with disabled check",
  3207  			proxy: &structs.ConnectManagedProxy{
  3208  				ExecMode: structs.ProxyExecModeDaemon,
  3209  				Command:  []string{"consul", "connect", "proxy"},
  3210  				Config: map[string]interface{}{
  3211  					"foo":               "bar",
  3212  					"disable_tcp_check": true,
  3213  				},
  3214  				TargetServiceID: "web",
  3215  			},
  3216  			wantTCPCheck: "",
  3217  			wantErr:      false,
  3218  		},
  3219  	}
  3220  
  3221  	for _, tt := range tests {
  3222  		t.Run(tt.desc, func(t *testing.T) {
  3223  			require := require.New(t)
  3224  
  3225  			a := NewTestAgent(t, t.Name(), `
  3226  				node_name = "node1"
  3227  
  3228  				# Explicit test because proxies inheriting this value must have a health
  3229  				# check on a different IP.
  3230  				bind_addr = "0.0.0.0"
  3231  
  3232  				connect {
  3233  					proxy_defaults {
  3234  						exec_mode = "script"
  3235  						daemon_command = ["foo", "bar"]
  3236  						script_command = ["bar", "foo"]
  3237  					}
  3238  				}
  3239  
  3240  				ports {
  3241  					proxy_min_port = 20000
  3242  					proxy_max_port = 20000
  3243  				}
  3244  			`)
  3245  			defer a.Shutdown()
  3246  
  3247  			// Register a target service we can use
  3248  			reg := &structs.NodeService{
  3249  				Service: "web",
  3250  				Port:    8080,
  3251  			}
  3252  			require.NoError(a.AddService(reg, nil, false, "", ConfigSourceLocal))
  3253  
  3254  			err := a.AddProxy(tt.proxy, false, false, "", ConfigSourceLocal)
  3255  			if tt.wantErr {
  3256  				require.Error(err)
  3257  				return
  3258  			}
  3259  			require.NoError(err)
  3260  
  3261  			// Test the ID was created as we expect.
  3262  			got := a.State.Proxy("web-proxy")
  3263  			wantProxy := tt.wantProxy
  3264  			if wantProxy == nil {
  3265  				wantProxy = tt.proxy
  3266  			}
  3267  			wantProxy.ProxyService = got.Proxy.ProxyService
  3268  			require.Equal(wantProxy, got.Proxy)
  3269  
  3270  			// Ensure a TCP check was created for the service.
  3271  			gotCheck := a.State.Check("service:web-proxy")
  3272  			if tt.wantTCPCheck == "" {
  3273  				require.Nil(gotCheck)
  3274  			} else {
  3275  				require.NotNil(gotCheck)
  3276  				require.Equal("Connect Proxy Listening", gotCheck.Name)
  3277  
  3278  				// Confusingly, a.State.Check("service:web-proxy") will return the state
  3279  				// but it's Definition field will be empty. This appears to be expected
  3280  				// when adding Checks as part of `AddService`. Notice how `AddService`
  3281  				// tests in this file don't assert on that state but instead look at the
  3282  				// agent's check state directly to ensure the right thing was registered.
  3283  				// We'll do the same for now.
  3284  				gotTCP, ok := a.checkTCPs["service:web-proxy"]
  3285  				require.True(ok)
  3286  				require.Equal(tt.wantTCPCheck, gotTCP.TCP)
  3287  				require.Equal(10*time.Second, gotTCP.Interval)
  3288  			}
  3289  		})
  3290  	}
  3291  }
  3292  
  3293  func TestAgent_RemoveProxy(t *testing.T) {
  3294  	t.Parallel()
  3295  	a := NewTestAgent(t, t.Name(), `
  3296  		node_name = "node1"
  3297  	`)
  3298  	defer a.Shutdown()
  3299  	require := require.New(t)
  3300  
  3301  	// Register a target service we can use
  3302  	reg := &structs.NodeService{
  3303  		Service: "web",
  3304  		Port:    8080,
  3305  	}
  3306  	require.NoError(a.AddService(reg, nil, false, "", ConfigSourceLocal))
  3307  
  3308  	// Add a proxy for web
  3309  	pReg := &structs.ConnectManagedProxy{
  3310  		TargetServiceID: "web",
  3311  		ExecMode:        structs.ProxyExecModeDaemon,
  3312  		Command:         []string{"foo"},
  3313  	}
  3314  	require.NoError(a.AddProxy(pReg, false, false, "", ConfigSourceLocal))
  3315  
  3316  	// Test the ID was created as we expect.
  3317  	gotProxy := a.State.Proxy("web-proxy")
  3318  	require.NotNil(gotProxy)
  3319  
  3320  	err := a.RemoveProxy("web-proxy", false)
  3321  	require.NoError(err)
  3322  
  3323  	gotProxy = a.State.Proxy("web-proxy")
  3324  	require.Nil(gotProxy)
  3325  	require.Nil(a.State.Service("web-proxy"), "web-proxy service")
  3326  
  3327  	// Removing invalid proxy should be an error
  3328  	err = a.RemoveProxy("foobar", false)
  3329  	require.Error(err)
  3330  }
  3331  
  3332  func TestAgent_ReLoadProxiesFromConfig(t *testing.T) {
  3333  	t.Parallel()
  3334  	a := NewTestAgent(t, t.Name(),
  3335  		`node_name = "node1"
  3336  	`)
  3337  	defer a.Shutdown()
  3338  	require := require.New(t)
  3339  
  3340  	// Register a target service we can use
  3341  	reg := &structs.NodeService{
  3342  		Service: "web",
  3343  		Port:    8080,
  3344  	}
  3345  	require.NoError(a.AddService(reg, nil, false, "", ConfigSourceLocal))
  3346  
  3347  	proxies := a.State.Proxies()
  3348  	require.Len(proxies, 0)
  3349  
  3350  	config := config.RuntimeConfig{
  3351  		Services: []*structs.ServiceDefinition{
  3352  			&structs.ServiceDefinition{
  3353  				Name: "web",
  3354  				Connect: &structs.ServiceConnect{
  3355  					Native: false,
  3356  					Proxy:  &structs.ServiceDefinitionConnectProxy{},
  3357  				},
  3358  			},
  3359  		},
  3360  	}
  3361  
  3362  	require.NoError(a.loadProxies(&config))
  3363  
  3364  	// ensure we loaded the proxy
  3365  	proxies = a.State.Proxies()
  3366  	require.Len(proxies, 1)
  3367  
  3368  	// store the auto-generated token
  3369  	ptok := ""
  3370  	pid := ""
  3371  	for id := range proxies {
  3372  		pid = id
  3373  		ptok = proxies[id].ProxyToken
  3374  		break
  3375  	}
  3376  
  3377  	// reload the proxies and ensure the proxy token is the same
  3378  	require.NoError(a.unloadProxies())
  3379  	proxies = a.State.Proxies()
  3380  	require.Len(proxies, 0)
  3381  	require.NoError(a.loadProxies(&config))
  3382  	proxies = a.State.Proxies()
  3383  	require.Len(proxies, 1)
  3384  	require.Equal(ptok, proxies[pid].ProxyToken)
  3385  
  3386  	// make sure when the config goes away so does the proxy
  3387  	require.NoError(a.unloadProxies())
  3388  	proxies = a.State.Proxies()
  3389  	require.Len(proxies, 0)
  3390  
  3391  	// a.config contains no services or proxies
  3392  	require.NoError(a.loadProxies(a.config))
  3393  	proxies = a.State.Proxies()
  3394  	require.Len(proxies, 0)
  3395  }
  3396  
  3397  func TestAgent_SetupProxyManager(t *testing.T) {
  3398  	t.Parallel()
  3399  	dataDir := testutil.TempDir(t, "agent") // we manage the data dir
  3400  	defer os.RemoveAll(dataDir)
  3401  	hcl := `
  3402  		ports { http = -1 }
  3403  		data_dir = "` + dataDir + `"
  3404  	`
  3405  	a, err := NewUnstartedAgent(t, t.Name(), hcl)
  3406  	require.NoError(t, err)
  3407  	require.Error(t, a.setupProxyManager(), "setupProxyManager should fail with invalid HTTP API config")
  3408  
  3409  	hcl = `
  3410  		ports { http = 8001 }
  3411  		data_dir = "` + dataDir + `"
  3412  	`
  3413  	a, err = NewUnstartedAgent(t, t.Name(), hcl)
  3414  	require.NoError(t, err)
  3415  	require.NoError(t, a.setupProxyManager())
  3416  }
  3417  
  3418  func TestAgent_loadTokens(t *testing.T) {
  3419  	t.Parallel()
  3420  	a := NewTestAgent(t, t.Name(), `
  3421  		acl = {
  3422  			enabled = true
  3423  			tokens = {
  3424  				agent = "alfa"
  3425  				agent_master = "bravo",
  3426  				default = "charlie"
  3427  				replication = "delta"
  3428  			}
  3429  		}
  3430  
  3431  	`)
  3432  	defer a.Shutdown()
  3433  	require := require.New(t)
  3434  
  3435  	tokensFullPath := filepath.Join(a.config.DataDir, tokensPath)
  3436  
  3437  	t.Run("original-configuration", func(t *testing.T) {
  3438  		require.Equal("alfa", a.tokens.AgentToken())
  3439  		require.Equal("bravo", a.tokens.AgentMasterToken())
  3440  		require.Equal("charlie", a.tokens.UserToken())
  3441  		require.Equal("delta", a.tokens.ReplicationToken())
  3442  	})
  3443  
  3444  	t.Run("updated-configuration", func(t *testing.T) {
  3445  		cfg := &config.RuntimeConfig{
  3446  			ACLToken:            "echo",
  3447  			ACLAgentToken:       "foxtrot",
  3448  			ACLAgentMasterToken: "golf",
  3449  			ACLReplicationToken: "hotel",
  3450  		}
  3451  		// ensures no error for missing persisted tokens file
  3452  		require.NoError(a.loadTokens(cfg))
  3453  		require.Equal("echo", a.tokens.UserToken())
  3454  		require.Equal("foxtrot", a.tokens.AgentToken())
  3455  		require.Equal("golf", a.tokens.AgentMasterToken())
  3456  		require.Equal("hotel", a.tokens.ReplicationToken())
  3457  	})
  3458  
  3459  	t.Run("persisted-tokens", func(t *testing.T) {
  3460  		cfg := &config.RuntimeConfig{
  3461  			ACLToken:            "echo",
  3462  			ACLAgentToken:       "foxtrot",
  3463  			ACLAgentMasterToken: "golf",
  3464  			ACLReplicationToken: "hotel",
  3465  		}
  3466  
  3467  		tokens := `{
  3468  			"agent" : "india",
  3469  			"agent_master" : "juliett",
  3470  			"default": "kilo",
  3471  			"replication" : "lima"
  3472  		}`
  3473  
  3474  		require.NoError(ioutil.WriteFile(tokensFullPath, []byte(tokens), 0600))
  3475  		require.NoError(a.loadTokens(cfg))
  3476  
  3477  		// no updates since token persistence is not enabled
  3478  		require.Equal("echo", a.tokens.UserToken())
  3479  		require.Equal("foxtrot", a.tokens.AgentToken())
  3480  		require.Equal("golf", a.tokens.AgentMasterToken())
  3481  		require.Equal("hotel", a.tokens.ReplicationToken())
  3482  
  3483  		a.config.ACLEnableTokenPersistence = true
  3484  		require.NoError(a.loadTokens(cfg))
  3485  
  3486  		require.Equal("india", a.tokens.AgentToken())
  3487  		require.Equal("juliett", a.tokens.AgentMasterToken())
  3488  		require.Equal("kilo", a.tokens.UserToken())
  3489  		require.Equal("lima", a.tokens.ReplicationToken())
  3490  	})
  3491  
  3492  	t.Run("persisted-tokens-override", func(t *testing.T) {
  3493  		tokens := `{
  3494  			"agent" : "mike",
  3495  			"agent_master" : "november",
  3496  			"default": "oscar",
  3497  			"replication" : "papa"
  3498  		}`
  3499  
  3500  		cfg := &config.RuntimeConfig{
  3501  			ACLToken:            "quebec",
  3502  			ACLAgentToken:       "romeo",
  3503  			ACLAgentMasterToken: "sierra",
  3504  			ACLReplicationToken: "tango",
  3505  		}
  3506  
  3507  		require.NoError(ioutil.WriteFile(tokensFullPath, []byte(tokens), 0600))
  3508  		require.NoError(a.loadTokens(cfg))
  3509  
  3510  		require.Equal("mike", a.tokens.AgentToken())
  3511  		require.Equal("november", a.tokens.AgentMasterToken())
  3512  		require.Equal("oscar", a.tokens.UserToken())
  3513  		require.Equal("papa", a.tokens.ReplicationToken())
  3514  	})
  3515  
  3516  	t.Run("partial-persisted", func(t *testing.T) {
  3517  		tokens := `{
  3518  			"agent" : "uniform",
  3519  			"agent_master" : "victor"
  3520  		}`
  3521  
  3522  		cfg := &config.RuntimeConfig{
  3523  			ACLToken:            "whiskey",
  3524  			ACLAgentToken:       "xray",
  3525  			ACLAgentMasterToken: "yankee",
  3526  			ACLReplicationToken: "zulu",
  3527  		}
  3528  
  3529  		require.NoError(ioutil.WriteFile(tokensFullPath, []byte(tokens), 0600))
  3530  		require.NoError(a.loadTokens(cfg))
  3531  
  3532  		require.Equal("uniform", a.tokens.AgentToken())
  3533  		require.Equal("victor", a.tokens.AgentMasterToken())
  3534  		require.Equal("whiskey", a.tokens.UserToken())
  3535  		require.Equal("zulu", a.tokens.ReplicationToken())
  3536  	})
  3537  
  3538  	t.Run("persistence-error-not-json", func(t *testing.T) {
  3539  		cfg := &config.RuntimeConfig{
  3540  			ACLToken:            "one",
  3541  			ACLAgentToken:       "two",
  3542  			ACLAgentMasterToken: "three",
  3543  			ACLReplicationToken: "four",
  3544  		}
  3545  
  3546  		require.NoError(ioutil.WriteFile(tokensFullPath, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 0600))
  3547  		err := a.loadTokens(cfg)
  3548  		require.Error(err)
  3549  
  3550  		require.Equal("one", a.tokens.UserToken())
  3551  		require.Equal("two", a.tokens.AgentToken())
  3552  		require.Equal("three", a.tokens.AgentMasterToken())
  3553  		require.Equal("four", a.tokens.ReplicationToken())
  3554  	})
  3555  
  3556  	t.Run("persistence-error-wrong-top-level", func(t *testing.T) {
  3557  		cfg := &config.RuntimeConfig{
  3558  			ACLToken:            "alfa",
  3559  			ACLAgentToken:       "bravo",
  3560  			ACLAgentMasterToken: "charlie",
  3561  			ACLReplicationToken: "foxtrot",
  3562  		}
  3563  
  3564  		require.NoError(ioutil.WriteFile(tokensFullPath, []byte("[1,2,3]"), 0600))
  3565  		err := a.loadTokens(cfg)
  3566  		require.Error(err)
  3567  
  3568  		require.Equal("alfa", a.tokens.UserToken())
  3569  		require.Equal("bravo", a.tokens.AgentToken())
  3570  		require.Equal("charlie", a.tokens.AgentMasterToken())
  3571  		require.Equal("foxtrot", a.tokens.ReplicationToken())
  3572  	})
  3573  }
  3574  
  3575  func TestAgent_ReloadConfigOutgoingRPCConfig(t *testing.T) {
  3576  	t.Parallel()
  3577  	dataDir := testutil.TempDir(t, "agent") // we manage the data dir
  3578  	defer os.RemoveAll(dataDir)
  3579  	hcl := `
  3580  		data_dir = "` + dataDir + `"
  3581  		verify_outgoing = true
  3582  		ca_file = "../test/ca/root.cer"
  3583  		cert_file = "../test/key/ourdomain.cer"
  3584  		key_file = "../test/key/ourdomain.key"
  3585  		verify_server_hostname = false
  3586  	`
  3587  	a := NewTestAgent(t, t.Name(), hcl)
  3588  	defer a.Shutdown()
  3589  	tlsConf := a.tlsConfigurator.OutgoingRPCConfig()
  3590  	require.True(t, tlsConf.InsecureSkipVerify)
  3591  	require.Len(t, tlsConf.ClientCAs.Subjects(), 1)
  3592  	require.Len(t, tlsConf.RootCAs.Subjects(), 1)
  3593  
  3594  	hcl = `
  3595  		data_dir = "` + dataDir + `"
  3596  		verify_outgoing = true
  3597  		ca_path = "../test/ca_path"
  3598  		cert_file = "../test/key/ourdomain.cer"
  3599  		key_file = "../test/key/ourdomain.key"
  3600  		verify_server_hostname = true
  3601  	`
  3602  	c := TestConfig(config.Source{Name: t.Name(), Format: "hcl", Data: hcl})
  3603  	require.NoError(t, a.ReloadConfig(c))
  3604  	tlsConf = a.tlsConfigurator.OutgoingRPCConfig()
  3605  	require.False(t, tlsConf.InsecureSkipVerify)
  3606  	require.Len(t, tlsConf.RootCAs.Subjects(), 2)
  3607  	require.Len(t, tlsConf.ClientCAs.Subjects(), 2)
  3608  }
  3609  
  3610  func TestAgent_ReloadConfigIncomingRPCConfig(t *testing.T) {
  3611  	t.Parallel()
  3612  	dataDir := testutil.TempDir(t, "agent") // we manage the data dir
  3613  	defer os.RemoveAll(dataDir)
  3614  	hcl := `
  3615  		data_dir = "` + dataDir + `"
  3616  		verify_outgoing = true
  3617  		ca_file = "../test/ca/root.cer"
  3618  		cert_file = "../test/key/ourdomain.cer"
  3619  		key_file = "../test/key/ourdomain.key"
  3620  		verify_server_hostname = false
  3621  	`
  3622  	a := NewTestAgent(t, t.Name(), hcl)
  3623  	defer a.Shutdown()
  3624  	tlsConf := a.tlsConfigurator.IncomingRPCConfig()
  3625  	require.NotNil(t, tlsConf.GetConfigForClient)
  3626  	tlsConf, err := tlsConf.GetConfigForClient(nil)
  3627  	require.NoError(t, err)
  3628  	require.NotNil(t, tlsConf)
  3629  	require.True(t, tlsConf.InsecureSkipVerify)
  3630  	require.Len(t, tlsConf.ClientCAs.Subjects(), 1)
  3631  	require.Len(t, tlsConf.RootCAs.Subjects(), 1)
  3632  
  3633  	hcl = `
  3634  		data_dir = "` + dataDir + `"
  3635  		verify_outgoing = true
  3636  		ca_path = "../test/ca_path"
  3637  		cert_file = "../test/key/ourdomain.cer"
  3638  		key_file = "../test/key/ourdomain.key"
  3639  		verify_server_hostname = true
  3640  	`
  3641  	c := TestConfig(config.Source{Name: t.Name(), Format: "hcl", Data: hcl})
  3642  	require.NoError(t, a.ReloadConfig(c))
  3643  	tlsConf, err = tlsConf.GetConfigForClient(nil)
  3644  	require.NoError(t, err)
  3645  	require.False(t, tlsConf.InsecureSkipVerify)
  3646  	require.Len(t, tlsConf.ClientCAs.Subjects(), 2)
  3647  	require.Len(t, tlsConf.RootCAs.Subjects(), 2)
  3648  }
  3649  
  3650  func TestAgent_ReloadConfigTLSConfigFailure(t *testing.T) {
  3651  	t.Parallel()
  3652  	dataDir := testutil.TempDir(t, "agent") // we manage the data dir
  3653  	defer os.RemoveAll(dataDir)
  3654  	hcl := `
  3655  		data_dir = "` + dataDir + `"
  3656  		verify_outgoing = true
  3657  		ca_file = "../test/ca/root.cer"
  3658  		cert_file = "../test/key/ourdomain.cer"
  3659  		key_file = "../test/key/ourdomain.key"
  3660  		verify_server_hostname = false
  3661  	`
  3662  	a := NewTestAgent(t, t.Name(), hcl)
  3663  	defer a.Shutdown()
  3664  	tlsConf := a.tlsConfigurator.IncomingRPCConfig()
  3665  
  3666  	hcl = `
  3667  		data_dir = "` + dataDir + `"
  3668  		verify_incoming = true
  3669  	`
  3670  	c := TestConfig(config.Source{Name: t.Name(), Format: "hcl", Data: hcl})
  3671  	require.Error(t, a.ReloadConfig(c))
  3672  	tlsConf, err := tlsConf.GetConfigForClient(nil)
  3673  	require.NoError(t, err)
  3674  	require.Equal(t, tls.NoClientCert, tlsConf.ClientAuth)
  3675  	require.Len(t, tlsConf.ClientCAs.Subjects(), 1)
  3676  	require.Len(t, tlsConf.RootCAs.Subjects(), 1)
  3677  }