mirror of
https://github.com/grafana/grafana.git
synced 2024-12-28 01:41:24 -06:00
Prometheus: Fix Azure authentication support (#44407)
Re-adding back Azure authentication support to Prometheus datasource after the datasource query logic was rewritten from plugin.json routes to Go backend. Ref #35857
This commit is contained in:
parent
6d931226d8
commit
85ea1a5d64
@ -4,8 +4,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"github.com/grafana/grafana/pkg/tsdb/prometheus/middleware"
|
||||
"github.com/grafana/grafana/pkg/util/maputil"
|
||||
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
@ -16,30 +16,28 @@ import (
|
||||
|
||||
type Provider struct {
|
||||
settings backend.DataSourceInstanceSettings
|
||||
jsonData JsonData
|
||||
jsonData map[string]interface{}
|
||||
httpMethod string
|
||||
clientProvider httpclient.Provider
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func NewProvider(
|
||||
settings backend.DataSourceInstanceSettings,
|
||||
jsonData JsonData,
|
||||
jsonData map[string]interface{},
|
||||
clientProvider httpclient.Provider,
|
||||
log log.Logger,
|
||||
) *Provider {
|
||||
httpMethod, _ := maputil.GetStringOptional(jsonData, "httpMethod")
|
||||
return &Provider{
|
||||
settings: settings,
|
||||
jsonData: jsonData,
|
||||
httpMethod: httpMethod,
|
||||
clientProvider: clientProvider,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
type JsonData struct {
|
||||
Method string `json:"httpMethod"`
|
||||
TimeInterval string `json:"timeInterval"`
|
||||
}
|
||||
|
||||
func (p *Provider) GetClient(headers map[string]string) (apiv1.API, error) {
|
||||
opts, err := p.settings.HTTPClientOptions()
|
||||
if err != nil {
|
||||
@ -54,6 +52,12 @@ func (p *Provider) GetClient(headers map[string]string) (apiv1.API, error) {
|
||||
opts.SigV4.Service = "aps"
|
||||
}
|
||||
|
||||
// Azure authentication
|
||||
err = p.configureAzureAuthentication(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roundTripper, err := p.clientProvider.GetTransport(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -77,7 +81,7 @@ func (p *Provider) middlewares() []sdkhttpclient.Middleware {
|
||||
middleware.CustomQueryParameters(p.log),
|
||||
sdkhttpclient.CustomHeadersMiddleware(),
|
||||
}
|
||||
if strings.ToLower(p.jsonData.Method) == "get" {
|
||||
if strings.ToLower(p.httpMethod) == "get" {
|
||||
middlewares = append(middlewares, middleware.ForceHttpGet(p.log))
|
||||
}
|
||||
|
||||
|
32
pkg/tsdb/prometheus/promclient/provider_azure.go
Normal file
32
pkg/tsdb/prometheus/promclient/provider_azure.go
Normal file
@ -0,0 +1,32 @@
|
||||
package promclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/azcredentials"
|
||||
"github.com/grafana/grafana/pkg/util/maputil"
|
||||
)
|
||||
|
||||
func (p *Provider) configureAzureAuthentication(opts sdkhttpclient.Options) error {
|
||||
credentials, err := azcredentials.FromDatasourceData(p.jsonData, p.settings.DecryptedSecureJSONData)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("invalid Azure credentials: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if credentials != nil {
|
||||
opts.CustomOptions["_azureCredentials"] = credentials
|
||||
|
||||
resourceId, err := maputil.GetStringOptional(p.jsonData, "azureEndpointResourceId")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resourceId != "" {
|
||||
opts.CustomOptions["azureEndpointResourceId"] = resourceId
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -135,7 +135,7 @@ func setup(jsonData ...string) *testContext {
|
||||
rawData = []byte(jsonData[0])
|
||||
}
|
||||
|
||||
var jd promclient.JsonData
|
||||
var jd map[string]interface{}
|
||||
_ = json.Unmarshal(rawData, &jd)
|
||||
|
||||
settings := backend.DataSourceInstanceSettings{URL: "test-url", JSONData: rawData}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
||||
"github.com/grafana/grafana/pkg/util/maputil"
|
||||
apiv1 "github.com/prometheus/client_golang/api/prometheus/v1"
|
||||
)
|
||||
|
||||
@ -42,7 +43,7 @@ func ProvideService(httpClientProvider httpclient.Provider, tracer tracing.Trace
|
||||
|
||||
func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.InstanceFactoryFunc {
|
||||
return func(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
|
||||
var jsonData promclient.JsonData
|
||||
var jsonData map[string]interface{}
|
||||
err := json.Unmarshal(settings.JSONData, &jsonData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading settings: %w", err)
|
||||
@ -54,10 +55,15 @@ func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.Inst
|
||||
return nil, err
|
||||
}
|
||||
|
||||
timeInterval, err := maputil.GetStringOptional(jsonData, "timeInterval")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mdl := DatasourceInfo{
|
||||
ID: settings.ID,
|
||||
URL: settings.URL,
|
||||
TimeInterval: jsonData.TimeInterval,
|
||||
TimeInterval: timeInterval,
|
||||
getClient: pc.GetClient,
|
||||
}
|
||||
|
||||
|
73
pkg/util/maputil/maputil.go
Normal file
73
pkg/util/maputil/maputil.go
Normal file
@ -0,0 +1,73 @@
|
||||
package maputil
|
||||
|
||||
import "fmt"
|
||||
|
||||
func GetMap(obj map[string]interface{}, key string) (map[string]interface{}, error) {
|
||||
if untypedValue, ok := obj[key]; ok {
|
||||
if value, ok := untypedValue.(map[string]interface{}); ok {
|
||||
return value, nil
|
||||
} else {
|
||||
err := fmt.Errorf("the field '%s' should be an object", key)
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
err := fmt.Errorf("the field '%s' should be set", key)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func GetBool(obj map[string]interface{}, key string) (bool, error) {
|
||||
if untypedValue, ok := obj[key]; ok {
|
||||
if value, ok := untypedValue.(bool); ok {
|
||||
return value, nil
|
||||
} else {
|
||||
err := fmt.Errorf("the field '%s' should be a bool", key)
|
||||
return false, err
|
||||
}
|
||||
} else {
|
||||
err := fmt.Errorf("the field '%s' should be set", key)
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
func GetBoolOptional(obj map[string]interface{}, key string) (bool, error) {
|
||||
if untypedValue, ok := obj[key]; ok {
|
||||
if value, ok := untypedValue.(bool); ok {
|
||||
return value, nil
|
||||
} else {
|
||||
err := fmt.Errorf("the field '%s' should be a bool", key)
|
||||
return false, err
|
||||
}
|
||||
} else {
|
||||
// Value optional, not error
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetString(obj map[string]interface{}, key string) (string, error) {
|
||||
if untypedValue, ok := obj[key]; ok {
|
||||
if value, ok := untypedValue.(string); ok {
|
||||
return value, nil
|
||||
} else {
|
||||
err := fmt.Errorf("the field '%s' should be a string", key)
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
err := fmt.Errorf("the field '%s' should be set", key)
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
func GetStringOptional(obj map[string]interface{}, key string) (string, error) {
|
||||
if untypedValue, ok := obj[key]; ok {
|
||||
if value, ok := untypedValue.(string); ok {
|
||||
return value, nil
|
||||
} else {
|
||||
err := fmt.Errorf("the field '%s' should be a string", key)
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
// Value optional, not error
|
||||
return "", nil
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user