diff --git a/api/api.go b/api/api.go index 87aa45ec751..bacb7c3c9ef 100644 --- a/api/api.go +++ b/api/api.go @@ -453,8 +453,8 @@ func (c *Client) getNodeClientImpl(nodeID string, timeout time.Duration, q *Quer // If the client is configured for a particular region use that region = c.config.Region default: - // No region information is given so use the default. - region = "global" + // No region information is given so use GlobalRegion as the default. + region = GlobalRegion } // Get an API client for the node diff --git a/api/jobs.go b/api/jobs.go index 901b41e7f17..9964990235c 100644 --- a/api/jobs.go +++ b/api/jobs.go @@ -25,6 +25,13 @@ const ( // DefaultNamespace is the default namespace. DefaultNamespace = "default" + + // For Job configuration, GlobalRegion is a sentinel region value + // that users may specify to indicate the job should be run on + // the region of the node that the job was submitted to. + // For Client configuration, if no region information is given, + // the client node will default to be part of the GlobalRegion. + GlobalRegion = "global" ) const ( @@ -704,7 +711,7 @@ func (j *Job) Canonicalize() { j.Stop = boolToPtr(false) } if j.Region == nil { - j.Region = stringToPtr("global") + j.Region = stringToPtr(GlobalRegion) } if j.Namespace == nil { j.Namespace = stringToPtr("default") diff --git a/command/agent/job_endpoint.go b/command/agent/job_endpoint.go index a42ce63de9f..6353c51e2c2 100644 --- a/command/agent/job_endpoint.go +++ b/command/agent/job_endpoint.go @@ -141,12 +141,16 @@ func (s *HTTPServer) jobPlan(resp http.ResponseWriter, req *http.Request, return nil, CodedError(400, "Job ID does not match") } - // Http region takes precedence over hcl region + // Region in http request query param takes precedence over region in job hcl config if args.WriteRequest.Region != "" { args.Job.Region = helper.StringToPtr(args.WriteRequest.Region) } + // If 'global' region is specified or if no region is given, + // default to region of the node you're submitting to + if args.Job.Region == nil || *args.Job.Region == "" || *args.Job.Region == api.GlobalRegion { + args.Job.Region = &s.agent.config.Region + } - // If no region given, region is canonicalized to 'global' sJob := ApiJobToStructJob(args.Job) planReq := structs.JobPlanRequest{ @@ -157,6 +161,8 @@ func (s *HTTPServer) jobPlan(resp http.ResponseWriter, req *http.Request, Region: sJob.Region, }, } + // parseWriteRequest overrides Namespace, Region and AuthToken + // based on values from the original http request s.parseWriteRequest(req, &planReq.WriteRequest) planReq.Namespace = sJob.Namespace @@ -384,12 +390,16 @@ func (s *HTTPServer) jobUpdate(resp http.ResponseWriter, req *http.Request, return nil, CodedError(400, "Job ID does not match name") } - // Http region takes precedence over hcl region + // Region in http request query param takes precedence over region in job hcl config if args.WriteRequest.Region != "" { args.Job.Region = helper.StringToPtr(args.WriteRequest.Region) } + // If 'global' region is specified or if no region is given, + // default to region of the node you're submitting to + if args.Job.Region == nil || *args.Job.Region == "" || *args.Job.Region == api.GlobalRegion { + args.Job.Region = &s.agent.config.Region + } - // If no region given, region is canonicalized to 'global' sJob := ApiJobToStructJob(args.Job) regReq := structs.JobRegisterRequest{ @@ -402,6 +412,8 @@ func (s *HTTPServer) jobUpdate(resp http.ResponseWriter, req *http.Request, AuthToken: args.WriteRequest.SecretID, }, } + // parseWriteRequest overrides Namespace, Region and AuthToken + // based on values from the original http request s.parseWriteRequest(req, ®Req.WriteRequest) regReq.Namespace = sJob.Namespace diff --git a/command/agent/job_endpoint_test.go b/command/agent/job_endpoint_test.go index ba2912bbcb9..fdc2f4a1282 100644 --- a/command/agent/job_endpoint_test.go +++ b/command/agent/job_endpoint_test.go @@ -493,11 +493,17 @@ func TestHTTP_JobUpdateRegion(t *testing.T) { ExpectedRegion: "north-america", }, { - Name: "falls back to default if no region is provided", + Name: "defaults to node region global if no region is provided", ConfigRegion: "", APIRegion: "", ExpectedRegion: "global", }, + { + Name: "defaults to node region not-global if no region is provided", + ConfigRegion: "", + APIRegion: "", + ExpectedRegion: "not-global", + }, } for _, tc := range cases {