// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package command import ( "fmt" "sort" "strings" "github.com/hashicorp/nomad/api" "github.com/mitchellh/cli" "github.com/posener/complete" ) // Ensure ScalingPolicyListCommand satisfies the cli.Command interface. var _ cli.Command = &ScalingPolicyListCommand{} // ScalingPolicyListCommand implements cli.Command. type ScalingPolicyListCommand struct { Meta } // Help satisfies the cli.Command Help function. func (s *ScalingPolicyListCommand) Help() string { helpText := ` Usage: nomad scaling policy list [options] List is used to list the currently configured scaling policies. If ACLs are enabled, this command requires a token with the 'read-job' and 'list-jobs' capabilities for the namespace of all policies. Any namespaces that the token does not have access to will have its policies filtered from the results. General Options: ` + generalOptionsUsage(usageOptsDefault) + ` Policy Info Options: -job Specifies the job ID to filter the scaling policies list by. -type Filter scaling policies by type. -verbose Display full information. -json Output the scaling policy in its JSON format. -t Format and display the scaling policy using a Go template. ` return strings.TrimSpace(helpText) } // Synopsis satisfies the cli.Command Synopsis function. func (s *ScalingPolicyListCommand) Synopsis() string { return "Display all Nomad scaling policies" } func (s *ScalingPolicyListCommand) AutocompleteFlags() complete.Flags { return mergeAutocompleteFlags(s.Meta.AutocompleteFlags(FlagSetClient), complete.Flags{ "-verbose": complete.PredictNothing, "-job": complete.PredictNothing, "-type": complete.PredictNothing, "-json": complete.PredictNothing, "-t": complete.PredictAnything, }) } // Name returns the name of this command. func (s *ScalingPolicyListCommand) Name() string { return "scaling policy list" } // Run satisfies the cli.Command Run function. func (s *ScalingPolicyListCommand) Run(args []string) int { var json, verbose bool var tmpl, policyType, job string flags := s.Meta.FlagSet(s.Name(), FlagSetClient) flags.Usage = func() { s.Ui.Output(s.Help()) } flags.BoolVar(&verbose, "verbose", false, "") flags.BoolVar(&json, "json", false, "") flags.StringVar(&tmpl, "t", "", "") flags.StringVar(&policyType, "type", "", "") flags.StringVar(&job, "job", "", "") if err := flags.Parse(args); err != nil { return 1 } if args = flags.Args(); len(args) > 0 { s.Ui.Error("This command takes no arguments") s.Ui.Error(commandErrorText(s)) return 1 } // Truncate the id unless full length is requested length := shortId if verbose { length = fullId } // Get the HTTP client. client, err := s.Meta.Client() if err != nil { s.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) return 1 } q := &api.QueryOptions{ Params: map[string]string{}, } if policyType != "" { q.Params["type"] = policyType } if job != "" { q.Params["job"] = job } policies, _, err := client.Scaling().ListPolicies(q) if err != nil { s.Ui.Error(fmt.Sprintf("Error listing scaling policies: %s", err)) return 1 } if json || len(tmpl) > 0 { out, err := Format(json, tmpl, policies) if err != nil { s.Ui.Error(err.Error()) return 1 } s.Ui.Output(out) return 0 } output := formatScalingPolicies(policies, length) s.Ui.Output(output) return 0 } func formatScalingPolicies(stubs []*api.ScalingPolicyListStub, uuidLength int) string { if len(stubs) == 0 { return "No policies found" } // Create the output table header. policies := []string{"ID|Enabled|Type|Target"} // Sort the list of policies based on their target. sortedPolicies := scalingPolicyStubList{policies: stubs} sort.Sort(sortedPolicies) // Iterate the policies and add to the output. for _, policy := range sortedPolicies.policies { policies = append(policies, fmt.Sprintf( "%s|%v|%s|%s", limit(policy.ID, uuidLength), policy.Enabled, policy.Type, formatScalingPolicyTarget(policy.Target))) } return formatList(policies) } // scalingPolicyStubList is a wrapper around []*api.ScalingPolicyListStub that // list us sort the policies alphabetically based on their target. type scalingPolicyStubList struct { policies []*api.ScalingPolicyListStub } // Len satisfies the Len function of the sort.Interface interface. func (s scalingPolicyStubList) Len() int { return len(s.policies) } // Swap satisfies the Swap function of the sort.Interface interface. func (s scalingPolicyStubList) Swap(i, j int) { s.policies[i], s.policies[j] = s.policies[j], s.policies[i] } // Less satisfies the Less function of the sort.Interface interface. func (s scalingPolicyStubList) Less(i, j int) bool { iTarget := formatScalingPolicyTarget(s.policies[i].Target) jTarget := formatScalingPolicyTarget(s.policies[j].Target) stringList := []string{iTarget, jTarget} sort.Strings(stringList) return stringList[0] == iTarget }