Add multiple dashboard stores to server
parent
b54ed7705c
commit
ac41c384f2
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
"github.com/influxdata/chronograf"
|
"github.com/influxdata/chronograf"
|
||||||
"github.com/influxdata/chronograf/uuid"
|
"github.com/influxdata/chronograf/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -51,11 +51,11 @@ func NewClient() *Client {
|
||||||
c.ServersStore = &ServersStore{client: c}
|
c.ServersStore = &ServersStore{client: c}
|
||||||
c.LayoutsStore = &LayoutsStore{
|
c.LayoutsStore = &LayoutsStore{
|
||||||
client: c,
|
client: c,
|
||||||
IDs: &uuid.V4{},
|
IDs: &id.UUID{},
|
||||||
}
|
}
|
||||||
c.DashboardsStore = &DashboardsStore{
|
c.DashboardsStore = &DashboardsStore{
|
||||||
client: c,
|
client: c,
|
||||||
IDs: &uuid.V4{},
|
IDs: &id.UUID{},
|
||||||
}
|
}
|
||||||
c.UsersStore = &UsersStore{client: c}
|
c.UsersStore = &UsersStore{client: c}
|
||||||
c.OrganizationsStore = &OrganizationsStore{client: c}
|
c.OrganizationsStore = &OrganizationsStore{client: c}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/influxdata/chronograf"
|
"github.com/influxdata/chronograf"
|
||||||
"github.com/influxdata/chronograf/uuid"
|
"github.com/influxdata/chronograf/id"
|
||||||
client "github.com/influxdata/kapacitor/client/v1"
|
client "github.com/influxdata/kapacitor/client/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ func NewClient(url, username, password string, insecureSkipVerify bool) *Client
|
||||||
Username: username,
|
Username: username,
|
||||||
Password: password,
|
Password: password,
|
||||||
InsecureSkipVerify: insecureSkipVerify,
|
InsecureSkipVerify: insecureSkipVerify,
|
||||||
ID: &uuid.V4{},
|
ID: &id.UUID{},
|
||||||
Ticker: &Alert{},
|
Ticker: &Alert{},
|
||||||
kapaClient: NewKapaClient,
|
kapaClient: NewKapaClient,
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,35 @@ func (builder *MultiLayoutBuilder) Build(db chronograf.LayoutsStore) (*multistor
|
||||||
return layouts, nil
|
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
|
// SourcesBuilder builds a MultiSourceStore
|
||||||
type SourcesBuilder interface {
|
type SourcesBuilder interface {
|
||||||
Build(chronograf.SourcesStore) (*multistore.SourcesStore, error)
|
Build(chronograf.SourcesStore) (*multistore.SourcesStore, error)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/bouk/httprouter"
|
"github.com/bouk/httprouter"
|
||||||
"github.com/influxdata/chronograf"
|
"github.com/influxdata/chronograf"
|
||||||
"github.com/influxdata/chronograf/uuid"
|
idgen "github.com/influxdata/chronograf/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -210,7 +210,7 @@ func (s *Service) NewDashboardCell(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ids := uuid.V4{}
|
ids := &idgen.UUID{}
|
||||||
cid, err := ids.Generate()
|
cid, err := ids.Generate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("Error creating cell ID of dashboard %d: %v", id, err)
|
msg := fmt.Sprintf("Error creating cell ID of dashboard %d: %v", id, err)
|
||||||
|
|
|
@ -16,10 +16,10 @@ import (
|
||||||
|
|
||||||
"github.com/influxdata/chronograf"
|
"github.com/influxdata/chronograf"
|
||||||
"github.com/influxdata/chronograf/bolt"
|
"github.com/influxdata/chronograf/bolt"
|
||||||
|
idgen "github.com/influxdata/chronograf/id"
|
||||||
"github.com/influxdata/chronograf/influx"
|
"github.com/influxdata/chronograf/influx"
|
||||||
clog "github.com/influxdata/chronograf/log"
|
clog "github.com/influxdata/chronograf/log"
|
||||||
"github.com/influxdata/chronograf/oauth2"
|
"github.com/influxdata/chronograf/oauth2"
|
||||||
"github.com/influxdata/chronograf/uuid"
|
|
||||||
client "github.com/influxdata/usage-client/v1"
|
client "github.com/influxdata/usage-client/v1"
|
||||||
flags "github.com/jessevdk/go-flags"
|
flags "github.com/jessevdk/go-flags"
|
||||||
"github.com/tylerb/graceful"
|
"github.com/tylerb/graceful"
|
||||||
|
@ -122,6 +122,7 @@ func (s *Server) UseHeroku() bool {
|
||||||
return s.TokenSecret != "" && s.HerokuClientID != "" && s.HerokuSecret != ""
|
return s.TokenSecret != "" && s.HerokuClientID != "" && s.HerokuSecret != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UseAuth0 validates the CLI parameters to enable Auth0 oauth support
|
||||||
func (s *Server) UseAuth0() bool {
|
func (s *Server) UseAuth0() bool {
|
||||||
return s.Auth0ClientID != "" && s.Auth0ClientSecret != ""
|
return s.Auth0ClientID != "" && s.Auth0ClientSecret != ""
|
||||||
}
|
}
|
||||||
|
@ -269,24 +270,41 @@ func (s *Server) NewListener() (net.Listener, error) {
|
||||||
return listener, nil
|
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
|
// Serve starts and runs the chronograf server
|
||||||
func (s *Server) Serve(ctx context.Context) error {
|
func (s *Server) Serve(ctx context.Context) error {
|
||||||
logger := clog.New(clog.ParseLevel(s.LogLevel))
|
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)
|
_, err := NewCustomLinks(s.CustomLinks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.
|
logger.
|
||||||
|
@ -295,7 +313,7 @@ func (s *Server) Serve(ctx context.Context) error {
|
||||||
Error(err)
|
Error(err)
|
||||||
return 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 {
|
if err := service.HandleNewSources(ctx, s.NewSources); err != nil {
|
||||||
logger.
|
logger.
|
||||||
WithField("component", "server").
|
WithField("component", "server").
|
||||||
|
@ -390,18 +408,18 @@ func (s *Server) Serve(ctx context.Context) error {
|
||||||
return nil
|
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 := 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.
|
logger.
|
||||||
WithField("component", "boltstore").
|
WithField("component", "boltstore").
|
||||||
Error(err)
|
Error(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
layouts, err := lBuilder.Build(db.LayoutsStore)
|
layouts, err := builder.Layouts.Build(db.LayoutsStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.
|
logger.
|
||||||
WithField("component", "LayoutsStore").
|
WithField("component", "LayoutsStore").
|
||||||
|
@ -409,7 +427,14 @@ func openService(ctx context.Context, s *Server, lBuilder LayoutBuilder, sBuilde
|
||||||
os.Exit(1)
|
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 {
|
if err != nil {
|
||||||
logger.
|
logger.
|
||||||
WithField("component", "SourcesStore").
|
WithField("component", "SourcesStore").
|
||||||
|
@ -417,7 +442,7 @@ func openService(ctx context.Context, s *Server, lBuilder LayoutBuilder, sBuilde
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
kapacitors, err := kapBuilder.Build(db.ServersStore)
|
kapacitors, err := builder.Kapacitors.Build(db.ServersStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.
|
logger.
|
||||||
WithField("component", "KapacitorStore").
|
WithField("component", "KapacitorStore").
|
||||||
|
@ -428,16 +453,16 @@ func openService(ctx context.Context, s *Server, lBuilder LayoutBuilder, sBuilde
|
||||||
return Service{
|
return Service{
|
||||||
TimeSeriesClient: &InfluxClient{},
|
TimeSeriesClient: &InfluxClient{},
|
||||||
Store: &Store{
|
Store: &Store{
|
||||||
|
LayoutsStore: layouts,
|
||||||
|
DashboardsStore: dashboards,
|
||||||
SourcesStore: sources,
|
SourcesStore: sources,
|
||||||
ServersStore: kapacitors,
|
ServersStore: kapacitors,
|
||||||
UsersStore: db.UsersStore,
|
UsersStore: db.UsersStore,
|
||||||
OrganizationsStore: db.OrganizationsStore,
|
OrganizationsStore: db.OrganizationsStore,
|
||||||
LayoutsStore: layouts,
|
|
||||||
DashboardsStore: db.DashboardsStore,
|
|
||||||
ConfigStore: db.ConfigStore,
|
ConfigStore: db.ConfigStore,
|
||||||
},
|
},
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
UseAuth: s.useAuth(),
|
UseAuth: useAuth,
|
||||||
Databases: &influx.Client{Logger: logger},
|
Databases: &influx.Client{Logger: logger},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/bouk/httprouter"
|
"github.com/bouk/httprouter"
|
||||||
"github.com/influxdata/chronograf"
|
"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.
|
// 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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ids := uuid.V4{}
|
ids := idgen.UUID{}
|
||||||
tid, err := ids.Generate()
|
tid, err := ids.Generate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("Error creating template ID for dashboard %d: %v", id, err)
|
msg := fmt.Sprintf("Error creating template ID for dashboard %d: %v", id, err)
|
||||||
|
|
Loading…
Reference in New Issue