github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/command/job_inspect.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/hashicorp/nomad/api"
     8  	"github.com/hashicorp/nomad/api/contexts"
     9  	"github.com/posener/complete"
    10  )
    11  
    12  type JobInspectCommand struct {
    13  	Meta
    14  }
    15  
    16  func (c *JobInspectCommand) Help() string {
    17  	helpText := `
    18  Usage: nomad job inspect [options] <job>
    19  Alias: nomad inspect
    20  
    21    Inspect is used to see the specification of a submitted job.
    22  
    23    When ACLs are enabled, this command requires a token with the 'read-job' and
    24    'list-jobs' capabilities for the job's namespace.
    25  
    26  General Options:
    27  
    28    ` + generalOptionsUsage(usageOptsDefault) + `
    29  
    30  Inspect Options:
    31  
    32    -version <job version>
    33      Display the job at the given job version.
    34  
    35    -json
    36      Output the job in its JSON format.
    37  
    38    -t
    39      Format and display job using a Go template.
    40  `
    41  	return strings.TrimSpace(helpText)
    42  }
    43  
    44  func (c *JobInspectCommand) Synopsis() string {
    45  	return "Inspect a submitted job"
    46  }
    47  
    48  func (c *JobInspectCommand) AutocompleteFlags() complete.Flags {
    49  	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
    50  		complete.Flags{
    51  			"-version": complete.PredictAnything,
    52  			"-json":    complete.PredictNothing,
    53  			"-t":       complete.PredictAnything,
    54  		})
    55  }
    56  
    57  func (c *JobInspectCommand) AutocompleteArgs() complete.Predictor {
    58  	return complete.PredictFunc(func(a complete.Args) []string {
    59  		client, err := c.Meta.Client()
    60  		if err != nil {
    61  			return nil
    62  		}
    63  
    64  		resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Jobs, nil)
    65  		if err != nil {
    66  			return []string{}
    67  		}
    68  		return resp.Matches[contexts.Jobs]
    69  	})
    70  }
    71  
    72  func (c *JobInspectCommand) Name() string { return "job inspect" }
    73  
    74  func (c *JobInspectCommand) Run(args []string) int {
    75  	var json bool
    76  	var tmpl, versionStr string
    77  
    78  	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
    79  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    80  	flags.BoolVar(&json, "json", false, "")
    81  	flags.StringVar(&tmpl, "t", "", "")
    82  	flags.StringVar(&versionStr, "version", "", "")
    83  
    84  	if err := flags.Parse(args); err != nil {
    85  		return 1
    86  	}
    87  	args = flags.Args()
    88  
    89  	// Get the HTTP client
    90  	client, err := c.Meta.Client()
    91  	if err != nil {
    92  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
    93  		return 1
    94  	}
    95  
    96  	// If args not specified but output format is specified, format and output the jobs data list
    97  	if len(args) == 0 && (json || len(tmpl) > 0) {
    98  		jobs, _, err := client.Jobs().List(nil)
    99  		if err != nil {
   100  			c.Ui.Error(fmt.Sprintf("Error querying jobs: %v", err))
   101  			return 1
   102  		}
   103  
   104  		out, err := Format(json, tmpl, jobs)
   105  		if err != nil {
   106  			c.Ui.Error(err.Error())
   107  			return 1
   108  		}
   109  
   110  		c.Ui.Output(out)
   111  		return 0
   112  	}
   113  
   114  	// Check that we got exactly one job
   115  	if len(args) != 1 {
   116  		c.Ui.Error("This command takes one argument: <job>")
   117  		c.Ui.Error(commandErrorText(c))
   118  		return 1
   119  	}
   120  	jobID := args[0]
   121  
   122  	// Check if the job exists
   123  	jobs, _, err := client.Jobs().PrefixList(jobID)
   124  	if err != nil {
   125  		c.Ui.Error(fmt.Sprintf("Error inspecting job: %s", err))
   126  		return 1
   127  	}
   128  	if len(jobs) == 0 {
   129  		c.Ui.Error(fmt.Sprintf("No job(s) with prefix or id %q found", jobID))
   130  		return 1
   131  	}
   132  	if len(jobs) > 1 && (c.allNamespaces() || strings.TrimSpace(jobID) != jobs[0].ID) {
   133  		c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs, c.allNamespaces())))
   134  		return 1
   135  	}
   136  
   137  	var version *uint64
   138  	if versionStr != "" {
   139  		v, _, err := parseVersion(versionStr)
   140  		if err != nil {
   141  			c.Ui.Error(fmt.Sprintf("Error parsing version value %q: %v", versionStr, err))
   142  			return 1
   143  		}
   144  
   145  		version = &v
   146  	}
   147  
   148  	// Prefix lookup matched a single job
   149  	job, err := getJob(client, jobs[0].JobSummary.Namespace, jobs[0].ID, version)
   150  	if err != nil {
   151  		c.Ui.Error(fmt.Sprintf("Error inspecting job: %s", err))
   152  		return 1
   153  	}
   154  
   155  	// If output format is specified, format and output the data
   156  	if json || len(tmpl) > 0 {
   157  		out, err := Format(json, tmpl, job)
   158  		if err != nil {
   159  			c.Ui.Error(err.Error())
   160  			return 1
   161  		}
   162  
   163  		c.Ui.Output(out)
   164  		return 0
   165  	}
   166  
   167  	// Print the contents of the job
   168  	req := struct {
   169  		Job *api.Job
   170  	}{
   171  		Job: job,
   172  	}
   173  	f, err := DataFormat("json", "")
   174  	if err != nil {
   175  		c.Ui.Error(fmt.Sprintf("Error getting formatter: %s", err))
   176  		return 1
   177  	}
   178  
   179  	out, err := f.TransformData(req)
   180  	if err != nil {
   181  		c.Ui.Error(fmt.Sprintf("Error formatting the data: %s", err))
   182  		return 1
   183  	}
   184  	c.Ui.Output(out)
   185  	return 0
   186  }
   187  
   188  // getJob retrieves the job optionally at a particular version.
   189  func getJob(client *api.Client, namespace, jobID string, version *uint64) (*api.Job, error) {
   190  	var q *api.QueryOptions
   191  	if namespace != "" {
   192  		q = &api.QueryOptions{Namespace: namespace}
   193  	}
   194  	if version == nil {
   195  		job, _, err := client.Jobs().Info(jobID, q)
   196  		return job, err
   197  	}
   198  
   199  	versions, _, _, err := client.Jobs().Versions(jobID, false, q)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  
   204  	for _, j := range versions {
   205  		if *j.Version != *version {
   206  			continue
   207  		}
   208  		return j, nil
   209  	}
   210  
   211  	return nil, fmt.Errorf("job %q with version %d couldn't be found", jobID, *version)
   212  }