Skip to content

Commit

Permalink
docs: update json jobs docs (#12766)
Browse files Browse the repository at this point in the history
* docs: update json jobs docs

Did you know that Nomad has not 1 but 2 JSON formats for jobs? 2½ if you
want to acknowledge that sometimes our JSON job representations have a
Job top-level wrapper and sometimes do not.

The 2½ formats are:
```
 1.   HCL JSON
 2.   Input API JSON (top-level Job field)
 2.5. Output API JSON (lacks top-level Job field)
```

`#2` is what our docs consider our API JSON. `#2.5` seems to be an
accident of history we can't fix with breaking API compatibility.

`#1` is an even more interesting accident of history: the `jobspec2`
package automatically detects if the input to Parse is JSON and switches
to a JSON parser. This behavior is undocumented, the format is
unspecified, and there is no official HashiCorp tooling to produce this
JSON from HCL. The plot thickens when you discover popular third party
tools like hcl2json.com and https://github.com/tmccombs/hcl2json seem to
produce JSON that `nomad run` accepts!

Since we have no telemetry around whether or not anyone passes HCL JSON
to `nomad run`, and people don't file bugs around features that Just
Work, I'm choosing to leave that code path in place and *acknowledged
but not suggested* in documentation.

See hashicorp/hcl#498 for a more comprehensive
discussion of what officially supporting HCL JSON in Nomad would look
like.

(I also added some of the missing fields to the (Input API flavor) JSON
Job documentation, but it still needs a lot of work to be
comprehensive.)

Co-authored-by: Tim Gross <tgross@hashicorp.com>
  • Loading branch information
schmichael and tgross committed May 13, 2022
1 parent a0374cd commit 937f0eb
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 106 deletions.
275 changes: 184 additions & 91 deletions website/content/api-docs/json-jobs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,149 +8,221 @@ description: |-

# JSON Job Specification

This guide covers the JSON syntax for submitting jobs to Nomad. A useful command
for generating valid JSON versions of HCL jobs is:
Nomad's HTTP API uses JSON formatted job specifications except for the
[`/job/parse` API][job-parse] which exists to convert HCL to JSON.

The Nomad CLI includes a number of useful commands for working with JSON jobs.

The [`nomad job run -output`][job-output] flag converts HCL jobs to JSON
without submitting the job:

```shell-session
$ nomad job run -output my-job.nomad
```

The [`nomad job inspect`][job-inspect] command retrieves the JSON specification
for an existing job:

```shell-session
$ nomad job inspect example
```

The [`nomad job run -json`][job-run-json] flag submits a JSON formatted job:

```shell-session
$ nomad job run -json example.json
```

[job-inspect]: /docs/commands/job/inspect
[job-output]: /docs/commands/job/run#output
[job-parse]: /api-docs/jobs#parse-job
[job-run-json]: /docs/commands/job/run#json

## Syntax

Below is the JSON representation of the job outputted by `$ nomad init`:
Below is the JSON representation of the example job as well as the commands to
reproduce it:

```shell-session
$ nomad init
Example job file written to example.nomad
$ nomad job run -output example.nomad
```

```json
{
"Job": {
"Region": null,
"Namespace": null,
"ID": "example",
"Name": "example",
"Type": "service",
"Priority": 50,
"Datacenters": ["dc1"],
"Priority": null,
"AllAtOnce": null,
"Datacenters": [
"dc1"
],
"Constraints": null,
"Affinities": null,
"TaskGroups": [
{
"Name": "cache",
"Count": 1,
"Migrate": {
"HealthCheck": "checks",
"HealthyDeadline": 300000000000,
"MaxParallel": 1,
"MinHealthyTime": 10000000000
},
"Constraints": null,
"Affinities": null,
"Tasks": [
{
"Name": "redis",
"Driver": "docker",
"User": "",
"Lifecycle": null,
"Config": {
"image": "redis:3.2",
"port_map": [
{
"db": 6379
}
"ports": [
"db"
]
},
"Services": [
{
"Id": "",
"Name": "redis-cache",
"Tags": ["global", "cache"],
"Meta": {
"meta": "for my service"
},
"PortLabel": "db",
"AddressMode": "",
"Checks": [
{
"Id": "",
"Name": "alive",
"Type": "tcp",
"Command": "",
"Args": null,
"Header": {},
"Method": "",
"Path": "",
"Protocol": "",
"PortLabel": "",
"Interval": 10000000000,
"Timeout": 2000000000,
"InitialStatus": "",
"TLSSkipVerify": false,
"CheckRestart": {
"Limit": 3,
"Grace": 30000000000,
"IgnoreWarnings": false
}
}
]
}
],
"Constraints": null,
"Affinities": null,
"Env": null,
"Services": null,
"Resources": {
"CPU": 500,
"Cores": null,
"MemoryMB": 256,
"Networks": [
{
"Device": "",
"CIDR": "",
"IP": "",
"MBits": 10,
"DynamicPorts": [
{
"Label": "db",
"Value": 0
}
]
}
]
"MemoryMaxMB": null,
"DiskMB": null,
"Networks": null,
"Devices": null,
"IOPS": null
},
"Leader": false
"RestartPolicy": null,
"Meta": null,
"KillTimeout": null,
"LogConfig": null,
"Artifacts": null,
"Vault": null,
"Templates": null,
"DispatchPayload": null,
"VolumeMounts": null,
"Leader": false,
"ShutdownDelay": 0,
"KillSignal": "",
"Kind": "",
"ScalingPolicies": null
}
],
"Spreads": null,
"Volumes": null,
"RestartPolicy": {
"Interval": 1800000000000,
"Attempts": 2,
"Delay": 15000000000,
"Mode": "fail"
},
"ReschedulePolicy": {
"Attempts": 10,
"Delay": 30000000000,
"DelayFunction": "exponential",
"Interval": 0,
"MaxDelay": 3600000000000,
"Unlimited": true
},
"ReschedulePolicy": null,
"EphemeralDisk": {
"Sticky": null,
"Migrate": null,
"SizeMB": 300
}
},
"Update": null,
"Migrate": null,
"Networks": [
{
"Mode": "",
"Device": "",
"CIDR": "",
"IP": "",
"DNS": null,
"ReservedPorts": null,
"DynamicPorts": [
{
"Label": "db",
"Value": 0,
"To": 6379,
"HostNetwork": ""
}
],
"Hostname": "",
"MBits": null
}
],
"Meta": null,
"Services": [
{
"Id": "",
"Name": "redis-cache",
"Tags": [
"global",
"cache"
],
"CanaryTags": null,
"EnableTagOverride": false,
"PortLabel": "db",
"AddressMode": "",
"Checks": null,
"CheckRestart": null,
"Connect": null,
"Meta": null,
"CanaryMeta": null,
"TaskName": "",
"OnUpdate": "",
"Provider": ""
}
],
"ShutdownDelay": null,
"StopAfterClientDisconnect": null,
"MaxClientDisconnect": null,
"Scaling": null,
"Consul": null
}
],
"Update": {
"Stagger": null,
"MaxParallel": 1,
"HealthCheck": null,
"MinHealthyTime": 10000000000,
"HealthyDeadline": 180000000000,
"ProgressDeadline": 600000000000,
"Canary": 0,
"AutoRevert": false,
"Canary": 0
}
"AutoPromote": null
},
"Multiregion": null,
"Spreads": null,
"Periodic": null,
"ParameterizedJob": null,
"Reschedule": null,
"Migrate": {
"MaxParallel": 1,
"HealthCheck": "checks",
"MinHealthyTime": 10000000000,
"HealthyDeadline": 300000000000
},
"Meta": null,
"ConsulToken": null,
"VaultToken": null,
"Stop": null,
"ParentID": null,
"Dispatched": false,
"DispatchIdempotencyToken": null,
"Payload": null,
"ConsulNamespace": null,
"VaultNamespace": null,
"NomadTokenID": null,
"Status": null,
"StatusDescription": null,
"Stable": null,
"Version": null,
"SubmitTime": null,
"CreateIndex": null,
"ModifyIndex": null,
"JobModifyIndex": null
}
}
```

The example JSON could be submitted as a job using the following:

```shell-session
$ curl -XPUT -d @example.json http://127.0.0.1:4646/v1/job/example
{
"EvalID": "5d6ded54-0b2a-8858-6583-be5f476dec9d",
"EvalCreateIndex": 12,
"JobModifyIndex": 11,
"Warnings": "",
"Index": 12,
"LastContact": 0,
"KnownLeader": false
}
```

## Syntax Reference

Following is a syntax reference for the possible keys that are supported and
Expand Down Expand Up @@ -183,6 +255,15 @@ The `Job` object supports the following keys:

- `Meta` - Annotates the job with opaque metadata.

- `ConsulToken` - Specifies the Consul token that proves the submitter of the
job has access to the Service Identity policies associated with the job's
Consul Connect enabled services. This field is only used to transfer the
token and is not stored after job submission.

- `VaultToken` - Specifies the Vault token that proves the submitter of the job
has access to the specified policies in the `vault` stanza. This field is
only used to transfer the token and is not stored after job submission.

- `Namespace` - The namespace to execute the job in, defaults to "default".
Prior to Nomad 1.0 namespaces were Enterprise-only.

Expand All @@ -200,6 +281,9 @@ The `Job` object supports the following keys:
dispatching against the parameterized job. The options for this field are
"optional", "required" and "forbidden". The default value is "optional".

- `DispatchIdempotencyToken` - Optional identifier used to prevent more than one
instance of the job from being dispatched.

- `Payload` - The payload may not be set when submitting a job but may appear in
a dispatched job. The `Payload` will be a base64 encoded string containing the
payload that the job was dispatched with. The `payload` has a **maximum size
Expand Down Expand Up @@ -438,6 +522,15 @@ The `Task` object supports the following keys:
defined in the resources block. This could be a label of either a
dynamic or a static port.

- `Provider`: Specifies the service registration provider to use for service
registrations. Valid options are either `consul` or `nomad`. All services
within a single task group must utilise the same provider value.

- `Address`: Specifies a custom address to advertise in Consul or Nomad
service registration. If set, `AddressMode` must be in `auto` mode. Useful
with interpolation - for example to advertise the public IP address of an
AWS EC2 instance set this to `${attr.unique.platform.aws.public-ipv4}`.

- `AddressMode`: Specifies what address (host or driver-specific) this
service should advertise. This setting is supported in Docker since
Nomad 0.6 and rkt since Nomad 0.7. Valid options are:
Expand Down
19 changes: 15 additions & 4 deletions website/content/docs/commands/job/run.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ that volume.
- `-eval-priority`: Override the priority of the evaluations produced as a result
of this job submission. By default, this is set to the priority of the job.

- `-json`: Parses the job file as JSON. If the outer object has a Job field,
such as from "nomad job inspect" or "nomad run -output", the value of the
field is used as the job. See [JSON Jobs] for details.

- `-hcl1`: If set, HCL1 parser is used for parsing the job spec.

- `-hcl2-strict`: Whether an error should be produced from the HCL2 parser where
Expand Down Expand Up @@ -225,11 +229,18 @@ $ nomad job run example.nomad
==> 2021-06-14T09:25:09-07:00: Evaluation "88a91284" finished with status "complete"
```

[`go-getter`]: https://github.com/hashicorp/go-getter
[deployment status]: /docs/commands/deployment#status
[`batch`]: /docs/schedulers#batch
[`system`]: /docs/schedulers#system
[`job plan` command]: /docs/commands/job/plan
[`consul` stanza `allow_unauthenticated`]: /docs/configuration/consul#allow_unauthenticated
[deployment status]: /docs/commands/deployment#status
[eval status]: /docs/commands/eval-status
[`go-getter`]: https://github.com/hashicorp/go-getter
[`job plan` command]: /docs/commands/job/plan
[job specification]: /docs/job-specification
<<<<<<< HEAD
[`allow_unauthenticated`]: /docs/configuration/consul#allow_unauthenticated
=======
[JSON jobs]: /api-docs/json-jobs
[`system`]: /docs/schedulers#system
[`vault` stanza `allow_unauthenticated`]: /docs/configuration/vault#allow_unauthenticated
[`vault_token`]: /docs/job-specification/job#vault_token
>>>>>>> e4d6d5103 (docs: update json jobs docs (#12766))
Loading

0 comments on commit 937f0eb

Please sign in to comment.