237 lines
6.4 KiB
Go
237 lines
6.4 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/bouk/httprouter"
|
|
platform "github.com/influxdata/platform/chronograf/v2"
|
|
)
|
|
|
|
type dashboardV2Links struct {
|
|
Self string `json:"self"`
|
|
}
|
|
|
|
type dashboardV2Response struct {
|
|
platform.Dashboard
|
|
Links dashboardV2Links `json:"links"`
|
|
}
|
|
|
|
func newDashboardV2Response(d *platform.Dashboard) dashboardV2Response {
|
|
// Make nil slice values into empty array for front end.
|
|
if d.Cells == nil {
|
|
d.Cells = []platform.DashboardCell{}
|
|
}
|
|
return dashboardV2Response{
|
|
Links: dashboardV2Links{
|
|
Self: fmt.Sprintf("/chronograf/v2/dashboards/%s", d.ID),
|
|
},
|
|
Dashboard: *d,
|
|
}
|
|
}
|
|
|
|
// DashboardsV2 returns all dashboards within the store.
|
|
func (s *Service) DashboardsV2(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
// TODO: support filtering via query params
|
|
dashboards, _, err := s.Store.DashboardsV2(ctx).FindDashboards(ctx, platform.DashboardFilter{})
|
|
if err != nil {
|
|
Error(w, http.StatusInternalServerError, "Error loading dashboards", s.Logger)
|
|
return
|
|
}
|
|
|
|
s.encodeGetDashboardsResponse(w, dashboards)
|
|
}
|
|
|
|
type getDashboardsV2Links struct {
|
|
Self string `json:"self"`
|
|
}
|
|
|
|
type getDashboardsV2Response struct {
|
|
Links getDashboardsV2Links `json:"links"`
|
|
Dashboards []dashboardV2Response `json:"dashboards"`
|
|
}
|
|
|
|
func (s *Service) encodeGetDashboardsResponse(w http.ResponseWriter, dashboards []*platform.Dashboard) {
|
|
res := getDashboardsV2Response{
|
|
Links: getDashboardsV2Links{
|
|
Self: "/chronograf/v2/dashboards",
|
|
},
|
|
Dashboards: make([]dashboardV2Response, 0, len(dashboards)),
|
|
}
|
|
|
|
for _, dashboard := range dashboards {
|
|
res.Dashboards = append(res.Dashboards, newDashboardV2Response(dashboard))
|
|
}
|
|
|
|
encodeJSON(w, http.StatusOK, res, s.Logger)
|
|
}
|
|
|
|
// NewDashboardV2 creates a new dashboard.
|
|
func (s *Service) NewDashboardV2(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
|
|
req, err := decodePostDashboardRequest(ctx, r)
|
|
if err != nil {
|
|
Error(w, http.StatusBadRequest, err.Error(), s.Logger)
|
|
return
|
|
}
|
|
if err := s.Store.DashboardsV2(ctx).CreateDashboard(ctx, req.Dashboard); err != nil {
|
|
Error(w, http.StatusInternalServerError, fmt.Sprintf("Error loading dashboards: %v", err), s.Logger)
|
|
return
|
|
}
|
|
|
|
s.encodePostDashboardResponse(w, req.Dashboard)
|
|
}
|
|
|
|
type postDashboardRequest struct {
|
|
Dashboard *platform.Dashboard
|
|
}
|
|
|
|
func decodePostDashboardRequest(ctx context.Context, r *http.Request) (*postDashboardRequest, error) {
|
|
c := &platform.Dashboard{}
|
|
if err := json.NewDecoder(r.Body).Decode(c); err != nil {
|
|
return nil, err
|
|
}
|
|
return &postDashboardRequest{
|
|
Dashboard: c,
|
|
}, nil
|
|
}
|
|
|
|
func (s *Service) encodePostDashboardResponse(w http.ResponseWriter, dashboard *platform.Dashboard) {
|
|
encodeJSON(w, http.StatusCreated, newDashboardV2Response(dashboard), s.Logger)
|
|
}
|
|
|
|
// DashboardIDV2 retrieves a dashboard by ID.
|
|
func (s *Service) DashboardIDV2(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
|
|
req, err := decodeGetDashboardRequest(ctx, r)
|
|
if err != nil {
|
|
Error(w, http.StatusBadRequest, err.Error(), s.Logger)
|
|
return
|
|
}
|
|
dashboard, err := s.Store.DashboardsV2(ctx).FindDashboardByID(ctx, req.DashboardID)
|
|
if err == platform.ErrDashboardNotFound {
|
|
Error(w, http.StatusNotFound, err.Error(), s.Logger)
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
Error(w, http.StatusInternalServerError, fmt.Sprintf("Error loading dashboard: %v", err), s.Logger)
|
|
return
|
|
}
|
|
|
|
s.encodeGetDashboardResponse(w, dashboard)
|
|
}
|
|
|
|
type getDashboardRequest struct {
|
|
DashboardID platform.ID
|
|
}
|
|
|
|
func decodeGetDashboardRequest(ctx context.Context, r *http.Request) (*getDashboardRequest, error) {
|
|
param := httprouter.GetParamFromContext(ctx, "id")
|
|
return &getDashboardRequest{
|
|
DashboardID: platform.ID(param),
|
|
}, nil
|
|
}
|
|
|
|
func (s *Service) encodeGetDashboardResponse(w http.ResponseWriter, dashboard *platform.Dashboard) {
|
|
encodeJSON(w, http.StatusOK, newDashboardV2Response(dashboard), s.Logger)
|
|
}
|
|
|
|
// RemoveDashboardV2 removes a dashboard by ID.
|
|
func (s *Service) RemoveDashboardV2(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
|
|
req, err := decodeDeleteDashboardRequest(ctx, r)
|
|
if err != nil {
|
|
Error(w, http.StatusBadRequest, err.Error(), s.Logger)
|
|
return
|
|
}
|
|
err = s.Store.DashboardsV2(ctx).DeleteDashboard(ctx, req.DashboardID)
|
|
if err == platform.ErrDashboardNotFound {
|
|
Error(w, http.StatusNotFound, err.Error(), s.Logger)
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
Error(w, http.StatusInternalServerError, fmt.Sprintf("Error deleting dashboard: %v", err), s.Logger)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
type deleteDashboardRequest struct {
|
|
DashboardID platform.ID
|
|
}
|
|
|
|
func decodeDeleteDashboardRequest(ctx context.Context, r *http.Request) (*deleteDashboardRequest, error) {
|
|
param := httprouter.GetParamFromContext(ctx, "id")
|
|
return &deleteDashboardRequest{
|
|
DashboardID: platform.ID(param),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateDashboardV2 updates a dashboard.
|
|
func (s *Service) UpdateDashboardV2(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
|
|
req, err := decodePatchDashboardRequest(ctx, r)
|
|
if err != nil {
|
|
Error(w, http.StatusBadRequest, err.Error(), s.Logger)
|
|
return
|
|
}
|
|
dashboard, err := s.Store.DashboardsV2(ctx).UpdateDashboard(ctx, req.DashboardID, req.Upd)
|
|
if err == platform.ErrDashboardNotFound {
|
|
Error(w, http.StatusNotFound, err.Error(), s.Logger)
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
Error(w, http.StatusInternalServerError, fmt.Sprintf("Error updating dashboard: %v", err), s.Logger)
|
|
return
|
|
}
|
|
|
|
s.encodePatchDashboardResponse(w, dashboard)
|
|
}
|
|
|
|
type patchDashboardRequest struct {
|
|
DashboardID platform.ID
|
|
Upd platform.DashboardUpdate
|
|
}
|
|
|
|
func decodePatchDashboardRequest(ctx context.Context, r *http.Request) (*patchDashboardRequest, error) {
|
|
req := &patchDashboardRequest{}
|
|
upd := platform.DashboardUpdate{}
|
|
if err := json.NewDecoder(r.Body).Decode(&upd); err != nil {
|
|
return nil, err
|
|
}
|
|
req.Upd = upd
|
|
|
|
param := httprouter.GetParamFromContext(ctx, "id")
|
|
req.DashboardID = platform.ID(param)
|
|
|
|
if err := req.Valid(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return req, nil
|
|
}
|
|
|
|
// Valid validates that the dashboard ID is non zero valued and update has expected values set.
|
|
func (r *patchDashboardRequest) Valid() error {
|
|
if r.DashboardID == "" {
|
|
return fmt.Errorf("missing dashboard ID")
|
|
}
|
|
|
|
return r.Upd.Valid()
|
|
}
|
|
|
|
func (s *Service) encodePatchDashboardResponse(w http.ResponseWriter, dashboard *platform.Dashboard) {
|
|
encodeJSON(w, http.StatusOK, newDashboardV2Response(dashboard), s.Logger)
|
|
}
|