From a4a5b53bf51d0bee2a1af1b9329c6491e5de7798 Mon Sep 17 00:00:00 2001 From: Chris Goller Date: Thu, 23 Feb 2017 21:54:20 -0600 Subject: [PATCH] Add roles endpoint and switching between OSS and enterprise --- enterprise/enterprise.go | 22 +++++++- enterprise/enterprise_test.go | 14 +++-- mocks/timeseries.go | 5 ++ server/admin.go | 58 ++++++++++++-------- server/admin_test.go | 100 +++++++++++++++++----------------- server/influx.go | 11 +++- server/mux.go | 8 +++ server/server.go | 21 +++---- server/service.go | 47 ++++++++++++---- 9 files changed, 183 insertions(+), 103 deletions(-) diff --git a/enterprise/enterprise.go b/enterprise/enterprise.go index a2fe5178a..0df064057 100644 --- a/enterprise/enterprise.go +++ b/enterprise/enterprise.go @@ -47,8 +47,24 @@ type Client struct { } // NewClientWithTimeSeries initializes a Client with a known set of TimeSeries. -func NewClientWithTimeSeries(lg chronograf.Logger, series ...chronograf.TimeSeries) *Client { - c := &Client{} +func NewClientWithTimeSeries(lg chronograf.Logger, mu, username, password string, tls bool, series ...chronograf.TimeSeries) (*Client, error) { + metaURL, err := parseMetaURL(mu, tls) + if err != nil { + return nil, err + } + metaURL.User = url.UserPassword(username, password) + ctrl := NewMetaClient(metaURL) + c := &Client{ + Ctrl: ctrl, + UsersStore: &UserStore{ + Ctrl: ctrl, + Logger: lg, + }, + RolesStore: &RolesStore{ + Ctrl: ctrl, + Logger: lg, + }, + } c.dataNodes = ring.New(len(series)) @@ -57,7 +73,7 @@ func NewClientWithTimeSeries(lg chronograf.Logger, series ...chronograf.TimeSeri c.dataNodes = c.dataNodes.Next() } - return c + return c, nil } // NewClientWithURL initializes an Enterprise client with a URL to a Meta Node. diff --git a/enterprise/enterprise_test.go b/enterprise/enterprise_test.go index 260dca712..f26560ddb 100644 --- a/enterprise/enterprise_test.go +++ b/enterprise/enterprise_test.go @@ -75,9 +75,12 @@ func Test_Enterprise_IssuesQueries(t *testing.T) { func Test_Enterprise_AdvancesDataNodes(t *testing.T) { m1 := NewMockTimeSeries("http://host-1.example.com:8086") m2 := NewMockTimeSeries("http://host-2.example.com:8086") - cl := enterprise.NewClientWithTimeSeries(log.New(log.DebugLevel), chronograf.TimeSeries(m1), chronograf.TimeSeries(m2)) + cl, err := enterprise.NewClientWithTimeSeries(log.New(log.DebugLevel), "http://meta.example.com:8091", "marty", "thelake", false, chronograf.TimeSeries(m1), chronograf.TimeSeries(m2)) + if err != nil { + t.Error("Unexpected error while initializing client: err:", err) + } - err := cl.Connect(context.Background(), &chronograf.Source{}) + err = cl.Connect(context.Background(), &chronograf.Source{}) if err != nil { t.Error("Unexpected error while initializing client: err:", err) } @@ -132,8 +135,11 @@ func Test_Enterprise_NewClientWithURL(t *testing.T) { func Test_Enterprise_ComplainsIfNotOpened(t *testing.T) { m1 := NewMockTimeSeries("http://host-1.example.com:8086") - cl := enterprise.NewClientWithTimeSeries(log.New(log.DebugLevel), chronograf.TimeSeries(m1)) - _, err := cl.Query(context.Background(), chronograf.Query{Command: "show shards", DB: "_internal", RP: "autogen"}) + cl, err := enterprise.NewClientWithTimeSeries(log.New(log.DebugLevel), "http://meta.example.com:8091", "docbrown", "1.21 gigawatts", false, chronograf.TimeSeries(m1)) + if err != nil { + t.Error("Expected ErrUnitialized, but was this err:", err) + } + _, err = cl.Query(context.Background(), chronograf.Query{Command: "show shards", DB: "_internal", RP: "autogen"}) if err != chronograf.ErrUninitialized { t.Error("Expected ErrUnitialized, but was this err:", err) } diff --git a/mocks/timeseries.go b/mocks/timeseries.go index af4e967d4..064ccc16b 100644 --- a/mocks/timeseries.go +++ b/mocks/timeseries.go @@ -22,6 +22,11 @@ type TimeSeries struct { RolesF func(context.Context) (chronograf.RolesStore, error) } +// New implements TimeSeriesClient +func (t *TimeSeries) New(chronograf.Source, chronograf.Logger) (chronograf.TimeSeries, error) { + return t, nil +} + // 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) diff --git a/server/admin.go b/server/admin.go index 202332715..f39b6d213 100644 --- a/server/admin.go +++ b/server/admin.go @@ -223,40 +223,47 @@ func (h *Service) UpdateSourceUser(w http.ResponseWriter, r *http.Request) { encodeJSON(w, http.StatusOK, su, h.Logger) } -func (h *Service) sourcesSeries(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, error) { +func (h *Service) sourcesSeries(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, chronograf.TimeSeries, error) { srcID, err := paramID("id", r) if err != nil { Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) - return 0, err + return 0, nil, err } src, err := h.SourcesStore.Get(ctx, srcID) if err != nil { notFound(w, srcID, h.Logger) - return 0, err + return 0, nil, err } - if err = h.TimeSeries.Connect(ctx, &src); err != nil { + ts, err := h.TimeSeries(src) + if err != nil { msg := fmt.Sprintf("Unable to connect to source %d", srcID) Error(w, http.StatusBadRequest, msg, h.Logger) - return 0, err + return 0, nil, err } - return srcID, nil + + if err = ts.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d", srcID) + Error(w, http.StatusBadRequest, msg, h.Logger) + return 0, nil, err + } + return srcID, ts, nil } func (h *Service) sourceUsersStore(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, chronograf.UsersStore, error) { - srcID, err := h.sourcesSeries(ctx, w, r) + srcID, ts, err := h.sourcesSeries(ctx, w, r) if err != nil { return 0, nil, err } - store := h.TimeSeries.Users(ctx) + store := ts.Users(ctx) return srcID, store, nil } // hasRoles checks if the influx source has roles or not -func (h *Service) hasRoles(ctx context.Context) (chronograf.RolesStore, bool) { - store, err := h.TimeSeries.Roles(ctx) +func (h *Service) hasRoles(ctx context.Context, ts chronograf.TimeSeries) (chronograf.RolesStore, bool) { + store, err := ts.Roles(ctx) if err != nil { return nil, false } @@ -278,13 +285,20 @@ func (h *Service) Permissions(w http.ResponseWriter, r *http.Request) { return } - if err = h.TimeSeries.Connect(ctx, &src); err != nil { + ts, err := h.TimeSeries(src) + if err != nil { msg := fmt.Sprintf("Unable to connect to source %d", srcID) Error(w, http.StatusBadRequest, msg, h.Logger) return } - perms := h.TimeSeries.Allowances(ctx) + if err = ts.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d", srcID) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + perms := ts.Allowances(ctx) if err != nil { Error(w, http.StatusBadRequest, err.Error(), h.Logger) return @@ -373,12 +387,12 @@ func (h *Service) NewRole(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - srcID, err := h.sourcesSeries(ctx, w, r) + srcID, ts, err := h.sourcesSeries(ctx, w, r) if err != nil { return } - roles, ok := h.hasRoles(ctx) + roles, ok := h.hasRoles(ctx, ts) if !ok { Error(w, http.StatusNotFound, fmt.Sprintf("Source %d does not have role capability", srcID), h.Logger) return @@ -408,12 +422,12 @@ func (h *Service) UpdateRole(w http.ResponseWriter, r *http.Request) { } ctx := r.Context() - srcID, err := h.sourcesSeries(ctx, w, r) + srcID, ts, err := h.sourcesSeries(ctx, w, r) if err != nil { return } - roles, ok := h.hasRoles(ctx) + roles, ok := h.hasRoles(ctx, ts) if !ok { Error(w, http.StatusNotFound, fmt.Sprintf("Source %d does not have role capability", srcID), h.Logger) return @@ -440,12 +454,12 @@ func (h *Service) UpdateRole(w http.ResponseWriter, r *http.Request) { // RoleID retrieves a role with ID from store. func (h *Service) RoleID(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - srcID, err := h.sourcesSeries(ctx, w, r) + srcID, ts, err := h.sourcesSeries(ctx, w, r) if err != nil { return } - roles, ok := h.hasRoles(ctx) + roles, ok := h.hasRoles(ctx, ts) if !ok { Error(w, http.StatusNotFound, fmt.Sprintf("Source %d does not have role capability", srcID), h.Logger) return @@ -464,12 +478,12 @@ func (h *Service) RoleID(w http.ResponseWriter, r *http.Request) { // Roles retrieves all roles from the store func (h *Service) Roles(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - srcID, err := h.sourcesSeries(ctx, w, r) + srcID, ts, err := h.sourcesSeries(ctx, w, r) if err != nil { return } - store, ok := h.hasRoles(ctx) + store, ok := h.hasRoles(ctx, ts) if !ok { Error(w, http.StatusNotFound, fmt.Sprintf("Source %d does not have role capability", srcID), h.Logger) return @@ -495,12 +509,12 @@ func (h *Service) Roles(w http.ResponseWriter, r *http.Request) { // RemoveRole removes role from data source. func (h *Service) RemoveRole(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - srcID, err := h.sourcesSeries(ctx, w, r) + srcID, ts, err := h.sourcesSeries(ctx, w, r) if err != nil { return } - roles, ok := h.hasRoles(ctx) + roles, ok := h.hasRoles(ctx, ts) if !ok { Error(w, http.StatusNotFound, fmt.Sprintf("Source %d does not have role capability", srcID), h.Logger) return diff --git a/server/admin_test.go b/server/admin_test.go index b544198cd..9598f21b0 100644 --- a/server/admin_test.go +++ b/server/admin_test.go @@ -19,7 +19,7 @@ import ( func TestService_NewSourceUser(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger UseAuth bool } @@ -249,10 +249,10 @@ func TestService_NewSourceUser(t *testing.T) { })) h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, - UseAuth: tt.fields.UseAuth, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, + UseAuth: tt.fields.UseAuth, } h.NewSourceUser(tt.args.w, tt.args.r) @@ -276,7 +276,7 @@ func TestService_NewSourceUser(t *testing.T) { func TestService_SourceUsers(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger UseAuth bool } @@ -357,10 +357,10 @@ func TestService_SourceUsers(t *testing.T) { }, })) h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, - UseAuth: tt.fields.UseAuth, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, + UseAuth: tt.fields.UseAuth, } h.SourceUsers(tt.args.w, tt.args.r) @@ -383,7 +383,7 @@ func TestService_SourceUsers(t *testing.T) { func TestService_SourceUserID(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger UseAuth bool } @@ -464,10 +464,10 @@ func TestService_SourceUserID(t *testing.T) { }, })) h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, - UseAuth: tt.fields.UseAuth, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, + UseAuth: tt.fields.UseAuth, } h.SourceUserID(tt.args.w, tt.args.r) @@ -490,7 +490,7 @@ func TestService_SourceUserID(t *testing.T) { func TestService_RemoveSourceUser(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger UseAuth bool } @@ -559,10 +559,10 @@ func TestService_RemoveSourceUser(t *testing.T) { }, })) h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, - UseAuth: tt.fields.UseAuth, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, + UseAuth: tt.fields.UseAuth, } h.RemoveSourceUser(tt.args.w, tt.args.r) resp := tt.args.w.Result() @@ -584,7 +584,7 @@ func TestService_RemoveSourceUser(t *testing.T) { func TestService_UpdateSourceUser(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger UseAuth bool } @@ -681,10 +681,10 @@ func TestService_UpdateSourceUser(t *testing.T) { }, })) h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, - UseAuth: tt.fields.UseAuth, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, + UseAuth: tt.fields.UseAuth, } h.UpdateSourceUser(tt.args.w, tt.args.r) resp := tt.args.w.Result() @@ -706,7 +706,7 @@ func TestService_UpdateSourceUser(t *testing.T) { func TestService_Permissions(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger UseAuth bool } @@ -773,10 +773,10 @@ func TestService_Permissions(t *testing.T) { }, })) h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, - UseAuth: tt.fields.UseAuth, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, + UseAuth: tt.fields.UseAuth, } h.Permissions(tt.args.w, tt.args.r) resp := tt.args.w.Result() @@ -798,7 +798,7 @@ func TestService_Permissions(t *testing.T) { func TestService_NewSourceRole(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger } type args struct { @@ -990,9 +990,9 @@ func TestService_NewSourceRole(t *testing.T) { } for _, tt := range tests { h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, } tt.args.r = tt.args.r.WithContext(httprouter.WithParams( context.Background(), @@ -1024,7 +1024,7 @@ func TestService_NewSourceRole(t *testing.T) { func TestService_UpdateRole(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger } type args struct { @@ -1103,9 +1103,9 @@ func TestService_UpdateRole(t *testing.T) { } for _, tt := range tests { h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, } tt.args.r = tt.args.r.WithContext(httprouter.WithParams( @@ -1142,7 +1142,7 @@ func TestService_UpdateRole(t *testing.T) { func TestService_RoleID(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger } type args struct { @@ -1226,9 +1226,9 @@ func TestService_RoleID(t *testing.T) { } for _, tt := range tests { h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, } tt.args.r = tt.args.r.WithContext(httprouter.WithParams( @@ -1265,7 +1265,7 @@ func TestService_RoleID(t *testing.T) { func TestService_RemoveRole(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger } type args struct { @@ -1322,9 +1322,9 @@ func TestService_RemoveRole(t *testing.T) { } for _, tt := range tests { h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, } tt.args.r = tt.args.r.WithContext(httprouter.WithParams( @@ -1352,7 +1352,7 @@ func TestService_RemoveRole(t *testing.T) { func TestService_Roles(t *testing.T) { type fields struct { SourcesStore chronograf.SourcesStore - TimeSeries chronograf.TimeSeries + TimeSeries server.TimeSeriesClient Logger chronograf.Logger } type args struct { @@ -1434,9 +1434,9 @@ func TestService_Roles(t *testing.T) { } for _, tt := range tests { h := &server.Service{ - SourcesStore: tt.fields.SourcesStore, - TimeSeries: tt.fields.TimeSeries, - Logger: tt.fields.Logger, + SourcesStore: tt.fields.SourcesStore, + TimeSeriesClient: tt.fields.TimeSeries, + Logger: tt.fields.Logger, } tt.args.r = tt.args.r.WithContext(httprouter.WithParams( diff --git a/server/influx.go b/server/influx.go index d61b4a2aa..46d1488ed 100644 --- a/server/influx.go +++ b/server/influx.go @@ -45,13 +45,20 @@ func (h *Service) Influx(w http.ResponseWriter, r *http.Request) { return } - if err = h.TimeSeries.Connect(ctx, &src); err != nil { + ts, err := h.TimeSeries(src) + if err != nil { msg := fmt.Sprintf("Unable to connect to source %d", id) Error(w, http.StatusBadRequest, msg, h.Logger) return } - response, err := h.TimeSeries.Query(ctx, req) + if err = ts.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d", id) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + response, err := ts.Query(ctx, req) if err != nil { if err == chronograf.ErrUpstreamTimeout { msg := "Timeout waiting for Influx response" diff --git a/server/mux.go b/server/mux.go index 892d4f4ca..7c3d1da6b 100644 --- a/server/mux.go +++ b/server/mux.go @@ -80,6 +80,14 @@ func NewMux(opts MuxOpts, service Service) http.Handler { router.DELETE("/chronograf/v1/sources/:id/users/:uid", service.RemoveSourceUser) router.PATCH("/chronograf/v1/sources/:id/users/:uid", service.UpdateSourceUser) + // Roles associated with the data source + router.GET("/chronograf/v1/sources/:id/roles", service.Roles) + router.POST("/chronograf/v1/sources/:id/roles", service.NewRole) + + router.GET("/chronograf/v1/sources/:id/roles/:rid", service.RoleID) + router.DELETE("/chronograf/v1/sources/:id/roles/:rid", service.RemoveRole) + router.PATCH("/chronograf/v1/sources/:id/roles/:rid", service.UpdateRole) + // Kapacitor router.GET("/chronograf/v1/sources/:id/kapacitors", service.Kapacitors) router.POST("/chronograf/v1/sources/:id/kapacitors", service.NewKapacitor) diff --git a/server/server.go b/server/server.go index 247b448c0..ddecda336 100644 --- a/server/server.go +++ b/server/server.go @@ -12,7 +12,6 @@ import ( "github.com/influxdata/chronograf" "github.com/influxdata/chronograf/bolt" "github.com/influxdata/chronograf/canned" - "github.com/influxdata/chronograf/influx" "github.com/influxdata/chronograf/layouts" clog "github.com/influxdata/chronograf/log" "github.com/influxdata/chronograf/uuid" @@ -190,17 +189,15 @@ func openService(boltPath, cannedPath string, logger chronograf.Logger, useAuth } return Service{ - SourcesStore: db.SourcesStore, - ServersStore: db.ServersStore, - UsersStore: db.UsersStore, - TimeSeries: &influx.Client{ - Logger: logger, - }, - LayoutStore: layouts, - DashboardsStore: db.DashboardsStore, - AlertRulesStore: db.AlertsStore, - Logger: logger, - UseAuth: useAuth, + TimeSeriesClient: &InfluxClient{}, + SourcesStore: db.SourcesStore, + ServersStore: db.ServersStore, + UsersStore: db.UsersStore, + LayoutStore: layouts, + DashboardsStore: db.DashboardsStore, + AlertRulesStore: db.AlertsStore, + Logger: logger, + UseAuth: useAuth, } } diff --git a/server/service.go b/server/service.go index 1831484ec..673432945 100644 --- a/server/service.go +++ b/server/service.go @@ -1,18 +1,27 @@ package server -import "github.com/influxdata/chronograf" +import ( + "github.com/influxdata/chronograf" + "github.com/influxdata/chronograf/enterprise" + "github.com/influxdata/chronograf/influx" +) // Service handles REST calls to the persistence type Service struct { - SourcesStore chronograf.SourcesStore - ServersStore chronograf.ServersStore - LayoutStore chronograf.LayoutStore - AlertRulesStore chronograf.AlertRulesStore - UsersStore chronograf.UsersStore - DashboardsStore chronograf.DashboardsStore - TimeSeries chronograf.TimeSeries - Logger chronograf.Logger - UseAuth bool + SourcesStore chronograf.SourcesStore + ServersStore chronograf.ServersStore + LayoutStore chronograf.LayoutStore + AlertRulesStore chronograf.AlertRulesStore + UsersStore chronograf.UsersStore + DashboardsStore chronograf.DashboardsStore + TimeSeriesClient TimeSeriesClient + Logger chronograf.Logger + UseAuth bool +} + +// TimeSeriesClient returns the correct client for a time series database. +type TimeSeriesClient interface { + New(chronograf.Source, chronograf.Logger) (chronograf.TimeSeries, error) } // ErrorMessage is the error response format for all service errors @@ -20,3 +29,21 @@ type ErrorMessage struct { Code int `json:"code"` Message string `json:"message"` } + +// TimeSeries returns a new client connected to a time series database +func (s *Service) TimeSeries(src chronograf.Source) (chronograf.TimeSeries, error) { + return s.TimeSeriesClient.New(src, s.Logger) +} + +// InfluxClient returns a new client to connect to OSS or Enterprise +type InfluxClient struct{} + +// New creates a client to connect to OSS or enterprise +func (c *InfluxClient) New(src chronograf.Source, logger chronograf.Logger) (chronograf.TimeSeries, error) { + if src.Type == "influx-enterprise" { + return enterprise.NewClientWithURL(src.URL, src.Username, src.Password, false, logger) + } + return &influx.Client{ + Logger: logger, + }, nil +}