open-nomad/command/node_pool_nodes_test.go

188 lines
4.5 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package command
import (
"encoding/json"
"sort"
"strings"
"testing"
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/command/agent"
"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/testutil"
"github.com/mitchellh/cli"
"github.com/shoenig/test/must"
)
func TestNodePoolNodesCommand_Implements(t *testing.T) {
ci.Parallel(t)
var _ cli.Command = &NodePoolNodesCommand{}
}
func TestNodePoolNodesCommand_Run(t *testing.T) {
ci.Parallel(t)
// Start test server.
srv, client, url := testServer(t, true, func(c *agent.Config) {
c.Client.Enabled = false
})
testutil.WaitForLeader(t, srv.Agent.RPC)
// Start some test clients.
rpcAddr := srv.GetConfig().AdvertiseAddrs.RPC
clientNodePoolConfig := func(pool string) func(*agent.Config) {
return func(c *agent.Config) {
c.Client.NodePool = pool
c.Client.Servers = []string{rpcAddr}
c.Client.Enabled = true
c.Server.Enabled = false
}
}
testClient(t, "client-default", clientNodePoolConfig(""))
testClient(t, "client-dev", clientNodePoolConfig("dev"))
testClient(t, "client-prod-1", clientNodePoolConfig("prod"))
testClient(t, "client-prod-2", clientNodePoolConfig("prod"))
waitForNodes(t, client)
nodes, _, err := client.Nodes().List(nil)
must.NoError(t, err)
// Nodes().List() sort results by CreateIndex, but for pagination we need
// nodes sorted by ID.
sort.Slice(nodes, func(i, j int) bool {
return nodes[i].ID < nodes[j].ID
})
testCases := []struct {
name string
args []string
expectedCode int
expectedNodes []string
expectedErr string
}{
{
name: "nodes in prod",
args: []string{"prod"},
expectedCode: 0,
expectedNodes: []string{
"client-prod-1",
"client-prod-2",
},
},
{
name: "nodes in all",
args: []string{"all"},
expectedCode: 0,
expectedNodes: []string{
"client-default",
"client-dev",
"client-prod-1",
"client-prod-2",
},
},
{
name: "filter nodes",
args: []string{"-filter", `Name matches "dev"`, "all"},
expectedCode: 0,
expectedNodes: []string{
"client-dev",
},
},
{
name: "pool by prefix",
args: []string{"def"},
expectedNodes: []string{
"client-default",
},
},
{
name: "paginate page 1",
args: []string{"-per-page=2", "all"},
expectedCode: 0,
expectedNodes: []string{
nodes[0].Name,
nodes[1].Name,
},
},
{
name: "paginate page 2",
args: []string{"-per-page", "2", "-page-token", nodes[2].ID, "all"},
expectedCode: 0,
expectedNodes: []string{
nodes[2].Name,
nodes[3].Name,
},
},
{
name: "missing pool name",
args: []string{},
expectedCode: 1,
expectedErr: "This command takes one argument",
},
{
name: "prefix match multiple",
args: []string{"de"},
expectedCode: 1,
expectedErr: "Prefix matched multiple node pools",
},
{
name: "json and template not allowed",
args: []string{"-t", "{{.}}", "all"},
expectedCode: 1,
expectedErr: "Both json and template formatting are not allowed",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Initialize UI and command.
ui := cli.NewMockUi()
cmd := &NodePoolNodesCommand{Meta: Meta{Ui: ui}}
// Run command.
// Add -json to help parse and validate results.
args := []string{"-address", url, "-json"}
args = append(args, tc.args...)
code := cmd.Run(args)
if tc.expectedErr != "" {
must.StrContains(t, ui.ErrorWriter.String(), strings.TrimSpace(tc.expectedErr))
} else {
must.Eq(t, "", ui.ErrorWriter.String())
var nodes []*api.NodeListStub
err := json.Unmarshal(ui.OutputWriter.Bytes(), &nodes)
must.NoError(t, err)
gotNodes := helper.ConvertSlice(nodes,
func(n *api.NodeListStub) string { return n.Name })
must.SliceContainsAll(t, tc.expectedNodes, gotNodes)
}
must.Eq(t, tc.expectedCode, code)
})
}
t.Run("template formatting", func(t *testing.T) {
// Initialize UI and command.
ui := cli.NewMockUi()
cmd := &NodePoolNodesCommand{Meta: Meta{Ui: ui}}
// Run command.
args := []string{"-address", url, "-t", `{{range .}}{{.ID}} {{end}}`, "all"}
code := cmd.Run(args)
must.Zero(t, code)
var expected string
for _, n := range nodes {
expected += n.ID + " "
}
got := ui.OutputWriter.String()
must.Eq(t, strings.TrimSpace(expected), strings.TrimSpace(got))
})
}