diff --git a/multistore/dashboards.go b/multistore/dashboards.go new file mode 100644 index 0000000000..4380448e8e --- /dev/null +++ b/multistore/dashboards.go @@ -0,0 +1,97 @@ +package multistore + +import ( + "context" + + "github.com/influxdata/chronograf" +) + +// Ensure DashboardsStore implements chronograf.DashboardsStore. +var _ chronograf.DashboardsStore = &DashboardsStore{} + +// DashboardsStore implements the chronograf.DashboardsStore interface, and +// delegates to all contained DashboardsStores +type DashboardsStore struct { + Stores []chronograf.DashboardsStore +} + +// All concatenates the Dashboards of all contained Stores +func (multi *DashboardsStore) All(ctx context.Context) ([]chronograf.Dashboard, error) { + all := []chronograf.Dashboard{} + boardSet := map[chronograf.DashboardID]struct{}{} + + ok := false + var err error + for _, store := range multi.Stores { + var boards []chronograf.Dashboard + boards, err = store.All(ctx) + if err != nil { + // If this Store is unable to return an array of dashboards, skip to the + // next Store. + continue + } + ok = true // We've received a response from at least one Store + for _, board := range boards { + // Enforce that the dashboard has a unique ID + // If the ID has been seen before, ignore the dashboard + if _, okay := boardSet[board.ID]; !okay { // We have a new dashboard + boardSet[board.ID] = struct{}{} // We just care that the ID is unique + all = append(all, board) + } + } + } + if !ok { + return nil, err + } + return all, nil +} + +// Add the dashboard to the first responsive Store +func (multi *DashboardsStore) Add(ctx context.Context, dashboard chronograf.Dashboard) (chronograf.Dashboard, error) { + var err error + for _, store := range multi.Stores { + var d chronograf.Dashboard + d, err = store.Add(ctx, dashboard) + if err == nil { + return d, nil + } + } + return chronograf.Dashboard{}, nil +} + +// Delete delegates to all Stores, returns success if one Store is successful +func (multi *DashboardsStore) Delete(ctx context.Context, dashboard chronograf.Dashboard) error { + var err error + for _, store := range multi.Stores { + err = store.Delete(ctx, dashboard) + if err == nil { + return nil + } + } + return err +} + +// Get finds the Dashboard by id among all contained Stores +func (multi *DashboardsStore) Get(ctx context.Context, id chronograf.DashboardID) (chronograf.Dashboard, error) { + var err error + for _, store := range multi.Stores { + var d chronograf.Dashboard + d, err = store.Get(ctx, id) + if err == nil { + return d, nil + } + } + return chronograf.Dashboard{}, nil +} + +// Update the first responsive Store +func (multi *DashboardsStore) Update(ctx context.Context, dashboard chronograf.Dashboard) error { + var err error + for _, store := range multi.Stores { + err = store.Update(ctx, dashboard) + if err == nil { + return nil + } + } + return err +}