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

     1  package agent
     2  
     3  import (
     4  	"net/http"
     5  	"net/http/httptest"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/nomad/nomad/mock"
     9  	"github.com/hashicorp/nomad/nomad/structs"
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  func TestHTTP_NodesList(t *testing.T) {
    14  	t.Parallel()
    15  	httpTest(t, nil, func(s *TestAgent) {
    16  		for i := 0; i < 3; i++ {
    17  			// Create the node
    18  			node := mock.Node()
    19  			args := structs.NodeRegisterRequest{
    20  				Node:         node,
    21  				WriteRequest: structs.WriteRequest{Region: "global"},
    22  			}
    23  			var resp structs.NodeUpdateResponse
    24  			if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil {
    25  				t.Fatalf("err: %v", err)
    26  			}
    27  		}
    28  
    29  		// Make the HTTP request
    30  		req, err := http.NewRequest("GET", "/v1/nodes", nil)
    31  		if err != nil {
    32  			t.Fatalf("err: %v", err)
    33  		}
    34  		respW := httptest.NewRecorder()
    35  
    36  		// Make the request
    37  		obj, err := s.Server.NodesRequest(respW, req)
    38  		if err != nil {
    39  			t.Fatalf("err: %v", err)
    40  		}
    41  
    42  		// Check for the index
    43  		if respW.HeaderMap.Get("X-Nomad-Index") == "" {
    44  			t.Fatalf("missing index")
    45  		}
    46  		if respW.HeaderMap.Get("X-Nomad-KnownLeader") != "true" {
    47  			t.Fatalf("missing known leader")
    48  		}
    49  		if respW.HeaderMap.Get("X-Nomad-LastContact") == "" {
    50  			t.Fatalf("missing last contact")
    51  		}
    52  
    53  		// Check the nodes
    54  		n := obj.([]*structs.NodeListStub)
    55  		if len(n) < 3 { // Maybe 4 including client
    56  			t.Fatalf("bad: %#v", n)
    57  		}
    58  	})
    59  }
    60  
    61  func TestHTTP_NodesPrefixList(t *testing.T) {
    62  	t.Parallel()
    63  	httpTest(t, nil, func(s *TestAgent) {
    64  		ids := []string{
    65  			"12345678-abcd-efab-cdef-123456789abc",
    66  			"12345678-aaaa-efab-cdef-123456789abc",
    67  			"1234aaaa-abcd-efab-cdef-123456789abc",
    68  			"1234bbbb-abcd-efab-cdef-123456789abc",
    69  			"1234cccc-abcd-efab-cdef-123456789abc",
    70  			"1234dddd-abcd-efab-cdef-123456789abc",
    71  		}
    72  		for i := 0; i < 5; i++ {
    73  			// Create the node
    74  			node := mock.Node()
    75  			node.ID = ids[i]
    76  			args := structs.NodeRegisterRequest{
    77  				Node:         node,
    78  				WriteRequest: structs.WriteRequest{Region: "global"},
    79  			}
    80  			var resp structs.NodeUpdateResponse
    81  			if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil {
    82  				t.Fatalf("err: %v", err)
    83  			}
    84  		}
    85  
    86  		// Make the HTTP request
    87  		req, err := http.NewRequest("GET", "/v1/nodes?prefix=12345678", nil)
    88  		if err != nil {
    89  			t.Fatalf("err: %v", err)
    90  		}
    91  		respW := httptest.NewRecorder()
    92  
    93  		// Make the request
    94  		obj, err := s.Server.NodesRequest(respW, req)
    95  		if err != nil {
    96  			t.Fatalf("err: %v", err)
    97  		}
    98  
    99  		// Check for the index
   100  		if respW.HeaderMap.Get("X-Nomad-Index") == "" {
   101  			t.Fatalf("missing index")
   102  		}
   103  		if respW.HeaderMap.Get("X-Nomad-KnownLeader") != "true" {
   104  			t.Fatalf("missing known leader")
   105  		}
   106  		if respW.HeaderMap.Get("X-Nomad-LastContact") == "" {
   107  			t.Fatalf("missing last contact")
   108  		}
   109  
   110  		// Check the nodes
   111  		n := obj.([]*structs.NodeListStub)
   112  		if len(n) != 2 {
   113  			t.Fatalf("bad: %#v", n)
   114  		}
   115  	})
   116  }
   117  
   118  func TestHTTP_NodeForceEval(t *testing.T) {
   119  	t.Parallel()
   120  	httpTest(t, nil, func(s *TestAgent) {
   121  		// Create the node
   122  		node := mock.Node()
   123  		args := structs.NodeRegisterRequest{
   124  			Node:         node,
   125  			WriteRequest: structs.WriteRequest{Region: "global"},
   126  		}
   127  		var resp structs.NodeUpdateResponse
   128  		if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil {
   129  			t.Fatalf("err: %v", err)
   130  		}
   131  
   132  		// Directly manipulate the state
   133  		state := s.Agent.server.State()
   134  		alloc1 := mock.Alloc()
   135  		alloc1.NodeID = node.ID
   136  		if err := state.UpsertJobSummary(999, mock.JobSummary(alloc1.JobID)); err != nil {
   137  			t.Fatal(err)
   138  		}
   139  		err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1})
   140  		if err != nil {
   141  			t.Fatalf("err: %v", err)
   142  		}
   143  
   144  		// Make the HTTP request
   145  		req, err := http.NewRequest("POST", "/v1/node/"+node.ID+"/evaluate", nil)
   146  		if err != nil {
   147  			t.Fatalf("err: %v", err)
   148  		}
   149  		respW := httptest.NewRecorder()
   150  
   151  		// Make the request
   152  		obj, err := s.Server.NodeSpecificRequest(respW, req)
   153  		if err != nil {
   154  			t.Fatalf("err: %v", err)
   155  		}
   156  
   157  		// Check for the index
   158  		if respW.HeaderMap.Get("X-Nomad-Index") == "" {
   159  			t.Fatalf("missing index")
   160  		}
   161  
   162  		// Check the response
   163  		upd := obj.(structs.NodeUpdateResponse)
   164  		if len(upd.EvalIDs) == 0 {
   165  			t.Fatalf("bad: %v", upd)
   166  		}
   167  	})
   168  }
   169  
   170  func TestHTTP_NodeAllocations(t *testing.T) {
   171  	t.Parallel()
   172  	httpTest(t, nil, func(s *TestAgent) {
   173  		// Create the job
   174  		node := mock.Node()
   175  		args := structs.NodeRegisterRequest{
   176  			Node:         node,
   177  			WriteRequest: structs.WriteRequest{Region: "global"},
   178  		}
   179  		var resp structs.NodeUpdateResponse
   180  		if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil {
   181  			t.Fatalf("err: %v", err)
   182  		}
   183  
   184  		// Directly manipulate the state
   185  		state := s.Agent.server.State()
   186  		alloc1 := mock.Alloc()
   187  		alloc1.NodeID = node.ID
   188  		if err := state.UpsertJobSummary(999, mock.JobSummary(alloc1.JobID)); err != nil {
   189  			t.Fatal(err)
   190  		}
   191  		// Create a test event for the allocation
   192  		testEvent := structs.NewTaskEvent(structs.TaskStarted)
   193  		var events []*structs.TaskEvent
   194  		events = append(events, testEvent)
   195  		taskState := &structs.TaskState{Events: events}
   196  		alloc1.TaskStates = make(map[string]*structs.TaskState)
   197  		alloc1.TaskStates["test"] = taskState
   198  
   199  		err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1})
   200  		if err != nil {
   201  			t.Fatalf("err: %v", err)
   202  		}
   203  
   204  		// Make the HTTP request
   205  		req, err := http.NewRequest("GET", "/v1/node/"+node.ID+"/allocations", nil)
   206  		if err != nil {
   207  			t.Fatalf("err: %v", err)
   208  		}
   209  		respW := httptest.NewRecorder()
   210  
   211  		// Make the request
   212  		obj, err := s.Server.NodeSpecificRequest(respW, req)
   213  		if err != nil {
   214  			t.Fatalf("err: %v", err)
   215  		}
   216  
   217  		// Check for the index
   218  		if respW.HeaderMap.Get("X-Nomad-Index") == "" {
   219  			t.Fatalf("missing index")
   220  		}
   221  		if respW.HeaderMap.Get("X-Nomad-KnownLeader") != "true" {
   222  			t.Fatalf("missing known leader")
   223  		}
   224  		if respW.HeaderMap.Get("X-Nomad-LastContact") == "" {
   225  			t.Fatalf("missing last contact")
   226  		}
   227  
   228  		// Check the node
   229  		allocs := obj.([]*structs.Allocation)
   230  		if len(allocs) != 1 || allocs[0].ID != alloc1.ID {
   231  			t.Fatalf("bad: %#v", allocs)
   232  		}
   233  		expectedDisplayMsg := "Task started by client"
   234  		displayMsg := allocs[0].TaskStates["test"].Events[0].DisplayMessage
   235  		assert.Equal(t, expectedDisplayMsg, displayMsg)
   236  	})
   237  }
   238  
   239  func TestHTTP_NodeDrain(t *testing.T) {
   240  	t.Parallel()
   241  	httpTest(t, nil, func(s *TestAgent) {
   242  		// Create the node
   243  		node := mock.Node()
   244  		args := structs.NodeRegisterRequest{
   245  			Node:         node,
   246  			WriteRequest: structs.WriteRequest{Region: "global"},
   247  		}
   248  		var resp structs.NodeUpdateResponse
   249  		if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil {
   250  			t.Fatalf("err: %v", err)
   251  		}
   252  
   253  		// Directly manipulate the state
   254  		state := s.Agent.server.State()
   255  		alloc1 := mock.Alloc()
   256  		alloc1.NodeID = node.ID
   257  		if err := state.UpsertJobSummary(999, mock.JobSummary(alloc1.JobID)); err != nil {
   258  			t.Fatal(err)
   259  		}
   260  		err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1})
   261  		if err != nil {
   262  			t.Fatalf("err: %v", err)
   263  		}
   264  
   265  		// Make the HTTP request
   266  		req, err := http.NewRequest("POST", "/v1/node/"+node.ID+"/drain?enable=1", nil)
   267  		if err != nil {
   268  			t.Fatalf("err: %v", err)
   269  		}
   270  		respW := httptest.NewRecorder()
   271  
   272  		// Make the request
   273  		obj, err := s.Server.NodeSpecificRequest(respW, req)
   274  		if err != nil {
   275  			t.Fatalf("err: %v", err)
   276  		}
   277  
   278  		// Check for the index
   279  		if respW.HeaderMap.Get("X-Nomad-Index") == "" {
   280  			t.Fatalf("missing index")
   281  		}
   282  
   283  		// Check the response
   284  		upd := obj.(structs.NodeDrainUpdateResponse)
   285  		if len(upd.EvalIDs) == 0 {
   286  			t.Fatalf("bad: %v", upd)
   287  		}
   288  	})
   289  }
   290  
   291  func TestHTTP_NodePurge(t *testing.T) {
   292  	t.Parallel()
   293  	httpTest(t, nil, func(s *TestAgent) {
   294  		// Create the node
   295  		node := mock.Node()
   296  		args := structs.NodeRegisterRequest{
   297  			Node:         node,
   298  			WriteRequest: structs.WriteRequest{Region: "global"},
   299  		}
   300  		var resp structs.NodeUpdateResponse
   301  		if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil {
   302  			t.Fatalf("err: %v", err)
   303  		}
   304  
   305  		// Add some allocations to the node
   306  		state := s.Agent.server.State()
   307  		alloc1 := mock.Alloc()
   308  		alloc1.NodeID = node.ID
   309  		if err := state.UpsertJobSummary(999, mock.JobSummary(alloc1.JobID)); err != nil {
   310  			t.Fatal(err)
   311  		}
   312  		err := state.UpsertAllocs(1000, []*structs.Allocation{alloc1})
   313  		if err != nil {
   314  			t.Fatalf("err: %v", err)
   315  		}
   316  
   317  		// Make the HTTP request to purge it
   318  		req, err := http.NewRequest("POST", "/v1/node/"+node.ID+"/purge", nil)
   319  		if err != nil {
   320  			t.Fatalf("err: %v", err)
   321  		}
   322  		respW := httptest.NewRecorder()
   323  
   324  		// Make the request
   325  		obj, err := s.Server.NodeSpecificRequest(respW, req)
   326  		if err != nil {
   327  			t.Fatalf("err: %v", err)
   328  		}
   329  
   330  		// Check for the index
   331  		if respW.HeaderMap.Get("X-Nomad-Index") == "" {
   332  			t.Fatalf("missing index")
   333  		}
   334  
   335  		// Check the response
   336  		upd := obj.(structs.NodeUpdateResponse)
   337  		if len(upd.EvalIDs) == 0 {
   338  			t.Fatalf("bad: %v", upd)
   339  		}
   340  
   341  		// Ensure that the node is not present anymore
   342  		args1 := structs.NodeSpecificRequest{
   343  			NodeID:       node.ID,
   344  			QueryOptions: structs.QueryOptions{Region: "global"},
   345  		}
   346  		var resp1 structs.SingleNodeResponse
   347  		if err := s.Agent.RPC("Node.GetNode", &args1, &resp1); err != nil {
   348  			t.Fatalf("err: %v", err)
   349  		}
   350  		if resp1.Node != nil {
   351  			t.Fatalf("node still exists after purging: %#v", resp1.Node)
   352  		}
   353  	})
   354  }
   355  
   356  func TestHTTP_NodeQuery(t *testing.T) {
   357  	t.Parallel()
   358  	httpTest(t, nil, func(s *TestAgent) {
   359  		// Create the job
   360  		node := mock.Node()
   361  		args := structs.NodeRegisterRequest{
   362  			Node:         node,
   363  			WriteRequest: structs.WriteRequest{Region: "global"},
   364  		}
   365  		var resp structs.NodeUpdateResponse
   366  		if err := s.Agent.RPC("Node.Register", &args, &resp); err != nil {
   367  			t.Fatalf("err: %v", err)
   368  		}
   369  
   370  		// Make the HTTP request
   371  		req, err := http.NewRequest("GET", "/v1/node/"+node.ID, nil)
   372  		if err != nil {
   373  			t.Fatalf("err: %v", err)
   374  		}
   375  		respW := httptest.NewRecorder()
   376  
   377  		// Make the request
   378  		obj, err := s.Server.NodeSpecificRequest(respW, req)
   379  		if err != nil {
   380  			t.Fatalf("err: %v", err)
   381  		}
   382  
   383  		// Check for the index
   384  		if respW.HeaderMap.Get("X-Nomad-Index") == "" {
   385  			t.Fatalf("missing index")
   386  		}
   387  		if respW.HeaderMap.Get("X-Nomad-KnownLeader") != "true" {
   388  			t.Fatalf("missing known leader")
   389  		}
   390  		if respW.HeaderMap.Get("X-Nomad-LastContact") == "" {
   391  			t.Fatalf("missing last contact")
   392  		}
   393  
   394  		// Check the node
   395  		n := obj.(*structs.Node)
   396  		if n.ID != node.ID {
   397  			t.Fatalf("bad: %#v", n)
   398  		}
   399  	})
   400  }