github.com/manicqin/nomad@v0.9.5/command/alloc_signal.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/hashicorp/nomad/api/contexts"
     8  	"github.com/posener/complete"
     9  )
    10  
    11  type AllocSignalCommand struct {
    12  	Meta
    13  }
    14  
    15  func (a *AllocSignalCommand) Help() string {
    16  	helpText := `
    17  Usage: nomad alloc signal [options] <signal> <allocation> <task>
    18  
    19    signal an existing allocation. This command is used to signal a specific alloc
    20    and its subtasks. If no task is provided then all of the allocations subtasks
    21    will receive the signal.
    22  
    23  General Options:
    24  
    25    ` + generalOptionsUsage() + `
    26  
    27  Signal Specific Options:
    28  
    29    -s
    30      Specify the signal that the selected tasks should receive.
    31  
    32    -verbose
    33      Show full information.
    34  `
    35  	return strings.TrimSpace(helpText)
    36  }
    37  
    38  func (c *AllocSignalCommand) Name() string { return "alloc signal" }
    39  
    40  func (c *AllocSignalCommand) Run(args []string) int {
    41  	var verbose bool
    42  	var signal string
    43  
    44  	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
    45  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    46  	flags.BoolVar(&verbose, "verbose", false, "")
    47  	flags.StringVar(&signal, "s", "SIGKILL", "")
    48  
    49  	if err := flags.Parse(args); err != nil {
    50  		return 1
    51  	}
    52  
    53  	// Check that we got exactly one alloc
    54  	args = flags.Args()
    55  	if len(args) < 1 || len(args) > 2 {
    56  		c.Ui.Error("This command takes up to two arguments: <alloc-id> <task>")
    57  		c.Ui.Error(commandErrorText(c))
    58  		return 1
    59  	}
    60  
    61  	allocID := args[0]
    62  
    63  	// Truncate the id unless full length is requested
    64  	length := shortId
    65  	if verbose {
    66  		length = fullId
    67  	}
    68  
    69  	// Query the allocation info
    70  	if len(allocID) == 1 {
    71  		c.Ui.Error(fmt.Sprintf("Alloc ID must contain at least two characters."))
    72  		return 1
    73  	}
    74  
    75  	allocID = sanitizeUUIDPrefix(allocID)
    76  
    77  	// Get the HTTP client
    78  	client, err := c.Meta.Client()
    79  	if err != nil {
    80  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
    81  		return 1
    82  	}
    83  
    84  	allocs, _, err := client.Allocations().PrefixList(allocID)
    85  	if err != nil {
    86  		c.Ui.Error(fmt.Sprintf("Error querying allocation: %v", err))
    87  		return 1
    88  	}
    89  
    90  	if len(allocs) == 0 {
    91  		c.Ui.Error(fmt.Sprintf("No allocation(s) with prefix or id %q found", allocID))
    92  		return 1
    93  	}
    94  
    95  	if len(allocs) > 1 {
    96  		// Format the allocs
    97  		out := formatAllocListStubs(allocs, verbose, length)
    98  		c.Ui.Error(fmt.Sprintf("Prefix matched multiple allocations\n\n%s", out))
    99  		return 1
   100  	}
   101  
   102  	// Prefix lookup matched a single allocation
   103  	alloc, _, err := client.Allocations().Info(allocs[0].ID, nil)
   104  	if err != nil {
   105  		c.Ui.Error(fmt.Sprintf("Error querying allocation: %s", err))
   106  		return 1
   107  	}
   108  
   109  	var taskName string
   110  	if len(args) == 2 {
   111  		// Validate Task
   112  		taskName = args[1]
   113  		err := validateTaskExistsInAllocation(taskName, alloc)
   114  		if err != nil {
   115  			c.Ui.Error(err.Error())
   116  			return 1
   117  		}
   118  	}
   119  
   120  	err = client.Allocations().Signal(alloc, nil, taskName, signal)
   121  	if err != nil {
   122  		c.Ui.Error(fmt.Sprintf("Error signalling allocation: %s", err))
   123  		return 1
   124  	}
   125  
   126  	return 0
   127  }
   128  
   129  func (a *AllocSignalCommand) Synopsis() string {
   130  	return "Signal a running allocation"
   131  }
   132  
   133  func (c *AllocSignalCommand) AutocompleteFlags() complete.Flags {
   134  	return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
   135  		complete.Flags{
   136  			"-s":       complete.PredictNothing,
   137  			"-verbose": complete.PredictNothing,
   138  		})
   139  }
   140  func (c *AllocSignalCommand) AutocompleteArgs() complete.Predictor {
   141  	// Here we only autocomplete allocation names. Eventually we may consider
   142  	// expanding this to also autocomplete task names. To do so, we'll need to
   143  	// either change the autocompletion api, or implement parsing such that we can
   144  	// easily compute the current arg position.
   145  	return complete.PredictFunc(func(a complete.Args) []string {
   146  		client, err := c.Meta.Client()
   147  		if err != nil {
   148  			return nil
   149  		}
   150  
   151  		resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Allocs, nil)
   152  		if err != nil {
   153  			return []string{}
   154  		}
   155  		return resp.Matches[contexts.Allocs]
   156  	})
   157  }