open-nomad/command/var_get_test.go
Tim Gross 81516db4b2
variables: fix ENT-only test failure in command tests (#14599)
The `TestVarGetCommand` test uses the wrong namespace in the autocomplete
test. The namespace only gets validated against if we have quota enforcement (or
more typically by ACL checks), so the test only fails in the ENT repo test runs.
2022-09-15 10:37:57 -04:00

202 lines
5.5 KiB
Go

package command
import (
"fmt"
"strings"
"testing"
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/nomad/ci"
"github.com/mitchellh/cli"
"github.com/posener/complete"
"github.com/stretchr/testify/require"
)
func TestVarGetCommand_Implements(t *testing.T) {
ci.Parallel(t)
var _ cli.Command = &VarGetCommand{}
}
func TestVarGetCommand_Fails(t *testing.T) {
ci.Parallel(t)
t.Run("bad_args", func(t *testing.T) {
ci.Parallel(t)
ui := cli.NewMockUi()
cmd := &VarGetCommand{Meta: Meta{Ui: ui}}
code := cmd.Run([]string{"some", "bad", "args"})
out := ui.ErrorWriter.String()
require.Equal(t, 1, code, "expected exit code 1, got: %d")
require.Contains(t, out, commandErrorText(cmd), "expected help output, got: %s", out)
})
t.Run("bad_address", func(t *testing.T) {
ci.Parallel(t)
ui := cli.NewMockUi()
cmd := &VarGetCommand{Meta: Meta{Ui: ui}}
code := cmd.Run([]string{"-address=nope", "foo"})
out := ui.ErrorWriter.String()
require.Equal(t, 1, code, "expected exit code 1, got: %d")
require.Contains(t, ui.ErrorWriter.String(), "retrieving variable", "connection error, got: %s", out)
require.Zero(t, ui.OutputWriter.String())
})
t.Run("missing_template", func(t *testing.T) {
ci.Parallel(t)
ui := cli.NewMockUi()
cmd := &VarGetCommand{Meta: Meta{Ui: ui}}
code := cmd.Run([]string{`-out=go-template`, "foo"})
out := strings.TrimSpace(ui.ErrorWriter.String())
require.Equal(t, 1, code, "expected exit code 1, got: %d", code)
require.Equal(t, errMissingTemplate+"\n"+commandErrorText(cmd), out)
require.Zero(t, ui.OutputWriter.String())
})
t.Run("unexpected_template", func(t *testing.T) {
ci.Parallel(t)
ui := cli.NewMockUi()
cmd := &VarGetCommand{Meta: Meta{Ui: ui}}
code := cmd.Run([]string{`-out=json`, `-template="bad"`, "foo"})
out := strings.TrimSpace(ui.ErrorWriter.String())
require.Equal(t, 1, code, "expected exit code 1, got: %d", code)
require.Equal(t, errUnexpectedTemplate+"\n"+commandErrorText(cmd), out)
require.Zero(t, ui.OutputWriter.String())
})
}
func TestVarGetCommand(t *testing.T) {
ci.Parallel(t)
// Create a server
srv, client, url := testServer(t, true, nil)
t.Cleanup(func() {
srv.Shutdown()
})
testCases := []struct {
name string
format string
template string
expected string
testPath string // defaulted to "test/var" in code; used for not-found
exitCode int
isError bool
}{
{
name: "json",
format: "json",
},
{
name: "table",
format: "table",
},
{
name: "go-template",
format: "go-template",
template: `{{.Namespace}}.{{.Path}}`,
expected: "TestVarGetCommand-2-go-template.test/var",
},
{
name: "not-found",
format: "json",
expected: errVariableNotFound,
testPath: "not-found",
isError: true,
exitCode: 1,
},
}
for i, tc := range testCases {
t.Run(fmt.Sprintf("%v_%s", i, tc.name), func(t *testing.T) {
tc := tc
ci.Parallel(t)
var err error
// Create a namespace for the test case
testNS := strings.Map(validNS, t.Name())
_, err = client.Namespaces().Register(&api.Namespace{Name: testNS}, nil)
require.NoError(t, err)
t.Cleanup(func() {
client.Namespaces().Delete(testNS, nil)
})
// Create a var to get
sv := testVariable()
sv.Namespace = testNS
sv, _, err = client.Variables().Create(sv, nil)
require.NoError(t, err)
t.Cleanup(func() {
_, _ = client.Variables().Delete(sv.Path, nil)
})
// Build and run the command
ui := cli.NewMockUi()
cmd := &VarGetCommand{Meta: Meta{Ui: ui}}
args := []string{
"-address=" + url,
"-namespace=" + testNS,
"-out=" + tc.format,
}
if tc.template != "" {
args = append(args, "-template="+tc.template)
}
args = append(args, sv.Path)
if tc.testPath != "" {
// replace path with test case override
args[len(args)-1] = tc.testPath
}
code := cmd.Run(args)
// Check the output
require.Equal(t, tc.exitCode, code, "expected exit %v, got: %d; %v", tc.exitCode, code, ui.ErrorWriter.String())
if tc.isError {
require.Equal(t, tc.expected, strings.TrimSpace(ui.ErrorWriter.String()))
return
}
switch tc.format {
case "json":
require.Equal(t, sv.AsPrettyJSON(), strings.TrimSpace(ui.OutputWriter.String()))
case "table":
out := ui.OutputWriter.String()
outs := strings.Split(out, "\n")
require.Len(t, outs, 9)
require.Equal(t, "Namespace = "+testNS, outs[0])
require.Equal(t, "Path = test/var", outs[1])
case "go-template":
require.Equal(t, tc.expected, strings.TrimSpace(ui.OutputWriter.String()))
default:
t.Fatalf("invalid format: %q", tc.format)
}
})
}
t.Run("Autocomplete", func(t *testing.T) {
ci.Parallel(t)
_, client, url, shutdownFn := testAPIClient(t)
defer shutdownFn()
ui := cli.NewMockUi()
cmd := &VarGetCommand{Meta: Meta{Ui: ui, flagAddress: url}}
// Create a var
testNS := strings.Map(validNS, t.Name())
_, err := client.Namespaces().Register(&api.Namespace{Name: testNS}, nil)
require.NoError(t, err)
t.Cleanup(func() { client.Namespaces().Delete(testNS, nil) })
sv := testVariable()
sv.Path = "special/variable"
sv.Namespace = testNS
sv, _, err = client.Variables().Create(sv, nil)
require.NoError(t, err)
t.Cleanup(func() { client.Variables().Delete(sv.Path, nil) })
args := complete.Args{Last: "s"}
predictor := cmd.AutocompleteArgs()
res := predictor.Predict(args)
require.Equal(t, 1, len(res))
require.Equal(t, sv.Path, res[0])
})
}
func validNS(r rune) rune {
if r == '/' || r == '_' {
return '-'
}
return r
}