207 lines
4.9 KiB
Go
207 lines
4.9 KiB
Go
|
// Copyright (c) HashiCorp, Inc.
|
||
|
// SPDX-License-Identifier: MPL-2.0
|
||
|
|
||
|
package command
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/hashicorp/nomad/ci"
|
||
|
"github.com/mitchellh/cli"
|
||
|
"github.com/shoenig/test"
|
||
|
"github.com/shoenig/test/must"
|
||
|
)
|
||
|
|
||
|
func TestNodePoolApplyCommand_Implements(t *testing.T) {
|
||
|
ci.Parallel(t)
|
||
|
var _ cli.Command = &NodePoolApplyCommand{}
|
||
|
}
|
||
|
|
||
|
func TestNodePoolApplyCommand_Run(t *testing.T) {
|
||
|
ci.Parallel(t)
|
||
|
|
||
|
// Start test server.
|
||
|
srv, client, url := testServer(t, true, nil)
|
||
|
defer srv.Shutdown()
|
||
|
|
||
|
waitForNodes(t, client)
|
||
|
|
||
|
// Initialize UI and command.
|
||
|
ui := cli.NewMockUi()
|
||
|
cmd := &NodePoolApplyCommand{Meta: Meta{Ui: ui}}
|
||
|
|
||
|
// Create node pool with HCL file.
|
||
|
hclTestFile := `
|
||
|
node_pool "dev" {
|
||
|
description = "dev node pool"
|
||
|
}`
|
||
|
file, err := os.CreateTemp(t.TempDir(), "node-pool-test-*.hcl")
|
||
|
must.NoError(t, err)
|
||
|
_, err = file.WriteString(hclTestFile)
|
||
|
must.NoError(t, err)
|
||
|
|
||
|
// Run command.
|
||
|
args := []string{"-address", url, file.Name()}
|
||
|
code := cmd.Run(args)
|
||
|
must.Eq(t, 0, code)
|
||
|
|
||
|
// Verify node pool was created.
|
||
|
got, err := srv.Agent.Server().State().NodePoolByName(nil, "dev")
|
||
|
must.NoError(t, err)
|
||
|
must.NotNil(t, got)
|
||
|
|
||
|
// Update node pool.
|
||
|
file.Truncate(0)
|
||
|
file.Seek(0, 0)
|
||
|
hclTestFile = `
|
||
|
node_pool "dev" {
|
||
|
description = "dev node pool"
|
||
|
|
||
|
meta {
|
||
|
test = "true"
|
||
|
}
|
||
|
}`
|
||
|
_, err = file.WriteString(hclTestFile)
|
||
|
must.NoError(t, err)
|
||
|
|
||
|
// Run command.
|
||
|
code = cmd.Run(args)
|
||
|
must.Eq(t, 0, code)
|
||
|
|
||
|
// Verify node pool was updated.
|
||
|
got, err = srv.Agent.Server().State().NodePoolByName(nil, "dev")
|
||
|
must.NoError(t, err)
|
||
|
must.NotNil(t, got)
|
||
|
must.NotNil(t, got.Meta)
|
||
|
must.Eq(t, "true", got.Meta["test"])
|
||
|
|
||
|
// Create node pool with JSON file.
|
||
|
jsonTestFile := `
|
||
|
{
|
||
|
"Name": "prod",
|
||
|
"Description": "prod node pool"
|
||
|
}`
|
||
|
|
||
|
file, err = os.CreateTemp(t.TempDir(), "node-pool-test-*.json")
|
||
|
must.NoError(t, err)
|
||
|
_, err = file.WriteString(jsonTestFile)
|
||
|
must.NoError(t, err)
|
||
|
|
||
|
// Run command.
|
||
|
args = []string{"-address", url, "-json", file.Name()}
|
||
|
code = cmd.Run(args)
|
||
|
must.Eq(t, 0, code)
|
||
|
|
||
|
// Verify node pool was created.
|
||
|
got, err = srv.Agent.Server().State().NodePoolByName(nil, "prod")
|
||
|
must.NoError(t, err)
|
||
|
must.NotNil(t, got)
|
||
|
}
|
||
|
|
||
|
func TestNodePoolApplyCommand_Run_fail(t *testing.T) {
|
||
|
ci.Parallel(t)
|
||
|
|
||
|
// Start test server.
|
||
|
srv, client, url := testServer(t, true, nil)
|
||
|
defer srv.Shutdown()
|
||
|
|
||
|
waitForNodes(t, client)
|
||
|
|
||
|
testCases := []struct {
|
||
|
name string
|
||
|
args []string
|
||
|
input string
|
||
|
expectedOutput string
|
||
|
expectedCode int
|
||
|
}{
|
||
|
{
|
||
|
name: "missing file",
|
||
|
args: []string{},
|
||
|
expectedOutput: "This command takes one argument",
|
||
|
expectedCode: 1,
|
||
|
},
|
||
|
{
|
||
|
name: "file doesn't exist",
|
||
|
args: []string{"doesn-exist.hcl"},
|
||
|
expectedOutput: "no such file",
|
||
|
expectedCode: 1,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid json",
|
||
|
args: []string{"-json", "invalid.json"},
|
||
|
input: "not json",
|
||
|
expectedOutput: "Failed to parse input",
|
||
|
expectedCode: 1,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid hcl",
|
||
|
args: []string{"invalid.hcl"},
|
||
|
input: "not HCL",
|
||
|
expectedOutput: "Failed to parse input",
|
||
|
expectedCode: 1,
|
||
|
},
|
||
|
{
|
||
|
name: "valid json without json flag",
|
||
|
args: []string{"valid.json"},
|
||
|
input: `{"Name": "dev"}`,
|
||
|
expectedOutput: "Failed to parse input",
|
||
|
expectedCode: 1,
|
||
|
},
|
||
|
{
|
||
|
name: "valid hcl with json flag",
|
||
|
args: []string{"-json", "valid.hcl"},
|
||
|
input: `node_pool "dev" {}`,
|
||
|
expectedOutput: "Failed to parse input",
|
||
|
expectedCode: 1,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid node pool hcl",
|
||
|
args: []string{"invalid.hcl"},
|
||
|
input: `not_a_node_pool "dev" {}`,
|
||
|
expectedOutput: "Failed to parse input",
|
||
|
expectedCode: 1,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid node pool",
|
||
|
args: []string{"-address", url, "invalid_node_pool.hcl"},
|
||
|
input: `node_pool "invalid name" {}`,
|
||
|
expectedOutput: "Error applying node pool",
|
||
|
expectedCode: 1,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, tc := range testCases {
|
||
|
t.Run(tc.name, func(t *testing.T) {
|
||
|
// Initialize UI and command.
|
||
|
ui := cli.NewMockUi()
|
||
|
cmd := &NodePoolApplyCommand{Meta: Meta{Ui: ui}}
|
||
|
|
||
|
// Write input to file.
|
||
|
if tc.input != "" {
|
||
|
// Split the filename and extension from the last argument to
|
||
|
// add a "*" between them so os.CreateTemp retains the file
|
||
|
// extension.
|
||
|
filename := tc.args[len(tc.args)-1]
|
||
|
ext := filepath.Ext(filename)
|
||
|
name, _ := strings.CutSuffix(filename, ext)
|
||
|
|
||
|
file, err := os.CreateTemp(t.TempDir(), fmt.Sprintf("%s-*%s", name, ext))
|
||
|
must.NoError(t, err)
|
||
|
_, err = file.WriteString(tc.input)
|
||
|
must.NoError(t, err)
|
||
|
|
||
|
// Update last arg with full test file path.
|
||
|
tc.args[len(tc.args)-1] = file.Name()
|
||
|
}
|
||
|
|
||
|
got := cmd.Run(tc.args)
|
||
|
test.Eq(t, tc.expectedCode, got)
|
||
|
test.StrContains(t, ui.ErrorWriter.String(), tc.expectedOutput)
|
||
|
})
|
||
|
}
|
||
|
}
|