Azure Monitor: Azure routes from Grafana Azure SDK (#82043)
Prometheus: Azure routes from Grafana Azure SDK
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana-azure-sdk-go/azsettings"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
|
||||
|
||||
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/metrics"
|
||||
@@ -105,7 +104,7 @@ func Test_handleResourceReq(t *testing.T) {
|
||||
im: &fakeInstance{
|
||||
services: map[string]types.DatasourceService{
|
||||
azureMonitor: {
|
||||
URL: routes[azsettings.AzurePublic][azureMonitor].URL,
|
||||
URL: "https://management.azure.com",
|
||||
HTTPClient: &http.Client{},
|
||||
Logger: log.DefaultLogger,
|
||||
},
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana-azure-sdk-go/azcredentials"
|
||||
"github.com/grafana/grafana-azure-sdk-go/azsettings"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
|
||||
@@ -109,18 +108,12 @@ func NewInstanceSettings(clientProvider *httpclient.Provider, executors map[stri
|
||||
credentials = azmoncredentials.GetDefaultCredentials(azureSettings)
|
||||
}
|
||||
|
||||
cloud, err := azcredentials.GetAzureCloud(azureSettings, credentials)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting credentials: %w", err)
|
||||
}
|
||||
|
||||
routesForModel, err := getAzureRoutes(cloud, settings.JSONData)
|
||||
routesForModel, err := getAzureMonitorRoutes(azureSettings, credentials, settings.JSONData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
model := types.DatasourceInfo{
|
||||
Cloud: cloud,
|
||||
Credentials: credentials,
|
||||
Settings: azMonitorSettings,
|
||||
JSONData: jsonData,
|
||||
@@ -142,31 +135,6 @@ func NewInstanceSettings(clientProvider *httpclient.Provider, executors map[stri
|
||||
}
|
||||
}
|
||||
|
||||
func getCustomizedCloudSettings(cloud string, jsonData json.RawMessage) (types.AzureMonitorCustomizedCloudSettings, error) {
|
||||
customizedCloudSettings := types.AzureMonitorCustomizedCloudSettings{}
|
||||
err := json.Unmarshal(jsonData, &customizedCloudSettings)
|
||||
if err != nil {
|
||||
return types.AzureMonitorCustomizedCloudSettings{}, fmt.Errorf("error getting customized cloud settings: %w", err)
|
||||
}
|
||||
return customizedCloudSettings, nil
|
||||
}
|
||||
|
||||
func getAzureRoutes(cloud string, jsonData json.RawMessage) (map[string]types.AzRoute, error) {
|
||||
if cloud == azsettings.AzureCustomized {
|
||||
customizedCloudSettings, err := getCustomizedCloudSettings(cloud, jsonData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if customizedCloudSettings.CustomizedRoutes == nil {
|
||||
return nil, fmt.Errorf("unable to instantiate routes, customizedRoutes must be set")
|
||||
}
|
||||
azureRoutes := customizedCloudSettings.CustomizedRoutes
|
||||
return azureRoutes, nil
|
||||
} else {
|
||||
return routes[cloud], nil
|
||||
}
|
||||
}
|
||||
|
||||
type azDatasourceExecutor interface {
|
||||
ExecuteTimeSeriesQuery(ctx context.Context, originalQueries []backend.DataQuery, dsInfo types.DatasourceInfo, client *http.Client, url string) (*backend.QueryDataResponse, error)
|
||||
ResourceRequest(rw http.ResponseWriter, req *http.Request, cli *http.Client) (http.ResponseWriter, error)
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/grafana/grafana-azure-sdk-go/azcredentials"
|
||||
"github.com/grafana/grafana-azure-sdk-go/azsettings"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
||||
@@ -24,6 +23,32 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var testRoutes = map[string]types.AzRoute{
|
||||
azureMonitor: {
|
||||
URL: "https://management.azure.com",
|
||||
Scopes: []string{"https://management.azure.com/.default"},
|
||||
Headers: map[string]string{"x-ms-app": "Grafana"},
|
||||
},
|
||||
azureLogAnalytics: {
|
||||
URL: "https://api.loganalytics.io",
|
||||
Scopes: []string{"https://api.loganalytics.io/.default"},
|
||||
Headers: map[string]string{"x-ms-app": "Grafana", "Cache-Control": "public, max-age=60"},
|
||||
},
|
||||
azureResourceGraph: {
|
||||
URL: "https://management.azure.com",
|
||||
Scopes: []string{"https://management.azure.com/.default"},
|
||||
Headers: map[string]string{"x-ms-app": "Grafana"},
|
||||
},
|
||||
azureTraces: {
|
||||
URL: "https://api.loganalytics.io",
|
||||
Scopes: []string{"https://api.loganalytics.io/.default"},
|
||||
Headers: map[string]string{"x-ms-app": "Grafana", "Cache-Control": "public, max-age=60"},
|
||||
},
|
||||
azurePortal: {
|
||||
URL: "https://portal.azure.com",
|
||||
},
|
||||
}
|
||||
|
||||
func TestNewInstanceSettings(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -39,10 +64,9 @@ func TestNewInstanceSettings(t *testing.T) {
|
||||
ID: 40,
|
||||
},
|
||||
expectedModel: types.DatasourceInfo{
|
||||
Cloud: azsettings.AzurePublic,
|
||||
Credentials: &azcredentials.AzureManagedIdentityCredentials{},
|
||||
Settings: types.AzureMonitorSettings{},
|
||||
Routes: routes[azsettings.AzurePublic],
|
||||
Routes: testRoutes,
|
||||
JSONData: map[string]any{"azureAuthType": "msi"},
|
||||
DatasourceID: 40,
|
||||
DecryptedSecureJSONData: map[string]string{"key": "value"},
|
||||
@@ -58,7 +82,6 @@ func TestNewInstanceSettings(t *testing.T) {
|
||||
ID: 50,
|
||||
},
|
||||
expectedModel: types.DatasourceInfo{
|
||||
Cloud: "AzureCustomizedCloud",
|
||||
Credentials: &azcredentials.AzureClientSecretCredentials{
|
||||
AzureCloud: "AzureCustomizedCloud",
|
||||
ClientSecret: "secret",
|
||||
@@ -99,7 +122,6 @@ func TestNewInstanceSettings(t *testing.T) {
|
||||
}
|
||||
|
||||
type fakeInstance struct {
|
||||
cloud string
|
||||
routes map[string]types.AzRoute
|
||||
services map[string]types.DatasourceService
|
||||
settings types.AzureMonitorSettings
|
||||
@@ -107,7 +129,6 @@ type fakeInstance struct {
|
||||
|
||||
func (f *fakeInstance) Get(_ context.Context, _ backend.PluginContext) (instancemgmt.Instance, error) {
|
||||
return types.DatasourceInfo{
|
||||
Cloud: f.cloud,
|
||||
Routes: f.routes,
|
||||
Services: f.services,
|
||||
Settings: f.settings,
|
||||
@@ -149,19 +170,19 @@ func Test_newMux(t *testing.T) {
|
||||
{
|
||||
name: "creates an Azure Monitor executor",
|
||||
queryType: azureMonitor,
|
||||
expectedURL: routes[azsettings.AzurePublic][azureMonitor].URL,
|
||||
expectedURL: testRoutes[azureMonitor].URL,
|
||||
Err: require.NoError,
|
||||
},
|
||||
{
|
||||
name: "creates an Azure Log Analytics executor",
|
||||
queryType: azureLogAnalytics,
|
||||
expectedURL: routes[azsettings.AzurePublic][azureLogAnalytics].URL,
|
||||
expectedURL: testRoutes[azureLogAnalytics].URL,
|
||||
Err: require.NoError,
|
||||
},
|
||||
{
|
||||
name: "creates an Azure Traces executor",
|
||||
queryType: azureTraces,
|
||||
expectedURL: routes[azsettings.AzurePublic][azureLogAnalytics].URL,
|
||||
expectedURL: testRoutes[azureLogAnalytics].URL,
|
||||
Err: require.NoError,
|
||||
},
|
||||
}
|
||||
@@ -170,10 +191,10 @@ func Test_newMux(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &Service{
|
||||
im: &fakeInstance{
|
||||
routes: routes[azsettings.AzurePublic],
|
||||
routes: testRoutes,
|
||||
services: map[string]types.DatasourceService{
|
||||
tt.queryType: {
|
||||
URL: routes[azsettings.AzurePublic][tt.queryType].URL,
|
||||
URL: testRoutes[tt.queryType].URL,
|
||||
HTTPClient: &http.Client{},
|
||||
},
|
||||
},
|
||||
@@ -302,7 +323,6 @@ func TestCheckHealth(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
cloud := "AzureCloud"
|
||||
tests := []struct {
|
||||
name string
|
||||
errorExpected bool
|
||||
@@ -318,15 +338,15 @@ func TestCheckHealth(t *testing.T) {
|
||||
},
|
||||
customServices: map[string]types.DatasourceService{
|
||||
azureMonitor: {
|
||||
URL: routes[cloud]["Azure Monitor"].URL,
|
||||
URL: testRoutes["Azure Monitor"].URL,
|
||||
HTTPClient: azureMonitorClient(false, false),
|
||||
},
|
||||
azureLogAnalytics: {
|
||||
URL: routes[cloud]["Azure Log Analytics"].URL,
|
||||
URL: testRoutes["Azure Log Analytics"].URL,
|
||||
HTTPClient: okClient,
|
||||
},
|
||||
azureResourceGraph: {
|
||||
URL: routes[cloud]["Azure Resource Graph"].URL,
|
||||
URL: testRoutes["Azure Resource Graph"].URL,
|
||||
HTTPClient: okClient,
|
||||
}},
|
||||
},
|
||||
@@ -341,15 +361,15 @@ func TestCheckHealth(t *testing.T) {
|
||||
},
|
||||
customServices: map[string]types.DatasourceService{
|
||||
azureMonitor: {
|
||||
URL: routes[cloud]["Azure Monitor"].URL,
|
||||
URL: testRoutes["Azure Monitor"].URL,
|
||||
HTTPClient: azureMonitorClient(false, true),
|
||||
},
|
||||
azureLogAnalytics: {
|
||||
URL: routes[cloud]["Azure Log Analytics"].URL,
|
||||
URL: testRoutes["Azure Log Analytics"].URL,
|
||||
HTTPClient: okClient,
|
||||
},
|
||||
azureResourceGraph: {
|
||||
URL: routes[cloud]["Azure Resource Graph"].URL,
|
||||
URL: testRoutes["Azure Resource Graph"].URL,
|
||||
HTTPClient: okClient,
|
||||
}},
|
||||
},
|
||||
@@ -364,15 +384,15 @@ func TestCheckHealth(t *testing.T) {
|
||||
},
|
||||
customServices: map[string]types.DatasourceService{
|
||||
azureMonitor: {
|
||||
URL: routes[cloud]["Azure Monitor"].URL,
|
||||
URL: testRoutes["Azure Monitor"].URL,
|
||||
HTTPClient: azureMonitorClient(false, false),
|
||||
},
|
||||
azureLogAnalytics: {
|
||||
URL: routes[cloud]["Azure Log Analytics"].URL,
|
||||
URL: testRoutes["Azure Log Analytics"].URL,
|
||||
HTTPClient: failClient(false),
|
||||
},
|
||||
azureResourceGraph: {
|
||||
URL: routes[cloud]["Azure Resource Graph"].URL,
|
||||
URL: testRoutes["Azure Resource Graph"].URL,
|
||||
HTTPClient: okClient,
|
||||
}},
|
||||
},
|
||||
@@ -387,15 +407,15 @@ func TestCheckHealth(t *testing.T) {
|
||||
},
|
||||
customServices: map[string]types.DatasourceService{
|
||||
azureMonitor: {
|
||||
URL: routes[cloud]["Azure Monitor"].URL,
|
||||
URL: testRoutes["Azure Monitor"].URL,
|
||||
HTTPClient: azureMonitorClient(false, false),
|
||||
},
|
||||
azureLogAnalytics: {
|
||||
URL: routes[cloud]["Azure Log Analytics"].URL,
|
||||
URL: testRoutes["Azure Log Analytics"].URL,
|
||||
HTTPClient: okClient,
|
||||
},
|
||||
azureResourceGraph: {
|
||||
URL: routes[cloud]["Azure Resource Graph"].URL,
|
||||
URL: testRoutes["Azure Resource Graph"].URL,
|
||||
HTTPClient: failClient(false),
|
||||
}},
|
||||
},
|
||||
@@ -410,15 +430,15 @@ func TestCheckHealth(t *testing.T) {
|
||||
},
|
||||
customServices: map[string]types.DatasourceService{
|
||||
azureMonitor: {
|
||||
URL: routes[cloud]["Azure Monitor"].URL,
|
||||
URL: testRoutes["Azure Monitor"].URL,
|
||||
HTTPClient: azureMonitorClient(true, false),
|
||||
},
|
||||
azureLogAnalytics: {
|
||||
URL: routes[cloud]["Azure Log Analytics"].URL,
|
||||
URL: testRoutes["Azure Log Analytics"].URL,
|
||||
HTTPClient: okClient,
|
||||
},
|
||||
azureResourceGraph: {
|
||||
URL: routes[cloud]["Azure Resource Graph"].URL,
|
||||
URL: testRoutes["Azure Resource Graph"].URL,
|
||||
HTTPClient: okClient,
|
||||
}},
|
||||
},
|
||||
@@ -433,23 +453,22 @@ func TestCheckHealth(t *testing.T) {
|
||||
},
|
||||
customServices: map[string]types.DatasourceService{
|
||||
azureMonitor: {
|
||||
URL: routes[cloud]["Azure Monitor"].URL,
|
||||
URL: testRoutes["Azure Monitor"].URL,
|
||||
HTTPClient: failClient(true),
|
||||
},
|
||||
azureLogAnalytics: {
|
||||
URL: routes[cloud]["Azure Log Analytics"].URL,
|
||||
URL: testRoutes["Azure Log Analytics"].URL,
|
||||
HTTPClient: failClient(true),
|
||||
},
|
||||
azureResourceGraph: {
|
||||
URL: routes[cloud]["Azure Resource Graph"].URL,
|
||||
URL: testRoutes["Azure Resource Graph"].URL,
|
||||
HTTPClient: failClient(true),
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
instance := &fakeInstance{
|
||||
cloud: cloud,
|
||||
routes: routes[cloud],
|
||||
routes: testRoutes,
|
||||
services: map[string]types.DatasourceService{},
|
||||
settings: types.AzureMonitorSettings{
|
||||
LogAnalyticsDefaultWorkspace: "workspace-id",
|
||||
|
||||
@@ -326,12 +326,7 @@ func (e *AzureLogAnalyticsDatasource) executeQuery(ctx context.Context, query *A
|
||||
return &dataResponse, nil
|
||||
}
|
||||
|
||||
azurePortalBaseUrl, err := GetAzurePortalUrl(dsInfo.Cloud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queryUrl, err := getQueryUrl(query.Query, query.Resources, azurePortalBaseUrl, query.TimeRange)
|
||||
queryUrl, err := getQueryUrl(query.Query, query.Resources, dsInfo.Routes["Azure Portal"].URL, query.TimeRange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -365,7 +360,7 @@ func (e *AzureLogAnalyticsDatasource) executeQuery(ctx context.Context, query *A
|
||||
}
|
||||
|
||||
// Use the parent span query for the parent span data link
|
||||
err = addDataLinksToFields(query, azurePortalBaseUrl, frame, dsInfo, queryUrl)
|
||||
err = addDataLinksToFields(query, dsInfo.Routes["Azure Portal"].URL, frame, dsInfo, queryUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package loganalytics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana-azure-sdk-go/azsettings"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
)
|
||||
|
||||
@@ -34,16 +31,3 @@ func AddConfigLinks(frame data.Frame, dl string, title *string) data.Frame {
|
||||
|
||||
return frame
|
||||
}
|
||||
|
||||
func GetAzurePortalUrl(azureCloud string) (string, error) {
|
||||
switch azureCloud {
|
||||
case azsettings.AzurePublic:
|
||||
return "https://portal.azure.com", nil
|
||||
case azsettings.AzureChina:
|
||||
return "https://portal.azure.cn", nil
|
||||
case azsettings.AzureUSGovernment:
|
||||
return "https://portal.azure.us", nil
|
||||
default:
|
||||
return "", fmt.Errorf("the cloud is not supported")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,17 +339,12 @@ func (e *AzureMonitorDatasource) executeQuery(ctx context.Context, query *types.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
azurePortalUrl, err := loganalytics.GetAzurePortalUrl(dsInfo.Cloud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subscription, err := e.retrieveSubscriptionDetails(cli, ctx, query.Subscription, dsInfo.Routes["Azure Monitor"].URL, dsInfo.DatasourceID, dsInfo.OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
frames, err := e.parseResponse(data, query, azurePortalUrl, subscription)
|
||||
frames, err := e.parseResponse(data, query, dsInfo.Routes["Azure Portal"].URL, subscription)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -190,12 +190,7 @@ func (e *AzureResourceGraphDatasource) executeQuery(ctx context.Context, query *
|
||||
return &dataResponse, nil
|
||||
}
|
||||
|
||||
azurePortalUrl, err := loganalytics.GetAzurePortalUrl(dsInfo.Cloud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
url := azurePortalUrl + "/#blade/HubsExtension/ArgQueryBlade/query/" + url.PathEscape(query.InterpolatedQuery)
|
||||
url := dsInfo.Routes["Azure Portal"].URL + "/#blade/HubsExtension/ArgQueryBlade/query/" + url.PathEscape(query.InterpolatedQuery)
|
||||
frameWithLink := loganalytics.AddConfigLinks(*frame, url, nil)
|
||||
if frameWithLink.Meta == nil {
|
||||
frameWithLink.Meta = &data.FrameMeta{}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/grafana/grafana-azure-sdk-go/azsettings"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
@@ -136,23 +135,6 @@ func TestAddConfigData(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAzurePortalUrl(t *testing.T) {
|
||||
clouds := []string{azsettings.AzurePublic, azsettings.AzureChina, azsettings.AzureUSGovernment}
|
||||
expectedAzurePortalUrl := map[string]any{
|
||||
azsettings.AzurePublic: "https://portal.azure.com",
|
||||
azsettings.AzureChina: "https://portal.azure.cn",
|
||||
azsettings.AzureUSGovernment: "https://portal.azure.us",
|
||||
}
|
||||
|
||||
for _, cloud := range clouds {
|
||||
azurePortalUrl, err := loganalytics.GetAzurePortalUrl(cloud)
|
||||
if err != nil {
|
||||
t.Errorf("The cloud not supported")
|
||||
}
|
||||
assert.Equal(t, expectedAzurePortalUrl[cloud], azurePortalUrl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalResponse400(t *testing.T) {
|
||||
datasource := &AzureResourceGraphDatasource{}
|
||||
res, err := datasource.unmarshalResponse(&http.Response{
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package azuremonitor
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"github.com/grafana/grafana-azure-sdk-go/azcredentials"
|
||||
"github.com/grafana/grafana-azure-sdk-go/azsettings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/types"
|
||||
@@ -12,63 +18,99 @@ const (
|
||||
azureLogAnalytics = "Azure Log Analytics"
|
||||
azureResourceGraph = "Azure Resource Graph"
|
||||
azureTraces = "Azure Traces"
|
||||
azurePortal = "Azure Portal"
|
||||
)
|
||||
|
||||
var azManagement = types.AzRoute{
|
||||
URL: "https://management.azure.com",
|
||||
Scopes: []string{"https://management.azure.com/.default"},
|
||||
Headers: map[string]string{"x-ms-app": "Grafana"},
|
||||
}
|
||||
|
||||
var azUSGovManagement = types.AzRoute{
|
||||
URL: "https://management.usgovcloudapi.net",
|
||||
Scopes: []string{"https://management.usgovcloudapi.net/.default"},
|
||||
Headers: map[string]string{"x-ms-app": "Grafana"},
|
||||
}
|
||||
|
||||
var azChinaManagement = types.AzRoute{
|
||||
URL: "https://management.chinacloudapi.cn",
|
||||
Scopes: []string{"https://management.chinacloudapi.cn/.default"},
|
||||
Headers: map[string]string{"x-ms-app": "Grafana"},
|
||||
}
|
||||
|
||||
var azLogAnalytics = types.AzRoute{
|
||||
URL: "https://api.loganalytics.io",
|
||||
Scopes: []string{"https://api.loganalytics.io/.default"},
|
||||
Headers: map[string]string{"x-ms-app": "Grafana", "Cache-Control": "public, max-age=60"},
|
||||
}
|
||||
|
||||
var azChinaLogAnalytics = types.AzRoute{
|
||||
URL: "https://api.loganalytics.azure.cn",
|
||||
Scopes: []string{"https://api.loganalytics.azure.cn/.default"},
|
||||
Headers: map[string]string{"x-ms-app": "Grafana", "Cache-Control": "public, max-age=60"},
|
||||
}
|
||||
|
||||
var azUSGovLogAnalytics = types.AzRoute{
|
||||
URL: "https://api.loganalytics.us",
|
||||
Scopes: []string{"https://api.loganalytics.us/.default"},
|
||||
Headers: map[string]string{"x-ms-app": "Grafana", "Cache-Control": "public, max-age=60"},
|
||||
}
|
||||
|
||||
var (
|
||||
// The different Azure routes are identified by its cloud (e.g. public or gov)
|
||||
// and the service to query (e.g. Azure Monitor or Azure Log Analytics)
|
||||
routes = map[string]map[string]types.AzRoute{
|
||||
azsettings.AzurePublic: {
|
||||
azureMonitor: azManagement,
|
||||
azureLogAnalytics: azLogAnalytics,
|
||||
azureResourceGraph: azManagement,
|
||||
azureTraces: azLogAnalytics,
|
||||
},
|
||||
azsettings.AzureUSGovernment: {
|
||||
azureMonitor: azUSGovManagement,
|
||||
azureLogAnalytics: azUSGovLogAnalytics,
|
||||
azureResourceGraph: azUSGovManagement,
|
||||
},
|
||||
azsettings.AzureChina: {
|
||||
azureMonitor: azChinaManagement,
|
||||
azureLogAnalytics: azChinaLogAnalytics,
|
||||
azureResourceGraph: azChinaManagement,
|
||||
},
|
||||
func getAzureMonitorRoutes(settings *azsettings.AzureSettings, credentials azcredentials.AzureCredentials, jsonData json.RawMessage) (map[string]types.AzRoute, error) {
|
||||
azureCloud, err := azcredentials.GetAzureCloud(settings, credentials)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
)
|
||||
|
||||
if azureCloud == azsettings.AzureCustomized {
|
||||
routes, err := getCustomizedCloudRoutes(jsonData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return routes, nil
|
||||
}
|
||||
|
||||
cloudSettings, err := settings.GetCloud(azureCloud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resourceManagerUrl, ok := cloudSettings.Properties["resourceManager"]
|
||||
if !ok {
|
||||
err := fmt.Errorf("the Azure cloud '%s' doesn't have configuration for Azure Resource Manager", azureCloud)
|
||||
return nil, err
|
||||
}
|
||||
resourceManagerScopes, err := audienceToScopes(resourceManagerUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resourceManagerRoute := types.AzRoute{
|
||||
URL: resourceManagerUrl,
|
||||
Scopes: resourceManagerScopes,
|
||||
Headers: map[string]string{"x-ms-app": "Grafana"},
|
||||
}
|
||||
logAnalyticsUrl, ok := cloudSettings.Properties["logAnalytics"]
|
||||
if !ok {
|
||||
err := fmt.Errorf("the Azure cloud '%s' doesn't have configuration for Azure Log Analytics", azureCloud)
|
||||
return nil, err
|
||||
}
|
||||
logAnalyticsScopes, err := audienceToScopes(logAnalyticsUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logAnalyticsRoute := types.AzRoute{
|
||||
URL: logAnalyticsUrl,
|
||||
Scopes: logAnalyticsScopes,
|
||||
Headers: map[string]string{"x-ms-app": "Grafana", "Cache-Control": "public, max-age=60"},
|
||||
}
|
||||
portalUrl, ok := cloudSettings.Properties["portal"]
|
||||
if !ok {
|
||||
err := fmt.Errorf("the Azure cloud '%s' doesn't have configuration for Azure Portal", azureCloud)
|
||||
return nil, err
|
||||
}
|
||||
portalRoute := types.AzRoute{
|
||||
URL: portalUrl,
|
||||
}
|
||||
|
||||
routes := map[string]types.AzRoute{
|
||||
azureMonitor: resourceManagerRoute,
|
||||
azureLogAnalytics: logAnalyticsRoute,
|
||||
azureResourceGraph: resourceManagerRoute,
|
||||
azureTraces: logAnalyticsRoute,
|
||||
azurePortal: portalRoute,
|
||||
}
|
||||
|
||||
return routes, nil
|
||||
}
|
||||
|
||||
func getCustomizedCloudRoutes(jsonData json.RawMessage) (map[string]types.AzRoute, error) {
|
||||
customizedCloudSettings := types.AzureMonitorCustomizedCloudSettings{}
|
||||
err := json.Unmarshal(jsonData, &customizedCloudSettings)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting customized cloud settings: %w", err)
|
||||
}
|
||||
|
||||
if customizedCloudSettings.CustomizedRoutes == nil {
|
||||
return nil, fmt.Errorf("unable to instantiate routes, customizedRoutes must be set")
|
||||
}
|
||||
|
||||
azureRoutes := customizedCloudSettings.CustomizedRoutes
|
||||
return azureRoutes, nil
|
||||
}
|
||||
|
||||
func audienceToScopes(audience string) ([]string, error) {
|
||||
resourceId, err := url.Parse(audience)
|
||||
if err != nil || resourceId.Scheme == "" || resourceId.Host == "" {
|
||||
err = fmt.Errorf("endpoint resource ID (audience) '%s' invalid", audience)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resourceId.Path = path.Join(resourceId.Path, ".default")
|
||||
scopes := []string{resourceId.String()}
|
||||
return scopes, nil
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ type DatasourceService struct {
|
||||
}
|
||||
|
||||
type DatasourceInfo struct {
|
||||
Cloud string
|
||||
Credentials azcredentials.AzureCredentials
|
||||
Settings AzureMonitorSettings
|
||||
Routes map[string]AzRoute
|
||||
|
||||
Reference in New Issue
Block a user