github.com/anuvu/nomad@v0.8.7-atom1/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 } 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 drainRequest structs.NodeUpdateEligibilityRequest 166 if err := decodeBody(req, &drainRequest); err != nil { 167 return nil, CodedError(400, err.Error()) 168 } 169 s.parseWriteRequest(req, &drainRequest.WriteRequest) 170 171 var out structs.NodeEligibilityUpdateResponse 172 if err := s.agent.RPC("Node.UpdateEligibility", &drainRequest, &out); err != nil { 173 return nil, err 174 } 175 setIndex(resp, out.Index) 176 return out, nil 177 } 178 179 func (s *HTTPServer) nodeQuery(resp http.ResponseWriter, req *http.Request, 180 nodeID string) (interface{}, error) { 181 if req.Method != "GET" { 182 return nil, CodedError(405, ErrInvalidMethod) 183 } 184 args := structs.NodeSpecificRequest{ 185 NodeID: nodeID, 186 } 187 if s.parse(resp, req, &args.Region, &args.QueryOptions) { 188 return nil, nil 189 } 190 191 var out structs.SingleNodeResponse 192 if err := s.agent.RPC("Node.GetNode", &args, &out); err != nil { 193 return nil, err 194 } 195 196 setMeta(resp, &out.QueryMeta) 197 if out.Node == nil { 198 return nil, CodedError(404, "node not found") 199 } 200 return out.Node, nil 201 } 202 203 func (s *HTTPServer) nodePurge(resp http.ResponseWriter, req *http.Request, nodeID string) (interface{}, error) { 204 if req.Method != "PUT" && req.Method != "POST" { 205 return nil, CodedError(405, ErrInvalidMethod) 206 } 207 args := structs.NodeDeregisterRequest{ 208 NodeID: nodeID, 209 } 210 s.parseWriteRequest(req, &args.WriteRequest) 211 var out structs.NodeUpdateResponse 212 if err := s.agent.RPC("Node.Deregister", &args, &out); err != nil { 213 return nil, err 214 } 215 setIndex(resp, out.Index) 216 return out, nil 217 }