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

HCL to JSON api endpoint #4138

Merged
merged 11 commits into from
Apr 19, 2018
Merged

HCL to JSON api endpoint #4138

merged 11 commits into from
Apr 19, 2018

Conversation

nickethier
Copy link
Member

@nickethier nickethier commented Apr 11, 2018

The parse endpoint accepts a hcl jobspec body within a json object
and returns the parsed json object for the job. This allows users to
register jobs with the nomad json api without specifically needing
a nomad binary to parse their hcl encoded jobspec file.

Fixes #2782

@nickethier nickethier changed the title [WIP] HCL to JSON api endpoint HCL to JSON api endpoint Apr 16, 2018
Copy link
Member

@schmichael schmichael left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! 🎉 🎉 🎉

Go ahead and add a changelog entry like:

IMPROVEMENTS:

...
api: Add /v1/jobs/parse endpoint for rending HCL job files as JSON [GH-2782]

Then run make changelogfmt to replace the issue number with a link.

Changelog entries are sorted core first, then alphabetically by category. Within a category they're roughly sorted shortest-to-longest.

api/jobs.go Outdated
type JobsParseRequest struct {
//JobHCL is an hcl jobspec
JobHCL string
//Canonicalize is a flag as to if the server should return default values
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a newline between the previous field and the comment on the next one.

api/jobs.go Outdated
// Jobs returns a handle on the jobs endpoints.
func (c *Client) Jobs() *Jobs {
return &Jobs{client: c}
}

// Parse is used to convert the HCL repesentation of a Job to JSON server side
// To parse the HCL client side see package github.com/hashicorp/nomad/jobspec
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a period between multiple sentences in comments as godoc/godoc.org will run them together into one line.

t.Parallel()
httpTest(t, nil, func(s *TestAgent) {
buf := encodeReq(api.JobsParseRequest{JobHCL: mock.HCL()})
req, err := http.NewRequest("POST", "/v1/jobs/render", buf)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/parse not /render

Although since we're calling the handler directly it doesn't matter.

| Method | Path | Produces |
| ------ | ------------------------- | -------------------------- |
| `POST` | `/v1/jobs/parse` | `application/json` |

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the standard blocking/acl section even though neither apply:

 | Blocking Queries | ACL Required               |
 | ---------------- | -------------------------- |
 | `No`             | `none`       |

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

api/jobs.go Outdated
// Jobs returns a handle on the jobs endpoints.
func (c *Client) Jobs() *Jobs {
return &Jobs{client: c}
}

// Parse is used to convert the HCL repesentation of a Job to JSON server side
// To parse the HCL client side see package github.com/hashicorp/nomad/jobspec
func (j *Jobs) Parse(jobHCL string) (*Job, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add canonicalize as a boolean parameter.

Test it in api/jobs_test.go

api/jobs.go Outdated
@@ -36,11 +36,33 @@ type Jobs struct {
client *Client
}

// JobsParseRequest is used for arguments of the /vi/jobs/parse endpoint
type JobsParseRequest struct {
//JobHCL is an hcl jobspec
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a space between forward slashes and the first letter

api/jobs.go Outdated
// Jobs returns a handle on the jobs endpoints.
func (c *Client) Jobs() *Jobs {
return &Jobs{client: c}
}

// Parse is used to convert the HCL repesentation of a Job to JSON server side.
// To parse the HCL client side see package github.com/hashicorp/nomad/jobspec
func (j *Jobs) Parse(jobHCL string, canonicalize bool) (*Job, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name it ParseHCL so we are futureproofed if we want to add a ParseJSON with canonicalize for people who want to just have defaults set.

api/jobs_test.go Outdated

jobs := c.Jobs()

checkJob := func(job *Job, expected string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected -> expectedRegion

@@ -231,6 +231,83 @@ $ curl \
}
```

## Parse Job

This endpoint will parse an hcl jobspec and produce the equivalent json encoded
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HCL and JSON capitalized

}

if args.Canonicalize {
jobStruct.Canonicalize()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not capture the warnings returned here and return it: https://github.com/hashicorp/nomad/blob/master/nomad/structs/structs.go#L906-L908

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow. Canonicalize() does not return any errors? https://github.com/hashicorp/nomad/blob/master/api/jobs.go#L585

job.Datacenters[0] != expected.Datacenters[0] {
t.Fatalf("job datacenters is '%s', expected '%s'",
job.Datacenters[0], expected.Datacenters[0])
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would suggest checking all fields of the returned job against expected instead of just these three fields.
We have a diff helper in

func (j *Job) Diff(other *Job, contextual bool) (*JobDiff, error) {
that we use in nomad plan and other places.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are api.Job structs. Is there a helper to convert to a structs.Job?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func ApiJobToStructJob(job *api.Job) *structs.Job {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cautionary note - not sure if a direct translation like works okay when it comes to unset fields (esp if canonicalize is not called). so it may produce a diff complaining about empty list vs nil. I haven't tried it before, seem worth trying it and using it here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent some time looking at this and there are a few things:

  • Diff errors if IDs don't match (mock.Job() generates a unique ID)
  • Lots of unset fields yields a somewhat unuseful diff.
  • The mock.HCL() method doesn't quite mimic the mock.Job() fully.

At some point it feels like I'm testing more of the jobspec.Parse functionality than the api endpoint. Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair. It doesn't seem worth it here to use diff for this test given the above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the pointer though, I learned more about the structs package 😃

region := job.Region

if region == nil {
if expectedRegion != "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future feel free to use require.NotEmpty to condense these simple test assertions.

testify is kind of our blessed assertion utility library.

No need to change this PR.

@nickethier nickethier merged commit 95d9eb9 into master Apr 19, 2018
@nickethier nickethier deleted the i-hcl-json-endpoint branch April 19, 2018 18:18
@github-actions
Copy link

github-actions bot commented Mar 6, 2023

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.
If you have found a problem that seems related to this change, 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 Mar 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants