github.com/zhizhiboom/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/command/job_validate.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	multierror "github.com/hashicorp/go-multierror"
     8  	"github.com/hashicorp/nomad/api"
     9  	"github.com/hashicorp/nomad/command/agent"
    10  	"github.com/hashicorp/nomad/nomad/structs"
    11  	"github.com/posener/complete"
    12  )
    13  
    14  type JobValidateCommand struct {
    15  	Meta
    16  	JobGetter
    17  }
    18  
    19  func (c *JobValidateCommand) Help() string {
    20  	helpText := `
    21  Usage: nomad job validate [options] <path>
    22  Alias: nomad validate
    23  
    24    Checks if a given HCL job file has a valid specification. This can be used to
    25    check for any syntax errors or validation problems with a job.
    26  
    27    If the supplied path is "-", the jobfile is read from stdin. Otherwise
    28    it is read from the file at the supplied path or downloaded and
    29    read from URL specified.
    30  `
    31  	return strings.TrimSpace(helpText)
    32  }
    33  
    34  func (c *JobValidateCommand) Synopsis() string {
    35  	return "Checks if a given job specification is valid"
    36  }
    37  
    38  func (c *JobValidateCommand) AutocompleteFlags() complete.Flags {
    39  	return nil
    40  }
    41  
    42  func (c *JobValidateCommand) AutocompleteArgs() complete.Predictor {
    43  	return complete.PredictOr(complete.PredictFiles("*.nomad"), complete.PredictFiles("*.hcl"))
    44  }
    45  
    46  func (c *JobValidateCommand) Name() string { return "job validate" }
    47  
    48  func (c *JobValidateCommand) Run(args []string) int {
    49  	flags := c.Meta.FlagSet(c.Name(), FlagSetNone)
    50  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    51  	if err := flags.Parse(args); err != nil {
    52  		return 1
    53  	}
    54  
    55  	// Check that we got exactly one node
    56  	args = flags.Args()
    57  	if len(args) != 1 {
    58  		c.Ui.Error("This command takes one argument: <path>")
    59  		c.Ui.Error(commandErrorText(c))
    60  		return 1
    61  	}
    62  
    63  	// Get Job struct from Jobfile
    64  	job, err := c.JobGetter.ApiJob(args[0])
    65  	if err != nil {
    66  		c.Ui.Error(fmt.Sprintf("Error getting job struct: %s", err))
    67  		return 1
    68  	}
    69  
    70  	// Get the HTTP client
    71  	client, err := c.Meta.Client()
    72  	if err != nil {
    73  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
    74  		return 255
    75  	}
    76  
    77  	// Force the region to be that of the job.
    78  	if r := job.Region; r != nil {
    79  		client.SetRegion(*r)
    80  	}
    81  
    82  	// Check that the job is valid
    83  	jr, _, err := client.Jobs().Validate(job, nil)
    84  	if err != nil {
    85  		jr, err = c.validateLocal(job)
    86  	}
    87  	if err != nil {
    88  		c.Ui.Error(fmt.Sprintf("Error validating job: %s", err))
    89  		return 1
    90  	}
    91  
    92  	if jr != nil && !jr.DriverConfigValidated {
    93  		c.Ui.Output(
    94  			c.Colorize().Color("[bold][yellow]Driver configuration not validated since connection to Nomad agent couldn't be established.[reset]\n"))
    95  	}
    96  
    97  	if jr != nil && jr.Error != "" {
    98  		c.Ui.Error(
    99  			c.Colorize().Color("[bold][red]Job validation errors:[reset]"))
   100  		c.Ui.Error(jr.Error)
   101  		return 1
   102  	}
   103  
   104  	// Print any warnings if there are any
   105  	if jr.Warnings != "" {
   106  		c.Ui.Output(
   107  			c.Colorize().Color(fmt.Sprintf("[bold][yellow]Job Warnings:\n%s[reset]\n", jr.Warnings)))
   108  	}
   109  
   110  	// Done!
   111  	c.Ui.Output(
   112  		c.Colorize().Color("[bold][green]Job validation successful[reset]"))
   113  	return 0
   114  }
   115  
   116  // validateLocal validates without talking to a Nomad agent
   117  func (c *JobValidateCommand) validateLocal(aj *api.Job) (*api.JobValidateResponse, error) {
   118  	var out api.JobValidateResponse
   119  
   120  	job := agent.ApiJobToStructJob(aj)
   121  	canonicalizeWarnings := job.Canonicalize()
   122  
   123  	if vErr := job.Validate(); vErr != nil {
   124  		if merr, ok := vErr.(*multierror.Error); ok {
   125  			for _, err := range merr.Errors {
   126  				out.ValidationErrors = append(out.ValidationErrors, err.Error())
   127  			}
   128  			out.Error = merr.Error()
   129  		} else {
   130  			out.ValidationErrors = append(out.ValidationErrors, vErr.Error())
   131  			out.Error = vErr.Error()
   132  		}
   133  	}
   134  
   135  	warnings := job.Warnings()
   136  	out.Warnings = structs.MergeMultierrorWarnings(warnings, canonicalizeWarnings)
   137  	return &out, nil
   138  }