github.com/mattyr/nomad@v0.3.3-0.20160919021406-3485a065154a/command/agent/job_endpoint.go (about)

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