From 5e8bd48c3c984e3b051b8263668f764ac62fb0ab Mon Sep 17 00:00:00 2001 From: ZakharE Date: Tue, 23 May 2023 14:01:49 +0300 Subject: [PATCH] AzureMonitor: Remove `simplejson` * tsdb: azuremonitor: Remove usage of simplejson * Review fixes * Fix lint errors; review fix --- pkg/tsdb/azuremonitor/azuremonitor.go | 17 ++-- pkg/tsdb/azuremonitor/credentials.go | 20 ++-- pkg/tsdb/azuremonitor/credentials_test.go | 93 +++++++++---------- pkg/tsdb/azuremonitor/macros/macros.go | 26 ++++-- .../metrics/azuremonitor-datasource_test.go | 5 +- .../azuremonitor/metrics/migrations_test.go | 3 +- .../azure-resource-graph-datasource.go | 7 +- .../azure-resource-graph-datasource_test.go | 3 +- pkg/tsdb/azuremonitor/types/types.go | 12 +++ 9 files changed, 98 insertions(+), 88 deletions(-) diff --git a/pkg/tsdb/azuremonitor/azuremonitor.go b/pkg/tsdb/azuremonitor/azuremonitor.go index 42dccdd8ba3..9936eb13a3d 100644 --- a/pkg/tsdb/azuremonitor/azuremonitor.go +++ b/pkg/tsdb/azuremonitor/azuremonitor.go @@ -17,7 +17,6 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" "github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter" - "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/setting" @@ -83,23 +82,19 @@ func getDatasourceService(settings *backend.DataSourceInstanceSettings, cfg *set func NewInstanceSettings(cfg *setting.Cfg, clientProvider *httpclient.Provider, executors map[string]azDatasourceExecutor) datasource.InstanceFactoryFunc { return func(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { - jsonData, err := simplejson.NewJson(settings.JSONData) - if err != nil { - return nil, fmt.Errorf("error reading settings: %w", err) - } jsonDataObj := map[string]any{} - err = json.Unmarshal(settings.JSONData, &jsonDataObj) + err := json.Unmarshal(settings.JSONData, &jsonDataObj) if err != nil { return nil, fmt.Errorf("error reading settings: %w", err) } - azMonitorSettings := types.AzureMonitorSettings{} - err = json.Unmarshal(settings.JSONData, &azMonitorSettings) + azSettings := types.AzureSettings{} + err = json.Unmarshal(settings.JSONData, &azSettings) if err != nil { return nil, fmt.Errorf("error reading settings: %w", err) } - cloud, err := getAzureCloud(cfg, jsonData) + cloud, err := getAzureCloud(cfg, &azSettings.AzureClientSettings) if err != nil { return nil, fmt.Errorf("error getting credentials: %w", err) } @@ -109,7 +104,7 @@ func NewInstanceSettings(cfg *setting.Cfg, clientProvider *httpclient.Provider, return nil, err } - credentials, err := getAzureCredentials(cfg, jsonData, settings.DecryptedSecureJSONData) + credentials, err := getAzureCredentials(cfg, &azSettings.AzureClientSettings, settings.DecryptedSecureJSONData) if err != nil { return nil, fmt.Errorf("error getting credentials: %w", err) } @@ -117,7 +112,7 @@ func NewInstanceSettings(cfg *setting.Cfg, clientProvider *httpclient.Provider, model := types.DatasourceInfo{ Cloud: cloud, Credentials: credentials, - Settings: azMonitorSettings, + Settings: azSettings.AzureMonitorSettings, JSONData: jsonDataObj, DecryptedSecureJSONData: settings.DecryptedSecureJSONData, DatasourceID: settings.ID, diff --git a/pkg/tsdb/azuremonitor/credentials.go b/pkg/tsdb/azuremonitor/credentials.go index d5ccdb00a61..2e9f473d981 100644 --- a/pkg/tsdb/azuremonitor/credentials.go +++ b/pkg/tsdb/azuremonitor/credentials.go @@ -6,8 +6,8 @@ import ( "github.com/grafana/grafana-azure-sdk-go/azcredentials" "github.com/grafana/grafana-azure-sdk-go/azsettings" - "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/tsdb/azuremonitor/types" ) // Azure cloud names specific to Azure Monitor @@ -18,12 +18,12 @@ const ( azureMonitorCustomized = "customizedazuremonitor" ) -func getAuthType(cfg *setting.Cfg, jsonData *simplejson.Json) string { - if azureAuthType := jsonData.Get("azureAuthType").MustString(); azureAuthType != "" { +func getAuthType(cfg *setting.Cfg, jsonData *types.AzureClientSettings) string { + if azureAuthType := jsonData.AzureAuthType; azureAuthType != "" { return azureAuthType } else { - tenantId := jsonData.Get("tenantId").MustString() - clientId := jsonData.Get("clientId").MustString() + tenantId := jsonData.TenantId + clientId := jsonData.ClientId // If authentication type isn't explicitly specified and datasource has client credentials, // then this is existing datasource which is configured for app registration (client secret) @@ -81,14 +81,14 @@ func normalizeAzureCloud(cloudName string) (string, error) { } } -func getAzureCloud(cfg *setting.Cfg, jsonData *simplejson.Json) (string, error) { +func getAzureCloud(cfg *setting.Cfg, jsonData *types.AzureClientSettings) (string, error) { authType := getAuthType(cfg, jsonData) switch authType { case azcredentials.AzureAuthManagedIdentity: // In case of managed identity, the cloud is always same as where Grafana is hosted return getDefaultAzureCloud(cfg) case azcredentials.AzureAuthClientSecret: - if cloud := jsonData.Get("cloudName").MustString(); cloud != "" { + if cloud := jsonData.CloudName; cloud != "" { return normalizeAzureCloud(cloud) } else { return getDefaultAzureCloud(cfg) @@ -99,7 +99,7 @@ func getAzureCloud(cfg *setting.Cfg, jsonData *simplejson.Json) (string, error) } } -func getAzureCredentials(cfg *setting.Cfg, jsonData *simplejson.Json, secureJsonData map[string]string) (azcredentials.AzureCredentials, error) { +func getAzureCredentials(cfg *setting.Cfg, jsonData *types.AzureClientSettings, secureJsonData map[string]string) (azcredentials.AzureCredentials, error) { authType := getAuthType(cfg, jsonData) switch authType { @@ -117,8 +117,8 @@ func getAzureCredentials(cfg *setting.Cfg, jsonData *simplejson.Json, secureJson } credentials := &azcredentials.AzureClientSecretCredentials{ AzureCloud: cloud, - TenantId: jsonData.Get("tenantId").MustString(), - ClientId: jsonData.Get("clientId").MustString(), + TenantId: jsonData.TenantId, + ClientId: jsonData.ClientId, ClientSecret: secureJsonData["clientSecret"], } return credentials, nil diff --git a/pkg/tsdb/azuremonitor/credentials_test.go b/pkg/tsdb/azuremonitor/credentials_test.go index 16b16c04602..103c864cac6 100644 --- a/pkg/tsdb/azuremonitor/credentials_test.go +++ b/pkg/tsdb/azuremonitor/credentials_test.go @@ -3,10 +3,11 @@ package azuremonitor import ( "testing" + "github.com/grafana/grafana/pkg/tsdb/azuremonitor/types" + "github.com/grafana/grafana-azure-sdk-go/azcredentials" "github.com/grafana/grafana-azure-sdk-go/azsettings" - "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/setting" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -21,9 +22,9 @@ func TestCredentials_getAuthType(t *testing.T) { cfg.Azure.ManagedIdentityEnabled = true t.Run("should be client secret if auth type is set to client secret", func(t *testing.T) { - jsonData := simplejson.NewFromAny(map[string]interface{}{ - "azureAuthType": azcredentials.AzureAuthClientSecret, - }) + jsonData := &types.AzureClientSettings{ + AzureAuthType: azcredentials.AzureAuthClientSecret, + } authType := getAuthType(cfg, jsonData) @@ -31,9 +32,9 @@ func TestCredentials_getAuthType(t *testing.T) { }) t.Run("should be managed identity if datasource not configured", func(t *testing.T) { - jsonData := simplejson.NewFromAny(map[string]interface{}{ - "azureAuthType": "", - }) + jsonData := &types.AzureClientSettings{ + AzureAuthType: "", + } authType := getAuthType(cfg, jsonData) @@ -41,11 +42,11 @@ func TestCredentials_getAuthType(t *testing.T) { }) t.Run("should be client secret if auth type not specified but credentials configured", func(t *testing.T) { - jsonData := simplejson.NewFromAny(map[string]interface{}{ - "azureAuthType": "", - "tenantId": "9b9d90ee-a5cc-49c2-b97e-0d1b0f086b5c", - "clientId": "849ccbb0-92eb-4226-b228-ef391abd8fe6", - }) + jsonData := &types.AzureClientSettings{ + AzureAuthType: "", + TenantId: "9b9d90ee-a5cc-49c2-b97e-0d1b0f086b5c", + ClientId: "849ccbb0-92eb-4226-b228-ef391abd8fe6", + } authType := getAuthType(cfg, jsonData) @@ -57,9 +58,9 @@ func TestCredentials_getAuthType(t *testing.T) { cfg.Azure.ManagedIdentityEnabled = false t.Run("should be managed identity if auth type is set to managed identity", func(t *testing.T) { - jsonData := simplejson.NewFromAny(map[string]interface{}{ - "azureAuthType": azcredentials.AzureAuthManagedIdentity, - }) + jsonData := &types.AzureClientSettings{ + AzureAuthType: azcredentials.AzureAuthManagedIdentity, + } authType := getAuthType(cfg, jsonData) @@ -67,9 +68,9 @@ func TestCredentials_getAuthType(t *testing.T) { }) t.Run("should be client secret if datasource not configured", func(t *testing.T) { - jsonData := simplejson.NewFromAny(map[string]interface{}{ - "azureAuthType": "", - }) + jsonData := &types.AzureClientSettings{ + AzureAuthType: "", + } authType := getAuthType(cfg, jsonData) @@ -86,10 +87,10 @@ func TestCredentials_getAzureCloud(t *testing.T) { } t.Run("when auth type is managed identity", func(t *testing.T) { - jsonData := simplejson.NewFromAny(map[string]interface{}{ - "azureAuthType": azcredentials.AzureAuthManagedIdentity, - "cloudName": azureMonitorUSGovernment, - }) + jsonData := &types.AzureClientSettings{ + AzureAuthType: azcredentials.AzureAuthManagedIdentity, + CloudName: azureMonitorUSGovernment, + } t.Run("should be from server configuration regardless of datasource value", func(t *testing.T) { cloud, err := getAzureCloud(cfg, jsonData) @@ -114,10 +115,10 @@ func TestCredentials_getAzureCloud(t *testing.T) { t.Run("when auth type is client secret", func(t *testing.T) { t.Run("should be from datasource value normalized to known cloud name", func(t *testing.T) { - jsonData := simplejson.NewFromAny(map[string]interface{}{ - "azureAuthType": azcredentials.AzureAuthClientSecret, - "cloudName": azureMonitorUSGovernment, - }) + jsonData := &types.AzureClientSettings{ + AzureAuthType: azcredentials.AzureAuthClientSecret, + CloudName: azureMonitorUSGovernment, + } cloud, err := getAzureCloud(cfg, jsonData) require.NoError(t, err) @@ -126,10 +127,10 @@ func TestCredentials_getAzureCloud(t *testing.T) { }) t.Run("should be from server configuration if not set in datasource", func(t *testing.T) { - jsonData := simplejson.NewFromAny(map[string]interface{}{ - "azureAuthType": azcredentials.AzureAuthClientSecret, - "cloudName": "", - }) + jsonData := &types.AzureClientSettings{ + AzureAuthType: azcredentials.AzureAuthClientSecret, + CloudName: "", + } cloud, err := getAzureCloud(cfg, jsonData) require.NoError(t, err) @@ -151,12 +152,12 @@ func TestCredentials_getAzureCredentials(t *testing.T) { } t.Run("when auth type is managed identity", func(t *testing.T) { - jsonData := simplejson.NewFromAny(map[string]interface{}{ - "azureAuthType": azcredentials.AzureAuthManagedIdentity, - "cloudName": azureMonitorUSGovernment, - "tenantId": "9b9d90ee-a5cc-49c2-b97e-0d1b0f086b5c", - "clientId": "849ccbb0-92eb-4226-b228-ef391abd8fe6", - }) + jsonData := &types.AzureClientSettings{ + AzureAuthType: azcredentials.AzureAuthManagedIdentity, + CloudName: azureMonitorUSGovernment, + TenantId: "9b9d90ee-a5cc-49c2-b97e-0d1b0f086b5c", + ClientId: "849ccbb0-92eb-4226-b228-ef391abd8fe6", + } t.Run("should return managed identity credentials", func(t *testing.T) { credentials, err := getAzureCredentials(cfg, jsonData, secureJsonData) @@ -170,26 +171,22 @@ func TestCredentials_getAzureCredentials(t *testing.T) { }) t.Run("when auth type is client secret", func(t *testing.T) { - jsonData := simplejson.NewFromAny(map[string]interface{}{ - "azureAuthType": azcredentials.AzureAuthClientSecret, - "cloudName": azUSGovManagement, - "tenantId": "9b9d90ee-a5cc-49c2-b97e-0d1b0f086b5c", - "clientId": "849ccbb0-92eb-4226-b228-ef391abd8fe6", - }) + jsonData := &types.AzureClientSettings{ + AzureAuthType: azcredentials.AzureAuthClientSecret, + CloudName: azureMonitorUSGovernment, + TenantId: "9b9d90ee-a5cc-49c2-b97e-0d1b0f086b5c", + ClientId: "849ccbb0-92eb-4226-b228-ef391abd8fe6", + } t.Run("should return client secret credentials", func(t *testing.T) { - cfg := &setting.Cfg{ - Azure: &azsettings.AzureSettings{ - Cloud: azsettings.AzureChina, - }, - } + cfg := &setting.Cfg{} credentials, err := getAzureCredentials(cfg, jsonData, secureJsonData) require.NoError(t, err) require.IsType(t, &azcredentials.AzureClientSecretCredentials{}, credentials) clientSecretCredentials := credentials.(*azcredentials.AzureClientSecretCredentials) - assert.Equal(t, azsettings.AzureChina, clientSecretCredentials.AzureCloud) + assert.Equal(t, azsettings.AzureUSGovernment, clientSecretCredentials.AzureCloud) assert.Equal(t, "9b9d90ee-a5cc-49c2-b97e-0d1b0f086b5c", clientSecretCredentials.TenantId) assert.Equal(t, "849ccbb0-92eb-4226-b228-ef391abd8fe6", clientSecretCredentials.ClientId) assert.Equal(t, "59e3498f-eb12-4943-b8f0-a5aa42640058", clientSecretCredentials.ClientSecret) diff --git a/pkg/tsdb/azuremonitor/macros/macros.go b/pkg/tsdb/azuremonitor/macros/macros.go index b65d1e79e04..7b9e54861c2 100644 --- a/pkg/tsdb/azuremonitor/macros/macros.go +++ b/pkg/tsdb/azuremonitor/macros/macros.go @@ -1,6 +1,7 @@ package macros import ( + "encoding/json" "fmt" "regexp" "strings" @@ -8,12 +9,10 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/tsdb/azuremonitor/kinds/dataquery" "github.com/grafana/grafana/pkg/tsdb/azuremonitor/types" - "github.com/grafana/grafana/pkg/tsdb/legacydata/interval" + "github.com/grafana/grafana/pkg/tsdb/intervalv2" ) const rsIdentifier = `__(timeFilter|timeFrom|timeTo|interval|contains|escapeMulti)` @@ -90,6 +89,11 @@ func (m *kqlMacroEngine) Interpolate(logger log.Logger, query backend.DataQuery, return kql, nil } +type interval struct { + IntervalMs int64 + Interval string +} + func (m *kqlMacroEngine) evaluateMacro(logger log.Logger, name string, defaultTimeField string, args []string, dsInfo types.DatasourceInfo) (string, error) { switch name { case "timeFilter": @@ -111,16 +115,22 @@ func (m *kqlMacroEngine) evaluateMacro(logger log.Logger, name string, defaultTi from := m.timeRange.From.UnixNano() // default to "100 datapoints" if nothing in the query is more specific defaultInterval := time.Duration((to - from) / 60) - model, err := simplejson.NewJson(m.query.JSON) + var queryInterval interval + err := json.Unmarshal(m.query.JSON, &queryInterval) if err != nil { logger.Warn("Unable to parse model from query", "JSON", m.query.JSON) it = defaultInterval } else { - it, err = interval.GetIntervalFrom(&datasources.DataSource{ - JsonData: simplejson.NewFromAny(dsInfo.JSONData), - }, model, defaultInterval) + var ( + dsInterval string + ok bool + ) + if dsInterval, ok = dsInfo.JSONData["interval"].(string); !ok { + dsInterval = "" + } + it, err = intervalv2.GetIntervalFrom(dsInterval, queryInterval.Interval, queryInterval.IntervalMs, defaultInterval) if err != nil { - logger.Warn("Unable to get interval from query", "model", model) + logger.Warn("Unable to get interval from query", "model", queryInterval) it = defaultInterval } } diff --git a/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource_test.go b/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource_test.go index bd73dae3306..2764f3734ee 100644 --- a/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource_test.go +++ b/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource_test.go @@ -19,7 +19,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/tsdb/azuremonitor/testdata" azTime "github.com/grafana/grafana/pkg/tsdb/azuremonitor/time" @@ -326,7 +325,7 @@ func TestAzureMonitorBuildQueries(t *testing.T) { azureMonitorQuery.URL = "/subscriptions/12345678-aaaa-bbbb-cccc-123456789abc/resourceGroups/grafanastaging/providers/Microsoft.Compute/virtualMachines/grafana/providers/microsoft.insights/metrics" } - if diff := cmp.Diff(azureMonitorQuery, queries[0], cmpopts.IgnoreUnexported(simplejson.Json{}), cmpopts.IgnoreFields(types.AzureMonitorQuery{}, "Params", "Dimensions")); diff != "" { + if diff := cmp.Diff(azureMonitorQuery, queries[0], cmpopts.IgnoreUnexported(struct{}{}), cmpopts.IgnoreFields(types.AzureMonitorQuery{}, "Params", "Dimensions")); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } @@ -353,7 +352,7 @@ func TestCustomNamespace(t *testing.T) { { JSON: []byte(`{ "azureMonitor": { - "customNamespace": "custom/namespace" + "customNamespace": "custom/namespace" } }`), }, diff --git a/pkg/tsdb/azuremonitor/metrics/migrations_test.go b/pkg/tsdb/azuremonitor/metrics/migrations_test.go index 56b7508dbbe..1ac1e29601e 100644 --- a/pkg/tsdb/azuremonitor/metrics/migrations_test.go +++ b/pkg/tsdb/azuremonitor/metrics/migrations_test.go @@ -5,7 +5,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/tsdb/azuremonitor/types" ) @@ -54,7 +53,7 @@ func TestDimensionFiltersMigration(t *testing.T) { t.Run(tt.name, func(t *testing.T) { filters := MigrateDimensionFilters(tt.dimensionFilters) - if diff := cmp.Diff(tt.expectedDimensionFilters, filters, cmpopts.IgnoreUnexported(simplejson.Json{})); diff != "" { + if diff := cmp.Diff(tt.expectedDimensionFilters, filters, cmpopts.IgnoreUnexported(struct{}{})); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) diff --git a/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource.go b/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource.go index 20e9f70d098..06b011f0436 100644 --- a/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource.go +++ b/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource.go @@ -15,7 +15,6 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/data" "go.opentelemetry.io/otel/attribute" - "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/tsdb/azuremonitor/kinds/dataquery" @@ -139,15 +138,15 @@ func (e *AzureResourceGraphDatasource) executeQuery(ctx context.Context, logger dataResponse.Frames = frames return dataResponse } - - model, err := simplejson.NewJson(query.JSON) + var model dataquery.AzureMonitorQuery + err := json.Unmarshal(query.JSON, &model) if err != nil { dataResponse.Error = err return dataResponse } reqBody, err := json.Marshal(map[string]interface{}{ - "subscriptions": model.Get("subscriptions").MustStringArray(), + "subscriptions": model.Subscriptions, "query": query.InterpolatedQuery, "options": map[string]string{"resultFormat": "table"}, }) diff --git a/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource_test.go b/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource_test.go index d8bf3ced7a5..cc56741a071 100644 --- a/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource_test.go +++ b/pkg/tsdb/azuremonitor/resourcegraph/azure-resource-graph-datasource_test.go @@ -17,7 +17,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/tsdb/azuremonitor/loganalytics" "github.com/grafana/grafana/pkg/tsdb/azuremonitor/types" @@ -77,7 +76,7 @@ func TestBuildingAzureResourceGraphQueries(t *testing.T) { t.Run(tt.name, func(t *testing.T) { queries, err := datasource.buildQueries(logger, tt.queryModel, types.DatasourceInfo{}) tt.Err(t, err) - if diff := cmp.Diff(tt.azureResourceGraphQueries, queries, cmpopts.IgnoreUnexported(simplejson.Json{})); diff != "" { + if diff := cmp.Diff(tt.azureResourceGraphQueries, queries, cmpopts.IgnoreUnexported(struct{}{})); diff != "" { t.Errorf("Result mismatch (-want +got):\n%s", diff) } }) diff --git a/pkg/tsdb/azuremonitor/types/types.go b/pkg/tsdb/azuremonitor/types/types.go index ee464128897..1b78d125d40 100644 --- a/pkg/tsdb/azuremonitor/types/types.go +++ b/pkg/tsdb/azuremonitor/types/types.go @@ -30,12 +30,24 @@ type AzRoute struct { Headers map[string]string } +type AzureSettings struct { + AzureMonitorSettings + AzureClientSettings +} + type AzureMonitorSettings struct { SubscriptionId string `json:"subscriptionId"` LogAnalyticsDefaultWorkspace string `json:"logAnalyticsDefaultWorkspace"` AppInsightsAppId string `json:"appInsightsAppId"` } +type AzureClientSettings struct { + AzureAuthType string + CloudName string + TenantId string + ClientId string +} + // AzureMonitorCustomizedCloudSettings is the extended Azure Monitor settings for customized cloud type AzureMonitorCustomizedCloudSettings struct { CustomizedRoutes map[string]AzRoute `json:"customizedRoutes"`