github.com/maier/nomad@v0.4.1-0.20161110003312-a9e3d0b8549d/nomad/node_endpoint_test.go (about)

     1  package nomad
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/hashicorp/net-rpc-msgpackrpc"
    11  	"github.com/hashicorp/nomad/nomad/mock"
    12  	"github.com/hashicorp/nomad/nomad/structs"
    13  	"github.com/hashicorp/nomad/testutil"
    14  	vapi "github.com/hashicorp/vault/api"
    15  )
    16  
    17  func TestClientEndpoint_Register(t *testing.T) {
    18  	s1 := testServer(t, nil)
    19  	defer s1.Shutdown()
    20  	codec := rpcClient(t, s1)
    21  	testutil.WaitForLeader(t, s1.RPC)
    22  
    23  	// Create the register request
    24  	node := mock.Node()
    25  	req := &structs.NodeRegisterRequest{
    26  		Node:         node,
    27  		WriteRequest: structs.WriteRequest{Region: "global"},
    28  	}
    29  
    30  	// Fetch the response
    31  	var resp structs.GenericResponse
    32  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", req, &resp); err != nil {
    33  		t.Fatalf("err: %v", err)
    34  	}
    35  	if resp.Index == 0 {
    36  		t.Fatalf("bad index: %d", resp.Index)
    37  	}
    38  
    39  	// Check for the node in the FSM
    40  	state := s1.fsm.State()
    41  	out, err := state.NodeByID(node.ID)
    42  	if err != nil {
    43  		t.Fatalf("err: %v", err)
    44  	}
    45  	if out == nil {
    46  		t.Fatalf("expected node")
    47  	}
    48  	if out.CreateIndex != resp.Index {
    49  		t.Fatalf("index mis-match")
    50  	}
    51  	if out.ComputedClass == "" {
    52  		t.Fatal("ComputedClass not set")
    53  	}
    54  }
    55  
    56  func TestClientEndpoint_Register_NoSecret(t *testing.T) {
    57  	s1 := testServer(t, nil)
    58  	defer s1.Shutdown()
    59  	codec := rpcClient(t, s1)
    60  	testutil.WaitForLeader(t, s1.RPC)
    61  
    62  	// Create the register request
    63  	node := mock.Node()
    64  	node.SecretID = ""
    65  	req := &structs.NodeRegisterRequest{
    66  		Node:         node,
    67  		WriteRequest: structs.WriteRequest{Region: "global"},
    68  	}
    69  
    70  	// Fetch the response
    71  	var resp structs.GenericResponse
    72  	err := msgpackrpc.CallWithCodec(codec, "Node.Register", req, &resp)
    73  	if err == nil || !strings.Contains(err.Error(), "secret") {
    74  		t.Fatalf("Expecting error regarding missing secret id: %v", err)
    75  	}
    76  
    77  	// Update the node to be pre-0.5
    78  	node.Attributes["nomad.version"] = "0.4.1"
    79  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", req, &resp); err != nil {
    80  		t.Fatalf("Not expecting err: %v", err)
    81  	}
    82  	if resp.Index == 0 {
    83  		t.Fatalf("bad index: %d", resp.Index)
    84  	}
    85  
    86  	// Check for the node in the FSM
    87  	state := s1.fsm.State()
    88  	out, err := state.NodeByID(node.ID)
    89  	if err != nil {
    90  		t.Fatalf("err: %v", err)
    91  	}
    92  	if out == nil {
    93  		t.Fatalf("expected node")
    94  	}
    95  	if out.CreateIndex != resp.Index {
    96  		t.Fatalf("index mis-match")
    97  	}
    98  	if out.ComputedClass == "" {
    99  		t.Fatal("ComputedClass not set")
   100  	}
   101  }
   102  
   103  func TestClientEndpoint_Register_SecretMismatch(t *testing.T) {
   104  	s1 := testServer(t, nil)
   105  	defer s1.Shutdown()
   106  	codec := rpcClient(t, s1)
   107  	testutil.WaitForLeader(t, s1.RPC)
   108  
   109  	// Create the register request
   110  	node := mock.Node()
   111  	req := &structs.NodeRegisterRequest{
   112  		Node:         node,
   113  		WriteRequest: structs.WriteRequest{Region: "global"},
   114  	}
   115  
   116  	// Fetch the response
   117  	var resp structs.GenericResponse
   118  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", req, &resp); err != nil {
   119  		t.Fatalf("err: %v", err)
   120  	}
   121  
   122  	// Update the nodes SecretID
   123  	node.SecretID = structs.GenerateUUID()
   124  	err := msgpackrpc.CallWithCodec(codec, "Node.Register", req, &resp)
   125  	if err == nil || !strings.Contains(err.Error(), "Not registering") {
   126  		t.Fatalf("Expecting error regarding mismatching secret id", err)
   127  	}
   128  }
   129  
   130  func TestClientEndpoint_Deregister(t *testing.T) {
   131  	s1 := testServer(t, nil)
   132  	defer s1.Shutdown()
   133  	codec := rpcClient(t, s1)
   134  	testutil.WaitForLeader(t, s1.RPC)
   135  
   136  	// Create the register request
   137  	node := mock.Node()
   138  	reg := &structs.NodeRegisterRequest{
   139  		Node:         node,
   140  		WriteRequest: structs.WriteRequest{Region: "global"},
   141  	}
   142  
   143  	// Fetch the response
   144  	var resp structs.GenericResponse
   145  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   146  		t.Fatalf("err: %v", err)
   147  	}
   148  
   149  	// Deregister
   150  	dereg := &structs.NodeDeregisterRequest{
   151  		NodeID:       node.ID,
   152  		WriteRequest: structs.WriteRequest{Region: "global"},
   153  	}
   154  	var resp2 structs.GenericResponse
   155  	if err := msgpackrpc.CallWithCodec(codec, "Node.Deregister", dereg, &resp2); err != nil {
   156  		t.Fatalf("err: %v", err)
   157  	}
   158  	if resp2.Index == 0 {
   159  		t.Fatalf("bad index: %d", resp2.Index)
   160  	}
   161  
   162  	// Check for the node in the FSM
   163  	state := s1.fsm.State()
   164  	out, err := state.NodeByID(node.ID)
   165  	if err != nil {
   166  		t.Fatalf("err: %v", err)
   167  	}
   168  	if out != nil {
   169  		t.Fatalf("unexpected node")
   170  	}
   171  }
   172  
   173  func TestClientEndpoint_Deregister_Vault(t *testing.T) {
   174  	s1 := testServer(t, nil)
   175  	defer s1.Shutdown()
   176  	codec := rpcClient(t, s1)
   177  	testutil.WaitForLeader(t, s1.RPC)
   178  
   179  	// Create the register request
   180  	node := mock.Node()
   181  	reg := &structs.NodeRegisterRequest{
   182  		Node:         node,
   183  		WriteRequest: structs.WriteRequest{Region: "global"},
   184  	}
   185  
   186  	// Fetch the response
   187  	var resp structs.GenericResponse
   188  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   189  		t.Fatalf("err: %v", err)
   190  	}
   191  
   192  	// Swap the servers Vault Client
   193  	tvc := &TestVaultClient{}
   194  	s1.vault = tvc
   195  
   196  	// Put some Vault accessors in the state store for that node
   197  	state := s1.fsm.State()
   198  	va1 := mock.VaultAccessor()
   199  	va1.NodeID = node.ID
   200  	va2 := mock.VaultAccessor()
   201  	va2.NodeID = node.ID
   202  	state.UpsertVaultAccessor(100, []*structs.VaultAccessor{va1, va2})
   203  
   204  	// Deregister
   205  	dereg := &structs.NodeDeregisterRequest{
   206  		NodeID:       node.ID,
   207  		WriteRequest: structs.WriteRequest{Region: "global"},
   208  	}
   209  	var resp2 structs.GenericResponse
   210  	if err := msgpackrpc.CallWithCodec(codec, "Node.Deregister", dereg, &resp2); err != nil {
   211  		t.Fatalf("err: %v", err)
   212  	}
   213  	if resp2.Index == 0 {
   214  		t.Fatalf("bad index: %d", resp2.Index)
   215  	}
   216  
   217  	// Check for the node in the FSM
   218  	out, err := state.NodeByID(node.ID)
   219  	if err != nil {
   220  		t.Fatalf("err: %v", err)
   221  	}
   222  	if out != nil {
   223  		t.Fatalf("unexpected node")
   224  	}
   225  
   226  	// Check that the endpoint revoked the tokens
   227  	if l := len(tvc.RevokedTokens); l != 2 {
   228  		t.Fatalf("Deregister revoked %d tokens; want 2", l)
   229  	}
   230  }
   231  
   232  func TestClientEndpoint_UpdateStatus(t *testing.T) {
   233  	s1 := testServer(t, nil)
   234  	defer s1.Shutdown()
   235  	codec := rpcClient(t, s1)
   236  	testutil.WaitForLeader(t, s1.RPC)
   237  
   238  	// Create the register request
   239  	node := mock.Node()
   240  	reg := &structs.NodeRegisterRequest{
   241  		Node:         node,
   242  		WriteRequest: structs.WriteRequest{Region: "global"},
   243  	}
   244  
   245  	// Fetch the response
   246  	var resp structs.NodeUpdateResponse
   247  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   248  		t.Fatalf("err: %v", err)
   249  	}
   250  
   251  	// Check for heartbeat interval
   252  	ttl := resp.HeartbeatTTL
   253  	if ttl < s1.config.MinHeartbeatTTL || ttl > 2*s1.config.MinHeartbeatTTL {
   254  		t.Fatalf("bad: %#v", ttl)
   255  	}
   256  
   257  	// Update the status
   258  	dereg := &structs.NodeUpdateStatusRequest{
   259  		NodeID:       node.ID,
   260  		Status:       structs.NodeStatusInit,
   261  		WriteRequest: structs.WriteRequest{Region: "global"},
   262  	}
   263  	var resp2 structs.NodeUpdateResponse
   264  	if err := msgpackrpc.CallWithCodec(codec, "Node.UpdateStatus", dereg, &resp2); err != nil {
   265  		t.Fatalf("err: %v", err)
   266  	}
   267  	if resp2.Index == 0 {
   268  		t.Fatalf("bad index: %d", resp2.Index)
   269  	}
   270  
   271  	// Check for heartbeat interval
   272  	ttl = resp2.HeartbeatTTL
   273  	if ttl < s1.config.MinHeartbeatTTL || ttl > 2*s1.config.MinHeartbeatTTL {
   274  		t.Fatalf("bad: %#v", ttl)
   275  	}
   276  
   277  	// Check for the node in the FSM
   278  	state := s1.fsm.State()
   279  	out, err := state.NodeByID(node.ID)
   280  	if err != nil {
   281  		t.Fatalf("err: %v", err)
   282  	}
   283  	if out == nil {
   284  		t.Fatalf("expected node")
   285  	}
   286  	if out.ModifyIndex != resp2.Index {
   287  		t.Fatalf("index mis-match")
   288  	}
   289  }
   290  
   291  func TestClientEndpoint_UpdateStatus_Vault(t *testing.T) {
   292  	s1 := testServer(t, nil)
   293  	defer s1.Shutdown()
   294  	codec := rpcClient(t, s1)
   295  	testutil.WaitForLeader(t, s1.RPC)
   296  
   297  	// Create the register request
   298  	node := mock.Node()
   299  	reg := &structs.NodeRegisterRequest{
   300  		Node:         node,
   301  		WriteRequest: structs.WriteRequest{Region: "global"},
   302  	}
   303  
   304  	// Fetch the response
   305  	var resp structs.NodeUpdateResponse
   306  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   307  		t.Fatalf("err: %v", err)
   308  	}
   309  
   310  	// Check for heartbeat interval
   311  	ttl := resp.HeartbeatTTL
   312  	if ttl < s1.config.MinHeartbeatTTL || ttl > 2*s1.config.MinHeartbeatTTL {
   313  		t.Fatalf("bad: %#v", ttl)
   314  	}
   315  
   316  	// Swap the servers Vault Client
   317  	tvc := &TestVaultClient{}
   318  	s1.vault = tvc
   319  
   320  	// Put some Vault accessors in the state store for that node
   321  	state := s1.fsm.State()
   322  	va1 := mock.VaultAccessor()
   323  	va1.NodeID = node.ID
   324  	va2 := mock.VaultAccessor()
   325  	va2.NodeID = node.ID
   326  	state.UpsertVaultAccessor(100, []*structs.VaultAccessor{va1, va2})
   327  
   328  	// Update the status to be down
   329  	dereg := &structs.NodeUpdateStatusRequest{
   330  		NodeID:       node.ID,
   331  		Status:       structs.NodeStatusDown,
   332  		WriteRequest: structs.WriteRequest{Region: "global"},
   333  	}
   334  	var resp2 structs.NodeUpdateResponse
   335  	if err := msgpackrpc.CallWithCodec(codec, "Node.UpdateStatus", dereg, &resp2); err != nil {
   336  		t.Fatalf("err: %v", err)
   337  	}
   338  	if resp2.Index == 0 {
   339  		t.Fatalf("bad index: %d", resp2.Index)
   340  	}
   341  
   342  	// Check that the endpoint revoked the tokens
   343  	if l := len(tvc.RevokedTokens); l != 2 {
   344  		t.Fatalf("Deregister revoked %d tokens; want 2", l)
   345  	}
   346  }
   347  
   348  func TestClientEndpoint_Register_GetEvals(t *testing.T) {
   349  	s1 := testServer(t, nil)
   350  	defer s1.Shutdown()
   351  	codec := rpcClient(t, s1)
   352  	testutil.WaitForLeader(t, s1.RPC)
   353  
   354  	// Register a system job.
   355  	job := mock.SystemJob()
   356  	state := s1.fsm.State()
   357  	if err := state.UpsertJob(1, job); err != nil {
   358  		t.Fatalf("err: %v", err)
   359  	}
   360  
   361  	// Create the register request going directly to ready
   362  	node := mock.Node()
   363  	node.Status = structs.NodeStatusReady
   364  	reg := &structs.NodeRegisterRequest{
   365  		Node:         node,
   366  		WriteRequest: structs.WriteRequest{Region: "global"},
   367  	}
   368  
   369  	// Fetch the response
   370  	var resp structs.NodeUpdateResponse
   371  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   372  		t.Fatalf("err: %v", err)
   373  	}
   374  
   375  	// Check for heartbeat interval
   376  	ttl := resp.HeartbeatTTL
   377  	if ttl < s1.config.MinHeartbeatTTL || ttl > 2*s1.config.MinHeartbeatTTL {
   378  		t.Fatalf("bad: %#v", ttl)
   379  	}
   380  
   381  	// Check for an eval caused by the system job.
   382  	if len(resp.EvalIDs) != 1 {
   383  		t.Fatalf("expected one eval; got %#v", resp.EvalIDs)
   384  	}
   385  
   386  	evalID := resp.EvalIDs[0]
   387  	eval, err := state.EvalByID(evalID)
   388  	if err != nil {
   389  		t.Fatalf("could not get eval %v", evalID)
   390  	}
   391  
   392  	if eval.Type != "system" {
   393  		t.Fatalf("unexpected eval type; got %v; want %q", eval.Type, "system")
   394  	}
   395  
   396  	// Check for the node in the FSM
   397  	out, err := state.NodeByID(node.ID)
   398  	if err != nil {
   399  		t.Fatalf("err: %v", err)
   400  	}
   401  	if out == nil {
   402  		t.Fatalf("expected node")
   403  	}
   404  	if out.ModifyIndex != resp.Index {
   405  		t.Fatalf("index mis-match")
   406  	}
   407  
   408  	// Transistion it to down and then ready
   409  	node.Status = structs.NodeStatusDown
   410  	reg = &structs.NodeRegisterRequest{
   411  		Node:         node,
   412  		WriteRequest: structs.WriteRequest{Region: "global"},
   413  	}
   414  
   415  	// Fetch the response
   416  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   417  		t.Fatalf("err: %v", err)
   418  	}
   419  
   420  	if len(resp.EvalIDs) != 1 {
   421  		t.Fatalf("expected one eval; got %#v", resp.EvalIDs)
   422  	}
   423  
   424  	node.Status = structs.NodeStatusReady
   425  	reg = &structs.NodeRegisterRequest{
   426  		Node:         node,
   427  		WriteRequest: structs.WriteRequest{Region: "global"},
   428  	}
   429  
   430  	// Fetch the response
   431  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   432  		t.Fatalf("err: %v", err)
   433  	}
   434  
   435  	if len(resp.EvalIDs) != 1 {
   436  		t.Fatalf("expected one eval; got %#v", resp.EvalIDs)
   437  	}
   438  }
   439  
   440  func TestClientEndpoint_UpdateStatus_GetEvals(t *testing.T) {
   441  	s1 := testServer(t, nil)
   442  	defer s1.Shutdown()
   443  	codec := rpcClient(t, s1)
   444  	testutil.WaitForLeader(t, s1.RPC)
   445  
   446  	// Register a system job.
   447  	job := mock.SystemJob()
   448  	state := s1.fsm.State()
   449  	if err := state.UpsertJob(1, job); err != nil {
   450  		t.Fatalf("err: %v", err)
   451  	}
   452  
   453  	// Create the register request
   454  	node := mock.Node()
   455  	node.Status = structs.NodeStatusInit
   456  	reg := &structs.NodeRegisterRequest{
   457  		Node:         node,
   458  		WriteRequest: structs.WriteRequest{Region: "global"},
   459  	}
   460  
   461  	// Fetch the response
   462  	var resp structs.NodeUpdateResponse
   463  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   464  		t.Fatalf("err: %v", err)
   465  	}
   466  
   467  	// Check for heartbeat interval
   468  	ttl := resp.HeartbeatTTL
   469  	if ttl < s1.config.MinHeartbeatTTL || ttl > 2*s1.config.MinHeartbeatTTL {
   470  		t.Fatalf("bad: %#v", ttl)
   471  	}
   472  
   473  	// Update the status
   474  	update := &structs.NodeUpdateStatusRequest{
   475  		NodeID:       node.ID,
   476  		Status:       structs.NodeStatusReady,
   477  		WriteRequest: structs.WriteRequest{Region: "global"},
   478  	}
   479  	var resp2 structs.NodeUpdateResponse
   480  	if err := msgpackrpc.CallWithCodec(codec, "Node.UpdateStatus", update, &resp2); err != nil {
   481  		t.Fatalf("err: %v", err)
   482  	}
   483  	if resp2.Index == 0 {
   484  		t.Fatalf("bad index: %d", resp2.Index)
   485  	}
   486  
   487  	// Check for an eval caused by the system job.
   488  	if len(resp2.EvalIDs) != 1 {
   489  		t.Fatalf("expected one eval; got %#v", resp2.EvalIDs)
   490  	}
   491  
   492  	evalID := resp2.EvalIDs[0]
   493  	eval, err := state.EvalByID(evalID)
   494  	if err != nil {
   495  		t.Fatalf("could not get eval %v", evalID)
   496  	}
   497  
   498  	if eval.Type != "system" {
   499  		t.Fatalf("unexpected eval type; got %v; want %q", eval.Type, "system")
   500  	}
   501  
   502  	// Check for heartbeat interval
   503  	ttl = resp2.HeartbeatTTL
   504  	if ttl < s1.config.MinHeartbeatTTL || ttl > 2*s1.config.MinHeartbeatTTL {
   505  		t.Fatalf("bad: %#v", ttl)
   506  	}
   507  
   508  	// Check for the node in the FSM
   509  	out, err := state.NodeByID(node.ID)
   510  	if err != nil {
   511  		t.Fatalf("err: %v", err)
   512  	}
   513  	if out == nil {
   514  		t.Fatalf("expected node")
   515  	}
   516  	if out.ModifyIndex != resp2.Index {
   517  		t.Fatalf("index mis-match")
   518  	}
   519  }
   520  
   521  func TestClientEndpoint_UpdateStatus_HeartbeatOnly(t *testing.T) {
   522  	s1 := testServer(t, nil)
   523  	defer s1.Shutdown()
   524  
   525  	s2 := testServer(t, func(c *Config) {
   526  		c.DevDisableBootstrap = true
   527  	})
   528  	defer s2.Shutdown()
   529  
   530  	s3 := testServer(t, func(c *Config) {
   531  		c.DevDisableBootstrap = true
   532  	})
   533  	defer s3.Shutdown()
   534  	servers := []*Server{s1, s2, s3}
   535  	testJoin(t, s1, s2, s3)
   536  
   537  	for _, s := range servers {
   538  		testutil.WaitForResult(func() (bool, error) {
   539  			peers, _ := s.raftPeers.Peers()
   540  			return len(peers) == 3, nil
   541  		}, func(err error) {
   542  			t.Fatalf("should have 3 peers")
   543  		})
   544  	}
   545  
   546  	codec := rpcClient(t, s1)
   547  	testutil.WaitForLeader(t, s1.RPC)
   548  
   549  	// Create the register request
   550  	node := mock.Node()
   551  	reg := &structs.NodeRegisterRequest{
   552  		Node:         node,
   553  		WriteRequest: structs.WriteRequest{Region: "global"},
   554  	}
   555  
   556  	// Fetch the response
   557  	var resp structs.NodeUpdateResponse
   558  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   559  		t.Fatalf("err: %v", err)
   560  	}
   561  
   562  	// Check for heartbeat interval
   563  	ttl := resp.HeartbeatTTL
   564  	if ttl < s1.config.MinHeartbeatTTL || ttl > 2*s1.config.MinHeartbeatTTL {
   565  		t.Fatalf("bad: %#v", ttl)
   566  	}
   567  
   568  	// Check for heartbeat servers
   569  	serverAddrs := resp.Servers
   570  	if len(serverAddrs) == 0 {
   571  		t.Fatalf("bad: %#v", serverAddrs)
   572  	}
   573  
   574  	// Update the status, static state
   575  	dereg := &structs.NodeUpdateStatusRequest{
   576  		NodeID:       node.ID,
   577  		Status:       node.Status,
   578  		WriteRequest: structs.WriteRequest{Region: "global"},
   579  	}
   580  	var resp2 structs.NodeUpdateResponse
   581  	if err := msgpackrpc.CallWithCodec(codec, "Node.UpdateStatus", dereg, &resp2); err != nil {
   582  		t.Fatalf("err: %v", err)
   583  	}
   584  	if resp2.Index != 0 {
   585  		t.Fatalf("bad index: %d", resp2.Index)
   586  	}
   587  
   588  	// Check for heartbeat interval
   589  	ttl = resp2.HeartbeatTTL
   590  	if ttl < s1.config.MinHeartbeatTTL || ttl > 2*s1.config.MinHeartbeatTTL {
   591  		t.Fatalf("bad: %#v", ttl)
   592  	}
   593  }
   594  
   595  func TestClientEndpoint_UpdateDrain(t *testing.T) {
   596  	s1 := testServer(t, nil)
   597  	defer s1.Shutdown()
   598  	codec := rpcClient(t, s1)
   599  	testutil.WaitForLeader(t, s1.RPC)
   600  
   601  	// Create the register request
   602  	node := mock.Node()
   603  	reg := &structs.NodeRegisterRequest{
   604  		Node:         node,
   605  		WriteRequest: structs.WriteRequest{Region: "global"},
   606  	}
   607  
   608  	// Fetch the response
   609  	var resp structs.NodeUpdateResponse
   610  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   611  		t.Fatalf("err: %v", err)
   612  	}
   613  
   614  	// Update the status
   615  	dereg := &structs.NodeUpdateDrainRequest{
   616  		NodeID:       node.ID,
   617  		Drain:        true,
   618  		WriteRequest: structs.WriteRequest{Region: "global"},
   619  	}
   620  	var resp2 structs.NodeDrainUpdateResponse
   621  	if err := msgpackrpc.CallWithCodec(codec, "Node.UpdateDrain", dereg, &resp2); err != nil {
   622  		t.Fatalf("err: %v", err)
   623  	}
   624  	if resp2.Index == 0 {
   625  		t.Fatalf("bad index: %d", resp2.Index)
   626  	}
   627  
   628  	// Check for the node in the FSM
   629  	state := s1.fsm.State()
   630  	out, err := state.NodeByID(node.ID)
   631  	if err != nil {
   632  		t.Fatalf("err: %v", err)
   633  	}
   634  	if !out.Drain {
   635  		t.Fatalf("bad: %#v", out)
   636  	}
   637  }
   638  
   639  // This test ensures that Nomad marks client state of allocations which are in
   640  // pending/running state to lost when a node is marked as down.
   641  func TestClientEndpoint_Drain_Down(t *testing.T) {
   642  	s1 := testServer(t, nil)
   643  	defer s1.Shutdown()
   644  	codec := rpcClient(t, s1)
   645  	testutil.WaitForLeader(t, s1.RPC)
   646  
   647  	// Register a node
   648  	node := mock.Node()
   649  	reg := &structs.NodeRegisterRequest{
   650  		Node:         node,
   651  		WriteRequest: structs.WriteRequest{Region: "global"},
   652  	}
   653  	// Fetch the response
   654  	var resp structs.NodeUpdateResponse
   655  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   656  		t.Fatalf("err: %v", err)
   657  	}
   658  
   659  	// Register a service job
   660  	var jobResp structs.JobRegisterResponse
   661  	job := mock.Job()
   662  	job.TaskGroups[0].Count = 1
   663  	jobReq := &structs.JobRegisterRequest{
   664  		Job:          job,
   665  		WriteRequest: structs.WriteRequest{Region: "global"},
   666  	}
   667  	if err := msgpackrpc.CallWithCodec(codec, "Job.Register", jobReq, &jobResp); err != nil {
   668  		t.Fatalf("err: %v", err)
   669  	}
   670  
   671  	// Register a system job
   672  	var jobResp1 structs.JobRegisterResponse
   673  	job1 := mock.Job()
   674  	job1.TaskGroups[0].Count = 1
   675  	job1.Type = structs.JobTypeSystem
   676  	jobReq1 := &structs.JobRegisterRequest{
   677  		Job:          job1,
   678  		WriteRequest: structs.WriteRequest{Region: "global"},
   679  	}
   680  	if err := msgpackrpc.CallWithCodec(codec, "Job.Register", jobReq1, &jobResp1); err != nil {
   681  		t.Fatalf("err: %v", err)
   682  	}
   683  
   684  	// Wait for the scheduler to create an allocation
   685  	testutil.WaitForResult(func() (bool, error) {
   686  		allocs, err := s1.fsm.state.AllocsByJob(job.ID)
   687  		if err != nil {
   688  			return false, err
   689  		}
   690  		allocs1, err := s1.fsm.state.AllocsByJob(job1.ID)
   691  		if err != nil {
   692  			return false, err
   693  		}
   694  		return len(allocs) > 0 && len(allocs1) > 0, nil
   695  	}, func(err error) {
   696  		t.Fatalf("err: %v", err)
   697  	})
   698  
   699  	// Drain the node
   700  	dereg := &structs.NodeUpdateDrainRequest{
   701  		NodeID:       node.ID,
   702  		Drain:        true,
   703  		WriteRequest: structs.WriteRequest{Region: "global"},
   704  	}
   705  	var resp2 structs.NodeDrainUpdateResponse
   706  	if err := msgpackrpc.CallWithCodec(codec, "Node.UpdateDrain", dereg, &resp2); err != nil {
   707  		t.Fatalf("err: %v", err)
   708  	}
   709  
   710  	// Mark the node as down
   711  	node.Status = structs.NodeStatusDown
   712  	reg = &structs.NodeRegisterRequest{
   713  		Node:         node,
   714  		WriteRequest: structs.WriteRequest{Region: "global"},
   715  	}
   716  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   717  		t.Fatalf("err: %v", err)
   718  	}
   719  
   720  	// Ensure that the allocation has transitioned to lost
   721  	testutil.WaitForResult(func() (bool, error) {
   722  		summary, err := s1.fsm.state.JobSummaryByID(job.ID)
   723  		if err != nil {
   724  			return false, err
   725  		}
   726  		expectedSummary := &structs.JobSummary{
   727  			JobID: job.ID,
   728  			Summary: map[string]structs.TaskGroupSummary{
   729  				"web": structs.TaskGroupSummary{
   730  					Queued: 1,
   731  					Lost:   1,
   732  				},
   733  			},
   734  			CreateIndex: jobResp.JobModifyIndex,
   735  			ModifyIndex: summary.ModifyIndex,
   736  		}
   737  		if !reflect.DeepEqual(summary, expectedSummary) {
   738  			return false, fmt.Errorf("expected: %#v, actual: %#v", expectedSummary, summary)
   739  		}
   740  
   741  		summary1, err := s1.fsm.state.JobSummaryByID(job1.ID)
   742  		if err != nil {
   743  			return false, err
   744  		}
   745  		expectedSummary1 := &structs.JobSummary{
   746  			JobID: job1.ID,
   747  			Summary: map[string]structs.TaskGroupSummary{
   748  				"web": structs.TaskGroupSummary{
   749  					Lost: 1,
   750  				},
   751  			},
   752  			CreateIndex: jobResp1.JobModifyIndex,
   753  			ModifyIndex: summary1.ModifyIndex,
   754  		}
   755  		if !reflect.DeepEqual(summary1, expectedSummary1) {
   756  			return false, fmt.Errorf("expected: %#v, actual: %#v", expectedSummary1, summary1)
   757  		}
   758  		return true, nil
   759  	}, func(err error) {
   760  		t.Fatalf("err: %v", err)
   761  	})
   762  }
   763  
   764  func TestClientEndpoint_GetNode(t *testing.T) {
   765  	s1 := testServer(t, nil)
   766  	defer s1.Shutdown()
   767  	codec := rpcClient(t, s1)
   768  	testutil.WaitForLeader(t, s1.RPC)
   769  
   770  	// Create the register request
   771  	node := mock.Node()
   772  	reg := &structs.NodeRegisterRequest{
   773  		Node:         node,
   774  		WriteRequest: structs.WriteRequest{Region: "global"},
   775  	}
   776  
   777  	// Fetch the response
   778  	var resp structs.GenericResponse
   779  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   780  		t.Fatalf("err: %v", err)
   781  	}
   782  	node.CreateIndex = resp.Index
   783  	node.ModifyIndex = resp.Index
   784  
   785  	// Lookup the node
   786  	get := &structs.NodeSpecificRequest{
   787  		NodeID:       node.ID,
   788  		QueryOptions: structs.QueryOptions{Region: "global"},
   789  	}
   790  	var resp2 structs.SingleNodeResponse
   791  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetNode", get, &resp2); err != nil {
   792  		t.Fatalf("err: %v", err)
   793  	}
   794  	if resp2.Index != resp.Index {
   795  		t.Fatalf("Bad index: %d %d", resp2.Index, resp.Index)
   796  	}
   797  
   798  	if resp2.Node.ComputedClass == "" {
   799  		t.Fatalf("bad ComputedClass: %#v", resp2.Node)
   800  	}
   801  
   802  	// Update the status updated at value
   803  	node.StatusUpdatedAt = resp2.Node.StatusUpdatedAt
   804  	node.SecretID = ""
   805  	if !reflect.DeepEqual(node, resp2.Node) {
   806  		t.Fatalf("bad: %#v \n %#v", node, resp2.Node)
   807  	}
   808  
   809  	// Lookup non-existing node
   810  	get.NodeID = "12345678-abcd-efab-cdef-123456789abc"
   811  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetNode", get, &resp2); err != nil {
   812  		t.Fatalf("err: %v", err)
   813  	}
   814  	if resp2.Index != resp.Index {
   815  		t.Fatalf("Bad index: %d %d", resp2.Index, resp.Index)
   816  	}
   817  	if resp2.Node != nil {
   818  		t.Fatalf("unexpected node")
   819  	}
   820  }
   821  
   822  func TestClientEndpoint_GetNode_Blocking(t *testing.T) {
   823  	s1 := testServer(t, nil)
   824  	defer s1.Shutdown()
   825  	state := s1.fsm.State()
   826  	codec := rpcClient(t, s1)
   827  	testutil.WaitForLeader(t, s1.RPC)
   828  
   829  	// Create the node
   830  	node1 := mock.Node()
   831  	node2 := mock.Node()
   832  
   833  	// First create an unrelated node.
   834  	time.AfterFunc(100*time.Millisecond, func() {
   835  		if err := state.UpsertNode(100, node1); err != nil {
   836  			t.Fatalf("err: %v", err)
   837  		}
   838  	})
   839  
   840  	// Upsert the node we are watching later
   841  	time.AfterFunc(200*time.Millisecond, func() {
   842  		if err := state.UpsertNode(200, node2); err != nil {
   843  			t.Fatalf("err: %v", err)
   844  		}
   845  	})
   846  
   847  	// Lookup the node
   848  	req := &structs.NodeSpecificRequest{
   849  		NodeID: node2.ID,
   850  		QueryOptions: structs.QueryOptions{
   851  			Region:        "global",
   852  			MinQueryIndex: 50,
   853  		},
   854  	}
   855  	var resp structs.SingleNodeResponse
   856  	start := time.Now()
   857  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetNode", req, &resp); err != nil {
   858  		t.Fatalf("err: %v", err)
   859  	}
   860  
   861  	if elapsed := time.Since(start); elapsed < 200*time.Millisecond {
   862  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   863  	}
   864  	if resp.Index != 200 {
   865  		t.Fatalf("Bad index: %d %d", resp.Index, 200)
   866  	}
   867  	if resp.Node == nil || resp.Node.ID != node2.ID {
   868  		t.Fatalf("bad: %#v", resp.Node)
   869  	}
   870  
   871  	// Node update triggers watches
   872  	time.AfterFunc(100*time.Millisecond, func() {
   873  		nodeUpdate := mock.Node()
   874  		nodeUpdate.ID = node2.ID
   875  		nodeUpdate.Status = structs.NodeStatusDown
   876  		if err := state.UpsertNode(300, nodeUpdate); err != nil {
   877  			t.Fatalf("err: %v", err)
   878  		}
   879  	})
   880  
   881  	req.QueryOptions.MinQueryIndex = 250
   882  	var resp2 structs.SingleNodeResponse
   883  	start = time.Now()
   884  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetNode", req, &resp2); err != nil {
   885  		t.Fatalf("err: %v", err)
   886  	}
   887  
   888  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   889  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   890  	}
   891  	if resp2.Index != 300 {
   892  		t.Fatalf("Bad index: %d %d", resp2.Index, 300)
   893  	}
   894  	if resp2.Node == nil || resp2.Node.Status != structs.NodeStatusDown {
   895  		t.Fatalf("bad: %#v", resp2.Node)
   896  	}
   897  
   898  	// Node delete triggers watches
   899  	time.AfterFunc(100*time.Millisecond, func() {
   900  		if err := state.DeleteNode(400, node2.ID); err != nil {
   901  			t.Fatalf("err: %v", err)
   902  		}
   903  	})
   904  
   905  	req.QueryOptions.MinQueryIndex = 350
   906  	var resp3 structs.SingleNodeResponse
   907  	start = time.Now()
   908  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetNode", req, &resp3); err != nil {
   909  		t.Fatalf("err: %v", err)
   910  	}
   911  
   912  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   913  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   914  	}
   915  	if resp3.Index != 400 {
   916  		t.Fatalf("Bad index: %d %d", resp2.Index, 400)
   917  	}
   918  	if resp3.Node != nil {
   919  		t.Fatalf("bad: %#v", resp3.Node)
   920  	}
   921  }
   922  
   923  func TestClientEndpoint_GetAllocs(t *testing.T) {
   924  	s1 := testServer(t, nil)
   925  	defer s1.Shutdown()
   926  	codec := rpcClient(t, s1)
   927  	testutil.WaitForLeader(t, s1.RPC)
   928  
   929  	// Create the register request
   930  	node := mock.Node()
   931  	reg := &structs.NodeRegisterRequest{
   932  		Node:         node,
   933  		WriteRequest: structs.WriteRequest{Region: "global"},
   934  	}
   935  
   936  	// Fetch the response
   937  	var resp structs.GenericResponse
   938  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
   939  		t.Fatalf("err: %v", err)
   940  	}
   941  	node.CreateIndex = resp.Index
   942  	node.ModifyIndex = resp.Index
   943  
   944  	// Inject fake evaluations
   945  	alloc := mock.Alloc()
   946  	alloc.NodeID = node.ID
   947  	state := s1.fsm.State()
   948  	state.UpsertJobSummary(99, mock.JobSummary(alloc.JobID))
   949  	err := state.UpsertAllocs(100, []*structs.Allocation{alloc})
   950  	if err != nil {
   951  		t.Fatalf("err: %v", err)
   952  	}
   953  
   954  	// Lookup the allocs
   955  	get := &structs.NodeSpecificRequest{
   956  		NodeID:       node.ID,
   957  		QueryOptions: structs.QueryOptions{Region: "global"},
   958  	}
   959  	var resp2 structs.NodeAllocsResponse
   960  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetAllocs", get, &resp2); err != nil {
   961  		t.Fatalf("err: %v", err)
   962  	}
   963  	if resp2.Index != 100 {
   964  		t.Fatalf("Bad index: %d %d", resp2.Index, 100)
   965  	}
   966  
   967  	if len(resp2.Allocs) != 1 || resp2.Allocs[0].ID != alloc.ID {
   968  		t.Fatalf("bad: %#v", resp2.Allocs)
   969  	}
   970  
   971  	// Lookup non-existing node
   972  	get.NodeID = "foobarbaz"
   973  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetAllocs", get, &resp2); err != nil {
   974  		t.Fatalf("err: %v", err)
   975  	}
   976  	if resp2.Index != 100 {
   977  		t.Fatalf("Bad index: %d %d", resp2.Index, 100)
   978  	}
   979  	if len(resp2.Allocs) != 0 {
   980  		t.Fatalf("unexpected node")
   981  	}
   982  }
   983  
   984  func TestClientEndpoint_GetClientAllocs(t *testing.T) {
   985  	s1 := testServer(t, nil)
   986  	defer s1.Shutdown()
   987  	codec := rpcClient(t, s1)
   988  	testutil.WaitForLeader(t, s1.RPC)
   989  
   990  	// Create the register request
   991  	node := mock.Node()
   992  	reg := &structs.NodeRegisterRequest{
   993  		Node:         node,
   994  		WriteRequest: structs.WriteRequest{Region: "global"},
   995  	}
   996  
   997  	// Fetch the response
   998  	var resp structs.GenericResponse
   999  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
  1000  		t.Fatalf("err: %v", err)
  1001  	}
  1002  	node.CreateIndex = resp.Index
  1003  	node.ModifyIndex = resp.Index
  1004  
  1005  	// Inject fake evaluations
  1006  	alloc := mock.Alloc()
  1007  	alloc.NodeID = node.ID
  1008  	state := s1.fsm.State()
  1009  	state.UpsertJobSummary(99, mock.JobSummary(alloc.JobID))
  1010  	err := state.UpsertAllocs(100, []*structs.Allocation{alloc})
  1011  	if err != nil {
  1012  		t.Fatalf("err: %v", err)
  1013  	}
  1014  
  1015  	// Lookup the allocs
  1016  	get := &structs.NodeSpecificRequest{
  1017  		NodeID:       node.ID,
  1018  		SecretID:     node.SecretID,
  1019  		QueryOptions: structs.QueryOptions{Region: "global"},
  1020  	}
  1021  	var resp2 structs.NodeClientAllocsResponse
  1022  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetClientAllocs", get, &resp2); err != nil {
  1023  		t.Fatalf("err: %v", err)
  1024  	}
  1025  	if resp2.Index != 100 {
  1026  		t.Fatalf("Bad index: %d %d", resp2.Index, 100)
  1027  	}
  1028  
  1029  	if len(resp2.Allocs) != 1 || resp2.Allocs[alloc.ID] != 100 {
  1030  		t.Fatalf("bad: %#v", resp2.Allocs)
  1031  	}
  1032  
  1033  	// Lookup node with bad SecretID
  1034  	get.SecretID = "foobarbaz"
  1035  	var resp3 structs.NodeClientAllocsResponse
  1036  	err = msgpackrpc.CallWithCodec(codec, "Node.GetClientAllocs", get, &resp3)
  1037  	if err == nil || !strings.Contains(err.Error(), "does not match") {
  1038  		t.Fatalf("err: %v", err)
  1039  	}
  1040  
  1041  	// Lookup non-existing node
  1042  	get.NodeID = structs.GenerateUUID()
  1043  	var resp4 structs.NodeClientAllocsResponse
  1044  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetClientAllocs", get, &resp4); err != nil {
  1045  		t.Fatalf("err: %v", err)
  1046  	}
  1047  	if resp4.Index != 100 {
  1048  		t.Fatalf("Bad index: %d %d", resp3.Index, 100)
  1049  	}
  1050  	if len(resp4.Allocs) != 0 {
  1051  		t.Fatalf("unexpected node %#v", resp3.Allocs)
  1052  	}
  1053  }
  1054  
  1055  func TestClientEndpoint_GetClientAllocs_Blocking(t *testing.T) {
  1056  	s1 := testServer(t, nil)
  1057  	defer s1.Shutdown()
  1058  	codec := rpcClient(t, s1)
  1059  	testutil.WaitForLeader(t, s1.RPC)
  1060  
  1061  	// Create the register request
  1062  	node := mock.Node()
  1063  	reg := &structs.NodeRegisterRequest{
  1064  		Node:         node,
  1065  		WriteRequest: structs.WriteRequest{Region: "global"},
  1066  	}
  1067  
  1068  	// Fetch the response
  1069  	var resp structs.GenericResponse
  1070  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
  1071  		t.Fatalf("err: %v", err)
  1072  	}
  1073  	node.CreateIndex = resp.Index
  1074  	node.ModifyIndex = resp.Index
  1075  
  1076  	// Inject fake evaluations async
  1077  	alloc := mock.Alloc()
  1078  	alloc.NodeID = node.ID
  1079  	state := s1.fsm.State()
  1080  	state.UpsertJobSummary(99, mock.JobSummary(alloc.JobID))
  1081  	start := time.Now()
  1082  	time.AfterFunc(100*time.Millisecond, func() {
  1083  		err := state.UpsertAllocs(100, []*structs.Allocation{alloc})
  1084  		if err != nil {
  1085  			t.Fatalf("err: %v", err)
  1086  		}
  1087  	})
  1088  
  1089  	// Lookup the allocs in a blocking query
  1090  	req := &structs.NodeSpecificRequest{
  1091  		NodeID:   node.ID,
  1092  		SecretID: node.SecretID,
  1093  		QueryOptions: structs.QueryOptions{
  1094  			Region:        "global",
  1095  			MinQueryIndex: 50,
  1096  			MaxQueryTime:  time.Second,
  1097  		},
  1098  	}
  1099  	var resp2 structs.NodeClientAllocsResponse
  1100  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetClientAllocs", req, &resp2); err != nil {
  1101  		t.Fatalf("err: %v", err)
  1102  	}
  1103  
  1104  	// Should block at least 100ms
  1105  	if time.Since(start) < 100*time.Millisecond {
  1106  		t.Fatalf("too fast")
  1107  	}
  1108  
  1109  	if resp2.Index != 100 {
  1110  		t.Fatalf("Bad index: %d %d", resp2.Index, 100)
  1111  	}
  1112  
  1113  	if len(resp2.Allocs) != 1 || resp2.Allocs[alloc.ID] != 100 {
  1114  		t.Fatalf("bad: %#v", resp2.Allocs)
  1115  	}
  1116  
  1117  	// Alloc updates fire watches
  1118  	time.AfterFunc(100*time.Millisecond, func() {
  1119  		allocUpdate := mock.Alloc()
  1120  		allocUpdate.NodeID = alloc.NodeID
  1121  		allocUpdate.ID = alloc.ID
  1122  		allocUpdate.ClientStatus = structs.AllocClientStatusRunning
  1123  		state.UpsertJobSummary(199, mock.JobSummary(allocUpdate.JobID))
  1124  		err := state.UpsertAllocs(200, []*structs.Allocation{allocUpdate})
  1125  		if err != nil {
  1126  			t.Fatalf("err: %v", err)
  1127  		}
  1128  	})
  1129  
  1130  	req.QueryOptions.MinQueryIndex = 150
  1131  	var resp3 structs.NodeClientAllocsResponse
  1132  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetClientAllocs", req, &resp3); err != nil {
  1133  		t.Fatalf("err: %v", err)
  1134  	}
  1135  
  1136  	if time.Since(start) < 100*time.Millisecond {
  1137  		t.Fatalf("too fast")
  1138  	}
  1139  	if resp3.Index != 200 {
  1140  		t.Fatalf("Bad index: %d %d", resp3.Index, 200)
  1141  	}
  1142  	if len(resp3.Allocs) != 1 || resp3.Allocs[alloc.ID] != 200 {
  1143  		t.Fatalf("bad: %#v", resp3.Allocs)
  1144  	}
  1145  }
  1146  
  1147  func TestClientEndpoint_GetAllocs_Blocking(t *testing.T) {
  1148  	s1 := testServer(t, nil)
  1149  	defer s1.Shutdown()
  1150  	codec := rpcClient(t, s1)
  1151  	testutil.WaitForLeader(t, s1.RPC)
  1152  
  1153  	// Create the register request
  1154  	node := mock.Node()
  1155  	reg := &structs.NodeRegisterRequest{
  1156  		Node:         node,
  1157  		WriteRequest: structs.WriteRequest{Region: "global"},
  1158  	}
  1159  
  1160  	// Fetch the response
  1161  	var resp structs.GenericResponse
  1162  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
  1163  		t.Fatalf("err: %v", err)
  1164  	}
  1165  	node.CreateIndex = resp.Index
  1166  	node.ModifyIndex = resp.Index
  1167  
  1168  	// Inject fake evaluations async
  1169  	alloc := mock.Alloc()
  1170  	alloc.NodeID = node.ID
  1171  	state := s1.fsm.State()
  1172  	state.UpsertJobSummary(99, mock.JobSummary(alloc.JobID))
  1173  	start := time.Now()
  1174  	time.AfterFunc(100*time.Millisecond, func() {
  1175  		err := state.UpsertAllocs(100, []*structs.Allocation{alloc})
  1176  		if err != nil {
  1177  			t.Fatalf("err: %v", err)
  1178  		}
  1179  	})
  1180  
  1181  	// Lookup the allocs in a blocking query
  1182  	req := &structs.NodeSpecificRequest{
  1183  		NodeID: node.ID,
  1184  		QueryOptions: structs.QueryOptions{
  1185  			Region:        "global",
  1186  			MinQueryIndex: 50,
  1187  			MaxQueryTime:  time.Second,
  1188  		},
  1189  	}
  1190  	var resp2 structs.NodeAllocsResponse
  1191  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetAllocs", req, &resp2); err != nil {
  1192  		t.Fatalf("err: %v", err)
  1193  	}
  1194  
  1195  	// Should block at least 100ms
  1196  	if time.Since(start) < 100*time.Millisecond {
  1197  		t.Fatalf("too fast")
  1198  	}
  1199  
  1200  	if resp2.Index != 100 {
  1201  		t.Fatalf("Bad index: %d %d", resp2.Index, 100)
  1202  	}
  1203  
  1204  	if len(resp2.Allocs) != 1 || resp2.Allocs[0].ID != alloc.ID {
  1205  		t.Fatalf("bad: %#v", resp2.Allocs)
  1206  	}
  1207  
  1208  	// Alloc updates fire watches
  1209  	time.AfterFunc(100*time.Millisecond, func() {
  1210  		allocUpdate := mock.Alloc()
  1211  		allocUpdate.NodeID = alloc.NodeID
  1212  		allocUpdate.ID = alloc.ID
  1213  		allocUpdate.ClientStatus = structs.AllocClientStatusRunning
  1214  		state.UpsertJobSummary(199, mock.JobSummary(allocUpdate.JobID))
  1215  		err := state.UpdateAllocsFromClient(200, []*structs.Allocation{allocUpdate})
  1216  		if err != nil {
  1217  			t.Fatalf("err: %v", err)
  1218  		}
  1219  	})
  1220  
  1221  	req.QueryOptions.MinQueryIndex = 150
  1222  	var resp3 structs.NodeAllocsResponse
  1223  	if err := msgpackrpc.CallWithCodec(codec, "Node.GetAllocs", req, &resp3); err != nil {
  1224  		t.Fatalf("err: %v", err)
  1225  	}
  1226  
  1227  	if time.Since(start) < 100*time.Millisecond {
  1228  		t.Fatalf("too fast")
  1229  	}
  1230  	if resp3.Index != 200 {
  1231  		t.Fatalf("Bad index: %d %d", resp3.Index, 200)
  1232  	}
  1233  	if len(resp3.Allocs) != 1 || resp3.Allocs[0].ClientStatus != structs.AllocClientStatusRunning {
  1234  		t.Fatalf("bad: %#v", resp3.Allocs[0])
  1235  	}
  1236  }
  1237  
  1238  func TestClientEndpoint_UpdateAlloc(t *testing.T) {
  1239  	s1 := testServer(t, nil)
  1240  	defer s1.Shutdown()
  1241  	codec := rpcClient(t, s1)
  1242  	testutil.WaitForLeader(t, s1.RPC)
  1243  
  1244  	// Create the register request
  1245  	node := mock.Node()
  1246  	reg := &structs.NodeRegisterRequest{
  1247  		Node:         node,
  1248  		WriteRequest: structs.WriteRequest{Region: "global"},
  1249  	}
  1250  
  1251  	// Fetch the response
  1252  	var resp structs.GenericResponse
  1253  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
  1254  		t.Fatalf("err: %v", err)
  1255  	}
  1256  
  1257  	// Inject fake evaluations
  1258  	alloc := mock.Alloc()
  1259  	alloc.NodeID = node.ID
  1260  	state := s1.fsm.State()
  1261  	state.UpsertJobSummary(99, mock.JobSummary(alloc.JobID))
  1262  	err := state.UpsertAllocs(100, []*structs.Allocation{alloc})
  1263  	if err != nil {
  1264  		t.Fatalf("err: %v", err)
  1265  	}
  1266  
  1267  	// Attempt update
  1268  	clientAlloc := new(structs.Allocation)
  1269  	*clientAlloc = *alloc
  1270  	clientAlloc.ClientStatus = structs.AllocClientStatusFailed
  1271  
  1272  	// Update the alloc
  1273  	update := &structs.AllocUpdateRequest{
  1274  		Alloc:        []*structs.Allocation{clientAlloc},
  1275  		WriteRequest: structs.WriteRequest{Region: "global"},
  1276  	}
  1277  	var resp2 structs.NodeAllocsResponse
  1278  	start := time.Now()
  1279  	if err := msgpackrpc.CallWithCodec(codec, "Node.UpdateAlloc", update, &resp2); err != nil {
  1280  		t.Fatalf("err: %v", err)
  1281  	}
  1282  	if resp2.Index == 0 {
  1283  		t.Fatalf("Bad index: %d", resp2.Index)
  1284  	}
  1285  	if diff := time.Since(start); diff < batchUpdateInterval {
  1286  		t.Fatalf("too fast: %v", diff)
  1287  	}
  1288  
  1289  	// Lookup the alloc
  1290  	out, err := state.AllocByID(alloc.ID)
  1291  	if err != nil {
  1292  		t.Fatalf("err: %v", err)
  1293  	}
  1294  	if out.ClientStatus != structs.AllocClientStatusFailed {
  1295  		t.Fatalf("Bad: %#v", out)
  1296  	}
  1297  }
  1298  
  1299  func TestClientEndpoint_BatchUpdate(t *testing.T) {
  1300  	s1 := testServer(t, nil)
  1301  	defer s1.Shutdown()
  1302  	codec := rpcClient(t, s1)
  1303  	testutil.WaitForLeader(t, s1.RPC)
  1304  
  1305  	// Create the register request
  1306  	node := mock.Node()
  1307  	reg := &structs.NodeRegisterRequest{
  1308  		Node:         node,
  1309  		WriteRequest: structs.WriteRequest{Region: "global"},
  1310  	}
  1311  
  1312  	// Fetch the response
  1313  	var resp structs.GenericResponse
  1314  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
  1315  		t.Fatalf("err: %v", err)
  1316  	}
  1317  
  1318  	// Inject fake evaluations
  1319  	alloc := mock.Alloc()
  1320  	alloc.NodeID = node.ID
  1321  	state := s1.fsm.State()
  1322  	state.UpsertJobSummary(99, mock.JobSummary(alloc.JobID))
  1323  	err := state.UpsertAllocs(100, []*structs.Allocation{alloc})
  1324  	if err != nil {
  1325  		t.Fatalf("err: %v", err)
  1326  	}
  1327  
  1328  	// Attempt update
  1329  	clientAlloc := new(structs.Allocation)
  1330  	*clientAlloc = *alloc
  1331  	clientAlloc.ClientStatus = structs.AllocClientStatusFailed
  1332  
  1333  	// Call to do the batch update
  1334  	bf := NewBatchFuture()
  1335  	endpoint := s1.endpoints.Node
  1336  	endpoint.batchUpdate(bf, []*structs.Allocation{clientAlloc})
  1337  	if err := bf.Wait(); err != nil {
  1338  		t.Fatalf("err: %v", err)
  1339  	}
  1340  	if bf.Index() == 0 {
  1341  		t.Fatalf("Bad index: %d", bf.Index())
  1342  	}
  1343  
  1344  	// Lookup the alloc
  1345  	out, err := state.AllocByID(alloc.ID)
  1346  	if err != nil {
  1347  		t.Fatalf("err: %v", err)
  1348  	}
  1349  	if out.ClientStatus != structs.AllocClientStatusFailed {
  1350  		t.Fatalf("Bad: %#v", out)
  1351  	}
  1352  }
  1353  
  1354  func TestClientEndpoint_UpdateAlloc_Vault(t *testing.T) {
  1355  	s1 := testServer(t, nil)
  1356  	defer s1.Shutdown()
  1357  	codec := rpcClient(t, s1)
  1358  	testutil.WaitForLeader(t, s1.RPC)
  1359  
  1360  	// Create the register request
  1361  	node := mock.Node()
  1362  	reg := &structs.NodeRegisterRequest{
  1363  		Node:         node,
  1364  		WriteRequest: structs.WriteRequest{Region: "global"},
  1365  	}
  1366  
  1367  	// Fetch the response
  1368  	var resp structs.GenericResponse
  1369  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
  1370  		t.Fatalf("err: %v", err)
  1371  	}
  1372  
  1373  	// Swap the servers Vault Client
  1374  	tvc := &TestVaultClient{}
  1375  	s1.vault = tvc
  1376  
  1377  	// Inject fake allocation and vault accessor
  1378  	alloc := mock.Alloc()
  1379  	alloc.NodeID = node.ID
  1380  	state := s1.fsm.State()
  1381  	state.UpsertJobSummary(99, mock.JobSummary(alloc.JobID))
  1382  	if err := state.UpsertAllocs(100, []*structs.Allocation{alloc}); err != nil {
  1383  		t.Fatalf("err: %v", err)
  1384  	}
  1385  
  1386  	va := mock.VaultAccessor()
  1387  	va.NodeID = node.ID
  1388  	va.AllocID = alloc.ID
  1389  	if err := state.UpsertVaultAccessor(101, []*structs.VaultAccessor{va}); err != nil {
  1390  		t.Fatalf("err: %v", err)
  1391  	}
  1392  
  1393  	// Attempt update
  1394  	clientAlloc := new(structs.Allocation)
  1395  	*clientAlloc = *alloc
  1396  	clientAlloc.ClientStatus = structs.AllocClientStatusFailed
  1397  
  1398  	// Update the alloc
  1399  	update := &structs.AllocUpdateRequest{
  1400  		Alloc:        []*structs.Allocation{clientAlloc},
  1401  		WriteRequest: structs.WriteRequest{Region: "global"},
  1402  	}
  1403  	var resp2 structs.NodeAllocsResponse
  1404  	start := time.Now()
  1405  	if err := msgpackrpc.CallWithCodec(codec, "Node.UpdateAlloc", update, &resp2); err != nil {
  1406  		t.Fatalf("err: %v", err)
  1407  	}
  1408  	if resp2.Index == 0 {
  1409  		t.Fatalf("Bad index: %d", resp2.Index)
  1410  	}
  1411  	if diff := time.Since(start); diff < batchUpdateInterval {
  1412  		t.Fatalf("too fast: %v", diff)
  1413  	}
  1414  
  1415  	// Lookup the alloc
  1416  	out, err := state.AllocByID(alloc.ID)
  1417  	if err != nil {
  1418  		t.Fatalf("err: %v", err)
  1419  	}
  1420  	if out.ClientStatus != structs.AllocClientStatusFailed {
  1421  		t.Fatalf("Bad: %#v", out)
  1422  	}
  1423  
  1424  	if l := len(tvc.RevokedTokens); l != 1 {
  1425  		t.Fatalf("Deregister revoked %d tokens; want 1", l)
  1426  	}
  1427  }
  1428  
  1429  func TestClientEndpoint_CreateNodeEvals(t *testing.T) {
  1430  	s1 := testServer(t, nil)
  1431  	defer s1.Shutdown()
  1432  	testutil.WaitForLeader(t, s1.RPC)
  1433  
  1434  	// Inject fake evaluations
  1435  	alloc := mock.Alloc()
  1436  	state := s1.fsm.State()
  1437  	state.UpsertJobSummary(1, mock.JobSummary(alloc.JobID))
  1438  	if err := state.UpsertAllocs(2, []*structs.Allocation{alloc}); err != nil {
  1439  		t.Fatalf("err: %v", err)
  1440  	}
  1441  
  1442  	// Inject a fake system job.
  1443  	job := mock.SystemJob()
  1444  	if err := state.UpsertJob(3, job); err != nil {
  1445  		t.Fatalf("err: %v", err)
  1446  	}
  1447  
  1448  	// Create some evaluations
  1449  	ids, index, err := s1.endpoints.Node.createNodeEvals(alloc.NodeID, 1)
  1450  	if err != nil {
  1451  		t.Fatalf("err: %v", err)
  1452  	}
  1453  	if index == 0 {
  1454  		t.Fatalf("bad: %d", index)
  1455  	}
  1456  	if len(ids) != 2 {
  1457  		t.Fatalf("bad: %s", ids)
  1458  	}
  1459  
  1460  	// Lookup the evaluations
  1461  	evalByType := make(map[string]*structs.Evaluation, 2)
  1462  	for _, id := range ids {
  1463  		eval, err := state.EvalByID(id)
  1464  		if err != nil {
  1465  			t.Fatalf("err: %v", err)
  1466  		}
  1467  		if eval == nil {
  1468  			t.Fatalf("expected eval")
  1469  		}
  1470  
  1471  		if old, ok := evalByType[eval.Type]; ok {
  1472  			t.Fatalf("multiple evals of the same type: %v and %v", old, eval)
  1473  		}
  1474  
  1475  		evalByType[eval.Type] = eval
  1476  	}
  1477  
  1478  	if len(evalByType) != 2 {
  1479  		t.Fatalf("Expected a service and system job; got %#v", evalByType)
  1480  	}
  1481  
  1482  	// Ensure the evals are correct.
  1483  	for schedType, eval := range evalByType {
  1484  		expPriority := alloc.Job.Priority
  1485  		expJobID := alloc.JobID
  1486  		if schedType == "system" {
  1487  			expPriority = job.Priority
  1488  			expJobID = job.ID
  1489  		}
  1490  
  1491  		if eval.CreateIndex != index {
  1492  			t.Fatalf("CreateIndex mis-match on type %v: %#v", schedType, eval)
  1493  		}
  1494  		if eval.TriggeredBy != structs.EvalTriggerNodeUpdate {
  1495  			t.Fatalf("TriggeredBy incorrect on type %v: %#v", schedType, eval)
  1496  		}
  1497  		if eval.NodeID != alloc.NodeID {
  1498  			t.Fatalf("NodeID incorrect on type %v: %#v", schedType, eval)
  1499  		}
  1500  		if eval.NodeModifyIndex != 1 {
  1501  			t.Fatalf("NodeModifyIndex incorrect on type %v: %#v", schedType, eval)
  1502  		}
  1503  		if eval.Status != structs.EvalStatusPending {
  1504  			t.Fatalf("Status incorrect on type %v: %#v", schedType, eval)
  1505  		}
  1506  		if eval.Priority != expPriority {
  1507  			t.Fatalf("Priority incorrect on type %v: %#v", schedType, eval)
  1508  		}
  1509  		if eval.JobID != expJobID {
  1510  			t.Fatalf("JobID incorrect on type %v: %#v", schedType, eval)
  1511  		}
  1512  	}
  1513  }
  1514  
  1515  func TestClientEndpoint_Evaluate(t *testing.T) {
  1516  	s1 := testServer(t, func(c *Config) {
  1517  		c.NumSchedulers = 0 // Prevent automatic dequeue
  1518  	})
  1519  	defer s1.Shutdown()
  1520  	codec := rpcClient(t, s1)
  1521  	testutil.WaitForLeader(t, s1.RPC)
  1522  
  1523  	// Inject fake evaluations
  1524  	alloc := mock.Alloc()
  1525  	node := mock.Node()
  1526  	node.ID = alloc.NodeID
  1527  	state := s1.fsm.State()
  1528  	err := state.UpsertNode(1, node)
  1529  	if err != nil {
  1530  		t.Fatalf("err: %v", err)
  1531  	}
  1532  	state.UpsertJobSummary(2, mock.JobSummary(alloc.JobID))
  1533  	err = state.UpsertAllocs(3, []*structs.Allocation{alloc})
  1534  	if err != nil {
  1535  		t.Fatalf("err: %v", err)
  1536  	}
  1537  
  1538  	// Re-evaluate
  1539  	req := &structs.NodeEvaluateRequest{
  1540  		NodeID:       alloc.NodeID,
  1541  		WriteRequest: structs.WriteRequest{Region: "global"},
  1542  	}
  1543  
  1544  	// Fetch the response
  1545  	var resp structs.NodeUpdateResponse
  1546  	if err := msgpackrpc.CallWithCodec(codec, "Node.Evaluate", req, &resp); err != nil {
  1547  		t.Fatalf("err: %v", err)
  1548  	}
  1549  	if resp.Index == 0 {
  1550  		t.Fatalf("bad index: %d", resp.Index)
  1551  	}
  1552  
  1553  	// Create some evaluations
  1554  	ids := resp.EvalIDs
  1555  	if len(ids) != 1 {
  1556  		t.Fatalf("bad: %s", ids)
  1557  	}
  1558  
  1559  	// Lookup the evaluation
  1560  	eval, err := state.EvalByID(ids[0])
  1561  	if err != nil {
  1562  		t.Fatalf("err: %v", err)
  1563  	}
  1564  	if eval == nil {
  1565  		t.Fatalf("expected eval")
  1566  	}
  1567  	if eval.CreateIndex != resp.Index {
  1568  		t.Fatalf("index mis-match")
  1569  	}
  1570  
  1571  	if eval.Priority != alloc.Job.Priority {
  1572  		t.Fatalf("bad: %#v", eval)
  1573  	}
  1574  	if eval.Type != alloc.Job.Type {
  1575  		t.Fatalf("bad: %#v", eval)
  1576  	}
  1577  	if eval.TriggeredBy != structs.EvalTriggerNodeUpdate {
  1578  		t.Fatalf("bad: %#v", eval)
  1579  	}
  1580  	if eval.JobID != alloc.JobID {
  1581  		t.Fatalf("bad: %#v", eval)
  1582  	}
  1583  	if eval.NodeID != alloc.NodeID {
  1584  		t.Fatalf("bad: %#v", eval)
  1585  	}
  1586  	if eval.NodeModifyIndex != 1 {
  1587  		t.Fatalf("bad: %#v", eval)
  1588  	}
  1589  	if eval.Status != structs.EvalStatusPending {
  1590  		t.Fatalf("bad: %#v", eval)
  1591  	}
  1592  }
  1593  
  1594  func TestClientEndpoint_ListNodes(t *testing.T) {
  1595  	s1 := testServer(t, nil)
  1596  	defer s1.Shutdown()
  1597  	codec := rpcClient(t, s1)
  1598  	testutil.WaitForLeader(t, s1.RPC)
  1599  
  1600  	// Create the register request
  1601  	node := mock.Node()
  1602  	reg := &structs.NodeRegisterRequest{
  1603  		Node:         node,
  1604  		WriteRequest: structs.WriteRequest{Region: "global"},
  1605  	}
  1606  
  1607  	// Fetch the response
  1608  	var resp structs.GenericResponse
  1609  	if err := msgpackrpc.CallWithCodec(codec, "Node.Register", reg, &resp); err != nil {
  1610  		t.Fatalf("err: %v", err)
  1611  	}
  1612  	node.CreateIndex = resp.Index
  1613  	node.ModifyIndex = resp.Index
  1614  
  1615  	// Lookup the node
  1616  	get := &structs.NodeListRequest{
  1617  		QueryOptions: structs.QueryOptions{Region: "global"},
  1618  	}
  1619  	var resp2 structs.NodeListResponse
  1620  	if err := msgpackrpc.CallWithCodec(codec, "Node.List", get, &resp2); err != nil {
  1621  		t.Fatalf("err: %v", err)
  1622  	}
  1623  	if resp2.Index != resp.Index {
  1624  		t.Fatalf("Bad index: %d %d", resp2.Index, resp.Index)
  1625  	}
  1626  
  1627  	if len(resp2.Nodes) != 1 {
  1628  		t.Fatalf("bad: %#v", resp2.Nodes)
  1629  	}
  1630  	if resp2.Nodes[0].ID != node.ID {
  1631  		t.Fatalf("bad: %#v", resp2.Nodes[0])
  1632  	}
  1633  
  1634  	// Lookup the node with prefix
  1635  	get = &structs.NodeListRequest{
  1636  		QueryOptions: structs.QueryOptions{Region: "global", Prefix: node.ID[:4]},
  1637  	}
  1638  	var resp3 structs.NodeListResponse
  1639  	if err := msgpackrpc.CallWithCodec(codec, "Node.List", get, &resp3); err != nil {
  1640  		t.Fatalf("err: %v", err)
  1641  	}
  1642  	if resp3.Index != resp.Index {
  1643  		t.Fatalf("Bad index: %d %d", resp3.Index, resp2.Index)
  1644  	}
  1645  
  1646  	if len(resp3.Nodes) != 1 {
  1647  		t.Fatalf("bad: %#v", resp3.Nodes)
  1648  	}
  1649  	if resp3.Nodes[0].ID != node.ID {
  1650  		t.Fatalf("bad: %#v", resp3.Nodes[0])
  1651  	}
  1652  }
  1653  
  1654  func TestClientEndpoint_ListNodes_Blocking(t *testing.T) {
  1655  	s1 := testServer(t, nil)
  1656  	defer s1.Shutdown()
  1657  	state := s1.fsm.State()
  1658  	codec := rpcClient(t, s1)
  1659  	testutil.WaitForLeader(t, s1.RPC)
  1660  
  1661  	// Create the node
  1662  	node := mock.Node()
  1663  
  1664  	// Node upsert triggers watches
  1665  	time.AfterFunc(100*time.Millisecond, func() {
  1666  		if err := state.UpsertNode(2, node); err != nil {
  1667  			t.Fatalf("err: %v", err)
  1668  		}
  1669  	})
  1670  
  1671  	req := &structs.NodeListRequest{
  1672  		QueryOptions: structs.QueryOptions{
  1673  			Region:        "global",
  1674  			MinQueryIndex: 1,
  1675  		},
  1676  	}
  1677  	start := time.Now()
  1678  	var resp structs.NodeListResponse
  1679  	if err := msgpackrpc.CallWithCodec(codec, "Node.List", req, &resp); err != nil {
  1680  		t.Fatalf("err: %v", err)
  1681  	}
  1682  
  1683  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
  1684  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
  1685  	}
  1686  	if resp.Index != 2 {
  1687  		t.Fatalf("Bad index: %d %d", resp.Index, 2)
  1688  	}
  1689  	if len(resp.Nodes) != 1 || resp.Nodes[0].ID != node.ID {
  1690  		t.Fatalf("bad: %#v", resp.Nodes)
  1691  	}
  1692  
  1693  	// Node drain updates trigger watches.
  1694  	time.AfterFunc(100*time.Millisecond, func() {
  1695  		if err := state.UpdateNodeDrain(3, node.ID, true); err != nil {
  1696  			t.Fatalf("err: %v", err)
  1697  		}
  1698  	})
  1699  
  1700  	req.MinQueryIndex = 2
  1701  	var resp2 structs.NodeListResponse
  1702  	start = time.Now()
  1703  	if err := msgpackrpc.CallWithCodec(codec, "Node.List", req, &resp2); err != nil {
  1704  		t.Fatalf("err: %v", err)
  1705  	}
  1706  
  1707  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
  1708  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp2)
  1709  	}
  1710  	if resp2.Index != 3 {
  1711  		t.Fatalf("Bad index: %d %d", resp2.Index, 3)
  1712  	}
  1713  	if len(resp2.Nodes) != 1 || !resp2.Nodes[0].Drain {
  1714  		t.Fatalf("bad: %#v", resp2.Nodes)
  1715  	}
  1716  
  1717  	// Node status update triggers watches
  1718  	time.AfterFunc(100*time.Millisecond, func() {
  1719  		if err := state.UpdateNodeStatus(4, node.ID, structs.NodeStatusDown); err != nil {
  1720  			t.Fatalf("err: %v", err)
  1721  		}
  1722  	})
  1723  
  1724  	req.MinQueryIndex = 3
  1725  	var resp3 structs.NodeListResponse
  1726  	start = time.Now()
  1727  	if err := msgpackrpc.CallWithCodec(codec, "Node.List", req, &resp3); err != nil {
  1728  		t.Fatalf("err: %v", err)
  1729  	}
  1730  
  1731  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
  1732  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp3)
  1733  	}
  1734  	if resp3.Index != 4 {
  1735  		t.Fatalf("Bad index: %d %d", resp3.Index, 4)
  1736  	}
  1737  	if len(resp3.Nodes) != 1 || resp3.Nodes[0].Status != structs.NodeStatusDown {
  1738  		t.Fatalf("bad: %#v", resp3.Nodes)
  1739  	}
  1740  
  1741  	// Node delete triggers watches.
  1742  	time.AfterFunc(100*time.Millisecond, func() {
  1743  		if err := state.DeleteNode(5, node.ID); err != nil {
  1744  			t.Fatalf("err: %v", err)
  1745  		}
  1746  	})
  1747  
  1748  	req.MinQueryIndex = 4
  1749  	var resp4 structs.NodeListResponse
  1750  	start = time.Now()
  1751  	if err := msgpackrpc.CallWithCodec(codec, "Node.List", req, &resp4); err != nil {
  1752  		t.Fatalf("err: %v", err)
  1753  	}
  1754  
  1755  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
  1756  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp4)
  1757  	}
  1758  	if resp4.Index != 5 {
  1759  		t.Fatalf("Bad index: %d %d", resp4.Index, 5)
  1760  	}
  1761  	if len(resp4.Nodes) != 0 {
  1762  		t.Fatalf("bad: %#v", resp4.Nodes)
  1763  	}
  1764  }
  1765  
  1766  func TestBatchFuture(t *testing.T) {
  1767  	bf := NewBatchFuture()
  1768  
  1769  	// Async respond to the future
  1770  	expect := fmt.Errorf("testing")
  1771  	go func() {
  1772  		time.Sleep(10 * time.Millisecond)
  1773  		bf.Respond(1000, expect)
  1774  	}()
  1775  
  1776  	// Block for the result
  1777  	start := time.Now()
  1778  	err := bf.Wait()
  1779  	diff := time.Since(start)
  1780  	if diff < 5*time.Millisecond {
  1781  		t.Fatalf("too fast")
  1782  	}
  1783  
  1784  	// Check the results
  1785  	if err != expect {
  1786  		t.Fatalf("bad: %s", err)
  1787  	}
  1788  	if bf.Index() != 1000 {
  1789  		t.Fatalf("bad: %d", bf.Index())
  1790  	}
  1791  }
  1792  
  1793  func TestClientEndpoint_DeriveVaultToken_Bad(t *testing.T) {
  1794  	s1 := testServer(t, nil)
  1795  	defer s1.Shutdown()
  1796  	state := s1.fsm.State()
  1797  	codec := rpcClient(t, s1)
  1798  	testutil.WaitForLeader(t, s1.RPC)
  1799  
  1800  	// Create the node
  1801  	node := mock.Node()
  1802  	if err := state.UpsertNode(2, node); err != nil {
  1803  		t.Fatalf("err: %v", err)
  1804  	}
  1805  
  1806  	// Create an alloc
  1807  	alloc := mock.Alloc()
  1808  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1809  	tasks := []string{task.Name}
  1810  	if err := state.UpsertAllocs(3, []*structs.Allocation{alloc}); err != nil {
  1811  		t.Fatalf("err: %v", err)
  1812  	}
  1813  
  1814  	req := &structs.DeriveVaultTokenRequest{
  1815  		NodeID:   node.ID,
  1816  		SecretID: structs.GenerateUUID(),
  1817  		AllocID:  alloc.ID,
  1818  		Tasks:    tasks,
  1819  		QueryOptions: structs.QueryOptions{
  1820  			Region: "global",
  1821  		},
  1822  	}
  1823  
  1824  	var resp structs.DeriveVaultTokenResponse
  1825  	if err := msgpackrpc.CallWithCodec(codec, "Node.DeriveVaultToken", req, &resp); err != nil {
  1826  		t.Fatalf("bad: %v", err)
  1827  	}
  1828  
  1829  	if resp.Error == nil || !strings.Contains(resp.Error.Error(), "SecretID mismatch") {
  1830  		t.Fatalf("Expected SecretID mismatch: %v", resp.Error)
  1831  	}
  1832  
  1833  	// Put the correct SecretID
  1834  	req.SecretID = node.SecretID
  1835  
  1836  	// Now we should get an error about the allocation not running on the node
  1837  	if err := msgpackrpc.CallWithCodec(codec, "Node.DeriveVaultToken", req, &resp); err != nil {
  1838  		t.Fatalf("bad: %v", err)
  1839  	}
  1840  	if resp.Error == nil || !strings.Contains(resp.Error.Error(), "not running on Node") {
  1841  		t.Fatalf("Expected not running on node error: %v", resp.Error)
  1842  	}
  1843  
  1844  	// Update to be running on the node
  1845  	alloc.NodeID = node.ID
  1846  	if err := state.UpsertAllocs(4, []*structs.Allocation{alloc}); err != nil {
  1847  		t.Fatalf("err: %v", err)
  1848  	}
  1849  
  1850  	// Now we should get an error about the job not needing any Vault secrets
  1851  	if err := msgpackrpc.CallWithCodec(codec, "Node.DeriveVaultToken", req, &resp); err != nil {
  1852  		t.Fatalf("bad: %v", err)
  1853  	}
  1854  	if resp.Error == nil || !strings.Contains(resp.Error.Error(), "does not require") {
  1855  		t.Fatalf("Expected no policies error: %v", resp.Error)
  1856  	}
  1857  
  1858  	// Update to be terminal
  1859  	alloc.DesiredStatus = structs.AllocDesiredStatusStop
  1860  	if err := state.UpsertAllocs(5, []*structs.Allocation{alloc}); err != nil {
  1861  		t.Fatalf("err: %v", err)
  1862  	}
  1863  
  1864  	// Now we should get an error about the job not needing any Vault secrets
  1865  	if err := msgpackrpc.CallWithCodec(codec, "Node.DeriveVaultToken", req, &resp); err != nil {
  1866  		t.Fatalf("bad: %v", err)
  1867  	}
  1868  	if resp.Error == nil || !strings.Contains(resp.Error.Error(), "terminal") {
  1869  		t.Fatalf("Expected terminal allocation error: %v", resp.Error)
  1870  	}
  1871  }
  1872  
  1873  func TestClientEndpoint_DeriveVaultToken(t *testing.T) {
  1874  	s1 := testServer(t, nil)
  1875  	defer s1.Shutdown()
  1876  	state := s1.fsm.State()
  1877  	codec := rpcClient(t, s1)
  1878  	testutil.WaitForLeader(t, s1.RPC)
  1879  
  1880  	// Enable vault and allow authenticated
  1881  	tr := true
  1882  	s1.config.VaultConfig.Enabled = &tr
  1883  	s1.config.VaultConfig.AllowUnauthenticated = &tr
  1884  
  1885  	// Replace the Vault Client on the server
  1886  	tvc := &TestVaultClient{}
  1887  	s1.vault = tvc
  1888  
  1889  	// Create the node
  1890  	node := mock.Node()
  1891  	if err := state.UpsertNode(2, node); err != nil {
  1892  		t.Fatalf("err: %v", err)
  1893  	}
  1894  
  1895  	// Create an alloc an allocation that has vault policies required
  1896  	alloc := mock.Alloc()
  1897  	alloc.NodeID = node.ID
  1898  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1899  	tasks := []string{task.Name}
  1900  	task.Vault = &structs.Vault{Policies: []string{"a", "b"}}
  1901  	if err := state.UpsertAllocs(3, []*structs.Allocation{alloc}); err != nil {
  1902  		t.Fatalf("err: %v", err)
  1903  	}
  1904  
  1905  	// Return a secret for the task
  1906  	token := structs.GenerateUUID()
  1907  	accessor := structs.GenerateUUID()
  1908  	ttl := 10
  1909  	secret := &vapi.Secret{
  1910  		WrapInfo: &vapi.SecretWrapInfo{
  1911  			Token:           token,
  1912  			WrappedAccessor: accessor,
  1913  			TTL:             ttl,
  1914  		},
  1915  	}
  1916  	tvc.SetCreateTokenSecret(alloc.ID, task.Name, secret)
  1917  
  1918  	req := &structs.DeriveVaultTokenRequest{
  1919  		NodeID:   node.ID,
  1920  		SecretID: node.SecretID,
  1921  		AllocID:  alloc.ID,
  1922  		Tasks:    tasks,
  1923  		QueryOptions: structs.QueryOptions{
  1924  			Region: "global",
  1925  		},
  1926  	}
  1927  
  1928  	var resp structs.DeriveVaultTokenResponse
  1929  	if err := msgpackrpc.CallWithCodec(codec, "Node.DeriveVaultToken", req, &resp); err != nil {
  1930  		t.Fatalf("bad: %v", err)
  1931  	}
  1932  	if resp.Error != nil {
  1933  		t.Fatalf("bad: %v", resp.Error)
  1934  	}
  1935  
  1936  	// Check the state store and ensure that we created a VaultAccessor
  1937  	va, err := state.VaultAccessor(accessor)
  1938  	if err != nil {
  1939  		t.Fatalf("bad: %v", err)
  1940  	}
  1941  	if va == nil {
  1942  		t.Fatalf("bad: %v", va)
  1943  	}
  1944  
  1945  	if va.CreateIndex == 0 {
  1946  		t.Fatalf("bad: %v", va)
  1947  	}
  1948  
  1949  	va.CreateIndex = 0
  1950  	expected := &structs.VaultAccessor{
  1951  		AllocID:     alloc.ID,
  1952  		Task:        task.Name,
  1953  		NodeID:      alloc.NodeID,
  1954  		Accessor:    accessor,
  1955  		CreationTTL: ttl,
  1956  	}
  1957  
  1958  	if !reflect.DeepEqual(expected, va) {
  1959  		t.Fatalf("Got %#v; want %#v", va, expected)
  1960  	}
  1961  }
  1962  
  1963  func TestClientEndpoint_DeriveVaultToken_VaultError(t *testing.T) {
  1964  	s1 := testServer(t, nil)
  1965  	defer s1.Shutdown()
  1966  	state := s1.fsm.State()
  1967  	codec := rpcClient(t, s1)
  1968  	testutil.WaitForLeader(t, s1.RPC)
  1969  
  1970  	// Enable vault and allow authenticated
  1971  	tr := true
  1972  	s1.config.VaultConfig.Enabled = &tr
  1973  	s1.config.VaultConfig.AllowUnauthenticated = &tr
  1974  
  1975  	// Replace the Vault Client on the server
  1976  	tvc := &TestVaultClient{}
  1977  	s1.vault = tvc
  1978  
  1979  	// Create the node
  1980  	node := mock.Node()
  1981  	if err := state.UpsertNode(2, node); err != nil {
  1982  		t.Fatalf("err: %v", err)
  1983  	}
  1984  
  1985  	// Create an alloc an allocation that has vault policies required
  1986  	alloc := mock.Alloc()
  1987  	alloc.NodeID = node.ID
  1988  	task := alloc.Job.TaskGroups[0].Tasks[0]
  1989  	tasks := []string{task.Name}
  1990  	task.Vault = &structs.Vault{Policies: []string{"a", "b"}}
  1991  	if err := state.UpsertAllocs(3, []*structs.Allocation{alloc}); err != nil {
  1992  		t.Fatalf("err: %v", err)
  1993  	}
  1994  
  1995  	// Return an error when creating the token
  1996  	tvc.SetCreateTokenError(alloc.ID, task.Name,
  1997  		structs.NewRecoverableError(fmt.Errorf("recover"), true))
  1998  
  1999  	req := &structs.DeriveVaultTokenRequest{
  2000  		NodeID:   node.ID,
  2001  		SecretID: node.SecretID,
  2002  		AllocID:  alloc.ID,
  2003  		Tasks:    tasks,
  2004  		QueryOptions: structs.QueryOptions{
  2005  			Region: "global",
  2006  		},
  2007  	}
  2008  
  2009  	var resp structs.DeriveVaultTokenResponse
  2010  	err := msgpackrpc.CallWithCodec(codec, "Node.DeriveVaultToken", req, &resp)
  2011  	if err != nil {
  2012  		t.Fatalf("bad: %v", err)
  2013  	}
  2014  	if resp.Error == nil || !resp.Error.Recoverable {
  2015  		t.Fatalf("bad: %+v", resp.Error)
  2016  	}
  2017  }