github.com/mongey/nomad@v0.5.2/command/agent/job_endpoint.go (about)

     1  package agent
     2  
     3  import (
     4  	"net/http"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/nomad/nomad/structs"
     9  )
    10  
    11  func (s *HTTPServer) JobsRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
    12  	switch req.Method {
    13  	case "GET":
    14  		return s.jobListRequest(resp, req)
    15  	case "PUT", "POST":
    16  		return s.jobUpdate(resp, req, "")
    17  	default:
    18  		return nil, CodedError(405, ErrInvalidMethod)
    19  	}
    20  }
    21  
    22  func (s *HTTPServer) jobListRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
    23  	args := structs.JobListRequest{}
    24  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
    25  		return nil, nil
    26  	}
    27  
    28  	var out structs.JobListResponse
    29  	if err := s.agent.RPC("Job.List", &args, &out); err != nil {
    30  		return nil, err
    31  	}
    32  
    33  	setMeta(resp, &out.QueryMeta)
    34  	if out.Jobs == nil {
    35  		out.Jobs = make([]*structs.JobListStub, 0)
    36  	}
    37  	return out.Jobs, nil
    38  }
    39  
    40  func (s *HTTPServer) JobSpecificRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
    41  	path := strings.TrimPrefix(req.URL.Path, "/v1/job/")
    42  	switch {
    43  	case strings.HasSuffix(path, "/evaluate"):
    44  		jobName := strings.TrimSuffix(path, "/evaluate")
    45  		return s.jobForceEvaluate(resp, req, jobName)
    46  	case strings.HasSuffix(path, "/allocations"):
    47  		jobName := strings.TrimSuffix(path, "/allocations")
    48  		return s.jobAllocations(resp, req, jobName)
    49  	case strings.HasSuffix(path, "/evaluations"):
    50  		jobName := strings.TrimSuffix(path, "/evaluations")
    51  		return s.jobEvaluations(resp, req, jobName)
    52  	case strings.HasSuffix(path, "/periodic/force"):
    53  		jobName := strings.TrimSuffix(path, "/periodic/force")
    54  		return s.periodicForceRequest(resp, req, jobName)
    55  	case strings.HasSuffix(path, "/plan"):
    56  		jobName := strings.TrimSuffix(path, "/plan")
    57  		return s.jobPlan(resp, req, jobName)
    58  	case strings.HasSuffix(path, "/summary"):
    59  		jobName := strings.TrimSuffix(path, "/summary")
    60  		return s.jobSummaryRequest(resp, req, jobName)
    61  	default:
    62  		return s.jobCRUD(resp, req, path)
    63  	}
    64  }
    65  
    66  func (s *HTTPServer) jobForceEvaluate(resp http.ResponseWriter, req *http.Request,
    67  	jobName string) (interface{}, error) {
    68  	if req.Method != "PUT" && req.Method != "POST" {
    69  		return nil, CodedError(405, ErrInvalidMethod)
    70  	}
    71  	args := structs.JobEvaluateRequest{
    72  		JobID: jobName,
    73  	}
    74  	s.parseRegion(req, &args.Region)
    75  
    76  	var out structs.JobRegisterResponse
    77  	if err := s.agent.RPC("Job.Evaluate", &args, &out); err != nil {
    78  		return nil, err
    79  	}
    80  	setIndex(resp, out.Index)
    81  	return out, nil
    82  }
    83  
    84  func (s *HTTPServer) jobPlan(resp http.ResponseWriter, req *http.Request,
    85  	jobName string) (interface{}, error) {
    86  	if req.Method != "PUT" && req.Method != "POST" {
    87  		return nil, CodedError(405, ErrInvalidMethod)
    88  	}
    89  
    90  	var args structs.JobPlanRequest
    91  	if err := decodeBody(req, &args); err != nil {
    92  		return nil, CodedError(400, err.Error())
    93  	}
    94  	if args.Job == nil {
    95  		return nil, CodedError(400, "Job must be specified")
    96  	}
    97  	if jobName != "" && args.Job.ID != jobName {
    98  		return nil, CodedError(400, "Job ID does not match")
    99  	}
   100  	s.parseRegion(req, &args.Region)
   101  
   102  	var out structs.JobPlanResponse
   103  	if err := s.agent.RPC("Job.Plan", &args, &out); err != nil {
   104  		return nil, err
   105  	}
   106  	setIndex(resp, out.Index)
   107  	return out, nil
   108  }
   109  
   110  func (s *HTTPServer) periodicForceRequest(resp http.ResponseWriter, req *http.Request,
   111  	jobName string) (interface{}, error) {
   112  	if req.Method != "PUT" && req.Method != "POST" {
   113  		return nil, CodedError(405, ErrInvalidMethod)
   114  	}
   115  
   116  	args := structs.PeriodicForceRequest{
   117  		JobID: jobName,
   118  	}
   119  	s.parseRegion(req, &args.Region)
   120  
   121  	var out structs.PeriodicForceResponse
   122  	if err := s.agent.RPC("Periodic.Force", &args, &out); err != nil {
   123  		return nil, err
   124  	}
   125  	setIndex(resp, out.Index)
   126  	return out, nil
   127  }
   128  
   129  func (s *HTTPServer) jobAllocations(resp http.ResponseWriter, req *http.Request,
   130  	jobName string) (interface{}, error) {
   131  	if req.Method != "GET" {
   132  		return nil, CodedError(405, ErrInvalidMethod)
   133  	}
   134  	allAllocs, _ := strconv.ParseBool(req.URL.Query().Get("all"))
   135  
   136  	args := structs.JobSpecificRequest{
   137  		JobID:     jobName,
   138  		AllAllocs: allAllocs,
   139  	}
   140  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
   141  		return nil, nil
   142  	}
   143  
   144  	var out structs.JobAllocationsResponse
   145  	if err := s.agent.RPC("Job.Allocations", &args, &out); err != nil {
   146  		return nil, err
   147  	}
   148  
   149  	setMeta(resp, &out.QueryMeta)
   150  	if out.Allocations == nil {
   151  		out.Allocations = make([]*structs.AllocListStub, 0)
   152  	}
   153  	return out.Allocations, nil
   154  }
   155  
   156  func (s *HTTPServer) jobEvaluations(resp http.ResponseWriter, req *http.Request,
   157  	jobName string) (interface{}, error) {
   158  	if req.Method != "GET" {
   159  		return nil, CodedError(405, ErrInvalidMethod)
   160  	}
   161  	args := structs.JobSpecificRequest{
   162  		JobID: jobName,
   163  	}
   164  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
   165  		return nil, nil
   166  	}
   167  
   168  	var out structs.JobEvaluationsResponse
   169  	if err := s.agent.RPC("Job.Evaluations", &args, &out); err != nil {
   170  		return nil, err
   171  	}
   172  
   173  	setMeta(resp, &out.QueryMeta)
   174  	if out.Evaluations == nil {
   175  		out.Evaluations = make([]*structs.Evaluation, 0)
   176  	}
   177  	return out.Evaluations, nil
   178  }
   179  
   180  func (s *HTTPServer) jobCRUD(resp http.ResponseWriter, req *http.Request,
   181  	jobName string) (interface{}, error) {
   182  	switch req.Method {
   183  	case "GET":
   184  		return s.jobQuery(resp, req, jobName)
   185  	case "PUT", "POST":
   186  		return s.jobUpdate(resp, req, jobName)
   187  	case "DELETE":
   188  		return s.jobDelete(resp, req, jobName)
   189  	default:
   190  		return nil, CodedError(405, ErrInvalidMethod)
   191  	}
   192  }
   193  
   194  func (s *HTTPServer) jobQuery(resp http.ResponseWriter, req *http.Request,
   195  	jobName string) (interface{}, error) {
   196  	args := structs.JobSpecificRequest{
   197  		JobID: jobName,
   198  	}
   199  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
   200  		return nil, nil
   201  	}
   202  
   203  	var out structs.SingleJobResponse
   204  	if err := s.agent.RPC("Job.GetJob", &args, &out); err != nil {
   205  		return nil, err
   206  	}
   207  
   208  	setMeta(resp, &out.QueryMeta)
   209  	if out.Job == nil {
   210  		return nil, CodedError(404, "job not found")
   211  	}
   212  	return out.Job, nil
   213  }
   214  
   215  func (s *HTTPServer) jobUpdate(resp http.ResponseWriter, req *http.Request,
   216  	jobName string) (interface{}, error) {
   217  	var args structs.JobRegisterRequest
   218  	if err := decodeBody(req, &args); err != nil {
   219  		return nil, CodedError(400, err.Error())
   220  	}
   221  	if args.Job == nil {
   222  		return nil, CodedError(400, "Job must be specified")
   223  	}
   224  	if jobName != "" && args.Job.ID != jobName {
   225  		return nil, CodedError(400, "Job ID does not match")
   226  	}
   227  	s.parseRegion(req, &args.Region)
   228  
   229  	var out structs.JobRegisterResponse
   230  	if err := s.agent.RPC("Job.Register", &args, &out); err != nil {
   231  		return nil, err
   232  	}
   233  	setIndex(resp, out.Index)
   234  	return out, nil
   235  }
   236  
   237  func (s *HTTPServer) jobDelete(resp http.ResponseWriter, req *http.Request,
   238  	jobName string) (interface{}, error) {
   239  	args := structs.JobDeregisterRequest{
   240  		JobID: jobName,
   241  	}
   242  	s.parseRegion(req, &args.Region)
   243  
   244  	var out structs.JobDeregisterResponse
   245  	if err := s.agent.RPC("Job.Deregister", &args, &out); err != nil {
   246  		return nil, err
   247  	}
   248  	setIndex(resp, out.Index)
   249  	return out, nil
   250  }
   251  
   252  func (s *HTTPServer) jobSummaryRequest(resp http.ResponseWriter, req *http.Request, name string) (interface{}, error) {
   253  	args := structs.JobSummaryRequest{
   254  		JobID: name,
   255  	}
   256  	if s.parse(resp, req, &args.Region, &args.QueryOptions) {
   257  		return nil, nil
   258  	}
   259  
   260  	var out structs.JobSummaryResponse
   261  	if err := s.agent.RPC("Job.Summary", &args, &out); err != nil {
   262  		return nil, err
   263  	}
   264  
   265  	setMeta(resp, &out.QueryMeta)
   266  	if out.JobSummary == nil {
   267  		return nil, CodedError(404, "job not found")
   268  	}
   269  	setIndex(resp, out.Index)
   270  	return out.JobSummary, nil
   271  }