-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Accept JSON via nomad job run #6758
Comments
Hi @ccakes! You're right that the command line doesn't accept the JSON version of the jobspec directly, but the HTTP API does. In fact, the command line client converts the HCL to JSON before POSTing it to the HTTP API itself. So you're right that the best way to do this is to use ▶ nomad job init -short
▶ nomad job run ./example.nomad
==> Monitoring evaluation "6d962c2e"
Evaluation triggered by job "example"
Allocation "ea878e56" created: node "707a29ca", group "cache"
Evaluation within deployment: "8b08b848"
Allocation "ea878e56" status changed: "pending" -> "running" (Tasks are running)
Evaluation status changed: "pending" -> "complete"
==> Evaluation "6d962c2e" finished with status "complete"
▶ nomad job inspect example > example.json
▶ nomad job stop example
==> Monitoring evaluation "17721706"
Evaluation triggered by job "example"
Evaluation within deployment: "8b08b848"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "17721706" finished with status "complete"
▶ curl -XPOST -H "Content-Type: application/json" \
-d @example.json http://localhost:4646/v1/jobs
{"EvalCreateIndex":27,"EvalID":"0320367b-cdd8-dd4f-bedc-77aafcc5ec02","Index":27,"JobModifyIndex":26,"KnownLeader":false,"LastContact":0,"Warnings":""}%
▶ nomad job status example
ID = example
Name = example
Submit Date = 2019-11-22T08:25:19-05:00
Type = service
Priority = 50
Datacenters = dc1
Status = running
Periodic = false
Parameterized = false
Summary
Task Group Queued Starting Running Failed Complete Lost
cache 0 0 1 0 1 0
Latest Deployment
ID = 114691ea
Status = running
Description = Deployment is running
Deployed
Task Group Desired Placed Healthy Unhealthy Progress Deadline
cache 1 1 0 0 2019-11-22T13:35:19Z
Allocations
ID Node ID Task Group Version Desired Status Created Modified
157bdc9a 707a29ca cache 2 run running 8s ago 7s ago
ea878e56 707a29ca cache 0 stop complete 1m19s ago 53s ago I hope this helps! |
Thanks for the reply! The intent is to run this from within a Nomad job where the environment is already setup nicely to call the Definitely do-able, but not ideal 😉 Was intending this to be a bit of a feature request to create a way for the CLI to output a format which can be read back in. |
It'd be a nice quality-of-life improvement for sure to allow for some kind of round-tripping of the jobspec with the CLI. Marking this as an enhancement. |
This behavior is very surprising and disappointing. |
Also, since |
@tgross What would be a good way to approach this? Introduce a boolean CLI flag If this flag is set, you can either do (1) or (2):
where and use this generic interface
Then you can just use that job struct to OR
|
I'm new to Nomad and this lack of consistency is frustrating. Ideally you could |
+1 that this is a surprising omission, and one that feels like a bug given the HCL Readme (linked from the Nomad job spec docs):
Would it be reasonable for the CLI to detect JSON and just skip any of the parsing? |
I wanted to circle back to this because there was an internal discussion that generated some confusion around the command line vs the HTTP API, "round tripping", and what is and is not currently supported. A few important notes for the discussion here and any future implementations:
ReadJob HTTP API is not round-trippable
{
"Affinities": null,
"AllAtOnce": false,
"Constraints": null,
"ConsulToken": "",
"CreateIndex": 10,
"Datacenters": [
"dc1"
],
"Dispatched": false,
"ID": "example",
"JobModifyIndex": 10,
"Meta": null,
"ModifyIndex": 17,
"Multiregion": null,
"Name": "example",
"Namespace": "default",
"NomadTokenID": "",
"ParameterizedJob": null,
"ParentID": "",
"Payload": null,
"Periodic": null,
"Priority": 50,
"Region": "global",
"Spreads": null,
"Stable": true,
"Status": "running",
"StatusDescription": "",
"Stop": false,
"SubmitTime": 1615305947060406800,
"TaskGroups": [
{
"Affinities": null,
"Constraints": null,
"Count": 1,
"EphemeralDisk": {
"Migrate": false,
"SizeMB": 300,
"Sticky": false
},
"Meta": null,
"Migrate": {
"HealthCheck": "checks",
"HealthyDeadline": 300000000000,
"MaxParallel": 1,
"MinHealthyTime": 10000000000
},
"Name": "cache",
"Networks": [
{
"CIDR": "",
"DNS": null,
"Device": "",
"DynamicPorts": [
{
"HostNetwork": "default",
"Label": "db",
"To": 6379,
"Value": 0
}
],
"IP": "",
"MBits": 0,
"Mode": "",
"ReservedPorts": null
}
],
"ReschedulePolicy": {
"Attempts": 0,
"Delay": 30000000000,
"DelayFunction": "exponential",
"Interval": 0,
"MaxDelay": 3600000000000,
"Unlimited": true
},
"RestartPolicy": {
"Attempts": 2,
"Delay": 15000000000,
"Interval": 1800000000000,
"Mode": "fail"
},
"Scaling": null,
"Services": null,
"ShutdownDelay": null,
"Spreads": null,
"StopAfterClientDisconnect": null,
"Tasks": [
{
"Affinities": null,
"Artifacts": null,
"CSIPluginConfig": null,
"Config": {
"image": "redis:3.2",
"ports": [
"db"
]
},
"Constraints": null,
"DispatchPayload": null,
"Driver": "docker",
"Env": null,
"KillSignal": "",
"KillTimeout": 5000000000,
"Kind": "",
"Leader": false,
"Lifecycle": null,
"LogConfig": {
"MaxFileSizeMB": 10,
"MaxFiles": 10
},
"Meta": null,
"Name": "redis",
"Resources": {
"CPU": 500,
"Devices": null,
"DiskMB": 0,
"IOPS": 0,
"MemoryMB": 256,
"Networks": null
},
"RestartPolicy": {
"Attempts": 2,
"Delay": 15000000000,
"Interval": 1800000000000,
"Mode": "fail"
},
"ScalingPolicies": null,
"Services": null,
"ShutdownDelay": 0,
"Templates": null,
"User": "",
"Vault": null,
"VolumeMounts": null
}
],
"Update": {
"AutoPromote": false,
"AutoRevert": false,
"Canary": 0,
"HealthCheck": "checks",
"HealthyDeadline": 300000000000,
"MaxParallel": 1,
"MinHealthyTime": 10000000000,
"ProgressDeadline": 600000000000,
"Stagger": 30000000000
},
"Volumes": null
}
],
"Type": "service",
"Update": {
"AutoPromote": false,
"AutoRevert": false,
"Canary": 0,
"HealthCheck": "",
"HealthyDeadline": 0,
"MaxParallel": 1,
"MinHealthyTime": 0,
"ProgressDeadline": 0,
"Stagger": 30000000000
},
"VaultNamespace": "",
"VaultToken": "",
"Version": 0
} Read Job HTTP API with minimal manipulation is round-trippable
nomad inspect -json is not round-trippable
{
"Affinities": null,
"AllAtOnce": false,
"Constraints": null,
"ConsulToken": "",
"CreateIndex": 10,
"Datacenters": [
"dc1"
],
"Dispatched": false,
"ID": "example",
"JobModifyIndex": 10,
"Meta": null,
"Migrate": null,
"ModifyIndex": 17,
"Multiregion": null,
"Name": "example",
"Namespace": "default",
"NomadTokenID": "",
"ParameterizedJob": null,
"ParentID": "",
"Payload": null,
"Periodic": null,
"Priority": 50,
"Region": "global",
"Reschedule": null,
"Spreads": null,
"Stable": true,
"Status": "running",
"StatusDescription": "",
"Stop": false,
"SubmitTime": 1615305947060406757,
"TaskGroups": [
{
"Affinities": null,
"Constraints": null,
"Count": 1,
"EphemeralDisk": {
"Migrate": false,
"SizeMB": 300,
"Sticky": false
},
"Meta": null,
"Migrate": {
"HealthCheck": "checks",
"HealthyDeadline": 300000000000,
"MaxParallel": 1,
"MinHealthyTime": 10000000000
},
"Name": "cache",
"Networks": [
{
"CIDR": "",
"DNS": null,
"Device": "",
"DynamicPorts": [
{
"HostNetwork": "default",
"Label": "db",
"To": 6379,
"Value": 0
}
],
"IP": "",
"MBits": 0,
"Mode": "",
"ReservedPorts": null
}
],
"ReschedulePolicy": {
"Attempts": 0,
"Delay": 30000000000,
"DelayFunction": "exponential",
"Interval": 0,
"MaxDelay": 3600000000000,
"Unlimited": true
},
"RestartPolicy": {
"Attempts": 2,
"Delay": 15000000000,
"Interval": 1800000000000,
"Mode": "fail"
},
"Scaling": null,
"Services": null,
"ShutdownDelay": null,
"Spreads": null,
"StopAfterClientDisconnect": null,
"Tasks": [
{
"Affinities": null,
"Artifacts": null,
"Config": {
"image": "redis:3.2",
"ports": [
"db"
]
},
"Constraints": null,
"DispatchPayload": null,
"Driver": "docker",
"Env": null,
"KillSignal": "",
"KillTimeout": 5000000000,
"Kind": "",
"Leader": false,
"Lifecycle": null,
"LogConfig": {
"MaxFileSizeMB": 10,
"MaxFiles": 10
},
"Meta": null,
"Name": "redis",
"Resources": {
"CPU": 500,
"Devices": null,
"DiskMB": 0,
"IOPS": 0,
"MemoryMB": 256,
"Networks": null
},
"RestartPolicy": {
"Attempts": 2,
"Delay": 15000000000,
"Interval": 1800000000000,
"Mode": "fail"
},
"ScalingPolicies": null,
"Services": null,
"ShutdownDelay": 0,
"Templates": null,
"User": "",
"Vault": null,
"VolumeMounts": null
}
],
"Update": {
"AutoPromote": false,
"AutoRevert": false,
"Canary": 0,
"HealthCheck": "checks",
"HealthyDeadline": 300000000000,
"MaxParallel": 1,
"MinHealthyTime": 10000000000,
"ProgressDeadline": 600000000000,
"Stagger": 30000000000
},
"Volumes": null
}
],
"Type": "service",
"Update": {
"AutoPromote": false,
"AutoRevert": false,
"Canary": 0,
"HealthCheck": "",
"HealthyDeadline": 0,
"MaxParallel": 1,
"MinHealthyTime": 0,
"ProgressDeadline": 0,
"Stagger": 30000000000
},
"VaultNamespace": "",
"VaultToken": "",
"Version": 0
} nomad inspect -json with minimal manipulation is round-trippable
nomad inspect is round-trippable
{
"Job": {
"Affinities": null,
"AllAtOnce": false,
"Constraints": null,
"ConsulToken": "",
"CreateIndex": 10,
"Datacenters": [
"dc1"
],
"Dispatched": false,
"ID": "example",
"JobModifyIndex": 10,
"Meta": null,
"Migrate": null,
"ModifyIndex": 17,
"Multiregion": null,
"Name": "example",
"Namespace": "default",
"NomadTokenID": "",
"ParameterizedJob": null,
"ParentID": "",
"Payload": null,
"Periodic": null,
"Priority": 50,
"Region": "global",
"Reschedule": null,
"Spreads": null,
"Stable": true,
"Status": "running",
"StatusDescription": "",
"Stop": false,
"SubmitTime": 1615305947060406757,
"TaskGroups": [
{
"Affinities": null,
"Constraints": null,
"Count": 1,
"EphemeralDisk": {
"Migrate": false,
"SizeMB": 300,
"Sticky": false
},
"Meta": null,
"Migrate": {
"HealthCheck": "checks",
"HealthyDeadline": 300000000000,
"MaxParallel": 1,
"MinHealthyTime": 10000000000
},
"Name": "cache",
"Networks": [
{
"CIDR": "",
"DNS": null,
"Device": "",
"DynamicPorts": [
{
"HostNetwork": "default",
"Label": "db",
"To": 6379,
"Value": 0
}
],
"IP": "",
"MBits": 0,
"Mode": "",
"ReservedPorts": null
}
],
"ReschedulePolicy": {
"Attempts": 0,
"Delay": 30000000000,
"DelayFunction": "exponential",
"Interval": 0,
"MaxDelay": 3600000000000,
"Unlimited": true
},
"RestartPolicy": {
"Attempts": 2,
"Delay": 15000000000,
"Interval": 1800000000000,
"Mode": "fail"
},
"Scaling": null,
"Services": null,
"ShutdownDelay": null,
"Spreads": null,
"StopAfterClientDisconnect": null,
"Tasks": [
{
"Affinities": null,
"Artifacts": null,
"Config": {
"image": "redis:3.2",
"ports": [
"db"
]
},
"Constraints": null,
"DispatchPayload": null,
"Driver": "docker",
"Env": null,
"KillSignal": "",
"KillTimeout": 5000000000,
"Kind": "",
"Leader": false,
"Lifecycle": null,
"LogConfig": {
"MaxFileSizeMB": 10,
"MaxFiles": 10
},
"Meta": null,
"Name": "redis",
"Resources": {
"CPU": 500,
"Devices": null,
"DiskMB": 0,
"IOPS": 0,
"MemoryMB": 256,
"Networks": null
},
"RestartPolicy": {
"Attempts": 2,
"Delay": 15000000000,
"Interval": 1800000000000,
"Mode": "fail"
},
"ScalingPolicies": null,
"Services": null,
"ShutdownDelay": 0,
"Templates": null,
"User": "",
"Vault": null,
"VolumeMounts": null
}
],
"Update": {
"AutoPromote": false,
"AutoRevert": false,
"Canary": 0,
"HealthCheck": "checks",
"HealthyDeadline": 300000000000,
"MaxParallel": 1,
"MinHealthyTime": 10000000000,
"ProgressDeadline": 600000000000,
"Stagger": 30000000000
},
"Volumes": null
}
],
"Type": "service",
"Update": {
"AutoPromote": false,
"AutoRevert": false,
"Canary": 0,
"HealthCheck": "",
"HealthyDeadline": 0,
"MaxParallel": 1,
"MinHealthyTime": 0,
"ProgressDeadline": 0,
"Stagger": 30000000000
},
"VaultNamespace": "",
"VaultToken": "",
"Version": 0
}
} |
Is there any way to extract a JSON job spec locally from the CLI? The current behavior makes it impossible to interact with both an HCL spec and the API directly, because you need to round-trip to a Nomad server to get JSON (which is of course only possible if you already have a valid job spec). I think what's maybe being missed here by the Nomad team is that there are very strong use cases for working with a JSON job spec prior to submitting the job. For example:
It would be nice if using JSON did not lock you out of the CLI. |
|
We're not missing it. This issue is still open and marked as an enhancement, after all. But your examples of manipulating the JSON job spec, programmatically generating JSON, or submitting JSON via the API don't seem to the problem you have here? That's the motivation for why you want to convert from HCL to JSON. But you can already do this via Once you're at that point, it's true that you can't submit that JSON via |
@tgross The nomad CLI has two assets that are valuable, even if tooling is providing json output:
Maybe the internal discussion can be enhanced with those arguments and proper support for lingua franca (even french people learn english now a days 😄 ) We want to add first class /cc @kamadorueda EDIT: committing to maintaining wrapper tooling is not an option just to add first class support for |
Hi, some recent experience, I'm using dhall with https://github.com/seatgeek/dhall-nomad to generate json job files (as json is technically HCL2), and submit the results via |
@tgross the problem with HCL arises is when it comes to tooling, and using third parties solutions, and HCL is kind of esoteric. The way around, JSON and YAML are |
I'm going to lock this issue because it has been closed for 120 days ⏳. This helps our maintainers find and focus on the active issues. |
Nomad version
Nomad v0.9.6
Operating system and Environment details
Mac + Linux
Issue
From the Nomad CLI tool I want to be able to output a job spec and then "run" that output.
For example I have a script which stops a running tasks, applies changes to an underlying service, and then restarts it.
nomad job inspect
outputs JSON which I can submit back via the Job HTTP API but then I'm forced to pass Nomad and Vault tokens via CURL and it's a bit messy. I have an environment setup where thenomad
CLI works and it makes sense to be able to ingest the same format as is outputReproduction steps
I'm open to any alternatives suggested, but basically I want to be able to interact with a job (ie stop + start) from an environment with access to Nomad, but without access to the original jobspec files.
The text was updated successfully, but these errors were encountered: