Add tests to sources/users endpoints
parent
c784a6260e
commit
72dbae043f
|
@ -0,0 +1,43 @@
|
|||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
var _ chronograf.SourcesStore = &SourcesStore{}
|
||||
|
||||
// SourcesStore mock allows all functions to be set for testing
|
||||
type SourcesStore struct {
|
||||
AllF func(context.Context) ([]chronograf.Source, error)
|
||||
AddF func(context.Context, chronograf.Source) (chronograf.Source, error)
|
||||
DeleteF func(context.Context, chronograf.Source) error
|
||||
GetF func(ctx context.Context, ID int) (chronograf.Source, error)
|
||||
UpdateF func(context.Context, chronograf.Source) error
|
||||
}
|
||||
|
||||
// All returns all sources in the store
|
||||
func (s *SourcesStore) All(ctx context.Context) ([]chronograf.Source, error) {
|
||||
return s.AllF(ctx)
|
||||
}
|
||||
|
||||
// Add creates a new source in the SourcesStore and returns Source with ID
|
||||
func (s *SourcesStore) Add(ctx context.Context, src chronograf.Source) (chronograf.Source, error) {
|
||||
return s.AddF(ctx, src)
|
||||
}
|
||||
|
||||
// Delete the Source from the store
|
||||
func (s *SourcesStore) Delete(ctx context.Context, src chronograf.Source) error {
|
||||
return s.DeleteF(ctx, src)
|
||||
}
|
||||
|
||||
// Get retrieves Source if `ID` exists
|
||||
func (s *SourcesStore) Get(ctx context.Context, ID int) (chronograf.Source, error) {
|
||||
return s.GetF(ctx, ID)
|
||||
}
|
||||
|
||||
// Update the Source in the store.
|
||||
func (s *SourcesStore) Update(ctx context.Context, src chronograf.Source) error {
|
||||
return s.UpdateF(ctx, src)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
var _ chronograf.TimeSeries = &TimeSeries{}
|
||||
|
||||
// TimeSeries is a mockable chronograf time series by overriding the functions.
|
||||
type TimeSeries struct {
|
||||
// Query retrieves time series data from the database.
|
||||
QueryF func(context.Context, chronograf.Query) (chronograf.Response, error)
|
||||
// Connect will connect to the time series using the information in `Source`.
|
||||
ConnectF func(context.Context, *chronograf.Source) error
|
||||
// UsersStore represents the user accounts within the TimeSeries database
|
||||
UsersF func(context.Context) chronograf.UsersStore
|
||||
// Allowances returns all valid names permissions in this database
|
||||
AllowancesF func(context.Context) chronograf.Allowances
|
||||
}
|
||||
|
||||
// Query retrieves time series data from the database.
|
||||
func (t *TimeSeries) Query(ctx context.Context, query chronograf.Query) (chronograf.Response, error) {
|
||||
return t.QueryF(ctx, query)
|
||||
}
|
||||
|
||||
// Connect will connect to the time series using the information in `Source`.
|
||||
func (t *TimeSeries) Connect(ctx context.Context, src *chronograf.Source) error {
|
||||
return t.ConnectF(ctx, src)
|
||||
}
|
||||
|
||||
// Users represents the user accounts within the TimeSeries database
|
||||
func (t *TimeSeries) Users(ctx context.Context) chronograf.UsersStore {
|
||||
return t.UsersF(ctx)
|
||||
}
|
||||
|
||||
// Allowances returns all valid names permissions in this database
|
||||
func (t *TimeSeries) Allowances(ctx context.Context) chronograf.Allowances {
|
||||
return t.AllowancesF(ctx)
|
||||
}
|
|
@ -6,6 +6,8 @@ import (
|
|||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
var _ chronograf.UsersStore = &UsersStore{}
|
||||
|
||||
// UsersStore mock allows all functions to be set for testing
|
||||
type UsersStore struct {
|
||||
AllF func(context.Context) ([]chronograf.User, error)
|
||||
|
|
|
@ -40,8 +40,8 @@ type sourceUser struct {
|
|||
Links sourceUserLinks `json:"links"` // Links are URI locations related to user
|
||||
}
|
||||
|
||||
// NewSourceUser creates a new user in the InfluxDB data source
|
||||
func NewSourceUser(srcID int, name string, perms chronograf.Permissions) sourceUser {
|
||||
// newSourceUser creates a new user in the InfluxDB data source
|
||||
func newSourceUser(srcID int, name string, perms chronograf.Permissions) sourceUser {
|
||||
u := &url.URL{Path: name}
|
||||
encodedUser := u.String()
|
||||
httpAPISrcs := "/chronograf/v1/sources"
|
||||
|
@ -88,7 +88,7 @@ func (h *Service) NewSourceUser(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
su := NewSourceUser(srcID, res.Name, req.Permissions)
|
||||
su := newSourceUser(srcID, res.Name, req.Permissions)
|
||||
w.Header().Add("Location", su.Links.Self)
|
||||
encodeJSON(w, http.StatusCreated, su, h.Logger)
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ func (h *Service) SourceUsers(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
su := []sourceUser{}
|
||||
for _, u := range users {
|
||||
su = append(su, NewSourceUser(srcID, u.Name, u.Permissions))
|
||||
su = append(su, newSourceUser(srcID, u.Name, u.Permissions))
|
||||
}
|
||||
|
||||
res := sourceUsers{
|
||||
|
@ -140,7 +140,7 @@ func (h *Service) SourceUserID(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
res := NewSourceUser(srcID, u.Name, u.Permissions)
|
||||
res := newSourceUser(srcID, u.Name, u.Permissions)
|
||||
encodeJSON(w, http.StatusOK, res, h.Logger)
|
||||
}
|
||||
|
||||
|
@ -192,9 +192,9 @@ func (h *Service) UpdateSourceUser(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
su := NewSourceUser(srcID, user.Name, user.Permissions)
|
||||
su := newSourceUser(srcID, user.Name, user.Permissions)
|
||||
w.Header().Add("Location", su.Links.Self)
|
||||
encodeJSON(w, http.StatusCreated, su, h.Logger)
|
||||
encodeJSON(w, http.StatusOK, su, h.Logger)
|
||||
}
|
||||
|
||||
func (h *Service) sourceUsersStore(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, chronograf.UsersStore, error) {
|
||||
|
@ -246,11 +246,16 @@ func (h *Service) Permissions(w http.ResponseWriter, r *http.Request) {
|
|||
Error(w, http.StatusBadRequest, err.Error(), h.Logger)
|
||||
return
|
||||
}
|
||||
|
||||
httpAPISrcs := "/chronograf/v1/sources"
|
||||
res := struct {
|
||||
Permissions chronograf.Allowances `json:"permissions"`
|
||||
Links map[string]string `json:"links"` // Links are URI locations related to user
|
||||
}{
|
||||
Permissions: perms,
|
||||
Links: map[string]string{
|
||||
"self": fmt.Sprintf("%s/%d/permissions", httpAPISrcs, srcID),
|
||||
"source": fmt.Sprintf("%s/%d", httpAPISrcs, srcID),
|
||||
},
|
||||
}
|
||||
encodeJSON(w, http.StatusOK, res, h.Logger)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,797 @@
|
|||
package server_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/bouk/httprouter"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
"github.com/influxdata/chronograf/log"
|
||||
"github.com/influxdata/chronograf/mocks"
|
||||
"github.com/influxdata/chronograf/server"
|
||||
)
|
||||
|
||||
func TestService_NewSourceUser(t *testing.T) {
|
||||
type fields struct {
|
||||
SourcesStore chronograf.SourcesStore
|
||||
TimeSeries chronograf.TimeSeries
|
||||
Logger chronograf.Logger
|
||||
UseAuth bool
|
||||
}
|
||||
type args struct {
|
||||
w *httptest.ResponseRecorder
|
||||
r *http.Request
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
ID string
|
||||
wantStatus int
|
||||
wantContentType string
|
||||
wantBody string
|
||||
}{
|
||||
{
|
||||
name: "New user for data source",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"POST",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
ioutil.NopCloser(
|
||||
bytes.NewReader([]byte(`{"username": "marty", "password": "the_lake"}`)))),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, ID int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "muh source",
|
||||
Username: "username",
|
||||
Password: "hunter2",
|
||||
URL: "http://localhost:8086",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
TimeSeries: &mocks.TimeSeries{
|
||||
ConnectF: func(ctx context.Context, src *chronograf.Source) error {
|
||||
return nil
|
||||
},
|
||||
UsersF: func(ctx context.Context) chronograf.UsersStore {
|
||||
return &mocks.UsersStore{
|
||||
AddF: func(ctx context.Context, u *chronograf.User) (*chronograf.User, error) {
|
||||
return u, nil
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "1",
|
||||
wantStatus: http.StatusCreated,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"username":"marty","links":{"self":"/chronograf/v1/sources/1/users/marty"}}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "Error adding user",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"POST",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
ioutil.NopCloser(
|
||||
bytes.NewReader([]byte(`{"username": "marty", "password": "the_lake"}`)))),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, ID int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "muh source",
|
||||
Username: "username",
|
||||
Password: "hunter2",
|
||||
URL: "http://localhost:8086",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
TimeSeries: &mocks.TimeSeries{
|
||||
ConnectF: func(ctx context.Context, src *chronograf.Source) error {
|
||||
return nil
|
||||
},
|
||||
UsersF: func(ctx context.Context) chronograf.UsersStore {
|
||||
return &mocks.UsersStore{
|
||||
AddF: func(ctx context.Context, u *chronograf.User) (*chronograf.User, error) {
|
||||
return nil, fmt.Errorf("Weight Has Nothing to Do With It")
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "1",
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"code":400,"message":"Weight Has Nothing to Do With It"}`,
|
||||
},
|
||||
{
|
||||
name: "Failure connecting to user store",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"POST",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
ioutil.NopCloser(
|
||||
bytes.NewReader([]byte(`{"username": "marty", "password": "the_lake"}`)))),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, ID int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "muh source",
|
||||
Username: "username",
|
||||
Password: "hunter2",
|
||||
URL: "http://localhost:8086",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
TimeSeries: &mocks.TimeSeries{
|
||||
ConnectF: func(ctx context.Context, src *chronograf.Source) error {
|
||||
return fmt.Errorf("Biff just happens to be my supervisor")
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "1",
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"code":400,"message":"Unable to connect to source 1"}`,
|
||||
},
|
||||
{
|
||||
name: "Failure getting source",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"POST",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
ioutil.NopCloser(
|
||||
bytes.NewReader([]byte(`{"username": "marty", "password": "the_lake"}`)))),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, ID int) (chronograf.Source, error) {
|
||||
return chronograf.Source{}, fmt.Errorf("No McFly ever amounted to anything in the history of Hill Valley")
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "1",
|
||||
wantStatus: http.StatusNotFound,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"code":404,"message":"ID 1 not found"}`,
|
||||
},
|
||||
{
|
||||
name: "Bad ID",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"POST",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
ioutil.NopCloser(
|
||||
bytes.NewReader([]byte(`{"username": "marty", "password": "the_lake"}`)))),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
},
|
||||
ID: "BAD",
|
||||
wantStatus: http.StatusUnprocessableEntity,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"code":422,"message":"Error converting ID BAD"}`,
|
||||
},
|
||||
{
|
||||
name: "Bad username",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"POST",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
ioutil.NopCloser(
|
||||
bytes.NewReader([]byte(`{"password": "the_lake"}`)))),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
},
|
||||
ID: "BAD",
|
||||
wantStatus: http.StatusUnprocessableEntity,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"code":422,"message":"Username required"}`,
|
||||
},
|
||||
{
|
||||
name: "Bad JSON",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"POST",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
ioutil.NopCloser(
|
||||
bytes.NewReader([]byte(`{password}`)))),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
},
|
||||
ID: "BAD",
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"code":400,"message":"Unparsable JSON"}`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt.args.r = tt.args.r.WithContext(httprouter.WithParams(
|
||||
context.Background(),
|
||||
httprouter.Params{
|
||||
{
|
||||
Key: "id",
|
||||
Value: tt.ID,
|
||||
},
|
||||
}))
|
||||
|
||||
h := &server.Service{
|
||||
SourcesStore: tt.fields.SourcesStore,
|
||||
TimeSeries: tt.fields.TimeSeries,
|
||||
Logger: tt.fields.Logger,
|
||||
UseAuth: tt.fields.UseAuth,
|
||||
}
|
||||
|
||||
h.NewSourceUser(tt.args.w, tt.args.r)
|
||||
|
||||
resp := tt.args.w.Result()
|
||||
content := resp.Header.Get("Content-Type")
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if resp.StatusCode != tt.wantStatus {
|
||||
t.Errorf("%q. NewSourceUser() = %v, want %v", tt.name, resp.StatusCode, tt.wantStatus)
|
||||
}
|
||||
if tt.wantContentType != "" && content != tt.wantContentType {
|
||||
t.Errorf("%q. NewSourceUser() = %v, want %v", tt.name, content, tt.wantContentType)
|
||||
}
|
||||
if tt.wantBody != "" && string(body) != tt.wantBody {
|
||||
t.Errorf("%q. NewSourceUser() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), tt.wantBody)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_SourceUsers(t *testing.T) {
|
||||
type fields struct {
|
||||
SourcesStore chronograf.SourcesStore
|
||||
TimeSeries chronograf.TimeSeries
|
||||
Logger chronograf.Logger
|
||||
UseAuth bool
|
||||
}
|
||||
type args struct {
|
||||
w *httptest.ResponseRecorder
|
||||
r *http.Request
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
ID string
|
||||
wantStatus int
|
||||
wantContentType string
|
||||
wantBody string
|
||||
}{
|
||||
{
|
||||
name: "All users for data source",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"GET",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
nil),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, ID int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "muh source",
|
||||
Username: "username",
|
||||
Password: "hunter2",
|
||||
URL: "http://localhost:8086",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
TimeSeries: &mocks.TimeSeries{
|
||||
ConnectF: func(ctx context.Context, src *chronograf.Source) error {
|
||||
return nil
|
||||
},
|
||||
UsersF: func(ctx context.Context) chronograf.UsersStore {
|
||||
return &mocks.UsersStore{
|
||||
AllF: func(ctx context.Context) ([]chronograf.User, error) {
|
||||
return []chronograf.User{
|
||||
{
|
||||
Name: "strickland",
|
||||
Passwd: "discipline",
|
||||
Permissions: chronograf.Permissions{
|
||||
{
|
||||
Scope: chronograf.AllScope,
|
||||
Allowed: chronograf.Allowances{"READ"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "1",
|
||||
wantStatus: http.StatusOK,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"users":[{"username":"strickland","permissions":[{"scope":"all","allowed":["READ"]}],"links":{"self":"/chronograf/v1/sources/1/users/strickland"}}]}
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt.args.r = tt.args.r.WithContext(httprouter.WithParams(
|
||||
context.Background(),
|
||||
httprouter.Params{
|
||||
{
|
||||
Key: "id",
|
||||
Value: tt.ID,
|
||||
},
|
||||
}))
|
||||
h := &server.Service{
|
||||
SourcesStore: tt.fields.SourcesStore,
|
||||
TimeSeries: tt.fields.TimeSeries,
|
||||
Logger: tt.fields.Logger,
|
||||
UseAuth: tt.fields.UseAuth,
|
||||
}
|
||||
|
||||
h.SourceUsers(tt.args.w, tt.args.r)
|
||||
resp := tt.args.w.Result()
|
||||
content := resp.Header.Get("Content-Type")
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if resp.StatusCode != tt.wantStatus {
|
||||
t.Errorf("%q. SourceUsers() = %v, want %v", tt.name, resp.StatusCode, tt.wantStatus)
|
||||
}
|
||||
if tt.wantContentType != "" && content != tt.wantContentType {
|
||||
t.Errorf("%q. SourceUsers() = %v, want %v", tt.name, content, tt.wantContentType)
|
||||
}
|
||||
if tt.wantBody != "" && string(body) != tt.wantBody {
|
||||
t.Errorf("%q. SourceUsers() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), tt.wantBody)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_SourceUserID(t *testing.T) {
|
||||
type fields struct {
|
||||
SourcesStore chronograf.SourcesStore
|
||||
TimeSeries chronograf.TimeSeries
|
||||
Logger chronograf.Logger
|
||||
UseAuth bool
|
||||
}
|
||||
type args struct {
|
||||
w *httptest.ResponseRecorder
|
||||
r *http.Request
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
ID string
|
||||
UID string
|
||||
wantStatus int
|
||||
wantContentType string
|
||||
wantBody string
|
||||
}{
|
||||
{
|
||||
name: "Single user for data source",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"GET",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
nil),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, ID int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "muh source",
|
||||
Username: "username",
|
||||
Password: "hunter2",
|
||||
URL: "http://localhost:8086",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
TimeSeries: &mocks.TimeSeries{
|
||||
ConnectF: func(ctx context.Context, src *chronograf.Source) error {
|
||||
return nil
|
||||
},
|
||||
UsersF: func(ctx context.Context) chronograf.UsersStore {
|
||||
return &mocks.UsersStore{
|
||||
GetF: func(ctx context.Context, uid string) (*chronograf.User, error) {
|
||||
return &chronograf.User{
|
||||
Name: "strickland",
|
||||
Passwd: "discipline",
|
||||
Permissions: chronograf.Permissions{
|
||||
{
|
||||
Scope: chronograf.AllScope,
|
||||
Allowed: chronograf.Allowances{"READ"},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "1",
|
||||
UID: "strickland",
|
||||
wantStatus: http.StatusOK,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"username":"strickland","permissions":[{"scope":"all","allowed":["READ"]}],"links":{"self":"/chronograf/v1/sources/1/users/strickland"}}
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt.args.r = tt.args.r.WithContext(httprouter.WithParams(
|
||||
context.Background(),
|
||||
httprouter.Params{
|
||||
{
|
||||
Key: "id",
|
||||
Value: tt.ID,
|
||||
},
|
||||
}))
|
||||
h := &server.Service{
|
||||
SourcesStore: tt.fields.SourcesStore,
|
||||
TimeSeries: tt.fields.TimeSeries,
|
||||
Logger: tt.fields.Logger,
|
||||
UseAuth: tt.fields.UseAuth,
|
||||
}
|
||||
|
||||
h.SourceUserID(tt.args.w, tt.args.r)
|
||||
resp := tt.args.w.Result()
|
||||
content := resp.Header.Get("Content-Type")
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if resp.StatusCode != tt.wantStatus {
|
||||
t.Errorf("%q. SourceUserID() = %v, want %v", tt.name, resp.StatusCode, tt.wantStatus)
|
||||
}
|
||||
if tt.wantContentType != "" && content != tt.wantContentType {
|
||||
t.Errorf("%q. SourceUserID() = %v, want %v", tt.name, content, tt.wantContentType)
|
||||
}
|
||||
if tt.wantBody != "" && string(body) != tt.wantBody {
|
||||
t.Errorf("%q. SourceUserID() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), tt.wantBody)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_RemoveSourceUser(t *testing.T) {
|
||||
type fields struct {
|
||||
SourcesStore chronograf.SourcesStore
|
||||
TimeSeries chronograf.TimeSeries
|
||||
Logger chronograf.Logger
|
||||
UseAuth bool
|
||||
}
|
||||
type args struct {
|
||||
w *httptest.ResponseRecorder
|
||||
r *http.Request
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
ID string
|
||||
UID string
|
||||
wantStatus int
|
||||
wantContentType string
|
||||
wantBody string
|
||||
}{
|
||||
{
|
||||
name: "Delete user for data source",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"GET",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
nil),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, ID int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "muh source",
|
||||
Username: "username",
|
||||
Password: "hunter2",
|
||||
URL: "http://localhost:8086",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
TimeSeries: &mocks.TimeSeries{
|
||||
ConnectF: func(ctx context.Context, src *chronograf.Source) error {
|
||||
return nil
|
||||
},
|
||||
UsersF: func(ctx context.Context) chronograf.UsersStore {
|
||||
return &mocks.UsersStore{
|
||||
DeleteF: func(ctx context.Context, u *chronograf.User) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "1",
|
||||
UID: "strickland",
|
||||
wantStatus: http.StatusNoContent,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt.args.r = tt.args.r.WithContext(httprouter.WithParams(
|
||||
context.Background(),
|
||||
httprouter.Params{
|
||||
{
|
||||
Key: "id",
|
||||
Value: tt.ID,
|
||||
},
|
||||
}))
|
||||
h := &server.Service{
|
||||
SourcesStore: tt.fields.SourcesStore,
|
||||
TimeSeries: tt.fields.TimeSeries,
|
||||
Logger: tt.fields.Logger,
|
||||
UseAuth: tt.fields.UseAuth,
|
||||
}
|
||||
h.RemoveSourceUser(tt.args.w, tt.args.r)
|
||||
resp := tt.args.w.Result()
|
||||
content := resp.Header.Get("Content-Type")
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if resp.StatusCode != tt.wantStatus {
|
||||
t.Errorf("%q. RemoveSourceUser() = %v, want %v", tt.name, resp.StatusCode, tt.wantStatus)
|
||||
}
|
||||
if tt.wantContentType != "" && content != tt.wantContentType {
|
||||
t.Errorf("%q. RemoveSourceUser() = %v, want %v", tt.name, content, tt.wantContentType)
|
||||
}
|
||||
if tt.wantBody != "" && string(body) != tt.wantBody {
|
||||
t.Errorf("%q. RemoveSourceUser() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), tt.wantBody)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_UpdateSourceUser(t *testing.T) {
|
||||
type fields struct {
|
||||
SourcesStore chronograf.SourcesStore
|
||||
TimeSeries chronograf.TimeSeries
|
||||
Logger chronograf.Logger
|
||||
UseAuth bool
|
||||
}
|
||||
type args struct {
|
||||
w *httptest.ResponseRecorder
|
||||
r *http.Request
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
ID string
|
||||
UID string
|
||||
wantStatus int
|
||||
wantContentType string
|
||||
wantBody string
|
||||
}{
|
||||
{
|
||||
name: "Update user password for data source",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"POST",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
ioutil.NopCloser(
|
||||
bytes.NewReader([]byte(`{"username": "marty", "password": "the_lake"}`)))),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, ID int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "muh source",
|
||||
Username: "username",
|
||||
Password: "hunter2",
|
||||
URL: "http://localhost:8086",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
TimeSeries: &mocks.TimeSeries{
|
||||
ConnectF: func(ctx context.Context, src *chronograf.Source) error {
|
||||
return nil
|
||||
},
|
||||
UsersF: func(ctx context.Context) chronograf.UsersStore {
|
||||
return &mocks.UsersStore{
|
||||
UpdateF: func(ctx context.Context, u *chronograf.User) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "1",
|
||||
UID: "marty",
|
||||
wantStatus: http.StatusOK,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"username":"marty","links":{"self":"/chronograf/v1/sources/1/users/marty"}}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "Invalid update JSON",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"POST",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
ioutil.NopCloser(
|
||||
bytes.NewReader([]byte(`{"username": "marty"}`)))),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
},
|
||||
ID: "1",
|
||||
UID: "marty",
|
||||
wantStatus: http.StatusUnprocessableEntity,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"code":422,"message":"No fields to update"}`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt.args.r = tt.args.r.WithContext(httprouter.WithParams(
|
||||
context.Background(),
|
||||
httprouter.Params{
|
||||
{
|
||||
Key: "id",
|
||||
Value: tt.ID,
|
||||
},
|
||||
{
|
||||
Key: "uid",
|
||||
Value: tt.UID,
|
||||
},
|
||||
}))
|
||||
h := &server.Service{
|
||||
SourcesStore: tt.fields.SourcesStore,
|
||||
TimeSeries: tt.fields.TimeSeries,
|
||||
Logger: tt.fields.Logger,
|
||||
UseAuth: tt.fields.UseAuth,
|
||||
}
|
||||
h.UpdateSourceUser(tt.args.w, tt.args.r)
|
||||
resp := tt.args.w.Result()
|
||||
content := resp.Header.Get("Content-Type")
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if resp.StatusCode != tt.wantStatus {
|
||||
t.Errorf("%q. UpdateSourceUser() = %v, want %v", tt.name, resp.StatusCode, tt.wantStatus)
|
||||
}
|
||||
if tt.wantContentType != "" && content != tt.wantContentType {
|
||||
t.Errorf("%q. UpdateSourceUser() = %v, want %v", tt.name, content, tt.wantContentType)
|
||||
}
|
||||
if tt.wantBody != "" && string(body) != tt.wantBody {
|
||||
t.Errorf("%q. UpdateSourceUser() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), tt.wantBody)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_Permissions(t *testing.T) {
|
||||
type fields struct {
|
||||
SourcesStore chronograf.SourcesStore
|
||||
TimeSeries chronograf.TimeSeries
|
||||
Logger chronograf.Logger
|
||||
UseAuth bool
|
||||
}
|
||||
type args struct {
|
||||
w *httptest.ResponseRecorder
|
||||
r *http.Request
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
ID string
|
||||
wantStatus int
|
||||
wantContentType string
|
||||
wantBody string
|
||||
}{
|
||||
{
|
||||
name: "New user for data source",
|
||||
args: args{
|
||||
w: httptest.NewRecorder(),
|
||||
r: httptest.NewRequest(
|
||||
"POST",
|
||||
"http://server.local/chronograf/v1/sources/1",
|
||||
ioutil.NopCloser(
|
||||
bytes.NewReader([]byte(`{"username": "marty", "password": "the_lake"}`)))),
|
||||
},
|
||||
fields: fields{
|
||||
UseAuth: true,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
GetF: func(ctx context.Context, ID int) (chronograf.Source, error) {
|
||||
return chronograf.Source{
|
||||
ID: 1,
|
||||
Name: "muh source",
|
||||
Username: "username",
|
||||
Password: "hunter2",
|
||||
URL: "http://localhost:8086",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
TimeSeries: &mocks.TimeSeries{
|
||||
ConnectF: func(ctx context.Context, src *chronograf.Source) error {
|
||||
return nil
|
||||
},
|
||||
AllowancesF: func(ctx context.Context) chronograf.Allowances {
|
||||
return chronograf.Allowances{"READ", "WRITE"}
|
||||
},
|
||||
},
|
||||
},
|
||||
ID: "1",
|
||||
wantStatus: http.StatusOK,
|
||||
wantContentType: "application/json",
|
||||
wantBody: `{"permissions":["READ","WRITE"],"links":{"self":"/chronograf/v1/sources/1/permissions","source":"/chronograf/v1/sources/1"}}
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt.args.r = tt.args.r.WithContext(httprouter.WithParams(
|
||||
context.Background(),
|
||||
httprouter.Params{
|
||||
{
|
||||
Key: "id",
|
||||
Value: tt.ID,
|
||||
},
|
||||
}))
|
||||
h := &server.Service{
|
||||
SourcesStore: tt.fields.SourcesStore,
|
||||
TimeSeries: tt.fields.TimeSeries,
|
||||
Logger: tt.fields.Logger,
|
||||
UseAuth: tt.fields.UseAuth,
|
||||
}
|
||||
h.Permissions(tt.args.w, tt.args.r)
|
||||
resp := tt.args.w.Result()
|
||||
content := resp.Header.Get("Content-Type")
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
if resp.StatusCode != tt.wantStatus {
|
||||
t.Errorf("%q. Permissions() = %v, want %v", tt.name, resp.StatusCode, tt.wantStatus)
|
||||
}
|
||||
if tt.wantContentType != "" && content != tt.wantContentType {
|
||||
t.Errorf("%q. Permissions() = %v, want %v", tt.name, content, tt.wantContentType)
|
||||
}
|
||||
if tt.wantBody != "" && string(body) != tt.wantBody {
|
||||
t.Errorf("%q. Permissions() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), tt.wantBody)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue