github.com/manicqin/nomad@v0.9.5/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 General Options: 25 26 ` + generalOptionsUsage() + ` 27 28 Restart Specific Options: 29 30 -verbose 31 Show full information. 32 ` 33 return strings.TrimSpace(helpText) 34 } 35 36 func (c *AllocRestartCommand) Name() string { return "alloc restart" } 37 38 func (c *AllocRestartCommand) Run(args []string) int { 39 var verbose bool 40 41 flags := c.Meta.FlagSet(c.Name(), FlagSetClient) 42 flags.Usage = func() { c.Ui.Output(c.Help()) } 43 flags.BoolVar(&verbose, "verbose", false, "") 44 45 if err := flags.Parse(args); err != nil { 46 return 1 47 } 48 49 // Check that we got exactly one alloc 50 args = flags.Args() 51 if len(args) < 1 || len(args) > 2 { 52 c.Ui.Error("This command takes one or two arguments: <alloc-id> <task-name>") 53 c.Ui.Error(commandErrorText(c)) 54 return 1 55 } 56 57 allocID := args[0] 58 59 // Truncate the id unless full length is requested 60 length := shortId 61 if verbose { 62 length = fullId 63 } 64 65 // Query the allocation info 66 if len(allocID) == 1 { 67 c.Ui.Error(fmt.Sprintf("Alloc ID must contain at least two characters.")) 68 return 1 69 } 70 71 allocID = sanitizeUUIDPrefix(allocID) 72 73 // Get the HTTP client 74 client, err := c.Meta.Client() 75 if err != nil { 76 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 77 return 1 78 } 79 80 allocs, _, err := client.Allocations().PrefixList(allocID) 81 if err != nil { 82 c.Ui.Error(fmt.Sprintf("Error querying allocation: %v", err)) 83 return 1 84 } 85 86 if len(allocs) == 0 { 87 c.Ui.Error(fmt.Sprintf("No allocation(s) with prefix or id %q found", allocID)) 88 return 1 89 } 90 91 if len(allocs) > 1 { 92 // Format the allocs 93 out := formatAllocListStubs(allocs, verbose, length) 94 c.Ui.Error(fmt.Sprintf("Prefix matched multiple allocations\n\n%s", out)) 95 return 1 96 } 97 98 // Prefix lookup matched a single allocation 99 alloc, _, err := client.Allocations().Info(allocs[0].ID, nil) 100 if err != nil { 101 c.Ui.Error(fmt.Sprintf("Error querying allocation: %s", err)) 102 return 1 103 } 104 105 var taskName string 106 if len(args) == 2 { 107 // Validate Task 108 taskName = args[1] 109 err := validateTaskExistsInAllocation(taskName, alloc) 110 if err != nil { 111 c.Ui.Error(err.Error()) 112 return 1 113 } 114 } 115 116 err = client.Allocations().Restart(alloc, taskName, nil) 117 if err != nil { 118 c.Ui.Error(fmt.Sprintf("Failed to restart allocation:\n\n%s", err.Error())) 119 return 1 120 } 121 122 return 0 123 } 124 125 func validateTaskExistsInAllocation(taskName string, alloc *api.Allocation) error { 126 tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup) 127 if tg == nil { 128 return fmt.Errorf("Could not find allocation task group: %s", alloc.TaskGroup) 129 } 130 131 foundTaskNames := make([]string, len(tg.Tasks)) 132 for i, task := range tg.Tasks { 133 foundTaskNames[i] = task.Name 134 if task.Name == taskName { 135 return nil 136 } 137 } 138 139 return fmt.Errorf("Could not find task named: %s, found:\n%s", taskName, formatList(foundTaskNames)) 140 } 141 142 func (a *AllocRestartCommand) Synopsis() string { 143 return "Restart a running allocation" 144 } 145 146 func (c *AllocRestartCommand) AutocompleteArgs() complete.Predictor { 147 // Here we attempt to autocomplete allocations for any position of arg. 148 // We should eventually try to auto complete the task name if the arg is 149 // at position 2. 150 return complete.PredictFunc(func(a complete.Args) []string { 151 client, err := c.Meta.Client() 152 if err != nil { 153 return nil 154 } 155 156 resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Allocs, nil) 157 if err != nil { 158 return []string{} 159 } 160 return resp.Matches[contexts.Allocs] 161 }) 162 }