diff --git a/command/alloc_status.go b/command/alloc_status.go index 20987b16df9..c75e0a9f96d 100644 --- a/command/alloc_status.go +++ b/command/alloc_status.go @@ -142,12 +142,8 @@ func (c *AllocStatusCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters.")) return 1 } - if len(allocID)%2 == 1 { - // Identifiers must be of even length, so we strip off the last byte - // to provide a consistent user experience. - allocID = allocID[:len(allocID)-1] - } + allocID = sanatizeUUIDPrefix(allocID) allocs, _, err := client.Allocations().PrefixList(allocID) if err != nil { c.Ui.Error(fmt.Sprintf("Error querying allocation: %v", err)) diff --git a/command/alloc_status_test.go b/command/alloc_status_test.go index b17cfc9d7c4..f858eaf6b1d 100644 --- a/command/alloc_status_test.go +++ b/command/alloc_status_test.go @@ -144,6 +144,25 @@ func TestAllocStatusCommand_Run(t *testing.T) { t.Fatalf("expected to have 'Created At' but saw: %s", out) } ui.OutputWriter.Reset() + + // Try the query with an even prefix that includes the hyphen + if code := cmd.Run([]string{"-address=" + url, allocId1[:13]}); code != 0 { + t.Fatalf("expected exit 0, got: %d", code) + } + out = ui.OutputWriter.String() + if !strings.Contains(out, "Created At") { + t.Fatalf("expected to have 'Created At' but saw: %s", out) + } + ui.OutputWriter.Reset() + + if code := cmd.Run([]string{"-address=" + url, "-verbose", allocId1}); code != 0 { + t.Fatalf("expected exit 0, got: %d", code) + } + out = ui.OutputWriter.String() + if !strings.Contains(out, allocId1) { + t.Fatal("expected to find alloc id in output") + } + ui.OutputWriter.Reset() } func TestAllocStatusCommand_AutocompleteArgs(t *testing.T) { diff --git a/command/eval_status.go b/command/eval_status.go index 33b3d2cddab..a370a90edaa 100644 --- a/command/eval_status.go +++ b/command/eval_status.go @@ -130,12 +130,8 @@ func (c *EvalStatusCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters.")) return 1 } - if len(evalID)%2 == 1 { - // Identifiers must be of even length, so we strip off the last byte - // to provide a consistent user experience. - evalID = evalID[:len(evalID)-1] - } + evalID = sanatizeUUIDPrefix(evalID) evals, _, err := client.Evaluations().PrefixList(evalID) if err != nil { c.Ui.Error(fmt.Sprintf("Error querying evaluation: %v", err)) diff --git a/command/fs.go b/command/fs.go index e9c0df6a478..5fc3424cad7 100644 --- a/command/fs.go +++ b/command/fs.go @@ -169,12 +169,8 @@ func (f *FSCommand) Run(args []string) int { f.Ui.Error(fmt.Sprintf("Alloc ID must contain at least two characters.")) return 1 } - if len(allocID)%2 == 1 { - // Identifiers must be of even length, so we strip off the last byte - // to provide a consistent user experience. - allocID = allocID[:len(allocID)-1] - } + allocID = sanatizeUUIDPrefix(allocID) allocs, _, err := client.Allocations().PrefixList(allocID) if err != nil { f.Ui.Error(fmt.Sprintf("Error querying allocation: %v", err)) diff --git a/command/helpers.go b/command/helpers.go index 3bdf99322a7..13f74ba9d98 100644 --- a/command/helpers.go +++ b/command/helpers.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "strconv" + "strings" "time" gg "github.com/hashicorp/go-getter" @@ -330,3 +331,13 @@ func mergeAutocompleteFlags(flags ...complete.Flags) complete.Flags { } return merged } + +// sanatizeUUIDPrefix is used to sanatize a UUID prefix. The returned result +// will be a truncated version of the prefix if the prefix would not be +// queriable. +func sanatizeUUIDPrefix(prefix string) string { + hyphens := strings.Count(prefix, "-") + length := len(prefix) - hyphens + remainder := length % 2 + return prefix[:len(prefix)-remainder] +} diff --git a/command/logs.go b/command/logs.go index 36b5c974077..e9839cb130e 100644 --- a/command/logs.go +++ b/command/logs.go @@ -144,12 +144,8 @@ func (l *LogsCommand) Run(args []string) int { l.Ui.Error(fmt.Sprintf("Alloc ID must contain at least two characters.")) return 1 } - if len(allocID)%2 == 1 { - // Identifiers must be of even length, so we strip off the last byte - // to provide a consistent user experience. - allocID = allocID[:len(allocID)-1] - } + allocID = sanatizeUUIDPrefix(allocID) allocs, _, err := client.Allocations().PrefixList(allocID) if err != nil { l.Ui.Error(fmt.Sprintf("Error querying allocation: %v", err)) diff --git a/command/monitor.go b/command/monitor.go index ef0287071d8..1a4937a1cb8 100644 --- a/command/monitor.go +++ b/command/monitor.go @@ -194,12 +194,8 @@ func (m *monitor) monitor(evalID string, allowPrefix bool) int { m.ui.Error(fmt.Sprintf("Identifier must contain at least two characters.")) return 1 } - if len(evalID)%2 == 1 { - // Identifiers must be of even length, so we strip off the last byte - // to provide a consistent user experience. - evalID = evalID[:len(evalID)-1] - } + evalID = sanatizeUUIDPrefix(evalID) evals, _, err := m.client.Evaluations().PrefixList(evalID) if err != nil { m.ui.Error(fmt.Sprintf("Error reading evaluation: %s", err)) diff --git a/command/monitor_test.go b/command/monitor_test.go index a6dbf22531e..53e7c5e5808 100644 --- a/command/monitor_test.go +++ b/command/monitor_test.go @@ -239,7 +239,7 @@ func TestMonitor_MonitorWithPrefix(t *testing.T) { doneCh := make(chan struct{}) go func() { defer close(doneCh) - code = mon.monitor(resp.EvalID[:8], true) + code = mon.monitor(resp.EvalID[:13], true) }() // Wait for completion diff --git a/command/node_drain.go b/command/node_drain.go index 6d1e7410b1f..a9a87bfe185 100644 --- a/command/node_drain.go +++ b/command/node_drain.go @@ -117,12 +117,8 @@ func (c *NodeDrainCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters.")) return 1 } - if len(nodeID)%2 == 1 { - // Identifiers must be of even length, so we strip off the last byte - // to provide a consistent user experience. - nodeID = nodeID[:len(nodeID)-1] - } + nodeID = sanatizeUUIDPrefix(nodeID) nodes, _, err := client.Nodes().PrefixList(nodeID) if err != nil { c.Ui.Error(fmt.Sprintf("Error toggling drain mode: %s", err)) diff --git a/command/node_status.go b/command/node_status.go index 34dd1dbec7f..a57a6bd9f20 100644 --- a/command/node_status.go +++ b/command/node_status.go @@ -231,12 +231,8 @@ func (c *NodeStatusCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters.")) return 1 } - if len(nodeID)%2 == 1 { - // Identifiers must be of even length, so we strip off the last byte - // to provide a consistent user experience. - nodeID = nodeID[:len(nodeID)-1] - } + nodeID = sanatizeUUIDPrefix(nodeID) nodes, _, err := client.Nodes().PrefixList(nodeID) if err != nil { c.Ui.Error(fmt.Sprintf("Error querying node info: %s", err)) diff --git a/command/node_status_test.go b/command/node_status_test.go index bb1e5ac9cce..a3ec59f532d 100644 --- a/command/node_status_test.go +++ b/command/node_status_test.go @@ -127,8 +127,8 @@ func TestNodeStatusCommand_Run(t *testing.T) { t.Fatalf("should not dump allocations") } - // Query a single node based on prefix - if code := cmd.Run([]string{"-address=" + url, nodeID[:4]}); code != 0 { + // Query a single node based on a prefix that is even without the hyphen + if code := cmd.Run([]string{"-address=" + url, nodeID[:13]}); code != 0 { t.Fatalf("expected exit 0, got: %d", code) } out = ui.OutputWriter.String()