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