github.com/hernad/nomad@v1.6.112/command/var_get_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package command 5 6 import ( 7 "fmt" 8 "strings" 9 "testing" 10 11 "github.com/hernad/nomad/api" 12 "github.com/hernad/nomad/ci" 13 "github.com/mitchellh/cli" 14 "github.com/posener/complete" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestVarGetCommand_Implements(t *testing.T) { 19 ci.Parallel(t) 20 var _ cli.Command = &VarGetCommand{} 21 } 22 23 func TestVarGetCommand_Fails(t *testing.T) { 24 ci.Parallel(t) 25 t.Run("bad_args", func(t *testing.T) { 26 ci.Parallel(t) 27 ui := cli.NewMockUi() 28 cmd := &VarGetCommand{Meta: Meta{Ui: ui}} 29 code := cmd.Run([]string{"some", "bad", "args"}) 30 out := ui.ErrorWriter.String() 31 require.Equal(t, 1, code, "expected exit code 1, got: %d") 32 require.Contains(t, out, commandErrorText(cmd), "expected help output, got: %s", out) 33 }) 34 t.Run("bad_address", func(t *testing.T) { 35 ci.Parallel(t) 36 ui := cli.NewMockUi() 37 cmd := &VarGetCommand{Meta: Meta{Ui: ui}} 38 code := cmd.Run([]string{"-address=nope", "foo"}) 39 out := ui.ErrorWriter.String() 40 require.Equal(t, 1, code, "expected exit code 1, got: %d") 41 require.Contains(t, ui.ErrorWriter.String(), "retrieving variable", "connection error, got: %s", out) 42 require.Zero(t, ui.OutputWriter.String()) 43 }) 44 t.Run("missing_template", func(t *testing.T) { 45 ci.Parallel(t) 46 ui := cli.NewMockUi() 47 cmd := &VarGetCommand{Meta: Meta{Ui: ui}} 48 code := cmd.Run([]string{`-out=go-template`, "foo"}) 49 out := strings.TrimSpace(ui.ErrorWriter.String()) 50 require.Equal(t, 1, code, "expected exit code 1, got: %d", code) 51 require.Equal(t, errMissingTemplate+"\n"+commandErrorText(cmd), out) 52 require.Zero(t, ui.OutputWriter.String()) 53 }) 54 t.Run("unexpected_template", func(t *testing.T) { 55 ci.Parallel(t) 56 ui := cli.NewMockUi() 57 cmd := &VarGetCommand{Meta: Meta{Ui: ui}} 58 code := cmd.Run([]string{`-out=json`, `-template="bad"`, "foo"}) 59 out := strings.TrimSpace(ui.ErrorWriter.String()) 60 require.Equal(t, 1, code, "expected exit code 1, got: %d", code) 61 require.Equal(t, errUnexpectedTemplate+"\n"+commandErrorText(cmd), out) 62 require.Zero(t, ui.OutputWriter.String()) 63 }) 64 } 65 66 func TestVarGetCommand(t *testing.T) { 67 ci.Parallel(t) 68 69 // Create a server 70 srv, client, url := testServer(t, true, nil) 71 defer srv.Shutdown() 72 73 testCases := []struct { 74 name string 75 format string 76 template string 77 expected string 78 testPath string // defaulted to "test/var" in code; used for not-found 79 exitCode int 80 isError bool 81 }{ 82 { 83 name: "json", 84 format: "json", 85 }, 86 { 87 name: "table", 88 format: "table", 89 }, 90 { 91 name: "go-template", 92 format: "go-template", 93 template: `{{.Namespace}}.{{.Path}}`, 94 expected: "TestVarGetCommand-2-go-template.test/var", 95 }, 96 { 97 name: "not-found", 98 format: "json", 99 expected: errVariableNotFound, 100 testPath: "not-found", 101 isError: true, 102 exitCode: 1, 103 }, 104 } 105 for i, tc := range testCases { 106 t.Run(fmt.Sprintf("%v_%s", i, tc.name), func(t *testing.T) { 107 tc := tc 108 ci.Parallel(t) 109 var err error 110 // Create a namespace for the test case 111 testNS := strings.Map(validNS, t.Name()) 112 _, err = client.Namespaces().Register(&api.Namespace{Name: testNS}, nil) 113 require.NoError(t, err) 114 t.Cleanup(func() { 115 _, _ = client.Namespaces().Delete(testNS, nil) 116 }) 117 118 // Create a var to get 119 sv := testVariable() 120 sv.Namespace = testNS 121 sv, _, err = client.Variables().Create(sv, nil) 122 require.NoError(t, err) 123 t.Cleanup(func() { 124 _, _ = client.Variables().Delete(sv.Path, nil) 125 }) 126 127 // Build and run the command 128 ui := cli.NewMockUi() 129 cmd := &VarGetCommand{Meta: Meta{Ui: ui}} 130 args := []string{ 131 "-address=" + url, 132 "-namespace=" + testNS, 133 "-out=" + tc.format, 134 } 135 if tc.template != "" { 136 args = append(args, "-template="+tc.template) 137 } 138 args = append(args, sv.Path) 139 if tc.testPath != "" { 140 // replace path with test case override 141 args[len(args)-1] = tc.testPath 142 } 143 code := cmd.Run(args) 144 145 // Check the output 146 require.Equal(t, tc.exitCode, code, "expected exit %v, got: %d; %v", tc.exitCode, code, ui.ErrorWriter.String()) 147 if tc.isError { 148 require.Equal(t, tc.expected, strings.TrimSpace(ui.ErrorWriter.String())) 149 return 150 } 151 switch tc.format { 152 case "json": 153 require.Equal(t, sv.AsPrettyJSON(), strings.TrimSpace(ui.OutputWriter.String())) 154 case "table": 155 out := ui.OutputWriter.String() 156 outs := strings.Split(out, "\n") 157 require.Len(t, outs, 9) 158 require.Equal(t, "Namespace = "+testNS, outs[0]) 159 require.Equal(t, "Path = test/var", outs[1]) 160 case "go-template": 161 require.Equal(t, tc.expected, strings.TrimSpace(ui.OutputWriter.String())) 162 default: 163 t.Fatalf("invalid format: %q", tc.format) 164 } 165 }) 166 } 167 t.Run("Autocomplete", func(t *testing.T) { 168 ci.Parallel(t) 169 170 ui := cli.NewMockUi() 171 cmd := &VarGetCommand{Meta: Meta{Ui: ui, flagAddress: url}} 172 173 // Create a var 174 testNS := strings.Map(validNS, t.Name()) 175 _, err := client.Namespaces().Register(&api.Namespace{Name: testNS}, nil) 176 require.NoError(t, err) 177 t.Cleanup(func() { 178 _, _ = client.Namespaces().Delete(testNS, nil) 179 }) 180 181 sv := testVariable() 182 sv.Path = "special/variable" 183 sv.Namespace = testNS 184 sv, _, err = client.Variables().Create(sv, nil) 185 require.NoError(t, err) 186 t.Cleanup(func() { 187 _, _ = client.Variables().Delete(sv.Path, nil) 188 }) 189 190 args := complete.Args{Last: "s"} 191 predictor := cmd.AutocompleteArgs() 192 193 res := predictor.Predict(args) 194 require.Equal(t, 1, len(res)) 195 require.Equal(t, sv.Path, res[0]) 196 }) 197 } 198 199 func validNS(r rune) rune { 200 if r == '/' || r == '_' { 201 return '-' 202 } 203 return r 204 }