mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* wip: Implement kvstore for secrets
* wip: Refactor kvstore for secrets
* wip: Add format key function to secrets kvstore sql
* wip: Add migration for secrets kvstore
* Remove unused Key field from secrets kvstore
* Remove secret values from debug logs
* Integrate unified secrets with datasources
* Fix minor issues and tests for kvstore
* Create test service helper for secret store
* Remove encryption tests from datasources
* Move secret operations after datasources
* Fix datasource proxy tests
* Fix legacy data tests
* Add Name to all delete data source commands
* Implement decryption cache on sql secret store
* Fix minor issue with cache and tests
* Use secret type on secret store datasource operations
* Add comments to make create and update clear
* Rename itemFound variable to isFound
* Improve secret deletion and cache management
* Add base64 encoding to sql secret store
* Move secret retrieval to decrypted values function
* Refactor decrypt secure json data functions
* Fix expr tests
* Fix datasource tests
* Fix plugin proxy tests
* Fix query tests
* Fix metrics api tests
* Remove unused fake secrets service from query tests
* Add rename function to secret store
* Add check for error renaming secret
* Remove bus from tests to fix merge conflicts
* Add background secrets migration to datasources
* Get datasource secure json fields from secrets
* Move migration to secret store
* Revert "Move migration to secret store"
This reverts commit 7c3f872072
.
* Add secret service to datasource service on tests
* Fix datasource tests
* Remove merge conflict on wire
* Add ctx to data source http transport on prometheus stats collector
* Add ctx to data source http transport on stats collector test
120 lines
2.8 KiB
Go
120 lines
2.8 KiB
Go
package statscollector
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/grafana/grafana/pkg/models"
|
|
)
|
|
|
|
const promFlavorCacheLifetime = time.Hour
|
|
|
|
type memoPrometheusFlavor struct {
|
|
variants map[string]int64
|
|
|
|
memoized time.Time
|
|
}
|
|
|
|
func (s *Service) detectPrometheusVariants(ctx context.Context) (map[string]int64, error) {
|
|
if s.promFlavorCache.memoized.Add(promFlavorCacheLifetime).After(time.Now()) &&
|
|
s.promFlavorCache.variants != nil {
|
|
return s.promFlavorCache.variants, nil
|
|
}
|
|
|
|
dsProm := &models.GetDataSourcesByTypeQuery{Type: "prometheus"}
|
|
err := s.datasources.GetDataSourcesByType(ctx, dsProm)
|
|
if err != nil {
|
|
s.log.Error("Failed to read all Prometheus data sources", "error", err)
|
|
return nil, err
|
|
}
|
|
|
|
variants := map[string]int64{}
|
|
for _, ds := range dsProm.Result {
|
|
variant, err := s.detectPrometheusVariant(ctx, ds)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if variant == "" {
|
|
continue
|
|
}
|
|
|
|
if _, exists := variants[variant]; !exists {
|
|
variants[variant] = 0
|
|
}
|
|
variants[variant] += 1
|
|
}
|
|
|
|
s.promFlavorCache.variants = variants
|
|
s.promFlavorCache.memoized = time.Now()
|
|
return variants, nil
|
|
}
|
|
|
|
func (s *Service) detectPrometheusVariant(ctx context.Context, ds *models.DataSource) (string, error) {
|
|
type buildInfo struct {
|
|
Data struct {
|
|
Application *string `json:"application"`
|
|
Features map[string]interface{} `json:"features"`
|
|
} `json:"data"`
|
|
}
|
|
|
|
c, err := s.datasources.GetHTTPTransport(ctx, ds, s.httpClientProvider)
|
|
if err != nil {
|
|
s.log.Error("Failed to get HTTP client for Prometheus data source", "error", err)
|
|
return "", err
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, ds.Url+"/api/v1/status/buildinfo", nil)
|
|
if err != nil {
|
|
s.log.Error("Failed to create Prometheus build info request", "error", err)
|
|
return "", err
|
|
}
|
|
|
|
resp, err := c.RoundTrip(req)
|
|
if err != nil {
|
|
// Possibly configuration error, the risk of a false positive is
|
|
// too high.
|
|
s.log.Debug("Failed to send Prometheus build info request", "error", err)
|
|
return "", nil
|
|
}
|
|
defer func() {
|
|
err := resp.Body.Close()
|
|
if err != nil {
|
|
s.log.Error("Got error while closing response body")
|
|
}
|
|
}()
|
|
|
|
if resp.StatusCode == 404 {
|
|
return "cortex-like", nil
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return "unknown", nil
|
|
}
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
s.log.Error("Failed to read Prometheus build info", "error", err)
|
|
return "", err
|
|
}
|
|
|
|
bi := &buildInfo{}
|
|
err = json.Unmarshal(body, bi)
|
|
if err != nil {
|
|
s.log.Warn("Failed to read Prometheus build info JSON", "error", err)
|
|
return "", err
|
|
}
|
|
|
|
if bi.Data.Application != nil && *bi.Data.Application == "Grafana Mimir" {
|
|
return "mimir", nil
|
|
}
|
|
|
|
if bi.Data.Features != nil {
|
|
return "mimir-like", nil
|
|
}
|
|
|
|
return "vanilla", nil
|
|
}
|