github.com/djenriquez/nomad-1@v0.8.1/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) Run(args []string) int {
    47  	flags := c.Meta.FlagSet("job validate", FlagSetNone)
    48  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    49  	if err := flags.Parse(args); err != nil {
    50  		return 1
    51  	}
    52  
    53  	// Check that we got exactly one node
    54  	args = flags.Args()
    55  	if len(args) != 1 {
    56  		c.Ui.Error(c.Help())
    57  		return 1
    58  	}
    59  
    60  	// Get Job struct from Jobfile
    61  	job, err := c.JobGetter.ApiJob(args[0])
    62  	if err != nil {
    63  		c.Ui.Error(fmt.Sprintf("Error getting job struct: %s", err))
    64  		return 1
    65  	}
    66  
    67  	// Get the HTTP client
    68  	client, err := c.Meta.Client()
    69  	if err != nil {
    70  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
    71  		return 255
    72  	}
    73  
    74  	// Force the region to be that of the job.
    75  	if r := job.Region; r != nil {
    76  		client.SetRegion(*r)
    77  	}
    78  
    79  	// Check that the job is valid
    80  	jr, _, err := client.Jobs().Validate(job, nil)
    81  	if err != nil {
    82  		jr, err = c.validateLocal(job)
    83  	}
    84  	if err != nil {
    85  		c.Ui.Error(fmt.Sprintf("Error validating job: %s", err))
    86  		return 1
    87  	}
    88  
    89  	if jr != nil && !jr.DriverConfigValidated {
    90  		c.Ui.Output(
    91  			c.Colorize().Color("[bold][yellow]Driver configuration not validated since connection to Nomad agent couldn't be established.[reset]\n"))
    92  	}
    93  
    94  	if jr != nil && jr.Error != "" {
    95  		c.Ui.Error(
    96  			c.Colorize().Color("[bold][red]Job validation errors:[reset]"))
    97  		c.Ui.Error(jr.Error)
    98  		return 1
    99  	}
   100  
   101  	// Print any warnings if there are any
   102  	if jr.Warnings != "" {
   103  		c.Ui.Output(
   104  			c.Colorize().Color(fmt.Sprintf("[bold][yellow]Job Warnings:\n%s[reset]\n", jr.Warnings)))
   105  	}
   106  
   107  	// Done!
   108  	c.Ui.Output(
   109  		c.Colorize().Color("[bold][green]Job validation successful[reset]"))
   110  	return 0
   111  }
   112  
   113  // validateLocal validates without talking to a Nomad agent
   114  func (c *JobValidateCommand) validateLocal(aj *api.Job) (*api.JobValidateResponse, error) {
   115  	var out api.JobValidateResponse
   116  
   117  	job := agent.ApiJobToStructJob(aj)
   118  	canonicalizeWarnings := job.Canonicalize()
   119  
   120  	if vErr := job.Validate(); vErr != nil {
   121  		if merr, ok := vErr.(*multierror.Error); ok {
   122  			for _, err := range merr.Errors {
   123  				out.ValidationErrors = append(out.ValidationErrors, err.Error())
   124  			}
   125  			out.Error = merr.Error()
   126  		} else {
   127  			out.ValidationErrors = append(out.ValidationErrors, vErr.Error())
   128  			out.Error = vErr.Error()
   129  		}
   130  	}
   131  
   132  	warnings := job.Warnings()
   133  	out.Warnings = structs.MergeMultierrorWarnings(warnings, canonicalizeWarnings)
   134  	return &out, nil
   135  }