command/validate: Adding new command
This commit is contained in:
parent
fce6a5f7c7
commit
77a9e52449
|
@ -0,0 +1,60 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/nomad/jobspec"
|
||||
)
|
||||
|
||||
type ValidateCommand struct {
|
||||
Meta
|
||||
}
|
||||
|
||||
func (c *ValidateCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: nomad validate [options] <file>
|
||||
|
||||
Checks if a given job file has a valid specification. This can be used to check
|
||||
for any syntax errors or validation problems with a job.
|
||||
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *ValidateCommand) Synopsis() string {
|
||||
return "Checks if a given job specification is valid"
|
||||
}
|
||||
|
||||
func (c *ValidateCommand) Run(args []string) int {
|
||||
flags := c.Meta.FlagSet("validate", FlagSetNone)
|
||||
flags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Check that we got exactly one node
|
||||
args = flags.Args()
|
||||
if len(args) != 1 {
|
||||
c.Ui.Error(c.Help())
|
||||
return 1
|
||||
}
|
||||
file := args[0]
|
||||
|
||||
// Parse the job file
|
||||
job, err := jobspec.ParseFile(file)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing job file %s: %s", file, err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Check that the job is valid
|
||||
if err := job.Validate(); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error validating job: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Done!
|
||||
c.Ui.Output("Job validation successful")
|
||||
return 0
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func TestValidateCommand_Implements(t *testing.T) {
|
||||
var _ cli.Command = &ValidateCommand{}
|
||||
}
|
||||
|
||||
func TestValidateCommand(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
cmd := &ValidateCommand{Meta: Meta{Ui: ui}}
|
||||
|
||||
fh, err := ioutil.TempFile("", "nomad")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(fh.Name())
|
||||
_, err = fh.WriteString(`
|
||||
job "job1" {
|
||||
datacenters = [ "dc1" ]
|
||||
group "group1" {
|
||||
count = 1
|
||||
task "task1" {
|
||||
driver = "exec"
|
||||
resources = {
|
||||
cpu = 1000
|
||||
mem = 512
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if code := cmd.Run([]string{fh.Name()}); code != 0 {
|
||||
t.Fatalf("expect exit 0, got: %d: %s", code, ui.ErrorWriter.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCommand_Fails(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
cmd := &ValidateCommand{Meta: Meta{Ui: ui}}
|
||||
|
||||
// Fails on misuse
|
||||
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
|
||||
t.Fatalf("expected exit code 1, got: %d", code)
|
||||
}
|
||||
if out := ui.ErrorWriter.String(); !strings.Contains(out, cmd.Help()) {
|
||||
t.Fatalf("expected help output, got: %s", out)
|
||||
}
|
||||
ui.ErrorWriter.Reset()
|
||||
|
||||
// Fails when specified file does not exist
|
||||
if code := cmd.Run([]string{"/unicorns/leprechauns"}); code != 1 {
|
||||
t.Fatalf("expect exit 1, got: %d", code)
|
||||
}
|
||||
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error parsing") {
|
||||
t.Fatalf("expect parsing error, got: %s", out)
|
||||
}
|
||||
ui.ErrorWriter.Reset()
|
||||
|
||||
// Fails on invalid HCL
|
||||
fh1, err := ioutil.TempFile("", "nomad")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(fh1.Name())
|
||||
if _, err := fh1.WriteString("nope"); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if code := cmd.Run([]string{fh1.Name()}); code != 1 {
|
||||
t.Fatalf("expect exit 1, got: %d", code)
|
||||
}
|
||||
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error parsing") {
|
||||
t.Fatalf("expect parsing error, got: %s", err)
|
||||
}
|
||||
ui.ErrorWriter.Reset()
|
||||
|
||||
// Fails on invalid job spec
|
||||
fh2, err := ioutil.TempFile("", "nomad")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(fh2.Name())
|
||||
if _, err := fh2.WriteString(`job "job1" {}`); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if code := cmd.Run([]string{fh2.Name()}); code != 1 {
|
||||
t.Fatalf("expect exit 1, got: %d", code)
|
||||
}
|
||||
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error validating") {
|
||||
t.Fatalf("expect validation error, got: %s", out)
|
||||
}
|
||||
ui.ErrorWriter.Reset()
|
||||
}
|
|
@ -106,6 +106,12 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
|
|||
}, nil
|
||||
},
|
||||
|
||||
"validate": func() (cli.Command, error) {
|
||||
return &command.ValidateCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"version": func() (cli.Command, error) {
|
||||
ver := Version
|
||||
rel := VersionPrerelease
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "Commands: validate"
|
||||
sidebar_current: "docs-commands-validate"
|
||||
description: >
|
||||
The validate command is used to check a job specification for syntax errors and validation problems.
|
||||
---
|
||||
|
||||
# Command: validate
|
||||
|
||||
The `validate` command is used to check a [job specification](/docs/jobspec/index.html)
|
||||
for any syntax errors or validation problems.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
nomad validate <file>
|
||||
```
|
||||
|
||||
The validate command requires a single argument, specifying the path to a file
|
||||
containing a valid [job specification](/docs/jobspec/index.html). This file
|
||||
will be read and the job checked for any problems.
|
||||
|
||||
On successful validation, exit code 0 will be returned, otherwise an exit code
|
||||
of 1 indicates an error.
|
||||
|
|
@ -105,6 +105,9 @@
|
|||
</li>
|
||||
<li<%= sidebar_current("docs-commands-stop") %>>
|
||||
<a href="/docs/commands/stop.html">stop</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-commands-validate") %>>
|
||||
<a href="/docs/commands/validate.html">validate</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-commands-version") %>>
|
||||
<a href="/docs/commands/version.html">version</a>
|
||||
|
|
Loading…
Reference in New Issue