mirror of https://github.com/grafana/grafana.git
				
				
				
			Azure Monitor: Add support to customized routes (#54829)
This commit is contained in:
		
							parent
							
								
									4200d7b246
								
							
						
					
					
						commit
						ec024ae960
					
				
							
								
								
									
										2
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										2
									
								
								go.mod
								
								
								
								
							|  | @ -56,7 +56,7 @@ require ( | ||||||
| 	github.com/gosimple/slug v1.12.0 | 	github.com/gosimple/slug v1.12.0 | ||||||
| 	github.com/grafana/cuetsy v0.1.1 | 	github.com/grafana/cuetsy v0.1.1 | ||||||
| 	github.com/grafana/grafana-aws-sdk v0.11.0 | 	github.com/grafana/grafana-aws-sdk v0.11.0 | ||||||
| 	github.com/grafana/grafana-azure-sdk-go v1.3.0 | 	github.com/grafana/grafana-azure-sdk-go v1.3.1 | ||||||
| 	github.com/grafana/grafana-plugin-sdk-go v0.139.0 | 	github.com/grafana/grafana-plugin-sdk-go v0.139.0 | ||||||
| 	github.com/grafana/thema v0.0.0-20220817114012-ebeee841c104 | 	github.com/grafana/thema v0.0.0-20220817114012-ebeee841c104 | ||||||
| 	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 | 	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										2
									
								
								go.sum
								
								
								
								
							|  | @ -1378,6 +1378,8 @@ github.com/grafana/grafana-aws-sdk v0.11.0 h1:ncPD/UN0wNcKq3kEU90RdvrnK/6R4VW2Lo | ||||||
| github.com/grafana/grafana-aws-sdk v0.11.0/go.mod h1:5Iw3xY7iXJfNaYHrRHMXa/kaB2lWoyntg71PPLGvSs8= | github.com/grafana/grafana-aws-sdk v0.11.0/go.mod h1:5Iw3xY7iXJfNaYHrRHMXa/kaB2lWoyntg71PPLGvSs8= | ||||||
| github.com/grafana/grafana-azure-sdk-go v1.3.0 h1:zboQpq/ljBjqHo/6UQNZAUwqGTtnEGRYSEnqIQvLuAo= | github.com/grafana/grafana-azure-sdk-go v1.3.0 h1:zboQpq/ljBjqHo/6UQNZAUwqGTtnEGRYSEnqIQvLuAo= | ||||||
| github.com/grafana/grafana-azure-sdk-go v1.3.0/go.mod h1:rgrnK9m6CgKlgx4rH3FFP/6dTdyRO6LYC2mVZov35yo= | github.com/grafana/grafana-azure-sdk-go v1.3.0/go.mod h1:rgrnK9m6CgKlgx4rH3FFP/6dTdyRO6LYC2mVZov35yo= | ||||||
|  | github.com/grafana/grafana-azure-sdk-go v1.3.1 h1:xTgBmbDxUPj3X9Pl9vgIOgZoDdtxWl0fYDuHrHr79jM= | ||||||
|  | github.com/grafana/grafana-azure-sdk-go v1.3.1/go.mod h1:rgrnK9m6CgKlgx4rH3FFP/6dTdyRO6LYC2mVZov35yo= | ||||||
| github.com/grafana/grafana-google-sdk-go v0.0.0-20211104130251-b190293eaf58 h1:2ud7NNM7LrGPO4x0NFR8qLq68CqI4SmB7I2yRN2w9oE= | github.com/grafana/grafana-google-sdk-go v0.0.0-20211104130251-b190293eaf58 h1:2ud7NNM7LrGPO4x0NFR8qLq68CqI4SmB7I2yRN2w9oE= | ||||||
| github.com/grafana/grafana-google-sdk-go v0.0.0-20211104130251-b190293eaf58/go.mod h1:Vo2TKWfDVmNTELBUM+3lkrZvFtBws0qSZdXhQxRdJrE= | github.com/grafana/grafana-google-sdk-go v0.0.0-20211104130251-b190293eaf58/go.mod h1:Vo2TKWfDVmNTELBUM+3lkrZvFtBws0qSZdXhQxRdJrE= | ||||||
| github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk= | github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk= | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import ( | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/grafana/grafana-azure-sdk-go/azsettings" | ||||||
| 	"github.com/grafana/grafana-plugin-sdk-go/backend" | 	"github.com/grafana/grafana-plugin-sdk-go/backend" | ||||||
| 	"github.com/grafana/grafana-plugin-sdk-go/backend/datasource" | 	"github.com/grafana/grafana-plugin-sdk-go/backend/datasource" | ||||||
| 	"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" | 	"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" | ||||||
|  | @ -99,6 +100,11 @@ func NewInstanceSettings(cfg *setting.Cfg, clientProvider *httpclient.Provider, | ||||||
| 			return nil, fmt.Errorf("error getting credentials: %w", err) | 			return nil, fmt.Errorf("error getting credentials: %w", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		routesForModel, err := getAzureRoutes(cloud, settings.JSONData) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		credentials, err := getAzureCredentials(cfg, jsonData, settings.DecryptedSecureJSONData) | 		credentials, err := getAzureCredentials(cfg, jsonData, settings.DecryptedSecureJSONData) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, fmt.Errorf("error getting credentials: %w", err) | 			return nil, fmt.Errorf("error getting credentials: %w", err) | ||||||
|  | @ -111,7 +117,7 @@ func NewInstanceSettings(cfg *setting.Cfg, clientProvider *httpclient.Provider, | ||||||
| 			JSONData:                jsonDataObj, | 			JSONData:                jsonDataObj, | ||||||
| 			DecryptedSecureJSONData: settings.DecryptedSecureJSONData, | 			DecryptedSecureJSONData: settings.DecryptedSecureJSONData, | ||||||
| 			DatasourceID:            settings.ID, | 			DatasourceID:            settings.ID, | ||||||
| 			Routes:                  routes[cloud], | 			Routes:                  routesForModel, | ||||||
| 			Services:                map[string]types.DatasourceService{}, | 			Services:                map[string]types.DatasourceService{}, | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -127,6 +133,31 @@ func NewInstanceSettings(cfg *setting.Cfg, clientProvider *httpclient.Provider, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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 { | type azDatasourceExecutor interface { | ||||||
| 	ExecuteTimeSeriesQuery(ctx context.Context, originalQueries []backend.DataQuery, dsInfo types.DatasourceInfo, client *http.Client, url string, tracer tracing.Tracer) (*backend.QueryDataResponse, error) | 	ExecuteTimeSeriesQuery(ctx context.Context, originalQueries []backend.DataQuery, dsInfo types.DatasourceInfo, client *http.Client, url string, tracer tracing.Tracer) (*backend.QueryDataResponse, error) | ||||||
| 	ResourceRequest(rw http.ResponseWriter, req *http.Request, cli *http.Client) | 	ResourceRequest(rw http.ResponseWriter, req *http.Request, cli *http.Client) | ||||||
|  |  | ||||||
|  | @ -51,6 +51,40 @@ func TestNewInstanceSettings(t *testing.T) { | ||||||
| 			}, | 			}, | ||||||
| 			Err: require.NoError, | 			Err: require.NoError, | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "creates an instance for customized cloud", | ||||||
|  | 			settings: backend.DataSourceInstanceSettings{ | ||||||
|  | 				JSONData:                []byte(`{"cloudName":"customizedazuremonitor","customizedRoutes":{"Route":{"URL":"url"}},"azureAuthType":"clientsecret"}`), | ||||||
|  | 				DecryptedSecureJSONData: map[string]string{"clientSecret": "secret"}, | ||||||
|  | 				ID:                      50, | ||||||
|  | 			}, | ||||||
|  | 			expectedModel: types.DatasourceInfo{ | ||||||
|  | 				Cloud: "AzureCustomizedCloud", | ||||||
|  | 				Credentials: &azcredentials.AzureClientSecretCredentials{ | ||||||
|  | 					AzureCloud:   "AzureCustomizedCloud", | ||||||
|  | 					ClientSecret: "secret", | ||||||
|  | 				}, | ||||||
|  | 				Settings: types.AzureMonitorSettings{}, | ||||||
|  | 				Routes: map[string]types.AzRoute{ | ||||||
|  | 					"Route": { | ||||||
|  | 						URL: "url", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				JSONData: map[string]interface{}{ | ||||||
|  | 					"azureAuthType": "clientsecret", | ||||||
|  | 					"cloudName":     "customizedazuremonitor", | ||||||
|  | 					"customizedRoutes": map[string]interface{}{ | ||||||
|  | 						"Route": map[string]interface{}{ | ||||||
|  | 							"URL": "url", | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				DatasourceID:            50, | ||||||
|  | 				DecryptedSecureJSONData: map[string]string{"clientSecret": "secret"}, | ||||||
|  | 				Services:                map[string]types.DatasourceService{}, | ||||||
|  | 			}, | ||||||
|  | 			Err: require.NoError, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	cfg := &setting.Cfg{ | 	cfg := &setting.Cfg{ | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ const ( | ||||||
| 	azureMonitorChina        = "chinaazuremonitor" | 	azureMonitorChina        = "chinaazuremonitor" | ||||||
| 	azureMonitorUSGovernment = "govazuremonitor" | 	azureMonitorUSGovernment = "govazuremonitor" | ||||||
| 	azureMonitorGermany      = "germanyazuremonitor" | 	azureMonitorGermany      = "germanyazuremonitor" | ||||||
|  | 	azureMonitorCustomized   = "customizedazuremonitor" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func getAuthType(cfg *setting.Cfg, jsonData *simplejson.Json) string { | func getAuthType(cfg *setting.Cfg, jsonData *simplejson.Json) string { | ||||||
|  | @ -53,6 +54,8 @@ func getDefaultAzureCloud(cfg *setting.Cfg) (string, error) { | ||||||
| 		return azsettings.AzureUSGovernment, nil | 		return azsettings.AzureUSGovernment, nil | ||||||
| 	case azsettings.AzureGermany: | 	case azsettings.AzureGermany: | ||||||
| 		return azsettings.AzureGermany, nil | 		return azsettings.AzureGermany, nil | ||||||
|  | 	case azsettings.AzureCustomized: | ||||||
|  | 		return azsettings.AzureCustomized, nil | ||||||
| 	case "": | 	case "": | ||||||
| 		// Not set cloud defaults to public
 | 		// Not set cloud defaults to public
 | ||||||
| 		return azsettings.AzurePublic, nil | 		return azsettings.AzurePublic, nil | ||||||
|  | @ -72,6 +75,8 @@ func normalizeAzureCloud(cloudName string) (string, error) { | ||||||
| 		return azsettings.AzureUSGovernment, nil | 		return azsettings.AzureUSGovernment, nil | ||||||
| 	case azureMonitorGermany: | 	case azureMonitorGermany: | ||||||
| 		return azsettings.AzureGermany, nil | 		return azsettings.AzureGermany, nil | ||||||
|  | 	case azureMonitorCustomized: | ||||||
|  | 		return azsettings.AzureCustomized, nil | ||||||
| 	default: | 	default: | ||||||
| 		err := fmt.Errorf("the cloud '%s' not supported", cloudName) | 		err := fmt.Errorf("the cloud '%s' not supported", cloudName) | ||||||
| 		return "", err | 		return "", err | ||||||
|  |  | ||||||
|  | @ -33,6 +33,11 @@ type AzureMonitorSettings struct { | ||||||
| 	AppInsightsAppId             string `json:"appInsightsAppId"` | 	AppInsightsAppId             string `json:"appInsightsAppId"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // AzureMonitorCustomizedCloudSettings is the extended Azure Monitor settings for customized cloud
 | ||||||
|  | type AzureMonitorCustomizedCloudSettings struct { | ||||||
|  | 	CustomizedRoutes map[string]AzRoute `json:"customizedRoutes"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type DatasourceService struct { | type DatasourceService struct { | ||||||
| 	URL        string | 	URL        string | ||||||
| 	HTTPClient *http.Client | 	HTTPClient *http.Client | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue