Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cli: include all possible scores in alloc status metric table #11128

Merged
merged 2 commits into from
Sep 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/11128.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
cli: Display all possible scores in the allocation status table
```
37 changes: 18 additions & 19 deletions command/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
55 changes: 55 additions & 0 deletions command/monitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
})
}
}