Merge pull request #4786 from influxdata/bugfix/get-protoboards-from-multistore
Get protoboards from multistore if not able to find from ProtoboardsPathfix/ci-pivot
commit
bc21a59ec9
7
Makefile
7
Makefile
|
@ -46,7 +46,7 @@ docker: dep assets docker-${BINARY}
|
|||
|
||||
assets: .jssrc .bindata
|
||||
|
||||
.bindata: server/swagger_gen.go canned/bin_gen.go dist/dist_gen.go
|
||||
.bindata: server/swagger_gen.go canned/bin_gen.go protoboards/bin_gen.go dist/dist_gen.go
|
||||
@touch .bindata
|
||||
|
||||
dist/dist_gen.go: $(UISOURCES)
|
||||
|
@ -57,6 +57,9 @@ server/swagger_gen.go: server/swagger.json
|
|||
|
||||
canned/bin_gen.go: canned/*.json
|
||||
go generate -x ./canned
|
||||
|
||||
protoboards/bin_gen.go: protoboards/*.json
|
||||
go generate -x ./protoboards
|
||||
|
||||
.jssrc: $(UISOURCES)
|
||||
cd ui && yarn run clean && yarn run build
|
||||
|
@ -112,7 +115,7 @@ clean:
|
|||
if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
|
||||
cd ui && yarn run clean
|
||||
cd ui && rm -rf node_modules
|
||||
rm -f dist/dist_gen.go canned/bin_gen.go server/swagger_gen.go
|
||||
rm -f dist/dist_gen.go canned/bin_gen.go protoboards/bin_gen.go server/swagger_gen.go
|
||||
@rm -f .godep .jsdep .jssrc .bindata
|
||||
|
||||
ctags:
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package multistore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
// Protoboards is a ProtoboardsStore that contains multiple ProtoboardsStores
|
||||
// The All method will return the set of all Protoboards.
|
||||
// Each method will be tried against the Stores slice serially.
|
||||
type Protoboards struct {
|
||||
Stores []chronograf.ProtoboardsStore
|
||||
}
|
||||
|
||||
// All returns the set of all protoboards
|
||||
func (s *Protoboards) All(ctx context.Context) ([]chronograf.Protoboard, error) {
|
||||
all := []chronograf.Protoboard{}
|
||||
protoboardSet := map[string]chronograf.Protoboard{}
|
||||
ok := false
|
||||
var err error
|
||||
for _, store := range s.Stores {
|
||||
var protoboards []chronograf.Protoboard
|
||||
protoboards, err = store.All(ctx)
|
||||
if err != nil {
|
||||
// Try to load as many protoboards as possible
|
||||
continue
|
||||
}
|
||||
ok = true
|
||||
for _, l := range protoboards {
|
||||
// Enforce that the protoboard has a unique ID
|
||||
// If the protoboard has been seen before then skip
|
||||
if _, okay := protoboardSet[l.ID]; !okay {
|
||||
protoboardSet[l.ID] = l
|
||||
all = append(all, l)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
return all, nil
|
||||
}
|
||||
|
||||
// Get retrieves protoboard if `ID` exists. Searches through each store sequentially until success.
|
||||
func (s *Protoboards) Get(ctx context.Context, ID string) (chronograf.Protoboard, error) {
|
||||
var err error
|
||||
for _, store := range s.Stores {
|
||||
var l chronograf.Protoboard
|
||||
l, err = store.Get(ctx, ID)
|
||||
if err == nil {
|
||||
return l, nil
|
||||
}
|
||||
}
|
||||
return chronograf.Protoboard{}, err
|
||||
}
|
||||
|
||||
// Add creates a new protoboard in the protoboardsStore.
|
||||
func (s *Protoboards) Add(ctx context.Context, protoboard chronograf.Protoboard) (chronograf.Protoboard, error) {
|
||||
return chronograf.Protoboard{}, fmt.Errorf("Add to multistore/protoboards not supported")
|
||||
}
|
||||
|
||||
// Delete the protoboard from the store.
|
||||
func (s *Protoboards) Delete(ctx context.Context, protoboard chronograf.Protoboard) error {
|
||||
return fmt.Errorf("Delete to multistore/protoboards not supported")
|
||||
}
|
||||
|
||||
// Update the protoboard in the store.
|
||||
func (s *Protoboards) Update(ctx context.Context, protoboard chronograf.Protoboard) error {
|
||||
return fmt.Errorf("Update to multistore/protoboards not supported")
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package protoboards
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
//go:generate go-bindata -o bin_gen.go -ignore README|apps|.sh|go -pkg protoboards .
|
||||
|
||||
// BinProtoboardsStore represents a protoboards store using data generated by go-bindata
|
||||
type BinProtoboardsStore struct {
|
||||
Logger chronograf.Logger
|
||||
}
|
||||
|
||||
// All returns the set of all protoboards
|
||||
func (s *BinProtoboardsStore) All(ctx context.Context) ([]chronograf.Protoboard, error) {
|
||||
names := AssetNames()
|
||||
protoboards := make([]chronograf.Protoboard, len(names))
|
||||
for i, name := range names {
|
||||
octets, err := Asset(name)
|
||||
if err != nil {
|
||||
s.Logger.
|
||||
WithField("component", "protoboards").
|
||||
WithField("name", name).
|
||||
Error("Invalid protoboard: ", err)
|
||||
return nil, chronograf.ErrProtoboardInvalid
|
||||
}
|
||||
|
||||
var protoboard chronograf.Protoboard
|
||||
if err = json.Unmarshal(octets, &protoboard); err != nil {
|
||||
s.Logger.
|
||||
WithField("component", "protoboards").
|
||||
WithField("name", name).
|
||||
Error("Unable to read protoboard:", err)
|
||||
return nil, chronograf.ErrProtoboardInvalid
|
||||
}
|
||||
protoboards[i] = protoboard
|
||||
}
|
||||
|
||||
return protoboards, nil
|
||||
}
|
||||
|
||||
// Add is not support by BinProtoboardsStore
|
||||
func (s *BinProtoboardsStore) Add(ctx context.Context, protoboard chronograf.Protoboard) (chronograf.Protoboard, error) {
|
||||
return chronograf.Protoboard{}, fmt.Errorf("Add to BinProtoboardsStore not supported")
|
||||
}
|
||||
|
||||
// Delete is not support by BinProtoboardsStore
|
||||
func (s *BinProtoboardsStore) Delete(ctx context.Context, protoboard chronograf.Protoboard) error {
|
||||
return fmt.Errorf("Delete to BinProtoboardsStore not supported")
|
||||
}
|
||||
|
||||
// Get retrieves protoboard if `ID` exists.
|
||||
func (s *BinProtoboardsStore) Get(ctx context.Context, ID string) (chronograf.Protoboard, error) {
|
||||
protoboards, err := s.All(ctx)
|
||||
if err != nil {
|
||||
s.Logger.
|
||||
WithField("component", "protoboards").
|
||||
WithField("name", ID).
|
||||
Error("Invalid protoboard: ", err)
|
||||
return chronograf.Protoboard{}, chronograf.ErrProtoboardInvalid
|
||||
}
|
||||
|
||||
for _, protoboard := range protoboards {
|
||||
if protoboard.ID == ID {
|
||||
return protoboard, nil
|
||||
}
|
||||
}
|
||||
|
||||
s.Logger.
|
||||
WithField("component", "protoboards").
|
||||
WithField("name", ID).
|
||||
Error("protoboard not found")
|
||||
return chronograf.Protoboard{}, chronograf.ErrProtoboardNotFound
|
||||
}
|
||||
|
||||
// Update not supported
|
||||
func (s *BinProtoboardsStore) Update(ctx context.Context, protoboard chronograf.Protoboard) error {
|
||||
return fmt.Errorf("Update to BinProtoboardsStore not supported")
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/influxdata/chronograf/filestore"
|
||||
"github.com/influxdata/chronograf/memdb"
|
||||
"github.com/influxdata/chronograf/multistore"
|
||||
"github.com/influxdata/chronograf/protoboards"
|
||||
)
|
||||
|
||||
// LayoutBuilder is responsible for building Layouts
|
||||
|
@ -43,6 +44,40 @@ func (builder *MultiLayoutBuilder) Build(db chronograf.LayoutsStore) (*multistor
|
|||
return layouts, nil
|
||||
}
|
||||
|
||||
// ProtoboardsBuilder is responsible for building Protoboards
|
||||
type ProtoboardsBuilder interface {
|
||||
Build() (*multistore.Protoboards, error)
|
||||
}
|
||||
|
||||
// MultiProtoboardsBuilder implements LayoutBuilder and will return a Layouts
|
||||
type MultiProtoboardsBuilder struct {
|
||||
Logger chronograf.Logger
|
||||
UUID chronograf.ID
|
||||
ProtoboardsPath string
|
||||
}
|
||||
|
||||
// Build will construct a Layouts of canned and db-backed personalized
|
||||
// layouts
|
||||
func (builder *MultiProtoboardsBuilder) Build() (*multistore.Protoboards, error) {
|
||||
// These apps are those handled from a directory
|
||||
filesystemPBs := filestore.NewProtoboards(builder.ProtoboardsPath, builder.UUID, builder.Logger)
|
||||
// These apps are statically compiled into chronograf
|
||||
binPBs := &protoboards.BinProtoboardsStore{
|
||||
Logger: builder.Logger,
|
||||
}
|
||||
// Acts as a front-end to both the bolt layouts, filesystem layouts and binary statically compiled layouts.
|
||||
// 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 over binary data.
|
||||
protoboards := &multistore.Protoboards{
|
||||
Stores: []chronograf.ProtoboardsStore{
|
||||
filesystemPBs,
|
||||
binPBs,
|
||||
},
|
||||
}
|
||||
|
||||
return protoboards, nil
|
||||
}
|
||||
|
||||
// DashboardBuilder is responsible for building dashboards
|
||||
type DashboardBuilder interface {
|
||||
Build(chronograf.DashboardsStore) (*multistore.DashboardsStore, error)
|
||||
|
|
|
@ -18,7 +18,6 @@ import (
|
|||
|
||||
"github.com/influxdata/chronograf"
|
||||
"github.com/influxdata/chronograf/bolt"
|
||||
"github.com/influxdata/chronograf/filestore"
|
||||
idgen "github.com/influxdata/chronograf/id"
|
||||
"github.com/influxdata/chronograf/influx"
|
||||
clog "github.com/influxdata/chronograf/log"
|
||||
|
@ -286,6 +285,7 @@ type builders struct {
|
|||
Kapacitors KapacitorBuilder
|
||||
Dashboards DashboardBuilder
|
||||
Organizations OrganizationBuilder
|
||||
Protoboards ProtoboardsBuilder
|
||||
}
|
||||
|
||||
func (s *Server) newBuilders(logger chronograf.Logger) builders {
|
||||
|
@ -320,6 +320,11 @@ func (s *Server) newBuilders(logger chronograf.Logger) builders {
|
|||
Logger: logger,
|
||||
Path: s.ResourcesPath,
|
||||
},
|
||||
Protoboards: &MultiProtoboardsBuilder{
|
||||
Logger: logger,
|
||||
UUID: &idgen.UUID{},
|
||||
ProtoboardsPath: s.ProtoboardsPath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -488,7 +493,13 @@ func openService(ctx context.Context, buildInfo chronograf.BuildInfo, boltPath s
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
protoboards := filestore.NewProtoboards(protoboardsPath, idgen.NewTime(), logger)
|
||||
protoboards, err := builder.Protoboards.Build()
|
||||
if err != nil {
|
||||
logger.
|
||||
WithField("component", "LayoutsStore").
|
||||
Error("Unable to construct a MultiLayoutsStore", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return Service{
|
||||
TimeSeriesClient: &InfluxClient{},
|
||||
|
|
Loading…
Reference in New Issue