mirror of
https://github.com/grafana/grafana.git
synced 2025-02-12 08:35:43 -06:00
107 lines
2.4 KiB
Go
107 lines
2.4 KiB
Go
|
package generate_datasources
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"net/http"
|
||
|
"sort"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
type listPluginResponse struct {
|
||
|
Items []struct {
|
||
|
Slug string `json:"slug"`
|
||
|
} `json:"items"`
|
||
|
}
|
||
|
|
||
|
type datasourceDetails struct {
|
||
|
Slug string `json:"slug"`
|
||
|
Backend bool `json:"backend"`
|
||
|
Alerting bool `json:"alerting"`
|
||
|
}
|
||
|
|
||
|
type datasource struct {
|
||
|
Json datasourceDetails `json:"json"`
|
||
|
}
|
||
|
|
||
|
// Get the slugs of all datasource plugins that are compatible with public dashboards
|
||
|
func GetCompatibleDatasources(baseUrl string) ([]string, error) {
|
||
|
slugs, err := getDatasourcePluginSlugs(baseUrl)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
datasources := getDatasourceDetails(slugs, baseUrl)
|
||
|
|
||
|
// we only consider a datasource to be supported when alerting and backend are both true
|
||
|
var supported []string
|
||
|
for _, datasource := range datasources {
|
||
|
if datasource.Alerting && datasource.Backend {
|
||
|
supported = append(supported, datasource.Slug)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sort.Strings(supported)
|
||
|
return supported, nil
|
||
|
}
|
||
|
|
||
|
// Get a list of all the datasource plugin slugs
|
||
|
func getDatasourcePluginSlugs(baseUrl string) ([]string, error) {
|
||
|
resp, err := http.Get(baseUrl + allPluginsEndpoint())
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
res := &listPluginResponse{}
|
||
|
err = json.NewDecoder(resp.Body).Decode(res)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
var slugs []string
|
||
|
for _, meta := range res.Items {
|
||
|
slugs = append(slugs, meta.Slug)
|
||
|
}
|
||
|
_ = resp.Body.Close()
|
||
|
return slugs, nil
|
||
|
}
|
||
|
|
||
|
// Get the details for each datasource plugin by its slug
|
||
|
func getDatasourceDetails(slugs []string, baseUrl string) []datasourceDetails {
|
||
|
datasources := make([]datasourceDetails, len(slugs))
|
||
|
var wg sync.WaitGroup
|
||
|
for i, slug := range slugs {
|
||
|
wg.Add(1)
|
||
|
// create new goroutine for each outgoing request
|
||
|
go func(i int, slug string) {
|
||
|
defer wg.Done()
|
||
|
url := baseUrl + pluginEndpoint(slug)
|
||
|
// url can not be constant since it gets generated based on slug
|
||
|
//nolint:gosec
|
||
|
r, err := http.Get(url)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
datasource := &datasource{}
|
||
|
err = json.NewDecoder(r.Body).Decode(datasource)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
datasource.Json.Slug = slug
|
||
|
datasources[i] = datasource.Json
|
||
|
_ = r.Body.Close()
|
||
|
}(i, slug)
|
||
|
}
|
||
|
|
||
|
wg.Wait()
|
||
|
|
||
|
return datasources
|
||
|
}
|
||
|
|
||
|
func pluginEndpoint(slug string) string {
|
||
|
return fmt.Sprintf("/api/plugins/%s?version=latest", slug)
|
||
|
}
|
||
|
|
||
|
func allPluginsEndpoint() string {
|
||
|
return "/api/plugins?orderBy=weight&direction=asc&typeCodeIn[]=datasource"
|
||
|
}
|