github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/command/alloc_restart.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 AllocRestartCommand struct { 13 Meta 14 } 15 16 func (a *AllocRestartCommand) Help() string { 17 helpText := ` 18 Usage: nomad alloc restart [options] <allocation> <task> 19 20 Restart an existing allocation. This command is used to restart a specific alloc 21 and its tasks. If no task is provided then all of the allocation's tasks will 22 be restarted. 23 24 When ACLs are enabled, this command requires a token with the 25 'alloc-lifecycle', 'read-job', and 'list-jobs' capabilities for the 26 allocation's namespace. 27 28 General Options: 29 30 ` + generalOptionsUsage(usageOptsDefault) + ` 31 32 Restart Specific Options: 33 34 -verbose 35 Show full information. 36 ` 37 return strings.TrimSpace(helpText) 38 } 39 40 func (c *AllocRestartCommand) Name() string { return "alloc restart" } 41 42 func (c *AllocRestartCommand) Run(args []string) int { 43 var verbose bool 44 45 flags := c.Meta.FlagSet(c.Name(), FlagSetClient) 46 flags.Usage = func() { c.Ui.Output(c.Help()) } 47 flags.BoolVar(&verbose, "verbose", false, "") 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 one or two arguments: <alloc-id> <task-name>") 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("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 q := &api.QueryOptions{Namespace: allocs[0].Namespace} 104 alloc, _, err := client.Allocations().Info(allocs[0].ID, q) 105 if err != nil { 106 c.Ui.Error(fmt.Sprintf("Error querying allocation: %s", err)) 107 return 1 108 } 109 110 var taskName string 111 if len(args) == 2 { 112 // Validate Task 113 taskName = args[1] 114 err := validateTaskExistsInAllocation(taskName, alloc) 115 if err != nil { 116 c.Ui.Error(err.Error()) 117 return 1 118 } 119 } 120 121 err = client.Allocations().Restart(alloc, taskName, nil) 122 if err != nil { 123 c.Ui.Error(fmt.Sprintf("Failed to restart allocation:\n\n%s", err.Error())) 124 return 1 125 } 126 127 return 0 128 } 129 130 func validateTaskExistsInAllocation(taskName string, alloc *api.Allocation) error { 131 tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup) 132 if tg == nil { 133 return fmt.Errorf("Could not find allocation task group: %s", alloc.TaskGroup) 134 } 135 136 foundTaskNames := make([]string, len(tg.Tasks)) 137 for i, task := range tg.Tasks { 138 foundTaskNames[i] = task.Name 139 if task.Name == taskName { 140 return nil 141 } 142 } 143 144 return fmt.Errorf("Could not find task named: %s, found:\n%s", taskName, formatList(foundTaskNames)) 145 } 146 147 func (a *AllocRestartCommand) Synopsis() string { 148 return "Restart a running allocation" 149 } 150 151 func (c *AllocRestartCommand) AutocompleteArgs() complete.Predictor { 152 // Here we attempt to autocomplete allocations for any position of arg. 153 // We should eventually try to auto complete the task name if the arg is 154 // at position 2. 155 return complete.PredictFunc(func(a complete.Args) []string { 156 client, err := c.Meta.Client() 157 if err != nil { 158 return nil 159 } 160 161 resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Allocs, nil) 162 if err != nil { 163 return []string{} 164 } 165 return resp.Matches[contexts.Allocs] 166 }) 167 }