github.com/hernad/nomad@v1.6.112/command/job_inspect.go (about)

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