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

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/hashicorp/nomad/api"
     8  )
     9  
    10  type AllocStopCommand struct {
    11  	Meta
    12  }
    13  
    14  func (a *AllocStopCommand) Help() string {
    15  	helpText := `
    16  Usage: nomad alloc stop [options] <allocation>
    17  Alias: nomad stop
    18  
    19    Stop an existing allocation. This command is used to signal a specific alloc
    20    to shut down. When the allocation has been shut down, it will then be
    21    rescheduled. An interactive monitoring session will display log lines as the
    22    allocation completes shutting down. It is safe to exit the monitor early with
    23    ctrl-c.
    24  
    25    When ACLs are enabled, this command requires a token with the
    26    'alloc-lifecycle', 'read-job', and 'list-jobs' capabilities for the
    27    allocation's namespace.
    28  
    29  General Options:
    30  
    31    ` + generalOptionsUsage(usageOptsDefault) + `
    32  
    33  Stop Specific Options:
    34  
    35    -detach
    36      Return immediately instead of entering monitor mode. After the
    37      stop command is submitted, a new evaluation ID is printed to the
    38      screen, which can be used to examine the rescheduling evaluation using the
    39      eval-status command.
    40  
    41    -verbose
    42      Show full information.
    43  `
    44  	return strings.TrimSpace(helpText)
    45  }
    46  
    47  func (c *AllocStopCommand) Name() string { return "alloc stop" }
    48  
    49  func (c *AllocStopCommand) Run(args []string) int {
    50  	var detach, verbose bool
    51  
    52  	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
    53  	flags.Usage = func() { c.Ui.Output(c.Help()) }
    54  	flags.BoolVar(&detach, "detach", false, "")
    55  	flags.BoolVar(&verbose, "verbose", false, "")
    56  
    57  	if err := flags.Parse(args); err != nil {
    58  		return 1
    59  	}
    60  
    61  	// Check that we got exactly one alloc
    62  	args = flags.Args()
    63  	if len(args) != 1 {
    64  		c.Ui.Error("This command takes one argument: <alloc-id>")
    65  		c.Ui.Error(commandErrorText(c))
    66  		return 1
    67  	}
    68  
    69  	allocID := args[0]
    70  
    71  	// Truncate the id unless full length is requested
    72  	length := shortId
    73  	if verbose {
    74  		length = fullId
    75  	}
    76  
    77  	// Query the allocation info
    78  	if len(allocID) == 1 {
    79  		c.Ui.Error("Alloc ID must contain at least two characters.")
    80  		return 1
    81  	}
    82  
    83  	allocID = sanitizeUUIDPrefix(allocID)
    84  
    85  	// Get the HTTP client
    86  	client, err := c.Meta.Client()
    87  	if err != nil {
    88  		c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
    89  		return 1
    90  	}
    91  
    92  	allocs, _, err := client.Allocations().PrefixList(allocID)
    93  	if err != nil {
    94  		c.Ui.Error(fmt.Sprintf("Error querying allocation: %v", err))
    95  		return 1
    96  	}
    97  
    98  	if len(allocs) == 0 {
    99  		c.Ui.Error(fmt.Sprintf("No allocation(s) with prefix or id %q found", allocID))
   100  		return 1
   101  	}
   102  
   103  	if len(allocs) > 1 {
   104  		// Format the allocs
   105  		out := formatAllocListStubs(allocs, verbose, length)
   106  		c.Ui.Error(fmt.Sprintf("Prefix matched multiple allocations\n\n%s", out))
   107  		return 1
   108  	}
   109  
   110  	// Prefix lookup matched a single allocation
   111  	q := &api.QueryOptions{Namespace: allocs[0].Namespace}
   112  	alloc, _, err := client.Allocations().Info(allocs[0].ID, q)
   113  	if err != nil {
   114  		c.Ui.Error(fmt.Sprintf("Error querying allocation: %s", err))
   115  		return 1
   116  	}
   117  
   118  	resp, err := client.Allocations().Stop(alloc, nil)
   119  	if err != nil {
   120  		c.Ui.Error(fmt.Sprintf("Error stopping allocation: %s", err))
   121  		return 1
   122  	}
   123  
   124  	if detach {
   125  		c.Ui.Output(resp.EvalID)
   126  		return 0
   127  	}
   128  
   129  	mon := newMonitor(c.Ui, client, length)
   130  	return mon.monitor(resp.EvalID)
   131  }
   132  
   133  func (a *AllocStopCommand) Synopsis() string {
   134  	return "Stop and reschedule a running allocation"
   135  }