Use go-getter to get jobfile by URL
This commit is contained in:
parent
410e0f7fe3
commit
7fb866ae4c
|
@ -4,10 +4,16 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
gg "github.com/hashicorp/go-getter"
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/jobspec"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
|
||||
"github.com/ryanuber/columnize"
|
||||
)
|
||||
|
||||
|
@ -222,3 +228,63 @@ READ:
|
|||
// Just stream from the underlying reader now
|
||||
return l.ReadCloser.Read(p)
|
||||
}
|
||||
|
||||
type Helper struct {
|
||||
// The fields below can be overwritten for tests
|
||||
testStdin io.Reader
|
||||
}
|
||||
|
||||
// StructJob returns the Job struct from jobfile.
|
||||
func (h *Helper) StructJob(jpath string) (*structs.Job, error) {
|
||||
var jobfile io.Reader
|
||||
switch jpath {
|
||||
case "-":
|
||||
if h.testStdin != nil {
|
||||
jobfile = h.testStdin
|
||||
} else {
|
||||
jobfile = os.Stdin
|
||||
}
|
||||
default:
|
||||
if len(jpath) == 0 {
|
||||
return nil, fmt.Errorf("Error jobfile path has to be specified.")
|
||||
}
|
||||
|
||||
job, err := ioutil.TempFile("", "jobfile")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer os.Remove(job.Name())
|
||||
|
||||
// Get the pwd
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := &gg.Client{
|
||||
Src: jpath,
|
||||
Pwd: pwd,
|
||||
Dst: job.Name(),
|
||||
}
|
||||
|
||||
if err := client.Get(); err != nil {
|
||||
return nil, fmt.Errorf("Error getting jobfile from %q: %v", jpath, err)
|
||||
} else {
|
||||
file, err := os.Open(job.Name())
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error opening file %q: %v", jpath, err)
|
||||
}
|
||||
jobfile = file
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the JobFile
|
||||
jobStruct, err := jobspec.Parse(jobfile)
|
||||
if err != nil {
|
||||
fmt.Errorf("Error parsing job file from %s: %v", jpath, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return jobStruct, nil
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package command
|
|||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -185,3 +186,42 @@ func TestHelpers_LineLimitReader_TimeLimit(t *testing.T) {
|
|||
t.Fatalf("did not exit by time limit")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructJob(t *testing.T) {
|
||||
fh, err := ioutil.TempFile("", "nomad")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(fh.Name())
|
||||
_, err = fh.WriteString(`
|
||||
job "job1" {
|
||||
type = "service"
|
||||
datacenters = [ "dc1" ]
|
||||
group "group1" {
|
||||
count = 1
|
||||
task "task1" {
|
||||
driver = "exec"
|
||||
resources = {}
|
||||
}
|
||||
restart{
|
||||
attempts = 10
|
||||
mode = "delay"
|
||||
}
|
||||
}
|
||||
}`)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
h := &Helper{}
|
||||
sj, err := h.StructJob(fh.Name())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
err = sj.Validate()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/jobspec"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"github.com/hashicorp/nomad/scheduler"
|
||||
"github.com/mitchellh/colorstring"
|
||||
|
@ -30,10 +25,8 @@ potentially invalid.`
|
|||
|
||||
type PlanCommand struct {
|
||||
Meta
|
||||
Helper
|
||||
color *colorstring.Colorize
|
||||
|
||||
// The fields below can be overwritten for tests
|
||||
testStdin io.Reader
|
||||
}
|
||||
|
||||
func (c *PlanCommand) Help() string {
|
||||
|
@ -76,9 +69,6 @@ Plan Options:
|
|||
|
||||
-verbose
|
||||
Increase diff verbosity.
|
||||
|
||||
-k
|
||||
Allow insecure SSL connections to access jobfile.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
@ -88,13 +78,12 @@ func (c *PlanCommand) Synopsis() string {
|
|||
}
|
||||
|
||||
func (c *PlanCommand) Run(args []string) int {
|
||||
var diff, verbose, insecure bool
|
||||
var diff, verbose bool
|
||||
|
||||
flags := c.Meta.FlagSet("plan", FlagSetClient)
|
||||
flags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
flags.BoolVar(&diff, "diff", true, "")
|
||||
flags.BoolVar(&verbose, "verbose", false, "")
|
||||
flags.BoolVar(&insecure, "k", false, "")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return 255
|
||||
|
@ -107,66 +96,12 @@ func (c *PlanCommand) Run(args []string) int {
|
|||
return 255
|
||||
}
|
||||
|
||||
var path, url string
|
||||
// If prefix has http(s)://, read the Jobfile from the URL
|
||||
if strings.Index(args[0], "http://") == 0 || strings.Index(args[0], "https://") == 0 {
|
||||
path = "_url"
|
||||
url = args[0]
|
||||
} else {
|
||||
// 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"
|
||||
case "_url":
|
||||
if len(url) == 0 {
|
||||
c.Ui.Error(fmt.Sprintf("Error invalid Jobfile name"))
|
||||
}
|
||||
var resp *http.Response
|
||||
var err error
|
||||
if insecure == true {
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
client := &http.Client{Transport: tr}
|
||||
resp, err = client.Get(url)
|
||||
} else {
|
||||
resp, err = http.Get(url)
|
||||
}
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error accessing URL %s: %v", url, err))
|
||||
return 1
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
c.Ui.Error(fmt.Sprintf("Error reading URL (%d) : %s", resp.StatusCode, resp.Status))
|
||||
return 1
|
||||
}
|
||||
f = resp.Body
|
||||
path = url
|
||||
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 255
|
||||
}
|
||||
f = file
|
||||
}
|
||||
|
||||
// Parse the JobFile
|
||||
job, err := jobspec.Parse(f)
|
||||
path := args[0]
|
||||
// Get Job struct from Jobfile
|
||||
job, err := c.Helper.StructJob(args[0])
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing job file %s: %v", path, err))
|
||||
return 255
|
||||
c.Ui.Error(fmt.Sprintf("Error getting job struct: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Initialize any fields that need to be.
|
||||
|
|
|
@ -110,8 +110,8 @@ func TestPlanCommand_From_STDIN(t *testing.T) {
|
|||
|
||||
ui := new(cli.MockUi)
|
||||
cmd := &PlanCommand{
|
||||
Meta: Meta{Ui: ui},
|
||||
testStdin: stdinR,
|
||||
Meta: Meta{Ui: ui},
|
||||
Helper: Helper{testStdin: stdinR},
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
|
|
@ -2,20 +2,15 @@ package command
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/jobspec"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
|
||||
|
@ -26,9 +21,7 @@ var (
|
|||
|
||||
type RunCommand struct {
|
||||
Meta
|
||||
|
||||
// The fields below can be overwritten for tests
|
||||
testStdin io.Reader
|
||||
Helper
|
||||
}
|
||||
|
||||
func (c *RunCommand) Help() string {
|
||||
|
@ -82,10 +75,6 @@ Run Options:
|
|||
-output
|
||||
Output the JSON that would be submitted to the HTTP API without submitting
|
||||
the job.
|
||||
|
||||
-k
|
||||
Allow insecure SSL connections to access jobfile.
|
||||
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
@ -95,7 +84,7 @@ func (c *RunCommand) Synopsis() string {
|
|||
}
|
||||
|
||||
func (c *RunCommand) Run(args []string) int {
|
||||
var detach, verbose, output, insecure bool
|
||||
var detach, verbose, output bool
|
||||
var checkIndexStr string
|
||||
|
||||
flags := c.Meta.FlagSet("run", FlagSetClient)
|
||||
|
@ -103,7 +92,6 @@ func (c *RunCommand) Run(args []string) int {
|
|||
flags.BoolVar(&detach, "detach", false, "")
|
||||
flags.BoolVar(&verbose, "verbose", false, "")
|
||||
flags.BoolVar(&output, "output", false, "")
|
||||
flags.BoolVar(&insecure, "k", false, "")
|
||||
flags.StringVar(&checkIndexStr, "check-index", "", "")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
|
@ -123,65 +111,17 @@ func (c *RunCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
var path, url string
|
||||
// If prefix has http(s)://, read the Jobfile from the URL
|
||||
if strings.Index(args[0], "http://") == 0 || strings.Index(args[0], "https://") == 0 {
|
||||
path = "_url"
|
||||
url = args[0]
|
||||
} else {
|
||||
// Read the Jobfile
|
||||
path = args[0]
|
||||
// Check that we got exactly one node
|
||||
args = flags.Args()
|
||||
if len(args) != 1 {
|
||||
c.Ui.Error(c.Help())
|
||||
return 1
|
||||
}
|
||||
|
||||
var f io.Reader
|
||||
switch path {
|
||||
case "-":
|
||||
if c.testStdin != nil {
|
||||
f = c.testStdin
|
||||
} else {
|
||||
f = os.Stdin
|
||||
}
|
||||
path = "stdin"
|
||||
case "_url":
|
||||
if len(url) == 0 {
|
||||
c.Ui.Error(fmt.Sprintf("Error invalid Jobfile name"))
|
||||
}
|
||||
var resp *http.Response
|
||||
var err error
|
||||
if insecure == true {
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
client := &http.Client{Transport: tr}
|
||||
resp, err = client.Get(url)
|
||||
} else {
|
||||
resp, err = http.Get(url)
|
||||
}
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error accessing URL %s: %v", url, err))
|
||||
return 1
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
c.Ui.Error(fmt.Sprintf("Error reading URL (%d) : %s", resp.StatusCode, resp.Status))
|
||||
return 1
|
||||
}
|
||||
f = resp.Body
|
||||
path = url
|
||||
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)
|
||||
// Get Job struct from Jobfile
|
||||
job, err := c.Helper.StructJob(args[0])
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing job file from %s: %v", path, err))
|
||||
c.Ui.Error(fmt.Sprintf("Error getting job struct: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -156,8 +156,8 @@ func TestRunCommand_From_STDIN(t *testing.T) {
|
|||
|
||||
ui := new(cli.MockUi)
|
||||
cmd := &RunCommand{
|
||||
Meta: Meta{Ui: ui},
|
||||
testStdin: stdinR,
|
||||
Meta: Meta{Ui: ui},
|
||||
Helper: Helper{testStdin: stdinR},
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
|
|
@ -1,21 +1,13 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/nomad/jobspec"
|
||||
)
|
||||
|
||||
type ValidateCommand struct {
|
||||
Meta
|
||||
|
||||
// The fields below can be overwritten for tests
|
||||
testStdin io.Reader
|
||||
Helper
|
||||
}
|
||||
|
||||
func (c *ValidateCommand) Help() string {
|
||||
|
@ -27,10 +19,6 @@ Usage: nomad validate [options] <file>
|
|||
|
||||
If the supplied path is "-", the jobfile is read from stdin. Otherwise
|
||||
it is read from the file at the supplied path.
|
||||
|
||||
-k
|
||||
Allow insecure SSL connections to access jobfile.
|
||||
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
@ -40,10 +28,7 @@ func (c *ValidateCommand) Synopsis() string {
|
|||
}
|
||||
|
||||
func (c *ValidateCommand) Run(args []string) int {
|
||||
var insecure bool
|
||||
|
||||
flags := c.Meta.FlagSet("validate", FlagSetNone)
|
||||
flags.BoolVar(&insecure, "k", false, "")
|
||||
flags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return 1
|
||||
|
@ -56,66 +41,10 @@ func (c *ValidateCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
// Read the Jobfile
|
||||
var path, url string
|
||||
// If prefix has http(s)://, read the Jobfile from the URL
|
||||
if strings.Index(args[0], "http://") == 0 || strings.Index(args[0], "https://") == 0 {
|
||||
path = "_url"
|
||||
url = args[0]
|
||||
} else {
|
||||
// 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"
|
||||
case "_url":
|
||||
if len(url) == 0 {
|
||||
c.Ui.Error(fmt.Sprintf("Error invalid Jobfile name"))
|
||||
}
|
||||
var resp *http.Response
|
||||
var err error
|
||||
if insecure == true {
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
client := &http.Client{Transport: tr}
|
||||
resp, err = client.Get(url)
|
||||
} else {
|
||||
resp, err = http.Get(url)
|
||||
}
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error accessing URL %s: %v", url, err))
|
||||
return 1
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
c.Ui.Error(fmt.Sprintf("Error reading URL (%d) : %s", resp.StatusCode, resp.Status))
|
||||
return 1
|
||||
}
|
||||
f = resp.Body
|
||||
path = url
|
||||
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)
|
||||
// Get Job struct from Jobfile
|
||||
job, err := c.Helper.StructJob(args[0])
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error parsing job file from %s: %v", path, err))
|
||||
c.Ui.Error(fmt.Sprintf("Error getting job struct: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
|
|
@ -111,8 +111,8 @@ func TestValidateCommand_From_STDIN(t *testing.T) {
|
|||
|
||||
ui := new(cli.MockUi)
|
||||
cmd := &ValidateCommand{
|
||||
Meta: Meta{Ui: ui},
|
||||
testStdin: stdinR,
|
||||
Meta: Meta{Ui: ui},
|
||||
Helper: Helper{testStdin: stdinR},
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
|
Loading…
Reference in New Issue