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