mirror of
https://github.com/grafana/grafana.git
synced 2025-01-15 19:22:34 -06:00
AzureMonitor: Retrieve Azure clouds from SDK (#87944)
* AzureMonitor: get the list of azure clouds from the SDK instead of from a hard coded list * add azure-sdk to yarn.lock * merge legacy with custom options * Normalize legacy cloud names * Workaround: send new credential format to backend while we wait to migrate to the new format * Lint fix * resolveLegacyCloudName should not return undefined * re-add undefined handling in resolveLegacyCloudName so that we fallback to getDefaultAzureCloud when not defined --------- Co-authored-by: Jeremy Angel <jeremyangel@microsoft.com> Co-authored-by: Andreas Christou <andreas.christou@grafana.com>
This commit is contained in:
parent
1c339db7ad
commit
ba4c1fcf76
@ -4,7 +4,7 @@ import { DataSourceInstanceSettings, ScopedVars } from '@grafana/data';
|
||||
import { DataSourceWithBackend, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
|
||||
import ResponseParser from '../azure_monitor/response_parser';
|
||||
import { getAuthType, getAzureCloud, getAzurePortalUrl } from '../credentials';
|
||||
import { getAuthType } from '../credentials';
|
||||
import {
|
||||
AzureAPIResponse,
|
||||
AzureDataSourceJsonData,
|
||||
@ -24,7 +24,6 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
||||
AzureDataSourceJsonData
|
||||
> {
|
||||
resourcePath: string;
|
||||
azurePortalUrl: string;
|
||||
declare applicationId: string;
|
||||
|
||||
defaultSubscriptionId?: string;
|
||||
@ -40,8 +39,6 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend<
|
||||
|
||||
this.resourcePath = `${routeNames.logAnalytics}`;
|
||||
this.azureMonitorPath = `${routeNames.azureMonitor}/subscriptions`;
|
||||
const cloud = getAzureCloud(instanceSettings);
|
||||
this.azurePortalUrl = getAzurePortalUrl(cloud);
|
||||
|
||||
this.defaultSubscriptionId = this.instanceSettings.jsonData.subscriptionId || '';
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import { find, startsWith } from 'lodash';
|
||||
import { DataSourceInstanceSettings, ScopedVars } from '@grafana/data';
|
||||
import { DataSourceWithBackend, getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
|
||||
import { getAuthType, getAzureCloud, getAzurePortalUrl } from '../credentials';
|
||||
import { getAuthType } from '../credentials';
|
||||
import TimegrainConverter from '../time_grain_converter';
|
||||
import {
|
||||
AzureDataSourceJsonData,
|
||||
@ -46,7 +46,6 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
||||
defaultSubscriptionId?: string;
|
||||
basicLogsEnabled?: boolean;
|
||||
resourcePath: string;
|
||||
azurePortalUrl: string;
|
||||
declare resourceGroup: string;
|
||||
declare resourceName: string;
|
||||
|
||||
@ -59,9 +58,7 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
|
||||
this.defaultSubscriptionId = instanceSettings.jsonData.subscriptionId;
|
||||
this.basicLogsEnabled = instanceSettings.jsonData.basicLogsEnabled;
|
||||
|
||||
const cloud = getAzureCloud(instanceSettings);
|
||||
this.resourcePath = routeNames.azureMonitor;
|
||||
this.azurePortalUrl = getAzurePortalUrl(cloud);
|
||||
}
|
||||
|
||||
isConfigured(): boolean {
|
||||
|
@ -15,11 +15,6 @@ const setup = (propsFunc?: (props: Props) => Props) => {
|
||||
clientId: '34509fad-c0r9-45df-9e25-f1ee34af6900',
|
||||
clientSecret: undefined,
|
||||
},
|
||||
legacyAzureCloudOptions: [
|
||||
{ value: 'azuremonitor', label: 'Azure' },
|
||||
{ value: 'govazuremonitor', label: 'Azure US Government' },
|
||||
{ value: 'chinaazuremonitor', label: 'Azure China' },
|
||||
],
|
||||
onCredentialsChange: jest.fn(),
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import { getAzureClouds } from '@grafana/azure-sdk';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { ConfigSection } from '@grafana/experimental';
|
||||
import { Select, Field } from '@grafana/ui';
|
||||
@ -16,17 +17,23 @@ export interface Props {
|
||||
userIdentityEnabled: boolean;
|
||||
credentials: AzureCredentials;
|
||||
azureCloudOptions?: SelectableValue[];
|
||||
legacyAzureCloudOptions?: SelectableValue[];
|
||||
onCredentialsChange: (updatedCredentials: AzureCredentials) => void;
|
||||
disabled?: boolean;
|
||||
children?: JSX.Element;
|
||||
}
|
||||
|
||||
export function getAzureCloudOptions(): Array<SelectableValue<string>> {
|
||||
const cloudInfo = getAzureClouds();
|
||||
|
||||
return cloudInfo.map((cloud) => ({
|
||||
value: cloud.name,
|
||||
label: cloud.displayName,
|
||||
}));
|
||||
}
|
||||
|
||||
export const AzureCredentialsForm = (props: Props) => {
|
||||
const {
|
||||
credentials,
|
||||
azureCloudOptions,
|
||||
legacyAzureCloudOptions,
|
||||
onCredentialsChange,
|
||||
disabled,
|
||||
managedIdentityEnabled,
|
||||
@ -102,7 +109,7 @@ export const AzureCredentialsForm = (props: Props) => {
|
||||
{credentials.authType === 'clientsecret' && (
|
||||
<AppRegistrationCredentials
|
||||
credentials={credentials}
|
||||
azureCloudOptions={legacyAzureCloudOptions}
|
||||
azureCloudOptions={getAzureCloudOptions()}
|
||||
onCredentialsChange={onCredentialsChange}
|
||||
disabled={disabled}
|
||||
/>
|
||||
@ -111,7 +118,7 @@ export const AzureCredentialsForm = (props: Props) => {
|
||||
{credentials.authType === 'currentuser' && (
|
||||
<CurrentUserFallbackCredentials
|
||||
credentials={credentials}
|
||||
azureCloudOptions={azureCloudOptions}
|
||||
azureCloudOptions={getAzureCloudOptions()}
|
||||
onCredentialsChange={onCredentialsChange}
|
||||
disabled={disabled}
|
||||
managedIdentityEnabled={managedIdentityEnabled}
|
||||
|
@ -7,23 +7,10 @@ import { config } from '@grafana/runtime';
|
||||
import { getCredentials, updateCredentials } from '../../credentials';
|
||||
import { AzureDataSourceSettings, AzureCredentials } from '../../types';
|
||||
|
||||
import { AzureCredentialsForm } from './AzureCredentialsForm';
|
||||
import { AzureCredentialsForm, getAzureCloudOptions } from './AzureCredentialsForm';
|
||||
import { BasicLogsToggle } from './BasicLogsToggle';
|
||||
import { DefaultSubscription } from './DefaultSubscription';
|
||||
|
||||
const legacyAzureClouds: SelectableValue[] = [
|
||||
{ value: 'azuremonitor', label: 'Azure' },
|
||||
{ value: 'govazuremonitor', label: 'Azure US Government' },
|
||||
{ value: 'chinaazuremonitor', label: 'Azure China' },
|
||||
];
|
||||
|
||||
// This will be pulled from the azure-sdk in future
|
||||
const azureClouds: SelectableValue[] = [
|
||||
{ value: 'AzureCloud', label: 'Azure' },
|
||||
{ value: 'AzureUSGovernment', label: 'Azure US Government' },
|
||||
{ value: 'AzureChinaCloud', label: 'Azure China' },
|
||||
];
|
||||
|
||||
export interface Props {
|
||||
options: AzureDataSourceSettings;
|
||||
updateOptions: (optionsFunc: (options: AzureDataSourceSettings) => AzureDataSourceSettings) => void;
|
||||
@ -67,8 +54,7 @@ export const MonitorConfig = (props: Props) => {
|
||||
workloadIdentityEnabled={config.azure.workloadIdentityEnabled}
|
||||
userIdentityEnabled={config.azure.userIdentityEnabled}
|
||||
credentials={credentials}
|
||||
azureCloudOptions={azureClouds}
|
||||
legacyAzureCloudOptions={legacyAzureClouds}
|
||||
azureCloudOptions={getAzureCloudOptions()}
|
||||
onCredentialsChange={onCredentialsChange}
|
||||
disabled={props.options.readOnly}
|
||||
>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { getAzureClouds } from '@grafana/azure-sdk';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
import {
|
||||
@ -29,31 +30,43 @@ export function getAuthType(options: AzureDataSourceSettings | AzureDataSourceIn
|
||||
return options.jsonData.azureAuthType;
|
||||
}
|
||||
|
||||
function getDefaultAzureCloud(): string {
|
||||
switch (config.azure.cloud) {
|
||||
case AzureCloud.Public:
|
||||
case AzureCloud.None:
|
||||
case undefined:
|
||||
return 'azuremonitor';
|
||||
case AzureCloud.China:
|
||||
return 'chinaazuremonitor';
|
||||
case AzureCloud.USGovernment:
|
||||
return 'govazuremonitor';
|
||||
function resolveLegacyCloudName(cloudName: string | undefined): string | undefined {
|
||||
if (!cloudName) {
|
||||
// if undefined, allow the code to fallback to calling getDefaultAzureCloud() since that has the complete logic for handling an empty cloud name
|
||||
return undefined;
|
||||
}
|
||||
switch (cloudName) {
|
||||
case 'azuremonitor':
|
||||
return AzureCloud.Public;
|
||||
case 'chinaazuremonitor':
|
||||
return AzureCloud.China;
|
||||
case 'govazuremonitor':
|
||||
return AzureCloud.USGovernment;
|
||||
default:
|
||||
throw new Error(`The cloud '${config.azure.cloud}' not supported.`);
|
||||
return cloudName;
|
||||
}
|
||||
}
|
||||
|
||||
export function getAzurePortalUrl(azureCloud: string): string {
|
||||
switch (azureCloud) {
|
||||
case 'azuremonitor':
|
||||
return 'https://portal.azure.com';
|
||||
case 'chinaazuremonitor':
|
||||
return 'https://portal.azure.cn';
|
||||
case 'govazuremonitor':
|
||||
return 'https://portal.azure.us';
|
||||
function getDefaultAzureCloud(): string {
|
||||
const cloudName = resolveLegacyCloudName(config.azure.cloud);
|
||||
|
||||
switch (cloudName) {
|
||||
case AzureCloud.Public:
|
||||
case AzureCloud.None:
|
||||
return AzureCloud.Public;
|
||||
case AzureCloud.China:
|
||||
return AzureCloud.China;
|
||||
case AzureCloud.USGovernment:
|
||||
return AzureCloud.USGovernment;
|
||||
default:
|
||||
throw new Error('The cloud not supported.');
|
||||
const cloudInfo = getAzureClouds();
|
||||
|
||||
for (const cloud of cloudInfo) {
|
||||
if (cloud.name === config.azure.cloud) {
|
||||
return cloud.name;
|
||||
}
|
||||
}
|
||||
throw new Error(`The cloud '${config.azure.cloud}' is unsupported.`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +79,7 @@ export function getAzureCloud(options: AzureDataSourceSettings | AzureDataSource
|
||||
return getDefaultAzureCloud();
|
||||
case 'clientsecret':
|
||||
case 'currentuser':
|
||||
return options.jsonData.cloudName || getDefaultAzureCloud();
|
||||
return resolveLegacyCloudName(options.jsonData.cloudName) || getDefaultAzureCloud();
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,7 +144,7 @@ export function getCredentials(options: AzureDataSourceSettings): AzureCredentia
|
||||
case 'clientsecret':
|
||||
return {
|
||||
authType,
|
||||
azureCloud: options.jsonData.cloudName || getDefaultAzureCloud(),
|
||||
azureCloud: resolveLegacyCloudName(options.jsonData.cloudName) || getDefaultAzureCloud(),
|
||||
tenantId: options.jsonData.tenantId,
|
||||
clientId: options.jsonData.clientId,
|
||||
clientSecret: getSecret(options),
|
||||
@ -177,7 +190,9 @@ export function updateCredentials(
|
||||
jsonData: {
|
||||
...options.jsonData,
|
||||
azureAuthType: credentials.authType,
|
||||
azureCredentials: undefined,
|
||||
azureCredentials: {
|
||||
authType: credentials.authType,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -189,10 +204,15 @@ export function updateCredentials(
|
||||
jsonData: {
|
||||
...options.jsonData,
|
||||
azureAuthType: credentials.authType,
|
||||
cloudName: credentials.azureCloud || getDefaultAzureCloud(),
|
||||
cloudName: resolveLegacyCloudName(credentials.azureCloud) || getDefaultAzureCloud(),
|
||||
tenantId: credentials.tenantId,
|
||||
clientId: credentials.clientId,
|
||||
azureCredentials: undefined,
|
||||
azureCredentials: {
|
||||
authType: credentials.authType,
|
||||
azureCloud: resolveLegacyCloudName(credentials.azureCloud) || getDefaultAzureCloud(),
|
||||
tenantId: credentials.tenantId,
|
||||
clientId: credentials.clientId,
|
||||
},
|
||||
},
|
||||
secureJsonData: {
|
||||
...options.secureJsonData,
|
||||
|
Loading…
Reference in New Issue
Block a user