Skip to content
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

CLI should accept JSON job specs #1749

Closed
jippi opened this issue Sep 26, 2016 · 13 comments · Fixed by #12591
Closed

CLI should accept JSON job specs #1749

jippi opened this issue Sep 26, 2016 · 13 comments · Fixed by #12591

Comments

@jippi
Copy link
Contributor

jippi commented Sep 26, 2016

Nomad version

v0.4.1

Operating system and Environment details

Distributor ID: Debian
Description:    Debian GNU/Linux 7.9 (wheezy)
Release:    7.9
Codename:   wheezy

Issue

invalid key: Job when submitting JSON jobs

Trying nomad run -output <job.nomad> on an existing HCL job, converting it to JSON, fail with the same error

Reproduction steps

Nomad Server logs (if appropriate)

-> nomad run raw.json
Error getting job struct: 1 error(s) occurred:

* invalid key: Job

Job file (if appropriate)

The example JSON from the documentation.

Any other JSON job i've tried to submit fail on the same error :)

{
  "Job": {
    "Region": "global",
    "ID": "example",
    "Name": "example",
    "Type": "batch",
    "Priority": 50,
    "AllAtOnce": false,
    "Datacenters": [
      "dc1"
    ],
    "Constraints": [
      {
        "LTarget": "${attr.kernel.name}",
        "RTarget": "linux",
        "Operand": "="
      }
    ],
    "TaskGroups": [
      {
        "Name": "cache",
        "Count": 1,
        "Constraints": null,
        "Tasks": [
          {
            "Name": "redis",
            "Driver": "docker",
            "User": "foo-user",
            "Config": {
              "image": "redis:latest",
              "port_map": [
                {
                  "db": 6379
                }
              ]
            },
            "Constraints": null,
            "Env": {
              "foo": "bar",
              "baz": "pipe"
            },
            "Services": [
              {
                "Name": "cache-redis",
                "Tags": [
                  "global",
                  "cache"
                ],
                "PortLabel": "db",
                "Checks": [
                  {
                    "Id": "",
                    "Name": "alive",
                    "Type": "tcp",
                    "Command": "",
                    "Args": null,
                    "Path": "",
                    "Protocol": "",
                    "Interval": 10000000000,
                    "Timeout": 2000000000
                  }
                ]
              }
            ],
            "Resources": {
              "CPU": 500,
              "MemoryMB": 256,
              "DiskMB": 300,
              "IOPS": 0,
              "Networks": [
                {
                  "ReservedPorts": [
                    {
                      "Label": "rpc",
                      "Value": 25566
                    }
                  ],
                  "DynamicPorts": [
                    {
                      "Label": "db"
                    }
                  ],
                  "MBits": 10
                }
              ]
            },
            "Meta": {
              "foo": "bar",
              "baz": "pipe"
            },
            "KillTimeout": 5000000000,
            "LogConfig": {
              "MaxFiles": 10,
              "MaxFileSizeMB": 10
            },
            "Artifacts": [
              {
                "GetterSource": "http://foo.com/artifact.tar.gz",
                "GetterOptions": {
                  "checksum": "md5:c4aa853ad2215426eb7d70a21922e794"
                },
                "RelativeDest": "local/"
              }
            ]
          }
        ],
        "RestartPolicy": {
          "Interval": 300000000000,
          "Attempts": 10,
          "Delay": 25000000000,
          "Mode": "delay"
        },
        "Meta": {
          "foo": "bar",
          "baz": "pipe"
        }
      }
    ],
    "Update": {
      "Stagger": 10000000000,
      "MaxParallel": 1
    },
    "Periodic": {
      "Enabled": true,
      "Spec": "* * * * *",
      "SpecType": "cron",
      "ProhibitOverlap": true
    },
    "Meta": {
      "foo": "bar",
      "baz": "pipe"
    }
  }
}
@jippi
Copy link
Contributor Author

jippi commented Sep 26, 2016

I guess its the same issue as #1163

I don't get why JSON would be 2nd level citizen on CLI

HCL is terrible to write out programmatically from e.g. PHP (no lib to serialize an array to HCL), where JSON (or even YAML) are very easy to work with

Jobs can be specified either in HCL or JSON. This guide covers the JSON syntax for submitting jobs to Nomad. A useful command for generating valid JSON versions of HCL jobs is nomad run -output <job.nomad> which will emit a JSON version of the job

but doesn't mention the nomad CLI will not accept it ? :)

@sethvargo
Copy link
Contributor

Hi @jippi

I think I see the confusion here. The JobSpec and the Job File are different things. The result of the -output call is the JSON JobSpec; this is the HTTP API Payload that would be sent to /v1/jobs as the payload. It is not the conversion of the HCL job file to a JSON job file.

A JSON job file would need to map to the HCL. The mapping between HCL and JSON is not always 1-1, but here is an example to help you out:

