updated "scaling policy info" with prefix search and auto-complete
This commit is contained in:
parent
02bef2df0a
commit
452b738db1
|
@ -6,6 +6,9 @@ import (
|
|||
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/api/contexts"
|
||||
)
|
||||
|
||||
// Ensure ScalingPolicyInfoCommand satisfies the cli.Command interface.
|
||||
|
@ -54,6 +57,21 @@ func (s *ScalingPolicyInfoCommand) AutocompleteFlags() complete.Flags {
|
|||
})
|
||||
}
|
||||
|
||||
func (c *ScalingPolicyInfoCommand) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictFunc(func(a complete.Args) []string {
|
||||
client, err := c.Meta.Client()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
resp, _, err := client.Search().PrefixSearch(a.Last, contexts.ScalingPolicies, nil)
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
return resp.Matches[contexts.ScalingPolicies]
|
||||
})
|
||||
}
|
||||
|
||||
// Name returns the name of this command.
|
||||
func (s *ScalingPolicyInfoCommand) Name() string { return "scaling policy info" }
|
||||
|
||||
|
@ -70,15 +88,6 @@ func (s *ScalingPolicyInfoCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
if args = flags.Args(); len(args) != 1 {
|
||||
s.Ui.Error("This command takes one argument: <policy_id>")
|
||||
s.Ui.Error(commandErrorText(s))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Get the policy ID.
|
||||
policyID := args[0]
|
||||
|
||||
// Get the HTTP client.
|
||||
client, err := s.Meta.Client()
|
||||
if err != nil {
|
||||
|
@ -86,17 +95,16 @@ func (s *ScalingPolicyInfoCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
policy, _, err := client.Scaling().GetPolicy(policyID, nil)
|
||||
if err != nil {
|
||||
s.Ui.Error(fmt.Sprintf("Error listing scaling policies: %s", err))
|
||||
return 1
|
||||
}
|
||||
args = flags.Args()
|
||||
|
||||
// If the user has specified to output the policy as JSON or using a
|
||||
// template then perform this action for the entire object and exit the
|
||||
// command.
|
||||
if json || len(tmpl) > 0 {
|
||||
out, err := Format(json, tmpl, policy)
|
||||
// Formatted list mode if no policy ID
|
||||
if len(args) == 0 && (json || len(tmpl) > 0) {
|
||||
policies, _, err := client.Scaling().ListPolicies(nil)
|
||||
if err != nil {
|
||||
s.Ui.Error(fmt.Sprintf("Error listing scaling policies: %v", err))
|
||||
return 1
|
||||
}
|
||||
out, err := Format(json, tmpl, policies)
|
||||
if err != nil {
|
||||
s.Ui.Error(err.Error())
|
||||
return 1
|
||||
|
@ -105,14 +113,65 @@ func (s *ScalingPolicyInfoCommand) Run(args []string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
if len(args) != 1 {
|
||||
s.Ui.Error("This command takes one of the following argument conditions:")
|
||||
s.Ui.Error(" * A single <policy_id>")
|
||||
s.Ui.Error(" * No arguments, with output format specified")
|
||||
s.Ui.Error(commandErrorText(s))
|
||||
return 1
|
||||
}
|
||||
policyID := args[0]
|
||||
if len(policyID) == 1 {
|
||||
s.Ui.Error("Identifier must contain at least two characters.")
|
||||
return 1
|
||||
}
|
||||
|
||||
policyID = sanitizeUUIDPrefix(policyID)
|
||||
policies, _, err := client.Scaling().ListPolicies(&api.QueryOptions{
|
||||
Prefix: policyID,
|
||||
})
|
||||
if err != nil {
|
||||
s.Ui.Error(fmt.Sprintf("Error querying scaling policy: %v", err))
|
||||
return 1
|
||||
}
|
||||
if len(policies) == 0 {
|
||||
s.Ui.Error(fmt.Sprintf("No scaling policies with prefix or id %q found", policyID))
|
||||
return 1
|
||||
}
|
||||
if len(policies) > 1 {
|
||||
out := formatScalingPolicies(policies)
|
||||
s.Ui.Output(fmt.Sprintf("Prefix matched multiple scaling policies\n\n%s", out))
|
||||
return 0
|
||||
}
|
||||
|
||||
policy, _, err := client.Scaling().GetPolicy(policies[0].ID, nil)
|
||||
if err != nil {
|
||||
s.Ui.Error(fmt.Sprintf("Error querying scaling policy: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
if json || len(tmpl) > 0 {
|
||||
out, err := Format(json, tmpl, policy)
|
||||
if err != nil {
|
||||
s.Ui.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
s.Ui.Output(out)
|
||||
return 0
|
||||
}
|
||||
|
||||
// Format the policy document which is a freeform map[string]interface{}
|
||||
// and therefore can only be made pretty to a certain extent. Do this
|
||||
// before the rest of the formatting so any errors are clearly passed back
|
||||
// to the CLI.
|
||||
out, err := Format(true, "", policy.Policy)
|
||||
if err != nil {
|
||||
s.Ui.Error(err.Error())
|
||||
return 1
|
||||
out := "<empty>"
|
||||
if len(policy.Policy) > 0 {
|
||||
out, err = Format(true, "", policy.Policy)
|
||||
if err != nil {
|
||||
s.Ui.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
info := []string{
|
||||
|
|
|
@ -35,10 +35,10 @@ func TestScalingPolicyInfoCommand_Run(t *testing.T) {
|
|||
cmd := &ScalingPolicyInfoCommand{Meta: Meta{Ui: ui}}
|
||||
|
||||
// Calling without the policyID should result in an error.
|
||||
if code := cmd.Run([]string{"-address=" + url}); code != 1 {
|
||||
if code := cmd.Run([]string{"-address=" + url, "first", "second"}); code != 1 {
|
||||
t.Fatalf("expected cmd run exit code 1, got: %d", code)
|
||||
}
|
||||
if out := ui.ErrorWriter.String(); !strings.Contains(out, "This command takes one argument: <policy_id>") {
|
||||
if out := ui.ErrorWriter.String(); !strings.Contains(out, "This command takes one of the following argument conditions") {
|
||||
t.Fatalf("expected argument error within output: %v", out)
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,8 @@ func TestScalingPolicyInfoCommand_Run(t *testing.T) {
|
|||
if code := cmd.Run([]string{"-address=" + url, "scaling_policy_info"}); code != 1 {
|
||||
t.Fatalf("expected cmd run exit code 1, got: %d", code)
|
||||
}
|
||||
if out := ui.ErrorWriter.String(); !strings.Contains(out, "404 (policy not found)") {
|
||||
t.Fatalf("expected 404 not found within output: %v", out)
|
||||
if out := ui.ErrorWriter.String(); !strings.Contains(out, `No scaling policies with prefix or id "scaling_policy_inf" found`) {
|
||||
t.Fatalf("expected 'no policies found' within output: %v", out)
|
||||
}
|
||||
|
||||
// Generate a test job.
|
||||
|
|
|
@ -87,6 +87,7 @@ func (s *ScalingPolicyListCommand) Run(args []string) int {
|
|||
if args = flags.Args(); len(args) > 0 {
|
||||
s.Ui.Error("This command takes no arguments")
|
||||
s.Ui.Error(commandErrorText(s))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Get the HTTP client.
|
||||
|
@ -111,11 +112,6 @@ func (s *ScalingPolicyListCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
if len(policies) == 0 {
|
||||
s.Ui.Output("No policies found")
|
||||
return 0
|
||||
}
|
||||
|
||||
if json || len(tmpl) > 0 {
|
||||
out, err := Format(json, tmpl, policies)
|
||||
if err != nil {
|
||||
|
@ -126,23 +122,30 @@ func (s *ScalingPolicyListCommand) Run(args []string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
output := formatScalingPolicies(policies)
|
||||
s.Ui.Output(output)
|
||||
return 0
|
||||
}
|
||||
|
||||
func formatScalingPolicies(stubs []*api.ScalingPolicyListStub) string {
|
||||
if len(stubs) == 0 {
|
||||
return "No policies found"
|
||||
}
|
||||
|
||||
// Create the output table header.
|
||||
output := []string{"ID|Enabled|Type|Target"}
|
||||
policies := []string{"ID|Enabled|Type|Target"}
|
||||
|
||||
// Sort the list of policies based on their target.
|
||||
sortedPolicies := scalingPolicyStubList{policies: policies}
|
||||
sortedPolicies := scalingPolicyStubList{policies: stubs}
|
||||
sort.Sort(sortedPolicies)
|
||||
|
||||
// Iterate the policies and add to the output.
|
||||
for _, policy := range sortedPolicies.policies {
|
||||
output = append(output, fmt.Sprintf(
|
||||
policies = append(policies, fmt.Sprintf(
|
||||
"%s|%v|%s|%s",
|
||||
policy.ID, policy.Enabled, policy.Type, formatScalingPolicyTarget(policy.Target)))
|
||||
}
|
||||
|
||||
// Output.
|
||||
s.Ui.Output(formatList(output))
|
||||
return 0
|
||||
return formatList(policies)
|
||||
}
|
||||
|
||||
// scalingPolicyStubList is a wrapper around []*api.ScalingPolicyListStub that
|
||||
|
|
Loading…
Reference in New Issue