github.com/influxdata/influxdb/v2@v2.7.6/remotes/transport/http_test.go (about)

     1  package transport
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"testing"
     9  
    10  	"github.com/golang/mock/gomock"
    11  	"github.com/influxdata/influxdb/v2"
    12  	"github.com/influxdata/influxdb/v2/kit/platform"
    13  	"github.com/influxdata/influxdb/v2/remotes/mock"
    14  	"github.com/stretchr/testify/assert"
    15  	tmock "github.com/stretchr/testify/mock"
    16  	"github.com/stretchr/testify/require"
    17  	"go.uber.org/zap/zaptest"
    18  )
    19  
    20  //go:generate go run github.com/golang/mock/mockgen -package mock -destination ../mock/service.go github.com/influxdata/influxdb/v2/remotes/transport RemoteConnectionService
    21  
    22  var (
    23  	orgStr         = "1234123412341234"
    24  	orgID, _       = platform.IDFromString(orgStr)
    25  	remoteOrgStr   = "9876987698769876"
    26  	remoteOrgID, _ = platform.IDFromString(remoteOrgStr)
    27  	idStr          = "4321432143214321"
    28  	id, _          = platform.IDFromString(idStr)
    29  	testConn       = influxdb.RemoteConnection{
    30  		ID:               *id,
    31  		OrgID:            *orgID,
    32  		Name:             "example",
    33  		RemoteURL:        "https://influxdb.cloud",
    34  		RemoteOrgID:      remoteOrgID,
    35  		AllowInsecureTLS: true,
    36  	}
    37  )
    38  
    39  func TestRemoteConnectionHandler(t *testing.T) {
    40  	t.Run("get remotes happy path", func(t *testing.T) {
    41  		ts, svc := newTestServer(t)
    42  		defer ts.Close()
    43  
    44  		req := newTestRequest(t, "GET", ts.URL, nil)
    45  
    46  		q := req.URL.Query()
    47  		q.Add("orgID", orgStr)
    48  		q.Add("name", testConn.Name)
    49  		q.Add("remoteURL", testConn.RemoteURL)
    50  		req.URL.RawQuery = q.Encode()
    51  
    52  		expected := influxdb.RemoteConnections{Remotes: []influxdb.RemoteConnection{testConn}}
    53  
    54  		svc.EXPECT().
    55  			ListRemoteConnections(gomock.Any(), tmock.MatchedBy(func(in influxdb.RemoteConnectionListFilter) bool {
    56  				return assert.Equal(t, *orgID, in.OrgID) &&
    57  					assert.Equal(t, testConn.Name, *in.Name) &&
    58  					assert.Equal(t, testConn.RemoteURL, *in.RemoteURL)
    59  			})).Return(&expected, nil)
    60  
    61  		res := doTestRequest(t, req, http.StatusOK, true)
    62  
    63  		var got influxdb.RemoteConnections
    64  		require.NoError(t, json.NewDecoder(res.Body).Decode(&got))
    65  		require.Equal(t, expected, got)
    66  	})
    67  
    68  	t.Run("create remote happy path", func(t *testing.T) {
    69  		ts, svc := newTestServer(t)
    70  		defer ts.Close()
    71  
    72  		body := influxdb.CreateRemoteConnectionRequest{
    73  			OrgID:            testConn.OrgID,
    74  			Name:             testConn.Name,
    75  			RemoteURL:        testConn.RemoteURL,
    76  			RemoteToken:      "my super secret token",
    77  			RemoteOrgID:      testConn.RemoteOrgID,
    78  			AllowInsecureTLS: testConn.AllowInsecureTLS,
    79  		}
    80  
    81  		req := newTestRequest(t, "POST", ts.URL, &body)
    82  
    83  		svc.EXPECT().CreateRemoteConnection(gomock.Any(), body).Return(&testConn, nil)
    84  
    85  		res := doTestRequest(t, req, http.StatusCreated, true)
    86  
    87  		var got influxdb.RemoteConnection
    88  		require.NoError(t, json.NewDecoder(res.Body).Decode(&got))
    89  		require.Equal(t, testConn, got)
    90  	})
    91  
    92  	t.Run("get remote happy path", func(t *testing.T) {
    93  		ts, svc := newTestServer(t)
    94  		defer ts.Close()
    95  
    96  		req := newTestRequest(t, "GET", ts.URL+"/"+id.String(), nil)
    97  
    98  		svc.EXPECT().GetRemoteConnection(gomock.Any(), *id).Return(&testConn, nil)
    99  
   100  		res := doTestRequest(t, req, http.StatusOK, true)
   101  
   102  		var got influxdb.RemoteConnection
   103  		require.NoError(t, json.NewDecoder(res.Body).Decode(&got))
   104  		require.Equal(t, testConn, got)
   105  	})
   106  
   107  	t.Run("delete remote happy path", func(t *testing.T) {
   108  		ts, svc := newTestServer(t)
   109  		defer ts.Close()
   110  
   111  		req := newTestRequest(t, "DELETE", ts.URL+"/"+id.String(), nil)
   112  
   113  		svc.EXPECT().DeleteRemoteConnection(gomock.Any(), *id).Return(nil)
   114  
   115  		doTestRequest(t, req, http.StatusNoContent, false)
   116  	})
   117  
   118  	t.Run("update remote happy path", func(t *testing.T) {
   119  		ts, svc := newTestServer(t)
   120  		defer ts.Close()
   121  
   122  		newToken := "a new even more secret token"
   123  		body := influxdb.UpdateRemoteConnectionRequest{RemoteToken: &newToken}
   124  
   125  		req := newTestRequest(t, "PATCH", ts.URL+"/"+id.String(), &body)
   126  
   127  		svc.EXPECT().UpdateRemoteConnection(gomock.Any(), *id, body).Return(&testConn, nil)
   128  
   129  		res := doTestRequest(t, req, http.StatusOK, true)
   130  
   131  		var got influxdb.RemoteConnection
   132  		require.NoError(t, json.NewDecoder(res.Body).Decode(&got))
   133  		require.Equal(t, testConn, got)
   134  	})
   135  
   136  	t.Run("invalid remote IDs return 400", func(t *testing.T) {
   137  		ts, _ := newTestServer(t)
   138  		defer ts.Close()
   139  
   140  		req1 := newTestRequest(t, "GET", ts.URL+"/foo", nil)
   141  		req2 := newTestRequest(t, "PATCH", ts.URL+"/foo", &influxdb.UpdateRemoteConnectionRequest{})
   142  		req3 := newTestRequest(t, "DELETE", ts.URL+"/foo", nil)
   143  
   144  		for _, req := range []*http.Request{req1, req2, req3} {
   145  			t.Run(req.Method, func(t *testing.T) {
   146  				doTestRequest(t, req, http.StatusBadRequest, true)
   147  			})
   148  		}
   149  	})
   150  
   151  	t.Run("invalid org ID to GET /remotes returns 400", func(t *testing.T) {
   152  		ts, _ := newTestServer(t)
   153  		defer ts.Close()
   154  
   155  		req := newTestRequest(t, "GET", ts.URL, nil)
   156  		q := req.URL.Query()
   157  		q.Add("orgID", "foo")
   158  		req.URL.RawQuery = q.Encode()
   159  
   160  		doTestRequest(t, req, http.StatusBadRequest, true)
   161  	})
   162  
   163  	t.Run("invalid request bodies return 400", func(t *testing.T) {
   164  		ts, _ := newTestServer(t)
   165  		defer ts.Close()
   166  
   167  		body := "o no not an object"
   168  		req1 := newTestRequest(t, "POST", ts.URL, &body)
   169  		req2 := newTestRequest(t, "PATCH", ts.URL+"/"+id.String(), &body)
   170  
   171  		for _, req := range []*http.Request{req1, req2} {
   172  			t.Run(req.Method, func(t *testing.T) {
   173  				doTestRequest(t, req, http.StatusBadRequest, true)
   174  			})
   175  		}
   176  	})
   177  }
   178  
   179  func newTestServer(t *testing.T) (*httptest.Server, *mock.MockRemoteConnectionService) {
   180  	ctrlr := gomock.NewController(t)
   181  	svc := mock.NewMockRemoteConnectionService(ctrlr)
   182  	server := newRemoteConnectionHandler(zaptest.NewLogger(t), svc)
   183  	return httptest.NewServer(server), svc
   184  }
   185  
   186  func newTestRequest(t *testing.T, method, path string, body interface{}) *http.Request {
   187  	dat, err := json.Marshal(body)
   188  	require.NoError(t, err)
   189  
   190  	req, err := http.NewRequest(method, path, bytes.NewBuffer(dat))
   191  	require.NoError(t, err)
   192  
   193  	req.Header.Add("Content-Type", "application/json")
   194  
   195  	return req
   196  }
   197  
   198  func doTestRequest(t *testing.T, req *http.Request, wantCode int, needJSON bool) *http.Response {
   199  	res, err := http.DefaultClient.Do(req)
   200  	require.NoError(t, err)
   201  	require.Equal(t, wantCode, res.StatusCode)
   202  	if needJSON {
   203  		require.Equal(t, "application/json; charset=utf-8", res.Header.Get("Content-Type"))
   204  	}
   205  	return res
   206  }