github.com/djenriquez/nomad-1@v0.8.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.9. 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  		}
   128  	} else {
   129  		if err := decodeBody(req, &drainRequest); err != nil {
   130  			return nil, CodedError(400, err.Error())
   131  		}
   132  	}
   133  
   134  	args := structs.NodeUpdateDrainRequest{
   135  		NodeID:       nodeID,
   136  		MarkEligible: drainRequest.MarkEligible,
   137  	}
   138  	if drainRequest.DrainSpec != nil {
   139  		args.DrainStrategy = &structs.DrainStrategy{
   140  			DrainSpec: structs.DrainSpec{
   141  				Deadline:         drainRequest.DrainSpec.Deadline,
   142  				IgnoreSystemJobs: drainRequest.DrainSpec.IgnoreSystemJobs,
   143  			},
   144  		}
   145  	}
   146  	s.parseWriteRequest(req, &args.WriteRequest)
   147  
   148  	var out structs.NodeDrainUpdateResponse
   149  	if err := s.agent.RPC("Node.UpdateDrain", &args, &out); err != nil {
   150  		return nil, err
   151  	}
   152  	setIndex(resp, out.Index)
   153  	return out, nil
   154  }
   155  
   156  func (s *HTTPServer) nodeToggleEligibility(resp http.ResponseWriter, req *http.Request,
   157  	nodeID string) (interface{}, error) {
   158  	if req.Method != "PUT" && req.Method != "POST" {
   159  		return nil, CodedError(405, ErrInvalidMethod)
   160  	}
   161  
   162  	var drainRequest structs.NodeUpdateEligibilityRequest
   163  	if err := decodeBody(req, &drainRequest); err != nil {
   164  		return nil, CodedError(400, err.Error())
   165  	}
   166  	s.parseWriteRequest(req, &drainRequest.WriteRequest)
   167  
   168  	var out structs.NodeEligibilityUpdateResponse
   169  	if err := s.agent.RPC("Node.UpdateEligibility", &drainRequest, &out); err != nil {
   170  		return nil, err
   171  	}
   172  	setIndex(resp, out.Index)
   173  	return out, nil
   174  }
   175  
   176  func (s *HTTPServer) nodeQuery(resp http.ResponseWriter, req *http.Request,
   177  	nodeID string) (interface{}, error) {
   178  	if req.Method != "GET" {
   179  		return nil, CodedError(405, ErrInvalidMethod)
   180  	}
   181  	args := structs.NodeSpecificRequest{
   182  		NodeID: nodeID,
   183  	}
   184  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
   185  		return nil, nil
   186  	}
   187  
   188  	var out structs.SingleNodeResponse
   189  	if err := s.agent.RPC("Node.GetNode", &args, &out); err != nil {
   190  		return nil, err
   191  	}
   192  
   193  	setMeta(resp, &out.QueryMeta)
   194  	if out.Node == nil {
   195  		return nil, CodedError(404, "node not found")
   196  	}
   197  	return out.Node, nil
   198  }
   199  
   200  func (s *HTTPServer) nodePurge(resp http.ResponseWriter, req *http.Request, nodeID string) (interface{}, error) {
   201  	if req.Method != "PUT" && req.Method != "POST" {
   202  		return nil, CodedError(405, ErrInvalidMethod)
   203  	}
   204  	args := structs.NodeDeregisterRequest{
   205  		NodeID: nodeID,
   206  	}
   207  	s.parseWriteRequest(req, &args.WriteRequest)
   208  	var out structs.NodeUpdateResponse
   209  	if err := s.agent.RPC("Node.Deregister", &args, &out); err != nil {
   210  		return nil, err
   211  	}
   212  	setIndex(resp, out.Index)
   213  	return out, nil
   214  }