1package get
2
3import (
4	"encoding/base64"
5	"strings"
6	"testing"
7
8	"github.com/hashicorp/consul/agent"
9	"github.com/hashicorp/consul/api"
10	"github.com/mitchellh/cli"
11)
12
13func TestKVGetCommand_noTabs(t *testing.T) {
14	t.Parallel()
15	if strings.ContainsRune(New(nil).Help(), '\t') {
16		t.Fatal("help has tabs")
17	}
18}
19
20func TestKVGetCommand_Validation(t *testing.T) {
21	t.Parallel()
22	ui := cli.NewMockUi()
23	c := New(ui)
24
25	cases := map[string]struct {
26		args   []string
27		output string
28	}{
29		"no key": {
30			[]string{},
31			"Missing KEY argument",
32		},
33		"extra args": {
34			[]string{"foo", "bar", "baz"},
35			"Too many arguments",
36		},
37	}
38
39	for name, tc := range cases {
40		// Ensure our buffer is always clear
41		if ui.ErrorWriter != nil {
42			ui.ErrorWriter.Reset()
43		}
44		if ui.OutputWriter != nil {
45			ui.OutputWriter.Reset()
46		}
47
48		code := c.Run(tc.args)
49		if code == 0 {
50			t.Errorf("%s: expected non-zero exit", name)
51		}
52
53		output := ui.ErrorWriter.String()
54		if !strings.Contains(output, tc.output) {
55			t.Errorf("%s: expected %q to contain %q", name, output, tc.output)
56		}
57	}
58}
59
60func TestKVGetCommand(t *testing.T) {
61	t.Parallel()
62	a := agent.NewTestAgent(t, ``)
63	defer a.Shutdown()
64	client := a.Client()
65
66	ui := cli.NewMockUi()
67	c := New(ui)
68
69	pair := &api.KVPair{
70		Key:   "foo",
71		Value: []byte("bar"),
72	}
73	_, err := client.KV().Put(pair, nil)
74	if err != nil {
75		t.Fatalf("err: %#v", err)
76	}
77
78	args := []string{
79		"-http-addr=" + a.HTTPAddr(),
80		"foo",
81	}
82
83	code := c.Run(args)
84	if code != 0 {
85		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
86	}
87
88	output := ui.OutputWriter.String()
89	if !strings.Contains(output, "bar") {
90		t.Errorf("bad: %#v", output)
91	}
92}
93
94func TestKVGetCommand_Base64(t *testing.T) {
95	t.Parallel()
96	a := agent.NewTestAgent(t, ``)
97	defer a.Shutdown()
98	client := a.Client()
99
100	ui := cli.NewMockUi()
101	c := New(ui)
102
103	pair := &api.KVPair{
104		Key:   "foo",
105		Value: []byte("bar"),
106	}
107	_, err := client.KV().Put(pair, nil)
108	if err != nil {
109		t.Fatalf("err: %#v", err)
110	}
111
112	args := []string{
113		"-http-addr=" + a.HTTPAddr(),
114		"-base64",
115		"foo",
116	}
117
118	code := c.Run(args)
119	if code != 0 {
120		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
121	}
122
123	output := ui.OutputWriter.String()
124	if !strings.Contains(output, base64.StdEncoding.EncodeToString(pair.Value)) {
125		t.Errorf("bad: %#v", output)
126	}
127}
128
129func TestKVGetCommand_Missing(t *testing.T) {
130	t.Parallel()
131	a := agent.NewTestAgent(t, ``)
132	defer a.Shutdown()
133
134	ui := cli.NewMockUi()
135	c := New(ui)
136
137	args := []string{
138		"-http-addr=" + a.HTTPAddr(),
139		"not-a-real-key",
140	}
141
142	code := c.Run(args)
143	if code == 0 {
144		t.Fatalf("expected bad code")
145	}
146}
147
148func TestKVGetCommand_Empty(t *testing.T) {
149	t.Parallel()
150	a := agent.NewTestAgent(t, ``)
151	defer a.Shutdown()
152	client := a.Client()
153
154	ui := cli.NewMockUi()
155	c := New(ui)
156
157	pair := &api.KVPair{
158		Key:   "empty",
159		Value: []byte(""),
160	}
161	_, err := client.KV().Put(pair, nil)
162	if err != nil {
163		t.Fatalf("err: %#v", err)
164	}
165
166	args := []string{
167		"-http-addr=" + a.HTTPAddr(),
168		"empty",
169	}
170
171	code := c.Run(args)
172	if code != 0 {
173		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
174	}
175}
176
177func TestKVGetCommand_Detailed(t *testing.T) {
178	t.Parallel()
179	a := agent.NewTestAgent(t, ``)
180	defer a.Shutdown()
181	client := a.Client()
182
183	ui := cli.NewMockUi()
184	c := New(ui)
185
186	pair := &api.KVPair{
187		Key:   "foo",
188		Value: []byte("bar"),
189	}
190	_, err := client.KV().Put(pair, nil)
191	if err != nil {
192		t.Fatalf("err: %#v", err)
193	}
194
195	args := []string{
196		"-http-addr=" + a.HTTPAddr(),
197		"-detailed",
198		"foo",
199	}
200
201	code := c.Run(args)
202	if code != 0 {
203		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
204	}
205
206	output := ui.OutputWriter.String()
207	for _, key := range []string{
208		"CreateIndex",
209		"LockIndex",
210		"ModifyIndex",
211		"Flags",
212		"Session",
213		"Value",
214	} {
215		if !strings.Contains(output, key) {
216			t.Fatalf("bad %#v, missing %q", output, key)
217		}
218	}
219}
220
221func TestKVGetCommand_Keys(t *testing.T) {
222	t.Parallel()
223	a := agent.NewTestAgent(t, ``)
224	defer a.Shutdown()
225	client := a.Client()
226
227	ui := cli.NewMockUi()
228	c := New(ui)
229
230	keys := []string{"foo/bar", "foo/baz", "foo/zip"}
231	for _, key := range keys {
232		if _, err := client.KV().Put(&api.KVPair{Key: key}, nil); err != nil {
233			t.Fatalf("err: %#v", err)
234		}
235	}
236
237	args := []string{
238		"-http-addr=" + a.HTTPAddr(),
239		"-keys",
240		"foo/",
241	}
242
243	code := c.Run(args)
244	if code != 0 {
245		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
246	}
247
248	output := ui.OutputWriter.String()
249	for _, key := range keys {
250		if !strings.Contains(output, key) {
251			t.Fatalf("bad %#v missing %q", output, key)
252		}
253	}
254}
255
256func TestKVGetCommand_Recurse(t *testing.T) {
257	t.Parallel()
258	a := agent.NewTestAgent(t, ``)
259	defer a.Shutdown()
260	client := a.Client()
261
262	ui := cli.NewMockUi()
263	c := New(ui)
264
265	keys := map[string]string{
266		"foo/a": "a",
267		"foo/b": "b",
268		"foo/c": "c",
269	}
270	for k, v := range keys {
271		pair := &api.KVPair{Key: k, Value: []byte(v)}
272		if _, err := client.KV().Put(pair, nil); err != nil {
273			t.Fatalf("err: %#v", err)
274		}
275	}
276
277	args := []string{
278		"-http-addr=" + a.HTTPAddr(),
279		"-recurse",
280		"foo",
281	}
282
283	code := c.Run(args)
284	if code != 0 {
285		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
286	}
287
288	output := ui.OutputWriter.String()
289	for key, value := range keys {
290		if !strings.Contains(output, key+":"+value) {
291			t.Fatalf("bad %#v missing %q", output, key)
292		}
293	}
294}
295
296func TestKVGetCommand_RecurseBase64(t *testing.T) {
297	t.Parallel()
298	a := agent.NewTestAgent(t, ``)
299	defer a.Shutdown()
300	client := a.Client()
301
302	ui := cli.NewMockUi()
303	c := New(ui)
304
305	keys := map[string]string{
306		"foo/a": "Hello World 1",
307		"foo/b": "Hello World 2",
308		"foo/c": "Hello World 3",
309	}
310	for k, v := range keys {
311		pair := &api.KVPair{Key: k, Value: []byte(v)}
312		if _, err := client.KV().Put(pair, nil); err != nil {
313			t.Fatalf("err: %#v", err)
314		}
315	}
316
317	args := []string{
318		"-http-addr=" + a.HTTPAddr(),
319		"-recurse",
320		"-base64",
321		"foo",
322	}
323
324	code := c.Run(args)
325	if code != 0 {
326		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
327	}
328
329	output := ui.OutputWriter.String()
330	for key, value := range keys {
331		if !strings.Contains(output, key+":"+base64.StdEncoding.EncodeToString([]byte(value))) {
332			t.Fatalf("bad %#v missing %q", output, key)
333		}
334	}
335}
336
337func TestKVGetCommand_DetailedBase64(t *testing.T) {
338	t.Parallel()
339	a := agent.NewTestAgent(t, ``)
340	defer a.Shutdown()
341	client := a.Client()
342
343	ui := cli.NewMockUi()
344	c := New(ui)
345
346	pair := &api.KVPair{
347		Key:   "foo",
348		Value: []byte("bar"),
349	}
350	_, err := client.KV().Put(pair, nil)
351	if err != nil {
352		t.Fatalf("err: %#v", err)
353	}
354
355	args := []string{
356		"-http-addr=" + a.HTTPAddr(),
357		"-detailed",
358		"-base64",
359		"foo",
360	}
361
362	code := c.Run(args)
363	if code != 0 {
364		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
365	}
366
367	output := ui.OutputWriter.String()
368	for _, key := range []string{
369		"CreateIndex",
370		"LockIndex",
371		"ModifyIndex",
372		"Flags",
373		"Session",
374		"Value",
375	} {
376		if !strings.Contains(output, key) {
377			t.Fatalf("bad %#v, missing %q", output, key)
378		}
379	}
380
381	if !strings.Contains(output, base64.StdEncoding.EncodeToString([]byte("bar"))) {
382		t.Fatalf("bad %#v, value is not base64 encoded", output)
383	}
384}
385