github.com/thomasobenaus/nomad@v0.11.1/command/agent/node_endpoint.go (about)

     1  package agent
     2  
     3  import (
     4  	"net/http"
     5  	"strconv"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/hashicorp/nomad/api"
    10  	"github.com/hashicorp/nomad/nomad/structs"
    11  )
    12  
    13  func (s *HTTPServer) NodesRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
    14  	if req.Method != "GET" {
    15  		return nil, CodedError(405, ErrInvalidMethod)
    16  	}
    17  
    18  	args := structs.NodeListRequest{}
    19  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
    20  		return nil, nil
    21  	}
    22  
    23  	var out structs.NodeListResponse
    24  	if err := s.agent.RPC("Node.List", &args, &out); err != nil {
    25  		return nil, err
    26  	}
    27  
    28  	setMeta(resp, &out.QueryMeta)
    29  	if out.Nodes == nil {
    30  		out.Nodes = make([]*structs.NodeListStub, 0)
    31  	}
    32  	return out.Nodes, nil
    33  }
    34  
    35  func (s *HTTPServer) NodeSpecificRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
    36  	path := strings.TrimPrefix(req.URL.Path, "/v1/node/")
    37  	switch {
    38  	case strings.HasSuffix(path, "/evaluate"):
    39  		nodeName := strings.TrimSuffix(path, "/evaluate")
    40  		return s.nodeForceEvaluate(resp, req, nodeName)
    41  	case strings.HasSuffix(path, "/allocations"):
    42  		nodeName := strings.TrimSuffix(path, "/allocations")
    43  		return s.nodeAllocations(resp, req, nodeName)
    44  	case strings.HasSuffix(path, "/drain"):
    45  		nodeName := strings.TrimSuffix(path, "/drain")
    46  		return s.nodeToggleDrain(resp, req, nodeName)
    47  	case strings.HasSuffix(path, "/eligibility"):
    48  		nodeName := strings.TrimSuffix(path, "/eligibility")
    49  		return s.nodeToggleEligibility(resp, req, nodeName)
    50  	case strings.HasSuffix(path, "/purge"):
    51  		nodeName := strings.TrimSuffix(path, "/purge")
    52  		return s.nodePurge(resp, req, nodeName)
    53  	default:
    54  		return s.nodeQuery(resp, req, path)
    55  	}
    56  }
    57  
    58  func (s *HTTPServer) nodeForceEvaluate(resp http.ResponseWriter, req *http.Request,
    59  	nodeID string) (interface{}, error) {
    60  	if req.Method != "PUT" && req.Method != "POST" {
    61  		return nil, CodedError(405, ErrInvalidMethod)
    62  	}
    63  	args := structs.NodeEvaluateRequest{
    64  		NodeID: nodeID,
    65  	}
    66  	s.parseWriteRequest(req, &args.WriteRequest)
    67  
    68  	var out structs.NodeUpdateResponse
    69  	if err := s.agent.RPC("Node.Evaluate", &args, &out); err != nil {
    70  		return nil, err
    71  	}
    72  	setIndex(resp, out.Index)
    73  	return out, nil
    74  }
    75  
    76  func (s *HTTPServer) nodeAllocations(resp http.ResponseWriter, req *http.Request,
    77  	nodeID string) (interface{}, error) {
    78  	if req.Method != "GET" {
    79  		return nil, CodedError(405, ErrInvalidMethod)
    80  	}
    81  	args := structs.NodeSpecificRequest{
    82  		NodeID: nodeID,
    83  	}
    84  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
    85  		return nil, nil
    86  	}
    87  
    88  	var out structs.NodeAllocsResponse
    89  	if err := s.agent.RPC("Node.GetAllocs", &args, &out); err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	setMeta(resp, &out.QueryMeta)
    94  	if out.Allocs == nil {
    95  		out.Allocs = make([]*structs.Allocation, 0)
    96  	}
    97  	for _, alloc := range out.Allocs {
    98  		alloc.SetEventDisplayMessages()
    99  	}
   100  	return out.Allocs, nil
   101  }
   102  
   103  func (s *HTTPServer) nodeToggleDrain(resp http.ResponseWriter, req *http.Request,
   104  	nodeID string) (interface{}, error) {
   105  	if req.Method != "PUT" && req.Method != "POST" {
   106  		return nil, CodedError(405, ErrInvalidMethod)
   107  	}
   108  
   109  	var drainRequest api.NodeUpdateDrainRequest
   110  
   111  	// COMPAT: Remove in 0.10. Allow the old style enable query param.
   112  	// Get the enable parameter
   113  	enableRaw := req.URL.Query().Get("enable")
   114  	var enable bool
   115  	if enableRaw != "" {
   116  		var err error
   117  		enable, err = strconv.ParseBool(enableRaw)
   118  		if err != nil {
   119  			return nil, CodedError(400, "invalid enable value")
   120  		}
   121  
   122  		// Use the force drain to have it keep the same behavior as old clients.
   123  		if enable {
   124  			drainRequest.DrainSpec = &api.DrainSpec{
   125  				Deadline: -1 * time.Second,
   126  			}
   127  		} else {
   128  			// If drain is disabled on an old client, mark the node as eligible for backwards compatibility
   129  			drainRequest.MarkEligible = true
   130  		}
   131  	} else {
   132  		if err := decodeBody(req, &drainRequest); err != nil {
   133  			return nil, CodedError(400, err.Error())
   134  		}
   135  	}
   136  
   137  	args := structs.NodeUpdateDrainRequest{
   138  		NodeID:       nodeID,
   139  		MarkEligible: drainRequest.MarkEligible,
   140  	}
   141  	if drainRequest.DrainSpec != nil {
   142  		args.DrainStrategy = &structs.DrainStrategy{
   143  			DrainSpec: structs.DrainSpec{
   144  				Deadline:         drainRequest.DrainSpec.Deadline,
   145  				IgnoreSystemJobs: drainRequest.DrainSpec.IgnoreSystemJobs,
   146  			},
   147  		}
   148  	}
   149  	s.parseWriteRequest(req, &args.WriteRequest)
   150  
   151  	var out structs.NodeDrainUpdateResponse
   152  	if err := s.agent.RPC("Node.UpdateDrain", &args, &out); err != nil {
   153  		return nil, err
   154  	}
   155  	setIndex(resp, out.Index)
   156  	return out, nil
   157  }
   158  
   159  func (s *HTTPServer) nodeToggleEligibility(resp http.ResponseWriter, req *http.Request,
   160  	nodeID string) (interface{}, error) {
   161  	if req.Method != "PUT" && req.Method != "POST" {
   162  		return nil, CodedError(405, ErrInvalidMethod)
   163  	}
   164  
   165  	var eligibilityRequest structs.NodeUpdateEligibilityRequest
   166  	if err := decodeBody(req, &eligibilityRequest); err != nil {
   167  		return nil, CodedError(400, err.Error())
   168  	}
   169  	if eligibilityRequest.NodeID == "" {
   170  		eligibilityRequest.NodeID = nodeID
   171  	}
   172  
   173  	s.parseWriteRequest(req, &eligibilityRequest.WriteRequest)
   174  
   175  	var out structs.NodeEligibilityUpdateResponse
   176  	if err := s.agent.RPC("Node.UpdateEligibility", &eligibilityRequest, &out); err != nil {
   177  		return nil, err
   178  	}
   179  	setIndex(resp, out.Index)
   180  	return out, nil
   181  }
   182  
   183  func (s *HTTPServer) nodeQuery(resp http.ResponseWriter, req *http.Request,
   184  	nodeID string) (interface{}, error) {
   185  	if req.Method != "GET" {
   186  		return nil, CodedError(405, ErrInvalidMethod)
   187  	}
   188  	args := structs.NodeSpecificRequest{
   189  		NodeID: nodeID,
   190  	}
   191  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
   192  		return nil, nil
   193  	}
   194  
   195  	var out structs.SingleNodeResponse
   196  	if err := s.agent.RPC("Node.GetNode", &args, &out); err != nil {
   197  		return nil, err
   198  	}
   199  
   200  	setMeta(resp, &out.QueryMeta)
   201  	if out.Node == nil {
   202  		return nil, CodedError(404, "node not found")
   203  	}
   204  	return out.Node, nil
   205  }
   206  
   207  func (s *HTTPServer) nodePurge(resp http.ResponseWriter, req *http.Request, nodeID string) (interface{}, error) {
   208  	if req.Method != "PUT" && req.Method != "POST" {
   209  		return nil, CodedError(405, ErrInvalidMethod)
   210  	}
   211  	args := structs.NodeDeregisterRequest{
   212  		NodeID: nodeID,
   213  	}
   214  	s.parseWriteRequest(req, &args.WriteRequest)
   215  	var out structs.NodeUpdateResponse
   216  	if err := s.agent.RPC("Node.Deregister", &args, &out); err != nil {
   217  		return nil, err
   218  	}
   219  	setIndex(resp, out.Index)
   220  	return out, nil
   221  }