github.com/anuvu/nomad@v0.8.7-atom1/command/status.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/hashicorp/nomad/api/contexts"
     8  	"github.com/mitchellh/cli"
     9  	"github.com/posener/complete"
    10  )
    11  
    12  type StatusCommand struct {
    13  	Meta
    14  }
    15  
    16  func (s *StatusCommand) Help() string {
    17  	helpText := `
    18  Usage: nomad status [options] <identifier>
    19  
    20    Display the status output for any given resource. The command will
    21    detect the type of resource being queried and display the appropriate
    22    status output.
    23  
    24  General Options:
    25  
    26    ` + generalOptionsUsage()
    27  
    28  	return strings.TrimSpace(helpText)
    29  }
    30  
    31  func (c *StatusCommand) Synopsis() string {
    32  	return "Display the status output for a resource"
    33  }
    34  
    35  func (c *StatusCommand) AutocompleteFlags() complete.Flags {
    36  	return c.Meta.AutocompleteFlags(FlagSetClient)
    37  }
    38  
    39  func (c *StatusCommand) AutocompleteArgs() complete.Predictor {
    40  	return complete.PredictFunc(func(a complete.Args) []string {
    41  		client, err := c.Meta.Client()
    42  		if err != nil {
    43  			return nil
    44  		}
    45  
    46  		resp, _, err := client.Search().PrefixSearch(a.Last, contexts.All, nil)
    47  		if err != nil {
    48  			return []string{}
    49  		}
    50  
    51  		final := make([]string, 0)
    52  
    53  		for _, matches := range resp.Matches {
    54  			if len(matches) == 0 {
    55  				continue
    56  			}
    57  
    58  			final = append(final, matches...)
    59  		}
    60  
    61  		return final
    62  	})
    63  }
    64  
    65  func (c *StatusCommand) Run(args []string) int {
    66  	flags := c.Meta.FlagSet("status", FlagSetClient)
    67  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    68  
    69  	if err := flags.Parse(args); err != nil {
    70  		c.Ui.Error(fmt.Sprintf("Error parsing arguments: %q", err))
    71  		return 1
    72  	}
    73  
    74  	// Store the original arguments so we can pass them to the routed command
    75  	argsCopy := args
    76  
    77  	// Check that we got exactly one evaluation ID
    78  	args = flags.Args()
    79  
    80  	// Get the HTTP client
    81  	client, err := c.Meta.Client()
    82  	if err != nil {
    83  		c.Ui.Error(fmt.Sprintf("Error initializing client: %q", err))
    84  		return 1
    85  	}
    86  
    87  	// If no identifier is provided, default to listing jobs
    88  	if len(args) == 0 {
    89  		cmd := &JobStatusCommand{Meta: c.Meta}
    90  		return cmd.Run(argsCopy)
    91  	}
    92  
    93  	id := args[len(args)-1]
    94  
    95  	// Query for the context associated with the id
    96  	res, _, err := client.Search().PrefixSearch(id, contexts.All, nil)
    97  	if err != nil {
    98  		c.Ui.Error(fmt.Sprintf("Error querying search with id: %q", err))
    99  		return 1
   100  	}
   101  
   102  	if res.Matches == nil {
   103  		c.Ui.Error(fmt.Sprintf("No matches returned for query: %q", err))
   104  		return 1
   105  	}
   106  
   107  	var match contexts.Context
   108  	exactMatches := 0
   109  	for ctx, vers := range res.Matches {
   110  		if len(vers) > 0 && vers[0] == id {
   111  			match = ctx
   112  			exactMatches++
   113  		}
   114  	}
   115  
   116  	if exactMatches > 1 {
   117  		c.logMultiMatchError(id, res.Matches)
   118  		return 1
   119  	} else if exactMatches == 0 {
   120  		matchCount := 0
   121  		for ctx, vers := range res.Matches {
   122  			l := len(vers)
   123  			if l == 1 {
   124  				match = ctx
   125  				matchCount++
   126  			}
   127  
   128  			// Only a single result should return, as this is a match against a full id
   129  			if matchCount > 1 || l > 1 {
   130  				c.logMultiMatchError(id, res.Matches)
   131  				return 1
   132  			}
   133  		}
   134  	}
   135  
   136  	var cmd cli.Command
   137  	switch match {
   138  	case contexts.Evals:
   139  		cmd = &EvalStatusCommand{Meta: c.Meta}
   140  	case contexts.Nodes:
   141  		cmd = &NodeStatusCommand{Meta: c.Meta}
   142  	case contexts.Allocs:
   143  		cmd = &AllocStatusCommand{Meta: c.Meta}
   144  	case contexts.Jobs:
   145  		cmd = &JobStatusCommand{Meta: c.Meta}
   146  	case contexts.Deployments:
   147  		cmd = &DeploymentStatusCommand{Meta: c.Meta}
   148  	case contexts.Namespaces:
   149  		cmd = &NamespaceStatusCommand{Meta: c.Meta}
   150  	case contexts.Quotas:
   151  		cmd = &QuotaStatusCommand{Meta: c.Meta}
   152  	default:
   153  		c.Ui.Error(fmt.Sprintf("Unable to resolve ID: %q", id))
   154  		return 1
   155  	}
   156  
   157  	return cmd.Run(argsCopy)
   158  }
   159  
   160  // logMultiMatchError is used to log an error message when multiple matches are
   161  // found. The error message logged displays the matched IDs per context.
   162  func (c *StatusCommand) logMultiMatchError(id string, matches map[contexts.Context][]string) {
   163  	c.Ui.Error(fmt.Sprintf("Multiple matches found for id %q", id))
   164  	for ctx, vers := range matches {
   165  		if len(vers) == 0 {
   166  			continue
   167  		}
   168  
   169  		c.Ui.Error(fmt.Sprintf("\n%s:", strings.Title(string(ctx))))
   170  		c.Ui.Error(fmt.Sprintf("%s", strings.Join(vers, ", ")))
   171  	}
   172  }