job "jenkins" {
  datacenters = ["dc1"]

  group "jenkins" {
    ephemeral_disk {
      size = 300
    }

    task "jenkins" {
      driver = "docker"
      config {
        image = "jenkins:alpine"
        port_map {
          ui    = 8080
          agent = 50000
        }
      }

      resources {
        cpu    = 500
        memory = 256
        network {
          mbits = 10
          port "ui" {}
          port "agent" {}
        }
      }
    }
  }
}
{
  "job": {
    "jenkins": {
      "datacenters": ["us-east-1"],
      "group": [
        {
          "jenkins": {
            "ephemeral_disk": {
              "size": "300",
            },
            "task": [
              {
                "jenkins": {
                  "driver": "docker",
                  "config": {
                    "image": "jenkins:alpine",
                    "port_map": {
                      "ui": "8080",
                      "agent": "50000"
                    }
                  },
                  "resources": {
                    "cpu": "500",
                    "memory": "256",
                    "network": {
                      "mbits": "10",
                      "port": [
                        { "ui": {} },
                        { "agent": {} }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

To re-iterate, there are two kinds of JSON:

  • JSON that's submitted as the payload to the API
  • JSON job file

The -output is giving you the latter; there is no option for generating the former.

@dadgar do you think it would be a good idea to add the JSON schema to the nomad docs somewhere?

@dadgar
Copy link
Contributor

dadgar commented Sep 26, 2016

JSON version already exists: https://www.nomadproject.io/docs/jobspec/json.html

@dadgar
Copy link
Contributor

dadgar commented Sep 26, 2016

Going to update the issue to represent the fact that the CLI should detect if the job is JSON and submit it.

@dadgar dadgar changed the title "invalid key: Job" for JSON jobs CLI should accept JSON job specs Sep 26, 2016
@sethvargo
Copy link
Contributor

@dadgar I think there are two issues here - there are people who generate HCL-compliant JSON (which the HCL parser will happily parse), and there's the JSON spec. For example, the jobfile I posted above does work because it's parsed as JSON-HCL.

@dadgar
Copy link
Contributor

dadgar commented Sep 26, 2016

I think must people want nomad run -output foo.hcl | nomad run to work. Not in the literal sense but for the command to accept a JSON API version of the job

@sethvargo
Copy link
Contributor

I don't disagree with that, but I think people also want nomad run my-job.json to work if the JSON is the same as the HCL. Maybe you could just detect a capital letter?

@dadgar
Copy link
Contributor

dadgar commented Sep 26, 2016

@sethvargo Yeah I think we are on the same page! That is what I am saying I want to support

@jippi
Copy link
Contributor Author

jippi commented Sep 26, 2016

@dadgar @sethvargo thanks for the clarification

For me the confusion started with me assuming HCL Syntax and JSON Syntax was the different formats of the same thing. Not one being a JobFile (HCL) and the other a JobSpec (JSON) since both of the pages got a h1 with the value Job Specification - but they are actually quite different things apparently.

Also HCL page JSON Syntax header links to the JSON JobSpec for reference, which also tripped me up.

There don't seem to be any JSON JobFile examples in the docs atm then?

@rickardrosen
Copy link

rickardrosen commented Dec 9, 2016

Yeah, so this whole JSON <> HCL thing is a bit confusing. =)
The Nomad docs regarding JOB spec starts with the following statement:

For machine-friendliness, Nomad can also read JSON-equivalent configurations.

This leads you to believe you simply can convert a job spec written in HCL into JSON and it will work. Obviously this is not really the case...

I'm (trying to) autogenerating job (JSON) and have found that the HCL documentation can't really be followed.
The single resource for JSON job specification is the following out of date page:

https://www.nomadproject.io/docs/http/json-jobs.html

(The example job will not parse due to the task requesting a DiskMB allocation, something that is not allowed since version 0.5.0.)

The job @sethvargo posted above will not parse, if you add consul service and check to it.
This is due to "port" definitions being used but posting a job with "port" will result in the following error from Nomad:

* check FOO check for BAR invalid: check requires a port but the service "BAR" has no port

For a JSON job containing service with checks to parse one must use DynamicPorts or ReservedPorts.
Will this HCL <> JSON discrepancy be treated as a product or documentation bug if I file an issue?

@dadgar
Copy link
Contributor

dadgar commented Dec 12, 2016

@rickardrosen It is both a product and documentation bug unfortunately! Would you mind creating a PR to remedy the docs and make it parse as that is an easy win right now. Parsing JSON is a little bigger of a task

@yellowmegaman
Copy link

I think that HCL is way nicer, and would personally be happy to be able to submit hcl jobs via api.

@github-actions
Copy link

github-actions bot commented Oct 9, 2022

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.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 9, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants