github.com/outbrain/consul@v1.4.5/agent/kvs_endpoint_test.go (about)

     1  package agent
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"reflect"
     9  	"testing"
    10  
    11  	"github.com/hashicorp/consul/testrpc"
    12  
    13  	"github.com/hashicorp/consul/agent/structs"
    14  )
    15  
    16  func TestKVSEndpoint_PUT_GET_DELETE(t *testing.T) {
    17  	t.Parallel()
    18  	a := NewTestAgent(t, t.Name(), "")
    19  	defer a.Shutdown()
    20  
    21  	keys := []string{
    22  		"baz",
    23  		"bar",
    24  		"foo/sub1",
    25  		"foo/sub2",
    26  		"zip",
    27  	}
    28  
    29  	for _, key := range keys {
    30  		buf := bytes.NewBuffer([]byte("test"))
    31  		req, _ := http.NewRequest("PUT", "/v1/kv/"+key, buf)
    32  		resp := httptest.NewRecorder()
    33  		obj, err := a.srv.KVSEndpoint(resp, req)
    34  		if err != nil {
    35  			t.Fatalf("err: %v", err)
    36  		}
    37  
    38  		if res := obj.(bool); !res {
    39  			t.Fatalf("should work")
    40  		}
    41  	}
    42  
    43  	for _, key := range keys {
    44  		req, _ := http.NewRequest("GET", "/v1/kv/"+key, nil)
    45  		resp := httptest.NewRecorder()
    46  		obj, err := a.srv.KVSEndpoint(resp, req)
    47  		if err != nil {
    48  			t.Fatalf("err: %v", err)
    49  		}
    50  		assertIndex(t, resp)
    51  
    52  		res, ok := obj.(structs.DirEntries)
    53  		if !ok {
    54  			t.Fatalf("should work")
    55  		}
    56  
    57  		if len(res) != 1 {
    58  			t.Fatalf("bad: %v", res)
    59  		}
    60  
    61  		if res[0].Key != key {
    62  			t.Fatalf("bad: %v", res)
    63  		}
    64  	}
    65  
    66  	for _, key := range keys {
    67  		req, _ := http.NewRequest("DELETE", "/v1/kv/"+key, nil)
    68  		resp := httptest.NewRecorder()
    69  		if _, err := a.srv.KVSEndpoint(resp, req); err != nil {
    70  			t.Fatalf("err: %v", err)
    71  		}
    72  	}
    73  }
    74  
    75  func TestKVSEndpoint_Recurse(t *testing.T) {
    76  	t.Parallel()
    77  	a := NewTestAgent(t, t.Name(), "")
    78  	defer a.Shutdown()
    79  
    80  	keys := []string{
    81  		"bar",
    82  		"baz",
    83  		"foo/sub1",
    84  		"foo/sub2",
    85  		"zip",
    86  	}
    87  
    88  	for _, key := range keys {
    89  		buf := bytes.NewBuffer([]byte("test"))
    90  		req, _ := http.NewRequest("PUT", "/v1/kv/"+key, buf)
    91  		resp := httptest.NewRecorder()
    92  		obj, err := a.srv.KVSEndpoint(resp, req)
    93  		if err != nil {
    94  			t.Fatalf("err: %v", err)
    95  		}
    96  
    97  		if res := obj.(bool); !res {
    98  			t.Fatalf("should work")
    99  		}
   100  	}
   101  
   102  	{
   103  		// Get all the keys
   104  		req, _ := http.NewRequest("GET", "/v1/kv/?recurse", nil)
   105  		resp := httptest.NewRecorder()
   106  		obj, err := a.srv.KVSEndpoint(resp, req)
   107  		if err != nil {
   108  			t.Fatalf("err: %v", err)
   109  		}
   110  		assertIndex(t, resp)
   111  
   112  		res, ok := obj.(structs.DirEntries)
   113  		if !ok {
   114  			t.Fatalf("should work")
   115  		}
   116  
   117  		if len(res) != len(keys) {
   118  			t.Fatalf("bad: %v", res)
   119  		}
   120  
   121  		for idx, key := range keys {
   122  			if res[idx].Key != key {
   123  				t.Fatalf("bad: %v %v", res[idx].Key, key)
   124  			}
   125  		}
   126  	}
   127  
   128  	{
   129  		req, _ := http.NewRequest("DELETE", "/v1/kv/?recurse", nil)
   130  		resp := httptest.NewRecorder()
   131  		if _, err := a.srv.KVSEndpoint(resp, req); err != nil {
   132  			t.Fatalf("err: %v", err)
   133  		}
   134  	}
   135  
   136  	{
   137  		// Get all the keys
   138  		req, _ := http.NewRequest("GET", "/v1/kv/?recurse", nil)
   139  		resp := httptest.NewRecorder()
   140  		obj, err := a.srv.KVSEndpoint(resp, req)
   141  		if err != nil {
   142  			t.Fatalf("err: %v", err)
   143  		}
   144  
   145  		if obj != nil {
   146  			t.Fatalf("bad: %v", obj)
   147  		}
   148  	}
   149  }
   150  
   151  func TestKVSEndpoint_DELETE_CAS(t *testing.T) {
   152  	t.Parallel()
   153  	a := NewTestAgent(t, t.Name(), "")
   154  	defer a.Shutdown()
   155  
   156  	{
   157  		buf := bytes.NewBuffer([]byte("test"))
   158  		req, _ := http.NewRequest("PUT", "/v1/kv/test", buf)
   159  		resp := httptest.NewRecorder()
   160  		obj, err := a.srv.KVSEndpoint(resp, req)
   161  		if err != nil {
   162  			t.Fatalf("err: %v", err)
   163  		}
   164  
   165  		if res := obj.(bool); !res {
   166  			t.Fatalf("should work")
   167  		}
   168  	}
   169  
   170  	req, _ := http.NewRequest("GET", "/v1/kv/test", nil)
   171  	resp := httptest.NewRecorder()
   172  	obj, err := a.srv.KVSEndpoint(resp, req)
   173  	if err != nil {
   174  		t.Fatalf("err: %v", err)
   175  	}
   176  	d := obj.(structs.DirEntries)[0]
   177  
   178  	// Create a CAS request, bad index
   179  	{
   180  		buf := bytes.NewBuffer([]byte("zip"))
   181  		req, _ := http.NewRequest("DELETE", fmt.Sprintf("/v1/kv/test?cas=%d", d.ModifyIndex-1), buf)
   182  		resp := httptest.NewRecorder()
   183  		obj, err := a.srv.KVSEndpoint(resp, req)
   184  		if err != nil {
   185  			t.Fatalf("err: %v", err)
   186  		}
   187  
   188  		if res := obj.(bool); res {
   189  			t.Fatalf("should NOT work")
   190  		}
   191  	}
   192  
   193  	// Create a CAS request, good index
   194  	{
   195  		buf := bytes.NewBuffer([]byte("zip"))
   196  		req, _ := http.NewRequest("DELETE", fmt.Sprintf("/v1/kv/test?cas=%d", d.ModifyIndex), buf)
   197  		resp := httptest.NewRecorder()
   198  		obj, err := a.srv.KVSEndpoint(resp, req)
   199  		if err != nil {
   200  			t.Fatalf("err: %v", err)
   201  		}
   202  
   203  		if res := obj.(bool); !res {
   204  			t.Fatalf("should work")
   205  		}
   206  	}
   207  
   208  	// Verify the delete
   209  	req, _ = http.NewRequest("GET", "/v1/kv/test", nil)
   210  	resp = httptest.NewRecorder()
   211  	obj, _ = a.srv.KVSEndpoint(resp, req)
   212  	if obj != nil {
   213  		t.Fatalf("should be destroyed")
   214  	}
   215  }
   216  
   217  func TestKVSEndpoint_CAS(t *testing.T) {
   218  	t.Parallel()
   219  	a := NewTestAgent(t, t.Name(), "")
   220  	defer a.Shutdown()
   221  
   222  	{
   223  		buf := bytes.NewBuffer([]byte("test"))
   224  		req, _ := http.NewRequest("PUT", "/v1/kv/test?flags=50", buf)
   225  		resp := httptest.NewRecorder()
   226  		obj, err := a.srv.KVSEndpoint(resp, req)
   227  		if err != nil {
   228  			t.Fatalf("err: %v", err)
   229  		}
   230  
   231  		if res := obj.(bool); !res {
   232  			t.Fatalf("should work")
   233  		}
   234  	}
   235  
   236  	req, _ := http.NewRequest("GET", "/v1/kv/test", nil)
   237  	resp := httptest.NewRecorder()
   238  	obj, err := a.srv.KVSEndpoint(resp, req)
   239  	if err != nil {
   240  		t.Fatalf("err: %v", err)
   241  	}
   242  	d := obj.(structs.DirEntries)[0]
   243  
   244  	// Check the flags
   245  	if d.Flags != 50 {
   246  		t.Fatalf("bad: %v", d)
   247  	}
   248  
   249  	// Create a CAS request, bad index
   250  	{
   251  		buf := bytes.NewBuffer([]byte("zip"))
   252  		req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/kv/test?flags=42&cas=%d", d.ModifyIndex-1), buf)
   253  		resp := httptest.NewRecorder()
   254  		obj, err := a.srv.KVSEndpoint(resp, req)
   255  		if err != nil {
   256  			t.Fatalf("err: %v", err)
   257  		}
   258  
   259  		if res := obj.(bool); res {
   260  			t.Fatalf("should NOT work")
   261  		}
   262  	}
   263  
   264  	// Create a CAS request, good index
   265  	{
   266  		buf := bytes.NewBuffer([]byte("zip"))
   267  		req, _ := http.NewRequest("PUT", fmt.Sprintf("/v1/kv/test?flags=42&cas=%d", d.ModifyIndex), buf)
   268  		resp := httptest.NewRecorder()
   269  		obj, err := a.srv.KVSEndpoint(resp, req)
   270  		if err != nil {
   271  			t.Fatalf("err: %v", err)
   272  		}
   273  
   274  		if res := obj.(bool); !res {
   275  			t.Fatalf("should work")
   276  		}
   277  	}
   278  
   279  	// Verify the update
   280  	req, _ = http.NewRequest("GET", "/v1/kv/test", nil)
   281  	resp = httptest.NewRecorder()
   282  	obj, _ = a.srv.KVSEndpoint(resp, req)
   283  	d = obj.(structs.DirEntries)[0]
   284  
   285  	if d.Flags != 42 {
   286  		t.Fatalf("bad: %v", d)
   287  	}
   288  	if string(d.Value) != "zip" {
   289  		t.Fatalf("bad: %v", d)
   290  	}
   291  }
   292  
   293  func TestKVSEndpoint_ListKeys(t *testing.T) {
   294  	t.Parallel()
   295  	a := NewTestAgent(t, t.Name(), "")
   296  	defer a.Shutdown()
   297  
   298  	keys := []string{
   299  		"bar",
   300  		"baz",
   301  		"foo/sub1",
   302  		"foo/sub2",
   303  		"zip",
   304  	}
   305  
   306  	for _, key := range keys {
   307  		buf := bytes.NewBuffer([]byte("test"))
   308  		req, _ := http.NewRequest("PUT", "/v1/kv/"+key, buf)
   309  		resp := httptest.NewRecorder()
   310  		obj, err := a.srv.KVSEndpoint(resp, req)
   311  		if err != nil {
   312  			t.Fatalf("err: %v", err)
   313  		}
   314  
   315  		if res := obj.(bool); !res {
   316  			t.Fatalf("should work")
   317  		}
   318  	}
   319  
   320  	{
   321  		// Get all the keys
   322  		req, _ := http.NewRequest("GET", "/v1/kv/?keys&seperator=/", nil)
   323  		resp := httptest.NewRecorder()
   324  		obj, err := a.srv.KVSEndpoint(resp, req)
   325  		if err != nil {
   326  			t.Fatalf("err: %v", err)
   327  		}
   328  		assertIndex(t, resp)
   329  
   330  		res, ok := obj.([]string)
   331  		if !ok {
   332  			t.Fatalf("should work")
   333  		}
   334  
   335  		expect := []string{"bar", "baz", "foo/", "zip"}
   336  		if !reflect.DeepEqual(res, expect) {
   337  			t.Fatalf("bad: %v", res)
   338  		}
   339  	}
   340  }
   341  
   342  func TestKVSEndpoint_AcquireRelease(t *testing.T) {
   343  	t.Parallel()
   344  	a := NewTestAgent(t, t.Name(), "")
   345  	defer a.Shutdown()
   346  
   347  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   348  
   349  	// Acquire the lock
   350  	id := makeTestSession(t, a.srv)
   351  	req, _ := http.NewRequest("PUT", "/v1/kv/test?acquire="+id, bytes.NewReader(nil))
   352  	resp := httptest.NewRecorder()
   353  	obj, err := a.srv.KVSEndpoint(resp, req)
   354  	if err != nil {
   355  		t.Fatalf("err: %v", err)
   356  	}
   357  	if res := obj.(bool); !res {
   358  		t.Fatalf("should work")
   359  	}
   360  
   361  	// Verify we have the lock
   362  	req, _ = http.NewRequest("GET", "/v1/kv/test", nil)
   363  	resp = httptest.NewRecorder()
   364  	obj, err = a.srv.KVSEndpoint(resp, req)
   365  	if err != nil {
   366  		t.Fatalf("err: %v", err)
   367  	}
   368  	d := obj.(structs.DirEntries)[0]
   369  
   370  	// Check the flags
   371  	if d.Session != id {
   372  		t.Fatalf("bad: %v", d)
   373  	}
   374  
   375  	// Release the lock
   376  	req, _ = http.NewRequest("PUT", "/v1/kv/test?release="+id, bytes.NewReader(nil))
   377  	resp = httptest.NewRecorder()
   378  	obj, err = a.srv.KVSEndpoint(resp, req)
   379  	if err != nil {
   380  		t.Fatalf("err: %v", err)
   381  	}
   382  	if res := obj.(bool); !res {
   383  		t.Fatalf("should work")
   384  	}
   385  
   386  	// Verify we do not have the lock
   387  	req, _ = http.NewRequest("GET", "/v1/kv/test", nil)
   388  	resp = httptest.NewRecorder()
   389  	obj, err = a.srv.KVSEndpoint(resp, req)
   390  	if err != nil {
   391  		t.Fatalf("err: %v", err)
   392  	}
   393  	d = obj.(structs.DirEntries)[0]
   394  
   395  	// Check the flags
   396  	if d.Session != "" {
   397  		t.Fatalf("bad: %v", d)
   398  	}
   399  }
   400  
   401  func TestKVSEndpoint_GET_Raw(t *testing.T) {
   402  	t.Parallel()
   403  	a := NewTestAgent(t, t.Name(), "")
   404  	defer a.Shutdown()
   405  
   406  	buf := bytes.NewBuffer([]byte("test"))
   407  	req, _ := http.NewRequest("PUT", "/v1/kv/test", buf)
   408  	resp := httptest.NewRecorder()
   409  	obj, err := a.srv.KVSEndpoint(resp, req)
   410  	if err != nil {
   411  		t.Fatalf("err: %v", err)
   412  	}
   413  	if res := obj.(bool); !res {
   414  		t.Fatalf("should work")
   415  	}
   416  
   417  	req, _ = http.NewRequest("GET", "/v1/kv/test?raw", nil)
   418  	resp = httptest.NewRecorder()
   419  	obj, err = a.srv.KVSEndpoint(resp, req)
   420  	if err != nil {
   421  		t.Fatalf("err: %v", err)
   422  	}
   423  	assertIndex(t, resp)
   424  
   425  	// Check the body
   426  	if !bytes.Equal(resp.Body.Bytes(), []byte("test")) {
   427  		t.Fatalf("bad: %s", resp.Body.Bytes())
   428  	}
   429  }
   430  
   431  func TestKVSEndpoint_PUT_ConflictingFlags(t *testing.T) {
   432  	t.Parallel()
   433  	a := NewTestAgent(t, t.Name(), "")
   434  	defer a.Shutdown()
   435  
   436  	req, _ := http.NewRequest("PUT", "/v1/kv/test?cas=0&acquire=xxx", nil)
   437  	resp := httptest.NewRecorder()
   438  	if _, err := a.srv.KVSEndpoint(resp, req); err != nil {
   439  		t.Fatalf("err: %v", err)
   440  	}
   441  
   442  	if resp.Code != 400 {
   443  		t.Fatalf("expected 400, got %d", resp.Code)
   444  	}
   445  	if !bytes.Contains(resp.Body.Bytes(), []byte("Conflicting")) {
   446  		t.Fatalf("expected conflicting args error")
   447  	}
   448  }
   449  
   450  func TestKVSEndpoint_DELETE_ConflictingFlags(t *testing.T) {
   451  	t.Parallel()
   452  	a := NewTestAgent(t, t.Name(), "")
   453  	defer a.Shutdown()
   454  
   455  	req, _ := http.NewRequest("DELETE", "/v1/kv/test?recurse&cas=0", nil)
   456  	resp := httptest.NewRecorder()
   457  	if _, err := a.srv.KVSEndpoint(resp, req); err != nil {
   458  		t.Fatalf("err: %v", err)
   459  	}
   460  
   461  	if resp.Code != 400 {
   462  		t.Fatalf("expected 400, got %d", resp.Code)
   463  	}
   464  	if !bytes.Contains(resp.Body.Bytes(), []byte("Conflicting")) {
   465  		t.Fatalf("expected conflicting args error")
   466  	}
   467  }