Add multiple dashboard stores to server

pull/2617/head
Chris Goller 2017-12-14 22:53:14 -06:00 committed by Michael Desa
parent b54ed7705c
commit ac41c384f2
6 changed files with 89 additions and 35 deletions

View File

@ -10,7 +10,7 @@ import (
"github.com/boltdb/bolt"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/uuid"
"github.com/influxdata/chronograf/id"
)
const (
@ -51,11 +51,11 @@ func NewClient() *Client {
c.ServersStore = &ServersStore{client: c}
c.LayoutsStore = &LayoutsStore{
client: c,
IDs: &uuid.V4{},
IDs: &id.UUID{},
}
c.DashboardsStore = &DashboardsStore{
client: c,
IDs: &uuid.V4{},
IDs: &id.UUID{},
}
c.UsersStore = &UsersStore{client: c}
c.OrganizationsStore = &OrganizationsStore{client: c}

View File

@ -5,7 +5,7 @@ import (
"fmt"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/uuid"
"github.com/influxdata/chronograf/id"
client "github.com/influxdata/kapacitor/client/v1"
)
@ -44,7 +44,7 @@ func NewClient(url, username, password string, insecureSkipVerify bool) *Client
Username: username,
Password: password,
InsecureSkipVerify: insecureSkipVerify,
ID: &uuid.V4{},
ID: &id.UUID{},
Ticker: &Alert{},
kapaClient: NewKapaClient,
}

View File

@ -43,6 +43,35 @@ func (builder *MultiLayoutBuilder) Build(db chronograf.LayoutsStore) (*multistor
return layouts, nil
}
// DashboardBuilder is responsible for building dashboards
type DashboardBuilder interface {
Build(chronograf.DashboardsStore) (*multistore.DashboardsStore, error)
}
// MultiDashboardBuilder builds a DashboardsStore backed by bolt and the filesystem
type MultiDashboardBuilder struct {
Logger chronograf.Logger
ID chronograf.ID
Path string
}
// Build will construct a Dashboard store of filesystem and db-backed dashboards
func (builder *MultiDashboardBuilder) Build(db chronograf.DashboardsStore) (*multistore.DashboardsStore, error) {
// These dashboards are those handled from a directory
files := filestore.NewDashboards(builder.Path, builder.ID, builder.Logger)
// Acts as a front-end to both the bolt dashboard and filesystem dashboards.
// The idea here is that these stores form a hierarchy in which each is tried sequentially until
// the operation has success. So, the database is preferred over filesystem
dashboards := &multistore.DashboardsStore{
Stores: []chronograf.DashboardsStore{
db,
files,
},
}
return dashboards, nil
}
// SourcesBuilder builds a MultiSourceStore
type SourcesBuilder interface {
Build(chronograf.SourcesStore) (*multistore.SourcesStore, error)

View File

@ -7,7 +7,7 @@ import (
"github.com/bouk/httprouter"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/uuid"
idgen "github.com/influxdata/chronograf/id"
)
const (
@ -210,7 +210,7 @@ func (s *Service) NewDashboardCell(w http.ResponseWriter, r *http.Request) {
return
}
ids := uuid.V4{}
ids := &idgen.UUID{}
cid, err := ids.Generate()
if err != nil {
msg := fmt.Sprintf("Error creating cell ID of dashboard %d: %v", id, err)

View File

@ -16,10 +16,10 @@ import (
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/bolt"
idgen "github.com/influxdata/chronograf/id"
"github.com/influxdata/chronograf/influx"
clog "github.com/influxdata/chronograf/log"
"github.com/influxdata/chronograf/oauth2"
"github.com/influxdata/chronograf/uuid"
client "github.com/influxdata/usage-client/v1"
flags "github.com/jessevdk/go-flags"
"github.com/tylerb/graceful"
@ -122,6 +122,7 @@ func (s *Server) UseHeroku() bool {
return s.TokenSecret != "" && s.HerokuClientID != "" && s.HerokuSecret != ""
}
// UseAuth0 validates the CLI parameters to enable Auth0 oauth support
func (s *Server) UseAuth0() bool {
return s.Auth0ClientID != "" && s.Auth0ClientSecret != ""
}
@ -269,24 +270,41 @@ func (s *Server) NewListener() (net.Listener, error) {
return listener, nil
}
type builders struct {
Layouts LayoutBuilder
Sources SourcesBuilder
Kapacitors KapacitorBuilder
Dashboards DashboardBuilder
}
func (s *Server) newBuilders(logger chronograf.Logger) builders {
return builders{
Layouts: &MultiLayoutBuilder{
Logger: logger,
UUID: &idgen.UUID{},
CannedPath: s.CannedPath,
},
Dashboards: &MultiDashboardBuilder{
Logger: logger,
ID: idgen.NewTime(),
Path: s.CannedPath,
},
Sources: &MultiSourceBuilder{
InfluxDBURL: s.InfluxDBURL,
InfluxDBUsername: s.InfluxDBUsername,
InfluxDBPassword: s.InfluxDBPassword,
},
Kapacitors: &MultiKapacitorBuilder{
KapacitorURL: s.KapacitorURL,
KapacitorUsername: s.KapacitorUsername,
KapacitorPassword: s.KapacitorPassword,
},
}
}
// Serve starts and runs the chronograf server
func (s *Server) Serve(ctx context.Context) error {
logger := clog.New(clog.ParseLevel(s.LogLevel))
layoutBuilder := &MultiLayoutBuilder{
Logger: logger,
UUID: &uuid.V4{},
CannedPath: s.CannedPath,
}
sourcesBuilder := &MultiSourceBuilder{
InfluxDBURL: s.InfluxDBURL,
InfluxDBUsername: s.InfluxDBUsername,
InfluxDBPassword: s.InfluxDBPassword,
}
kapacitorBuilder := &MultiKapacitorBuilder{
KapacitorURL: s.KapacitorURL,
KapacitorUsername: s.KapacitorUsername,
KapacitorPassword: s.KapacitorPassword,
}
_, err := NewCustomLinks(s.CustomLinks)
if err != nil {
logger.
@ -295,7 +313,7 @@ func (s *Server) Serve(ctx context.Context) error {
Error(err)
return err
}
service := openService(ctx, s, layoutBuilder, sourcesBuilder, kapacitorBuilder, logger)
service := openService(ctx, s.BuildInfo, s.BoltPath, s.newBuilders(logger), logger, s.useAuth())
if err := service.HandleNewSources(ctx, s.NewSources); err != nil {
logger.
WithField("component", "server").
@ -390,18 +408,18 @@ func (s *Server) Serve(ctx context.Context) error {
return nil
}
func openService(ctx context.Context, s *Server, lBuilder LayoutBuilder, sBuilder SourcesBuilder, kapBuilder KapacitorBuilder, logger chronograf.Logger) Service {
func openService(ctx context.Context, buildInfo chronograf.BuildInfo, boltPath string, builder builders, logger chronograf.Logger, useAuth bool) Service {
db := bolt.NewClient()
db.Path = s.BoltPath
db.Path = boltPath
if err := db.Open(ctx, logger, s.BuildInfo, bolt.WithBackup()); err != nil {
if err := db.Open(ctx, logger, buildInfo, bolt.WithBackup()); err != nil {
logger.
WithField("component", "boltstore").
Error(err)
os.Exit(1)
}
layouts, err := lBuilder.Build(db.LayoutsStore)
layouts, err := builder.Layouts.Build(db.LayoutsStore)
if err != nil {
logger.
WithField("component", "LayoutsStore").
@ -409,7 +427,14 @@ func openService(ctx context.Context, s *Server, lBuilder LayoutBuilder, sBuilde
os.Exit(1)
}
sources, err := sBuilder.Build(db.SourcesStore)
dashboards, err := builder.Dashboards.Build(db.DashboardsStore)
if err != nil {
logger.
WithField("component", "DashboardsStore").
Error("Unable to construct a MultiDashboardsStore", err)
os.Exit(1)
}
sources, err := builder.Sources.Build(db.SourcesStore)
if err != nil {
logger.
WithField("component", "SourcesStore").
@ -417,7 +442,7 @@ func openService(ctx context.Context, s *Server, lBuilder LayoutBuilder, sBuilde
os.Exit(1)
}
kapacitors, err := kapBuilder.Build(db.ServersStore)
kapacitors, err := builder.Kapacitors.Build(db.ServersStore)
if err != nil {
logger.
WithField("component", "KapacitorStore").
@ -428,16 +453,16 @@ func openService(ctx context.Context, s *Server, lBuilder LayoutBuilder, sBuilde
return Service{
TimeSeriesClient: &InfluxClient{},
Store: &Store{
LayoutsStore: layouts,
DashboardsStore: dashboards,
SourcesStore: sources,
ServersStore: kapacitors,
UsersStore: db.UsersStore,
OrganizationsStore: db.OrganizationsStore,
LayoutsStore: layouts,
DashboardsStore: db.DashboardsStore,
ConfigStore: db.ConfigStore,
},
Logger: logger,
UseAuth: s.useAuth(),
UseAuth: useAuth,
Databases: &influx.Client{Logger: logger},
}
}

View File

@ -7,7 +7,7 @@ import (
"github.com/bouk/httprouter"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/uuid"
idgen "github.com/influxdata/chronograf/id"
)
// ValidTemplateRequest checks if the request sent to the server is the correct format.
@ -111,7 +111,7 @@ func (s *Service) NewTemplate(w http.ResponseWriter, r *http.Request) {
return
}
ids := uuid.V4{}
ids := idgen.UUID{}
tid, err := ids.Generate()
if err != nil {
msg := fmt.Sprintf("Error creating template ID for dashboard %d: %v", id, err)