Merge pull request #1329 from hashicorp/f-read-job-from-stdin

Read Nomad Jobfile from STDIN if specified.
This commit is contained in:
Jake Champlin 2016-06-22 17:46:58 -04:00 committed by GitHub
commit 5387e49c41
3 changed files with 77 additions and 9 deletions

View File

@ -5,6 +5,8 @@ import (
"encoding/gob"
"encoding/json"
"fmt"
"io"
"os"
"regexp"
"strconv"
"strings"
@ -22,16 +24,22 @@ var (
type RunCommand struct {
Meta
// The fields below can be overwritten for tests
testStdin io.Reader
}
func (c *RunCommand) Help() string {
helpText := `
Usage: nomad run [options] <file>
Usage: nomad run [options] <path>
Starts running a new job or updates an existing job using
the specification located at <file>. This is the main command
the specification located at <path>. This is the main command
used to interact with Nomad.
If the supplied path is "-", the jobfile is read from stdin. Otherwise
it is read from the file at the supplied path.
Upon successful job submission, this command will immediately
enter an interactive monitor. This is useful to watch Nomad's
internals make scheduling decisions and place the submitted work
@ -107,12 +115,32 @@ func (c *RunCommand) Run(args []string) int {
c.Ui.Error(c.Help())
return 1
}
file := args[0]
// Parse the job file
job, err := jobspec.ParseFile(file)
// Read the Jobfile
path := args[0]
var f io.Reader
switch path {
case "-":
if c.testStdin != nil {
f = c.testStdin
} else {
f = os.Stdin
}
default:
file, err := os.Open(path)
defer file.Close()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error opening file %q: %v", path, err))
return 1
}
f = file
}
// Parse the JobFile
job, err := jobspec.Parse(f)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error parsing job file %s: %s", file, err))
c.Ui.Error(fmt.Sprintf("Error parsing job file %s: %v", f, err))
return 1
}
@ -121,7 +149,7 @@ func (c *RunCommand) Run(args []string) int {
// Check that the job is valid
if err := job.Validate(); err != nil {
c.Ui.Error(fmt.Sprintf("Error validating job: %s", err))
c.Ui.Error(fmt.Sprintf("Error validating job: %v", err))
return 1
}

View File

@ -147,3 +147,41 @@ job "job1" {
ui.ErrorWriter.Reset()
}
func TestRunCommand_From_STDIN(t *testing.T) {
stdinR, stdinW, err := os.Pipe()
if err != nil {
t.Fatalf("err: %s", err)
}
ui := new(cli.MockUi)
cmd := &RunCommand{
Meta: Meta{Ui: ui},
testStdin: stdinR,
}
go func() {
stdinW.WriteString(`
job "job1" {
type = "service"
datacenters = [ "dc1" ]
group "group1" {
count = 1
task "task1" {
driver = "exec"
resources = {
cpu = 1000
disk = 150
memory = 512
}
}
}
}`)
stdinW.Close()
}()
args := []string{"-"}
if code := cmd.Run(args); code != 0 {
t.Fatalf("expected exit code 0, got %d: %q", code, ui.ErrorWriter.String())
}
}

View File

@ -15,12 +15,14 @@ format.
## Usage
```
nomad run [options] <file>
nomad run [options] <jobfile>
```
The run 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 will be submitted to Nomad for scheduling.
will be read and the job will be submitted to Nomad for scheduling. If the
supplied path is "-", the jobfile is read from STDIN. Otherwise it is read
from the file at the supplied path.
By default, on successful job submission the run command will enter an
interactive monitor and display log information detailing the scheduling