From 4dd8b6b571abf692fdada71264d9677bca52b538 Mon Sep 17 00:00:00 2001 From: Luiz Aoqui Date: Wed, 8 Sep 2021 17:30:11 -0400 Subject: [PATCH] cli: include all possible scores in alloc status metric table (#11128) --- .changelog/11128.txt | 3 +++ command/monitor.go | 37 ++++++++++++++------------- command/monitor_test.go | 55 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 .changelog/11128.txt diff --git a/.changelog/11128.txt b/.changelog/11128.txt new file mode 100644 index 000000000..9ff24245b --- /dev/null +++ b/.changelog/11128.txt @@ -0,0 +1,3 @@ +```release-note:bug +cli: Display all possible scores in the allocation status table +``` diff --git a/command/monitor.go b/command/monitor.go index 6e4daa681..459734f05 100644 --- a/command/monitor.go +++ b/command/monitor.go @@ -355,33 +355,32 @@ func formatAllocMetrics(metrics *api.AllocationMetric, scores bool, prefix strin if scores { if len(metrics.ScoreMetaData) > 0 { scoreOutput := make([]string, len(metrics.ScoreMetaData)+1) - var scorerNames []string - for i, scoreMeta := range metrics.ScoreMetaData { - // Add header as first row - if i == 0 { - scoreOutput[0] = "Node|" - // sort scores alphabetically - scores := make([]string, 0, len(scoreMeta.Scores)) - for score := range scoreMeta.Scores { - scores = append(scores, score) - } - sort.Strings(scores) - - // build score header output - for _, scorerName := range scores { - scoreOutput[0] += fmt.Sprintf("%v|", scorerName) - scorerNames = append(scorerNames, scorerName) - } - scoreOutput[0] += "final score" + // Find all possible scores and build header row. + allScores := make(map[string]struct{}) + for _, scoreMeta := range metrics.ScoreMetaData { + for score := range scoreMeta.Scores { + allScores[score] = struct{}{} } + } + // Sort scores alphabetically. + scores := make([]string, 0, len(allScores)) + for score := range allScores { + scores = append(scores, score) + } + sort.Strings(scores) + scoreOutput[0] = fmt.Sprintf("Node|%s|final score", strings.Join(scores, "|")) + + // Build row for each score. + for i, scoreMeta := range metrics.ScoreMetaData { scoreOutput[i+1] = fmt.Sprintf("%v|", scoreMeta.NodeID) - for _, scorerName := range scorerNames { + for _, scorerName := range scores { scoreVal := scoreMeta.Scores[scorerName] scoreOutput[i+1] += fmt.Sprintf("%.3g|", scoreVal) } scoreOutput[i+1] += fmt.Sprintf("%.3g", scoreMeta.NormScore) } + out += formatList(scoreOutput) } else { // Backwards compatibility for old allocs diff --git a/command/monitor_test.go b/command/monitor_test.go index 327dc4736..297560f06 100644 --- a/command/monitor_test.go +++ b/command/monitor_test.go @@ -5,8 +5,10 @@ import ( "testing" "time" + "github.com/hashicorp/nomad/api" "github.com/hashicorp/nomad/nomad/structs" "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" ) func TestMonitor_Update_Eval(t *testing.T) { @@ -216,3 +218,56 @@ func TestMonitor_Monitor(t *testing.T) { t.Fatalf("missing final status\n\n%s", out) } } + +func TestMonitor_formatAllocMetric(t *testing.T) { + tests := []struct { + Name string + Metrics *api.AllocationMetric + Expected string + }{ + { + Name: "display all possible scores", + Metrics: &api.AllocationMetric{ + NodesEvaluated: 3, + ScoreMetaData: []*api.NodeScoreMeta{ + { + NodeID: "node-1", + Scores: map[string]float64{ + "score-1": 1, + "score-2": 2, + }, + NormScore: 1, + }, + { + NodeID: "node-2", + Scores: map[string]float64{ + "score-1": 1, + "score-3": 3, + }, + NormScore: 2, + }, + { + NodeID: "node-3", + Scores: map[string]float64{ + "score-4": 4, + }, + NormScore: 3, + }, + }, + }, + Expected: ` +Node score-1 score-2 score-3 score-4 final score +node-1 1 2 0 0 1 +node-2 1 0 3 0 2 +node-3 0 0 0 4 3 +`, + }, + } + + for _, tc := range tests { + t.Run(tc.Name, func(t *testing.T) { + got := formatAllocMetrics(tc.Metrics, true, "") + require.Equal(t, strings.TrimSpace(tc.Expected), got) + }) + } +}