From 818d671407bb9177ef2ee7b9b727c4dd8e16a707 Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Fri, 22 Jul 2016 13:48:14 -0700 Subject: [PATCH] validate from stdin --- command/validate.go | 37 ++++++++++++++++++++++++++++++++---- command/validate_test.go | 41 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/command/validate.go b/command/validate.go index c32d76842..98abaf534 100644 --- a/command/validate.go +++ b/command/validate.go @@ -2,6 +2,8 @@ package command import ( "fmt" + "io" + "os" "strings" "github.com/hashicorp/nomad/jobspec" @@ -9,6 +11,9 @@ import ( type ValidateCommand struct { Meta + + // The fields below can be overwritten for tests + testStdin io.Reader } func (c *ValidateCommand) Help() string { @@ -18,6 +23,9 @@ Usage: nomad validate [options] Checks if a given HCL job file has a valid specification. This can be used to check for any syntax errors or validation problems with a job. + If the supplied path is "-", the jobfile is read from stdin. Otherwise + it is read from the file at the supplied path. + ` return strings.TrimSpace(helpText) } @@ -39,12 +47,33 @@ func (c *ValidateCommand) 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 + } + path = "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 from %s: %v", path, err)) return 1 } diff --git a/command/validate_test.go b/command/validate_test.go index 069e0af65..d566cc36a 100644 --- a/command/validate_test.go +++ b/command/validate_test.go @@ -63,7 +63,7 @@ func TestValidateCommand_Fails(t *testing.T) { 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") { + if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error opening") { t.Fatalf("expect parsing error, got: %s", out) } ui.ErrorWriter.Reset() @@ -102,3 +102,42 @@ func TestValidateCommand_Fails(t *testing.T) { } ui.ErrorWriter.Reset() } + +func TestValidateCommand_From_STDIN(t *testing.T) { + stdinR, stdinW, err := os.Pipe() + if err != nil { + t.Fatalf("err: %s", err) + } + + ui := new(cli.MockUi) + cmd := &ValidateCommand{ + 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()) + } + ui.ErrorWriter.Reset() +}