influxdb/remotes/transport/http_test.go

207 lines
6.1 KiB
Go

package transport
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/golang/mock/gomock"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/remotes/mock"
"github.com/stretchr/testify/assert"
tmock "github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)
//go:generate go run github.com/golang/mock/mockgen -package mock -destination ../mock/service.go github.com/influxdata/influxdb/v2/remotes/transport RemoteConnectionService
var (
orgStr = "1234123412341234"
orgID, _ = platform.IDFromString(orgStr)
remoteOrgStr = "9876987698769876"
remoteOrgID, _ = platform.IDFromString(remoteOrgStr)
idStr = "4321432143214321"
id, _ = platform.IDFromString(idStr)
testConn = influxdb.RemoteConnection{
ID: *id,
OrgID: *orgID,
Name: "example",
RemoteURL: "https://influxdb.cloud",
RemoteOrgID: remoteOrgID,
AllowInsecureTLS: true,
}
)
func TestRemoteConnectionHandler(t *testing.T) {
t.Run("get remotes happy path", func(t *testing.T) {
ts, svc := newTestServer(t)
defer ts.Close()
req := newTestRequest(t, "GET", ts.URL, nil)
q := req.URL.Query()
q.Add("orgID", orgStr)
q.Add("name", testConn.Name)
q.Add("remoteURL", testConn.RemoteURL)
req.URL.RawQuery = q.Encode()
expected := influxdb.RemoteConnections{Remotes: []influxdb.RemoteConnection{testConn}}
svc.EXPECT().
ListRemoteConnections(gomock.Any(), tmock.MatchedBy(func(in influxdb.RemoteConnectionListFilter) bool {
return assert.Equal(t, *orgID, in.OrgID) &&
assert.Equal(t, testConn.Name, *in.Name) &&
assert.Equal(t, testConn.RemoteURL, *in.RemoteURL)
})).Return(&expected, nil)
res := doTestRequest(t, req, http.StatusOK, true)
var got influxdb.RemoteConnections
require.NoError(t, json.NewDecoder(res.Body).Decode(&got))
require.Equal(t, expected, got)
})
t.Run("create remote happy path", func(t *testing.T) {
ts, svc := newTestServer(t)
defer ts.Close()
body := influxdb.CreateRemoteConnectionRequest{
OrgID: testConn.OrgID,
Name: testConn.Name,
RemoteURL: testConn.RemoteURL,
RemoteToken: "my super secret token",
RemoteOrgID: testConn.RemoteOrgID,
AllowInsecureTLS: testConn.AllowInsecureTLS,
}
req := newTestRequest(t, "POST", ts.URL, &body)
svc.EXPECT().CreateRemoteConnection(gomock.Any(), body).Return(&testConn, nil)
res := doTestRequest(t, req, http.StatusCreated, true)
var got influxdb.RemoteConnection
require.NoError(t, json.NewDecoder(res.Body).Decode(&got))
require.Equal(t, testConn, got)
})
t.Run("get remote happy path", func(t *testing.T) {
ts, svc := newTestServer(t)
defer ts.Close()
req := newTestRequest(t, "GET", ts.URL+"/"+id.String(), nil)
svc.EXPECT().GetRemoteConnection(gomock.Any(), *id).Return(&testConn, nil)
res := doTestRequest(t, req, http.StatusOK, true)
var got influxdb.RemoteConnection
require.NoError(t, json.NewDecoder(res.Body).Decode(&got))
require.Equal(t, testConn, got)
})
t.Run("delete remote happy path", func(t *testing.T) {
ts, svc := newTestServer(t)
defer ts.Close()
req := newTestRequest(t, "DELETE", ts.URL+"/"+id.String(), nil)
svc.EXPECT().DeleteRemoteConnection(gomock.Any(), *id).Return(nil)
doTestRequest(t, req, http.StatusNoContent, false)
})
t.Run("update remote happy path", func(t *testing.T) {
ts, svc := newTestServer(t)
defer ts.Close()
newToken := "a new even more secret token"
body := influxdb.UpdateRemoteConnectionRequest{RemoteToken: &newToken}
req := newTestRequest(t, "PATCH", ts.URL+"/"+id.String(), &body)
svc.EXPECT().UpdateRemoteConnection(gomock.Any(), *id, body).Return(&testConn, nil)
res := doTestRequest(t, req, http.StatusOK, true)
var got influxdb.RemoteConnection
require.NoError(t, json.NewDecoder(res.Body).Decode(&got))
require.Equal(t, testConn, got)
})
t.Run("invalid remote IDs return 400", func(t *testing.T) {
ts, _ := newTestServer(t)
defer ts.Close()
req1 := newTestRequest(t, "GET", ts.URL+"/foo", nil)
req2 := newTestRequest(t, "PATCH", ts.URL+"/foo", &influxdb.UpdateRemoteConnectionRequest{})
req3 := newTestRequest(t, "DELETE", ts.URL+"/foo", nil)
for _, req := range []*http.Request{req1, req2, req3} {
t.Run(req.Method, func(t *testing.T) {
doTestRequest(t, req, http.StatusBadRequest, true)
})
}
})
t.Run("invalid org ID to GET /remotes returns 400", func(t *testing.T) {
ts, _ := newTestServer(t)
defer ts.Close()
req := newTestRequest(t, "GET", ts.URL, nil)
q := req.URL.Query()
q.Add("orgID", "foo")
req.URL.RawQuery = q.Encode()
doTestRequest(t, req, http.StatusBadRequest, true)
})
t.Run("invalid request bodies return 400", func(t *testing.T) {
ts, _ := newTestServer(t)
defer ts.Close()
body := "o no not an object"
req1 := newTestRequest(t, "POST", ts.URL, &body)
req2 := newTestRequest(t, "PATCH", ts.URL+"/"+id.String(), &body)
for _, req := range []*http.Request{req1, req2} {
t.Run(req.Method, func(t *testing.T) {
doTestRequest(t, req, http.StatusBadRequest, true)
})
}
})
}
func newTestServer(t *testing.T) (*httptest.Server, *mock.MockRemoteConnectionService) {
ctrlr := gomock.NewController(t)
svc := mock.NewMockRemoteConnectionService(ctrlr)
server := newRemoteConnectionHandler(zaptest.NewLogger(t), svc)
return httptest.NewServer(server), svc
}
func newTestRequest(t *testing.T, method, path string, body interface{}) *http.Request {
dat, err := json.Marshal(body)
require.NoError(t, err)
req, err := http.NewRequest(method, path, bytes.NewBuffer(dat))
require.NoError(t, err)
req.Header.Add("Content-Type", "application/json")
return req
}
func doTestRequest(t *testing.T, req *http.Request, wantCode int, needJSON bool) *http.Response {
res, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, wantCode, res.StatusCode)
if needJSON {
require.Equal(t, "application/json; charset=utf-8", res.Header.Get("Content-Type"))
}
return res
}