-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add 'body' field to service's 'check' stanza #10186
Conversation
I've manually tested this using this job: https://gist.github.com/nick96/02b29844856de7ecafa9e1c2e8bc7c09 The CLI returns the expected health checks, including the $ ./bin/nomad inspect whoami | jq '.Job.TaskGroups[0].Services[0].Checks[]'
{
"AddressMode": "",
"Args": null,
"Body": "{}",
"CheckRestart": null,
"Command": "",
"Expose": false,
"FailuresBeforeCritical": 0,
"GRPCService": "",
"GRPCUseTLS": false,
"Header": null,
"Id": "",
"InitialStatus": "",
"Interval": 5000000000,
"Method": "POST",
"Name": "service: \"whoami\" check",
"OnUpdate": "require_healthy",
"Path": "/",
"PortLabel": "",
"Protocol": "",
"SuccessBeforePassing": 0,
"TLSSkipVerify": false,
"TaskName": "",
"Timeout": 5000000000,
"Type": "http"
}
{
"AddressMode": "",
"Args": null,
"Body": "",
"CheckRestart": null,
"Command": "",
"Expose": false,
"FailuresBeforeCritical": 0,
"GRPCService": "",
"GRPCUseTLS": false,
"Header": null,
"Id": "",
"InitialStatus": "",
"Interval": 5000000000,
"Method": "GET",
"Name": "service: \"whoami\" check",
"OnUpdate": "require_healthy",
"Path": "/health",
"PortLabel": "",
"Protocol": "",
"SuccessBeforePassing": 0,
"TLSSkipVerify": false,
"TaskName": "",
"Timeout": 5000000000,
"Type": "http"
} API result is the same, except it doesn't contain the the $ curl http://localhost:4646/v1/job/whoami | jq -S '.TaskGroups[0].Services[0].Checks[]'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3484 0 3484 0 0 1134k 0 --:--:-- --:--:-- --:--:-- 1134k
{
"AddressMode": "",
"Args": null,
"Body": "{}",
"CheckRestart": null,
"Command": "",
"Expose": false,
"FailuresBeforeCritical": 0,
"GRPCService": "",
"GRPCUseTLS": false,
"Header": null,
"InitialStatus": "",
"Interval": 5000000000,
"Method": "POST",
"Name": "service: \"whoami\" check",
"OnUpdate": "require_healthy",
"Path": "/",
"PortLabel": "",
"Protocol": "",
"SuccessBeforePassing": 0,
"TLSSkipVerify": false,
"TaskName": "",
"Timeout": 5000000000,
"Type": "http"
}
{
"AddressMode": "",
"Args": null,
"Body": "",
"CheckRestart": null,
"Command": "",
"Expose": false,
"FailuresBeforeCritical": 0,
"GRPCService": "",
"GRPCUseTLS": false,
"Header": null,
"InitialStatus": "",
"Interval": 5000000000,
"Method": "GET",
"Name": "service: \"whoami\" check",
"OnUpdate": "require_healthy",
"Path": "/health",
"PortLabel": "",
"Protocol": "",
"SuccessBeforePassing": 0,
"TLSSkipVerify": false,
"TaskName": "",
"Timeout": 5000000000,
"Type": "http"
} The health check is successfully registered in Consul: |
Just playing around with this if I change the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @nick96! This is looking great so far!
@tgross I think I've fixed all your comments. PTAL when you get the chance |
Thanks @nick96. I'm in a bit of crunch today but will try to give this another pass by end-of-week. |
Hi @nick96 sorry about the delay on this review. I just wrote the following job spec file and tested it end-to-end and it looks good (including updates): echo server jobspecjob "example" {
datacenters = ["dc1"]
group "web" {
network {
mode = "bridge"
port "www" {
to = 8000
}
}
service {
port = "www"
check {
type = "http"
port = "www"
method = "POST"
path = "/"
# body = "check, please"
body = "make sure updates work, please"
interval = "10s"
timeout = "2s"
}
}
task "httpd" {
driver = "docker"
config {
image = "python:3.8-alpine"
command = "python"
args = ["/local/job.py"]
ports = ["www"]
}
template {
data = <<EOT
import http.server
class Handler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
post_data.decode('utf-8')
print(post_data)
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write("{}\n".format(post_data).encode('utf-8'))
def run(server_class=http.server.HTTPServer, handler_class=Handler):
server_address = ('', 8000)
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
if __name__ == '__main__':
run()
EOT
destination = "local/job.py"
}
resources {
cpu = 128
memory = 128
}
}
}
} I'm going to take one more pass over this tomorrow just for style or testing issues but I think we should be good to merge shortly. There's currently a merge conflict but I can clean that up real quick. Thanks for your patience! |
No worries! I'm away for the rest of this week so won't be able to address anything but will get onto it ASAP when I'm back. |
Consul allows specifying the HTTP body to send in a health check. Nomad uses Consul for health checking so this just plumbs the value through to where the Consul API is called. There is no validation that `body` is not used with an incompatible check method like GET.
Merged! Thanks again @nick96! |
I'm going to lock this pull request because it has been closed for 120 days ⏳. This helps our maintainers find and focus on the active contributions. |
This adds a
body
field to the servicecheck
stanza.As described in #10084 Consul has this field so it's just a matter of parsing it out of the job config and plumbing it through.
Currently there is no validation that the
method
andbody
make sense together (e.g.method
can be "GET" and thebody
field can exist). I couldn't find this validation in the Consul codebase either.I'm also still having a look around the code to see where different bits are tested.
New
jobspec
Entry ChecklistCode
api/
packageapi/
structs usually have Canonicalize and Copy methodsnomad/structs
packagestructs/
structs usually have Copy, Equals, and Validate methodsapi/
packageapi/
andnomad/structs
incommand/agent/job_endpoint.go
nomad/structs/diff.go
- This seems to just be handled by the generic diff function becausebody
is a primitiveFieldDiff
slices innomad/structs/diff_test.go
scheduler/util.go/tasksUpdated
- I think this is already handle in the equality check.Equals
but might not be, check.HCL1 (deprecated)
New jobspec entries should only be added to
jobspec2
. It makes use of HCL2and the
api
package for automatic parsing. Before, additional parsing wasrequired in the original
jobspec
package.Parse in(HCL1 only)jobspec/parse.go
Test in
(HCL1 only)jobspec/parse_test.go
(preferably with ajobspec/text-fixtures/<feature>.hcl
test file)Docs
Jobspec sidebar entry https://github.com/hashicorp/nomad/blob/main/website/data/docs-navigation.js