cli: add policy list and info to new scaling cmd.
This adds the ability to detail scaling policies via the CLI.
This commit is contained in:
parent
fbcfccfc9e
commit
b8727997cd
|
@ -618,6 +618,26 @@ func Commands(metaPtr *Meta, agentUi cli.Ui) map[string]cli.CommandFactory {
|
|||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
"scaling": func() (cli.Command, error) {
|
||||
return &ScalingCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
"scaling policy": func() (cli.Command, error) {
|
||||
return &ScalingPolicyCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
"scaling policy info": func() (cli.Command, error) {
|
||||
return &ScalingPolicyInfoCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
"scaling policy list": func() (cli.Command, error) {
|
||||
return &ScalingPolicyListCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
"sentinel": func() (cli.Command, error) {
|
||||
return &SentinelCommand{
|
||||
Meta: meta,
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
// Ensure ScalingCommand satisfies the cli.Command interface.
|
||||
var _ cli.Command = &ScalingCommand{}
|
||||
|
||||
// ScalingCommand implements cli.Command.
|
||||
type ScalingCommand struct {
|
||||
Meta
|
||||
}
|
||||
|
||||
// Help satisfies the cli.Command Help function.
|
||||
func (s *ScalingCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: nomad scaling <subcommand> [options]
|
||||
|
||||
This command groups subcommands for interacting with the scaling API.
|
||||
|
||||
Please see the individual subcommand help for detailed usage information.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
// Synopsis satisfies the cli.Command Synopsis function.
|
||||
func (s *ScalingCommand) Synopsis() string {
|
||||
return "Interact with the Nomad scaling endpoint"
|
||||
}
|
||||
|
||||
// Name returns the name of this command.
|
||||
func (s *ScalingCommand) Name() string { return "scaling" }
|
||||
|
||||
// Run satisfies the cli.Command Run function.
|
||||
func (s *ScalingCommand) Run(_ []string) int { return cli.RunResultHelp }
|
|
@ -0,0 +1,79 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
// Ensure ScalingPolicyCommand satisfies the cli.Command interface.
|
||||
var _ cli.Command = &ScalingPolicyCommand{}
|
||||
|
||||
// ScalingPolicyCommand implements cli.Command.
|
||||
type ScalingPolicyCommand struct {
|
||||
Meta
|
||||
}
|
||||
|
||||
// Help satisfies the cli.Command Help function.
|
||||
func (s *ScalingPolicyCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: nomad scaling policy <subcommand> [options]
|
||||
|
||||
This command groups subcommands for interacting with scaling policies. Scaling
|
||||
policies can be used by an external autoscaler to perform scaling actions on
|
||||
Nomad targets.
|
||||
|
||||
List policies:
|
||||
|
||||
$ nomad scaling policy list
|
||||
|
||||
Detail an individual scaling policy:
|
||||
|
||||
$ nomad scaling policy info <policy_id>
|
||||
|
||||
Please see the individual subcommand help for detailed usage information.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
// Synopsis satisfies the cli.Command Synopsis function.
|
||||
func (s *ScalingPolicyCommand) Synopsis() string {
|
||||
return "Interact with Nomad scaling policies"
|
||||
}
|
||||
|
||||
// Name returns the name of this command.
|
||||
func (s *ScalingPolicyCommand) Name() string { return "scaling policy" }
|
||||
|
||||
// Run satisfies the cli.Command Run function.
|
||||
func (s *ScalingPolicyCommand) Run(_ []string) int { return cli.RunResultHelp }
|
||||
|
||||
// formatScalingPolicyTarget is a command helper that correctly formats a
|
||||
// scaling policy target map into a command string output.
|
||||
func formatScalingPolicyTarget(t map[string]string) string {
|
||||
var ns, j, g string
|
||||
var other []string
|
||||
|
||||
for k, v := range t {
|
||||
|
||||
s := fmt.Sprintf("%s:%s", k, v)
|
||||
|
||||
switch strings.ToLower(k) {
|
||||
case "namespace":
|
||||
ns = s
|
||||
case "job":
|
||||
j = s
|
||||
case "group":
|
||||
g = s
|
||||
default:
|
||||
other = append(other, s)
|
||||
}
|
||||
}
|
||||
|
||||
out := []string{ns, j, g}
|
||||
|
||||
if len(other) > 0 {
|
||||
out = append(out, other...)
|
||||
}
|
||||
return strings.Join(out, ",")
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
// Ensure ScalingPolicyInfoCommand satisfies the cli.Command interface.
|
||||
var _ cli.Command = &ScalingPolicyInfoCommand{}
|
||||
|
||||
// ScalingPolicyListCommand implements cli.Command.
|
||||
type ScalingPolicyInfoCommand struct {
|
||||
Meta
|
||||
}
|
||||
|
||||
// Help satisfies the cli.Command Help function.
|
||||
func (s *ScalingPolicyInfoCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: nomad scaling policy info [options] <policy_id>
|
||||
|
||||
Info is used to read the specified scaling policy.
|
||||
|
||||
General Options:
|
||||
|
||||
` + generalOptionsUsage() + `
|
||||
|
||||
Policy Info Options:
|
||||
|
||||
-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 *ScalingPolicyInfoCommand) Synopsis() string {
|
||||
return "Display an individual Nomad scaling policy"
|
||||
}
|
||||
|
||||
func (s *ScalingPolicyInfoCommand) AutocompleteFlags() complete.Flags {
|
||||
return mergeAutocompleteFlags(s.Meta.AutocompleteFlags(FlagSetClient),
|
||||
complete.Flags{
|
||||
"-json": complete.PredictNothing,
|
||||
"-t": complete.PredictAnything,
|
||||
})
|
||||
}
|
||||
|
||||
// Name returns the name of this command.
|
||||
func (s *ScalingPolicyInfoCommand) Name() string { return "scaling policy info" }
|
||||
|
||||
// Run satisfies the cli.Command Run function.
|
||||
func (s *ScalingPolicyInfoCommand) Run(args []string) int {
|
||||
var json bool
|
||||
var tmpl string
|
||||
|
||||
flags := s.Meta.FlagSet(s.Name(), FlagSetClient)
|
||||
flags.Usage = func() { s.Ui.Output(s.Help()) }
|
||||
flags.BoolVar(&json, "json", false, "")
|
||||
flags.StringVar(&tmpl, "t", "", "")
|
||||
if err := flags.Parse(args); err != nil {
|
||||
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 {
|
||||
s.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
|
||||
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
|
||||
}
|
||||
|
||||
// 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)
|
||||
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
|
||||
}
|
||||
|
||||
info := []string{
|
||||
fmt.Sprintf("ID|%s", policy.ID),
|
||||
fmt.Sprintf("Enabled|%v", *policy.Enabled),
|
||||
fmt.Sprintf("Target|%s", formatScalingPolicyTarget(policy.Target)),
|
||||
fmt.Sprintf("Min|%v", *policy.Min),
|
||||
fmt.Sprintf("Max|%v", *policy.Max),
|
||||
}
|
||||
s.Ui.Output(formatKV(info))
|
||||
s.Ui.Output("\nPolicy:")
|
||||
s.Ui.Output(out)
|
||||
return 0
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/testutil"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func TestScalingPolicyInfoCommand_Run(t *testing.T) {
|
||||
t.Parallel()
|
||||
srv, client, url := testServer(t, true, nil)
|
||||
defer srv.Shutdown()
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
nodes, _, err := client.Nodes().List(nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return false, fmt.Errorf("missing node")
|
||||
}
|
||||
if _, ok := nodes[0].Drivers["mock_driver"]; !ok {
|
||||
return false, fmt.Errorf("mock_driver not ready")
|
||||
}
|
||||
return true, nil
|
||||
}, func(err error) {
|
||||
t.Fatalf("err: %s", err)
|
||||
})
|
||||
|
||||
ui := cli.NewMockUi()
|
||||
cmd := &ScalingPolicyInfoCommand{Meta: Meta{Ui: ui}}
|
||||
|
||||
// Calling without the policyID should result in an error.
|
||||
if code := cmd.Run([]string{"-address=" + url}); 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>") {
|
||||
t.Fatalf("expected argument error within output: %v", out)
|
||||
}
|
||||
|
||||
// Perform an initial info, which should return zero results.
|
||||
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)
|
||||
}
|
||||
|
||||
// Generate a test job.
|
||||
job := testJob("scaling_policy_info")
|
||||
|
||||
// Generate an example scaling policy.
|
||||
job.TaskGroups[0].Scaling = &api.ScalingPolicy{
|
||||
Enabled: helper.BoolToPtr(true),
|
||||
Min: helper.Int64ToPtr(1),
|
||||
Max: helper.Int64ToPtr(1),
|
||||
}
|
||||
|
||||
// Register the job.
|
||||
resp, _, err := client.Jobs().Register(job, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if code := waitForSuccess(ui, client, fullId, t, resp.EvalID); code != 0 {
|
||||
t.Fatalf("expected waitForSuccess exit code 0, got: %d", code)
|
||||
}
|
||||
|
||||
// Grab the generated policyID.
|
||||
policies, _, err := client.Scaling().ListPolicies(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
numPolicies := len(policies)
|
||||
if numPolicies == 0 || numPolicies > 1 {
|
||||
t.Fatalf("expected 1 policy return, got %v", numPolicies)
|
||||
}
|
||||
|
||||
if code := cmd.Run([]string{"-address=" + url, policies[0].ID}); code != 0 {
|
||||
t.Fatalf("expected cmd run exit code 0, got: %d", code)
|
||||
}
|
||||
if out := ui.OutputWriter.String(); !strings.Contains(out, "Policy:") {
|
||||
t.Fatalf("expected policy ID within output: %v", out)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
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.
|
||||
|
||||
General Options:
|
||||
|
||||
` + generalOptionsUsage() + `
|
||||
|
||||
Policy Info Options:
|
||||
|
||||
-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{
|
||||
"-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 bool
|
||||
var tmpl string
|
||||
|
||||
flags := s.Meta.FlagSet(s.Name(), FlagSetClient)
|
||||
flags.Usage = func() { s.Ui.Output(s.Help()) }
|
||||
flags.BoolVar(&json, "json", false, "")
|
||||
flags.StringVar(&tmpl, "t", "", "")
|
||||
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))
|
||||
}
|
||||
|
||||
// Get the HTTP client.
|
||||
client, err := s.Meta.Client()
|
||||
if err != nil {
|
||||
s.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
policies, _, err := client.Scaling().ListPolicies(nil)
|
||||
if err != nil {
|
||||
s.Ui.Error(fmt.Sprintf("Error listing scaling policies: %s", err))
|
||||
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 {
|
||||
s.Ui.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
s.Ui.Output(out)
|
||||
return 0
|
||||
}
|
||||
|
||||
// Create the output table header.
|
||||
output := []string{"ID|Enabled|Target"}
|
||||
|
||||
// Sort the list of policies based on their target.
|
||||
sortedPolicies := scalingPolicyStubList{policies: policies}
|
||||
sort.Sort(sortedPolicies)
|
||||
|
||||
// Iterate the policies and add to the output.
|
||||
for _, policy := range sortedPolicies.policies {
|
||||
output = append(output, fmt.Sprintf(
|
||||
"%s|%v|%s",
|
||||
policy.ID, policy.Enabled, formatScalingPolicyTarget(policy.Target)))
|
||||
}
|
||||
|
||||
// Output.
|
||||
s.Ui.Output(formatList(output))
|
||||
return 0
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
if stringList[0] == iTarget {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/testutil"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func TestScalingPolicyListCommand_Run(t *testing.T) {
|
||||
t.Parallel()
|
||||
srv, client, url := testServer(t, true, nil)
|
||||
defer srv.Shutdown()
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
nodes, _, err := client.Nodes().List(nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return false, fmt.Errorf("missing node")
|
||||
}
|
||||
if _, ok := nodes[0].Drivers["mock_driver"]; !ok {
|
||||
return false, fmt.Errorf("mock_driver not ready")
|
||||
}
|
||||
return true, nil
|
||||
}, func(err error) {
|
||||
t.Fatalf("err: %s", err)
|
||||
})
|
||||
|
||||
ui := cli.NewMockUi()
|
||||
cmd := &ScalingPolicyListCommand{Meta: Meta{Ui: ui}}
|
||||
|
||||
// Perform an initial list, which should return zero results.
|
||||
if code := cmd.Run([]string{"-address=" + url}); code != 0 {
|
||||
t.Fatalf("expected cmd run exit code 0, got: %d", code)
|
||||
}
|
||||
if out := ui.OutputWriter.String(); !strings.Contains(out, "No policies found") {
|
||||
t.Fatalf("expected no policies found within output: %v", out)
|
||||
}
|
||||
|
||||
// Generate two test jobs.
|
||||
jobs := []*api.Job{testJob("scaling_policy_list_1"), testJob("scaling_policy_list_2")}
|
||||
|
||||
// Generate an example scaling policy.
|
||||
scalingPolicy := api.ScalingPolicy{
|
||||
Enabled: helper.BoolToPtr(true),
|
||||
Min: helper.Int64ToPtr(1),
|
||||
Max: helper.Int64ToPtr(1),
|
||||
}
|
||||
|
||||
// Iterate the jobs, add the scaling policy and register.
|
||||
for _, job := range jobs {
|
||||
job.TaskGroups[0].Scaling = &scalingPolicy
|
||||
resp, _, err := client.Jobs().Register(job, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if code := waitForSuccess(ui, client, fullId, t, resp.EvalID); code != 0 {
|
||||
t.Fatalf("expected waitForSuccess exit code 0, got: %d", code)
|
||||
}
|
||||
}
|
||||
|
||||
// Perform a new list which should yield results..
|
||||
if code := cmd.Run([]string{"-address=" + url}); code != 0 {
|
||||
t.Fatalf("expected cmd run exit code 0, got: %d", code)
|
||||
}
|
||||
out := ui.OutputWriter.String()
|
||||
if !strings.Contains(out, "ID") ||
|
||||
!strings.Contains(out, "Enabled") ||
|
||||
!strings.Contains(out, "Target") {
|
||||
t.Fatalf("expected table headers within output: %v", out)
|
||||
}
|
||||
if !strings.Contains(out, "scaling_policy_list_1") {
|
||||
t.Fatalf("expected job scaling_policy_list_1 within output: %v", out)
|
||||
}
|
||||
if !strings.Contains(out, "scaling_policy_list_2") {
|
||||
t.Fatalf("expected job scaling_policy_list_2 within output: %v", out)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_formatScalingPolicyTarget(t *testing.T) {
|
||||
testCases := []struct {
|
||||
inputMap map[string]string
|
||||
expectedOutput string
|
||||
name string
|
||||
}{
|
||||
{
|
||||
inputMap: map[string]string{
|
||||
"Namespace": "default",
|
||||
"Job": "example",
|
||||
"Group": "cache",
|
||||
},
|
||||
expectedOutput: "Namespace:default,Job:example,Group:cache",
|
||||
name: "generic horizontal scaling policy target",
|
||||
},
|
||||
{
|
||||
inputMap: map[string]string{
|
||||
"Namespace": "default",
|
||||
"Job": "example",
|
||||
"Group": "cache",
|
||||
"Unknown": "alien",
|
||||
},
|
||||
expectedOutput: "Namespace:default,Job:example,Group:cache,Unknown:alien",
|
||||
name: "extra key in input mapping",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
actualOutput := formatScalingPolicyTarget(tc.inputMap)
|
||||
assert.Equal(t, tc.expectedOutput, actualOutput, tc.name)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue