131 lines
4.0 KiB
Go
131 lines
4.0 KiB
Go
package superset
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
|
|
"github.com/fiskerinc/cloud-services/pkg/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"`
|
|
}
|