208 lines
5.7 KiB
Go
208 lines
5.7 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package agent
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
)
|
|
|
|
func (s *HTTPServer) NodePoolsRequest(resp http.ResponseWriter, req *http.Request) (any, error) {
|
|
switch req.Method {
|
|
case http.MethodGet:
|
|
return s.nodePoolList(resp, req)
|
|
case http.MethodPut, http.MethodPost:
|
|
return s.nodePoolUpsert(resp, req, "")
|
|
default:
|
|
return nil, CodedError(http.StatusMethodNotAllowed, ErrInvalidMethod)
|
|
}
|
|
}
|
|
|
|
func (s *HTTPServer) NodePoolSpecificRequest(resp http.ResponseWriter, req *http.Request) (any, error) {
|
|
path := strings.TrimPrefix(req.URL.Path, "/v1/node/pool/")
|
|
switch {
|
|
case strings.HasSuffix(path, "/nodes"):
|
|
poolName := strings.TrimSuffix(path, "/nodes")
|
|
return s.nodePoolNodesList(resp, req, poolName)
|
|
case strings.HasSuffix(path, "/jobs"):
|
|
poolName := strings.TrimSuffix(path, "/jobs")
|
|
return s.nodePoolJobList(resp, req, poolName)
|
|
default:
|
|
return s.nodePoolCRUD(resp, req, path)
|
|
}
|
|
}
|
|
|
|
func (s *HTTPServer) nodePoolCRUD(resp http.ResponseWriter, req *http.Request, poolName string) (any, error) {
|
|
switch req.Method {
|
|
case http.MethodGet:
|
|
return s.nodePoolQuery(resp, req, poolName)
|
|
case http.MethodPut, http.MethodPost:
|
|
return s.nodePoolUpsert(resp, req, poolName)
|
|
case http.MethodDelete:
|
|
return s.nodePoolDelete(resp, req, poolName)
|
|
default:
|
|
return nil, CodedError(http.StatusMethodNotAllowed, ErrInvalidMethod)
|
|
}
|
|
}
|
|
|
|
func (s *HTTPServer) nodePoolList(resp http.ResponseWriter, req *http.Request) (any, error) {
|
|
args := structs.NodePoolListRequest{}
|
|
if s.parse(resp, req, &args.Region, &args.QueryOptions) {
|
|
return nil, nil
|
|
}
|
|
|
|
var out structs.NodePoolListResponse
|
|
if err := s.agent.RPC("NodePool.List", &args, &out); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
setMeta(resp, &out.QueryMeta)
|
|
if out.NodePools == nil {
|
|
out.NodePools = make([]*structs.NodePool, 0)
|
|
}
|
|
return out.NodePools, nil
|
|
}
|
|
|
|
func (s *HTTPServer) nodePoolQuery(resp http.ResponseWriter, req *http.Request, poolName string) (any, error) {
|
|
args := structs.NodePoolSpecificRequest{
|
|
Name: poolName,
|
|
}
|
|
if s.parse(resp, req, &args.Region, &args.QueryOptions) {
|
|
return nil, nil
|
|
}
|
|
|
|
var out structs.SingleNodePoolResponse
|
|
if err := s.agent.RPC("NodePool.GetNodePool", &args, &out); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
setMeta(resp, &out.QueryMeta)
|
|
if out.NodePool == nil {
|
|
return nil, CodedError(http.StatusNotFound, "node pool not found")
|
|
}
|
|
|
|
return out.NodePool, nil
|
|
}
|
|
|
|
func (s *HTTPServer) nodePoolUpsert(resp http.ResponseWriter, req *http.Request, poolName string) (any, error) {
|
|
var pool structs.NodePool
|
|
if err := decodeBody(req, &pool); err != nil {
|
|
return nil, CodedError(http.StatusBadRequest, err.Error())
|
|
}
|
|
|
|
if poolName != "" && pool.Name != poolName {
|
|
return nil, CodedError(http.StatusBadRequest, "Node pool name does not match request path")
|
|
}
|
|
|
|
args := structs.NodePoolUpsertRequest{
|
|
NodePools: []*structs.NodePool{&pool},
|
|
}
|
|
s.parseWriteRequest(req, &args.WriteRequest)
|
|
|
|
var out structs.GenericResponse
|
|
if err := s.agent.RPC("NodePool.UpsertNodePools", &args, &out); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
setIndex(resp, out.Index)
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *HTTPServer) nodePoolDelete(resp http.ResponseWriter, req *http.Request, poolName string) (any, error) {
|
|
args := structs.NodePoolDeleteRequest{
|
|
Names: []string{poolName},
|
|
}
|
|
s.parseWriteRequest(req, &args.WriteRequest)
|
|
|
|
var out structs.GenericResponse
|
|
if err := s.agent.RPC("NodePool.DeleteNodePools", &args, &out); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
setIndex(resp, out.Index)
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *HTTPServer) nodePoolNodesList(resp http.ResponseWriter, req *http.Request, poolName string) (interface{}, error) {
|
|
if req.Method != http.MethodGet {
|
|
return nil, CodedError(http.StatusMethodNotAllowed, ErrInvalidMethod)
|
|
}
|
|
|
|
args := structs.NodePoolNodesRequest{
|
|
Name: poolName,
|
|
}
|
|
if s.parse(resp, req, &args.Region, &args.QueryOptions) {
|
|
return nil, nil
|
|
}
|
|
|
|
// Parse node fields selection.
|
|
fields, err := parseNodeListStubFields(req)
|
|
if err != nil {
|
|
return nil, CodedError(http.StatusBadRequest, fmt.Sprintf("Failed to parse node list fields: %v", err))
|
|
}
|
|
args.Fields = fields
|
|
|
|
if args.Prefix != "" {
|
|
// the prefix argument is ambiguous for this endpoint (does it refer to
|
|
// the node pool name or the node IDs like /v1/nodes?) so the RPC
|
|
// handler ignores it
|
|
return nil, CodedError(http.StatusBadRequest, "prefix argument not allowed")
|
|
}
|
|
|
|
var out structs.NodePoolNodesResponse
|
|
if err := s.agent.RPC("NodePool.ListNodes", &args, &out); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
setMeta(resp, &out.QueryMeta)
|
|
if out.Nodes == nil {
|
|
out.Nodes = make([]*structs.NodeListStub, 0)
|
|
}
|
|
return out.Nodes, nil
|
|
}
|
|
|
|
func (s *HTTPServer) nodePoolJobList(resp http.ResponseWriter, req *http.Request, poolName string) (any, error) {
|
|
if req.Method != http.MethodGet {
|
|
return nil, CodedError(http.StatusMethodNotAllowed, ErrInvalidMethod)
|
|
}
|
|
|
|
args := structs.NodePoolJobsRequest{
|
|
Name: poolName,
|
|
}
|
|
if s.parse(resp, req, &args.Region, &args.QueryOptions) {
|
|
return nil, nil
|
|
}
|
|
|
|
if args.Prefix != "" {
|
|
// the prefix argument is ambiguous for this endpoint (does it refer to
|
|
// the node pool name or the job names like /v1/jobs?) so the RPC
|
|
// handler ignores it
|
|
return nil, CodedError(http.StatusBadRequest, "prefix argument not allowed")
|
|
}
|
|
|
|
// Parse meta query param
|
|
args.Fields = &structs.JobStubFields{}
|
|
jobMeta, err := parseBool(req, "meta")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if jobMeta != nil {
|
|
args.Fields.Meta = *jobMeta
|
|
}
|
|
|
|
var out structs.NodePoolJobsResponse
|
|
if err := s.agent.RPC("NodePool.ListJobs", &args, &out); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
setMeta(resp, &out.QueryMeta)
|
|
if out.Jobs == nil {
|
|
out.Jobs = make([]*structs.JobListStub, 0)
|
|
}
|
|
return out.Jobs, nil
|
|
}
|