Files
cloud-services/pkg/superset/dashboards.go

131 lines
4.0 KiB
Go

package superset
import (
"encoding/json"
"net/http"
"net/url"
"strconv"
"fiskerinc.com/modules/logger"
"github.com/pkg/errors"
)
func GetEmbeddableDashboards(accToken string) (embeddableDashboards []EmbeddableDashboard, err error) {
publishedDashboards, err := getPublishedDashboards(accToken)
if err != nil {
return nil, err
}
embeddableDashboards = make([]EmbeddableDashboard, 0, len(publishedDashboards))
for _, dashboard := range publishedDashboards {
tempId, err := getDashboardsEmbeddedID(dashboard.ID, accToken)
// If one of the dashboards gets an error, that could be fine, as long as not all of them do
// The dashboard failed to have embedding data on it
if err != nil || tempId == "" {
continue
}
embeddableDashboards = append(embeddableDashboards, EmbeddableDashboard{Title: dashboard.DashboardTitle, EmbeddingId: tempId})
}
return embeddableDashboards, nil
}
func getPublishedDashboards(accToken string) (publishedDashboard []publishedDashboard, err error) {
// Host already has the /api/v1
targetURL, err := url.JoinPath(host, "dashboard")
if err != nil {
return nil, errors.WithStack(err)
}
// ulr.JoinPath with url escape the ?
// Filter that published == true
targetURL += "/?q=%7B%0A%20%20%22filters%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22col%22%3A%20%22published%22%2C%0A%20%20%20%20%20%20%22opr%22%3A%20%22eq%22%2C%0A%20%20%20%20%20%20%22value%22%3A%20true%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D"
req, err := http.NewRequest("GET", targetURL, nil)
if err != nil {
return nil, errors.WithStack(err)
}
req.Header.Set("Accept", "application/json")
req.Header.Add("Authorization", "Bearer "+accToken)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, errors.WithStack(err)
}
defer resp.Body.Close()
if resp.StatusCode == 404 {
logger.Warn().Msgf("404 while trying to access superset api, code: %s. Trying to get published dashboards\n", resp.Status)
} else if resp.StatusCode >= 300 {
logger.Error().Msgf("Failed to access superset api, code: %s. Trying to get published dashboards\n", resp.Status)
return nil, errors.New("failed to access superset api")
}
var dashboardResponse getDashboardResponse
err = json.NewDecoder(resp.Body).Decode(&dashboardResponse)
if err != nil {
return nil, errors.WithStack(err)
}
publishedDashboard = dashboardResponse.Result
return
}
func getDashboardsEmbeddedID(dashboardId int, accToken string) (embeddedId string, err error) {
targetURL, err := url.JoinPath(host, "dashboard/", strconv.Itoa(dashboardId), "embedded")
if err != nil {
return "", errors.WithStack(err)
}
req, err := http.NewRequest("GET", targetURL, nil)
if err != nil {
return "", errors.WithStack(err)
}
req.Header.Set("Accept", "application/json")
req.Header.Add("Authorization", "Bearer "+accToken)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", errors.WithStack(err)
}
defer resp.Body.Close()
if resp.StatusCode == 404 {
logger.Warn().Msgf("Superset dashboard id %s is public, but is not embedable", embeddedId)
return "", errors.New("failed to get embedable id")
} else if resp.StatusCode >= 300 {
logger.Error().Msgf("Failed to access superset api, code: %s. Trying to get embeded dashboard id\n", resp.Status)
return "", errors.New("failed to access superset api")
}
var embeddedResponse getEmbeddedDashboardInfoResponse
err = json.NewDecoder(resp.Body).Decode(&embeddedResponse)
if err != nil {
return "", errors.WithStack(err)
}
return embeddedResponse.Result.UUID, nil
}
type getDashboardResponse struct {
Count int `json:"count"`
Ids []int `json:"ids"`
Result []publishedDashboard `json:"result"`
}
type publishedDashboard struct {
DashboardTitle string `json:"dashboard_title"`
ID int `json:"id"`
}
type getEmbeddedDashboardInfoResponse struct {
Result struct {
UUID string `json:"uuid"`
} `json:"result"`
}
type EmbeddableDashboard struct {
Title string `json:"title"`
EmbeddingId string `json:"embedded_id"`
}