mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
parent
2303694293
commit
148289258f
@ -2,11 +2,11 @@ import { cx } from '@emotion/css';
|
|||||||
import { FormEvent, useMemo, useState } from 'react';
|
import { FormEvent, useMemo, useState } from 'react';
|
||||||
import { useEffectOnce } from 'react-use';
|
import { useEffectOnce } from 'react-use';
|
||||||
|
|
||||||
|
import { AzureCredentials } from '@grafana/azure-sdk';
|
||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
import { InlineField, InlineFieldRow, InlineSwitch, Input } from '@grafana/ui';
|
import { InlineField, InlineFieldRow, InlineSwitch, Input } from '@grafana/ui';
|
||||||
import { HttpSettingsBaseProps } from '@grafana/ui/src/components/DataSourceSettings/types';
|
import { HttpSettingsBaseProps } from '@grafana/ui/src/components/DataSourceSettings/types';
|
||||||
|
|
||||||
import { AzureCredentials } from './AzureCredentials';
|
|
||||||
import { getAzureCloudOptions, getCredentials, updateCredentials } from './AzureCredentialsConfig';
|
import { getAzureCloudOptions, getCredentials, updateCredentials } from './AzureCredentialsConfig';
|
||||||
import { AzureCredentialsForm } from './AzureCredentialsForm';
|
import { AzureCredentialsForm } from './AzureCredentialsForm';
|
||||||
|
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
export enum AzureCloud {
|
|
||||||
Public = 'AzureCloud',
|
|
||||||
China = 'AzureChinaCloud',
|
|
||||||
USGovernment = 'AzureUSGovernment',
|
|
||||||
None = '',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type AzureAuthType = 'msi' | 'clientsecret' | 'workloadidentity';
|
|
||||||
|
|
||||||
export type ConcealedSecret = symbol;
|
|
||||||
|
|
||||||
interface AzureCredentialsBase {
|
|
||||||
authType: AzureAuthType;
|
|
||||||
defaultSubscriptionId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AzureManagedIdentityCredentials extends AzureCredentialsBase {
|
|
||||||
authType: 'msi';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AzureWorkloadIdentityCredentials extends AzureCredentialsBase {
|
|
||||||
authType: 'workloadidentity';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AzureClientSecretCredentials extends AzureCredentialsBase {
|
|
||||||
authType: 'clientsecret';
|
|
||||||
azureCloud?: string;
|
|
||||||
tenantId?: string;
|
|
||||||
clientId?: string;
|
|
||||||
clientSecret?: string | ConcealedSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type AzureCredentials =
|
|
||||||
| AzureManagedIdentityCredentials
|
|
||||||
| AzureClientSecretCredentials
|
|
||||||
| AzureWorkloadIdentityCredentials;
|
|
||||||
|
|
||||||
export function isCredentialsComplete(credentials: AzureCredentials): boolean {
|
|
||||||
switch (credentials.authType) {
|
|
||||||
case 'msi':
|
|
||||||
case 'workloadidentity':
|
|
||||||
return true;
|
|
||||||
case 'clientsecret':
|
|
||||||
return !!(credentials.azureCloud && credentials.tenantId && credentials.clientId && credentials.clientSecret);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +1,17 @@
|
|||||||
import { getAzureClouds } from '@grafana/azure-sdk';
|
import {
|
||||||
|
AzureCredentials,
|
||||||
|
AzureDataSourceJsonData,
|
||||||
|
AzureDataSourceSecureJsonData,
|
||||||
|
AzureDataSourceSettings,
|
||||||
|
getAzureClouds,
|
||||||
|
getDatasourceCredentials,
|
||||||
|
getDefaultAzureCloud,
|
||||||
|
updateDatasourceCredentials,
|
||||||
|
} from '@grafana/azure-sdk';
|
||||||
import { DataSourceSettings, SelectableValue } from '@grafana/data';
|
import { DataSourceSettings, SelectableValue } from '@grafana/data';
|
||||||
|
import { PromOptions } from '@grafana/prometheus';
|
||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
|
|
||||||
import { AzureCloud, AzureCredentials, ConcealedSecret } from './AzureCredentials';
|
|
||||||
|
|
||||||
const concealed: ConcealedSecret = Symbol('Concealed client secret');
|
|
||||||
|
|
||||||
function getDefaultAzureCloud(): string {
|
|
||||||
return config.azure.cloud || AzureCloud.Public;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSecret(options: DataSourceSettings<any, any>): undefined | string | ConcealedSecret {
|
|
||||||
if (options.secureJsonFields.azureClientSecret) {
|
|
||||||
// The secret is concealed on server
|
|
||||||
return concealed;
|
|
||||||
} else {
|
|
||||||
const secret = options.secureJsonData?.azureClientSecret;
|
|
||||||
return typeof secret === 'string' && secret.length > 0 ? secret : undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function hasCredentials(options: DataSourceSettings<any, any>): boolean {
|
|
||||||
return !!options.jsonData.azureCredentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAzureCloudOptions(): Array<SelectableValue<string>> {
|
export function getAzureCloudOptions(): Array<SelectableValue<string>> {
|
||||||
const cloudInfo = getAzureClouds();
|
const cloudInfo = getAzureClouds();
|
||||||
|
|
||||||
@ -41,101 +29,25 @@ export function getDefaultCredentials(): AzureCredentials {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCredentials(options: DataSourceSettings<any, any>): AzureCredentials {
|
export function getCredentials(options: AzureDataSourceSettings): AzureCredentials {
|
||||||
const credentials = options.jsonData.azureCredentials as AzureCredentials | undefined;
|
const credentials = getDatasourceCredentials(options);
|
||||||
|
if (credentials) {
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
|
||||||
// If no credentials saved, then return empty credentials
|
// If no credentials saved, then return empty credentials
|
||||||
// of type based on whether the managed identity enabled
|
// of type based on whether the managed identity enabled
|
||||||
if (!credentials) {
|
return getDefaultCredentials();
|
||||||
return getDefaultCredentials();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (credentials.authType) {
|
|
||||||
case 'msi':
|
|
||||||
case 'workloadidentity':
|
|
||||||
if (
|
|
||||||
(credentials.authType === 'msi' && config.azure.managedIdentityEnabled) ||
|
|
||||||
(credentials.authType === 'workloadidentity' && config.azure.workloadIdentityEnabled)
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
authType: credentials.authType,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// If authentication type is managed identity or workload identity but either method is disabled in Grafana config,
|
|
||||||
// then we should fallback to an empty app registration (client secret) configuration
|
|
||||||
return {
|
|
||||||
authType: 'clientsecret',
|
|
||||||
azureCloud: getDefaultAzureCloud(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case 'clientsecret':
|
|
||||||
return {
|
|
||||||
authType: 'clientsecret',
|
|
||||||
azureCloud: credentials.azureCloud || getDefaultAzureCloud(),
|
|
||||||
tenantId: credentials.tenantId,
|
|
||||||
clientId: credentials.clientId,
|
|
||||||
clientSecret: getSecret(options),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateCredentials(
|
export function updateCredentials(
|
||||||
options: DataSourceSettings<any, any>,
|
options: AzurePromDataSourceSettings,
|
||||||
credentials: AzureCredentials
|
credentials: AzureCredentials
|
||||||
): DataSourceSettings<any, any> {
|
): AzurePromDataSourceSettings {
|
||||||
switch (credentials.authType) {
|
return updateDatasourceCredentials(options, credentials);
|
||||||
case 'msi':
|
|
||||||
case 'workloadidentity':
|
|
||||||
if (credentials.authType === 'msi' && !config.azure.managedIdentityEnabled) {
|
|
||||||
throw new Error('Managed Identity authentication is not enabled in Grafana config.');
|
|
||||||
}
|
|
||||||
if (credentials.authType === 'workloadidentity' && !config.azure.workloadIdentityEnabled) {
|
|
||||||
throw new Error('Workload Identity authentication is not enabled in Grafana config.');
|
|
||||||
}
|
|
||||||
|
|
||||||
options = {
|
|
||||||
...options,
|
|
||||||
jsonData: {
|
|
||||||
...options.jsonData,
|
|
||||||
azureAuthType: credentials.authType,
|
|
||||||
azureCredentials: {
|
|
||||||
authType: credentials.authType,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return options;
|
|
||||||
|
|
||||||
case 'clientsecret':
|
|
||||||
options = {
|
|
||||||
...options,
|
|
||||||
jsonData: {
|
|
||||||
...options.jsonData,
|
|
||||||
azureCredentials: {
|
|
||||||
authType: 'clientsecret',
|
|
||||||
azureCloud: credentials.azureCloud || getDefaultAzureCloud(),
|
|
||||||
tenantId: credentials.tenantId,
|
|
||||||
clientId: credentials.clientId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
secureJsonData: {
|
|
||||||
...options.secureJsonData,
|
|
||||||
azureClientSecret:
|
|
||||||
typeof credentials.clientSecret === 'string' && credentials.clientSecret.length > 0
|
|
||||||
? credentials.clientSecret
|
|
||||||
: undefined,
|
|
||||||
},
|
|
||||||
secureJsonFields: {
|
|
||||||
...options.secureJsonFields,
|
|
||||||
azureClientSecret: typeof credentials.clientSecret === 'symbol',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setDefaultCredentials(options: DataSourceSettings<any, any>): Partial<DataSourceSettings<any, any>> {
|
export function setDefaultCredentials(options: AzurePromDataSourceSettings): Partial<AzurePromDataSourceSettings> {
|
||||||
return {
|
return {
|
||||||
jsonData: {
|
jsonData: {
|
||||||
...options.jsonData,
|
...options.jsonData,
|
||||||
@ -144,13 +56,18 @@ export function setDefaultCredentials(options: DataSourceSettings<any, any>): Pa
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetCredentials(options: DataSourceSettings<any, any>): Partial<DataSourceSettings<any, any>> {
|
export function resetCredentials(options: AzurePromDataSourceSettings): Partial<AzurePromDataSourceSettings> {
|
||||||
return {
|
return {
|
||||||
jsonData: {
|
jsonData: {
|
||||||
...options.jsonData,
|
...options.jsonData,
|
||||||
azureAuth: undefined,
|
|
||||||
azureCredentials: undefined,
|
azureCredentials: undefined,
|
||||||
azureEndpointResourceId: undefined,
|
azureEndpointResourceId: undefined,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AzurePromDataSourceOptions extends PromOptions, AzureDataSourceJsonData {
|
||||||
|
azureEndpointResourceId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AzurePromDataSourceSettings = DataSourceSettings<AzurePromDataSourceOptions, AzureDataSourceSecureJsonData>;
|
||||||
|
@ -12,7 +12,6 @@ const setup = (propsFunc?: (props: Props) => Props) => {
|
|||||||
tenantId: 'e7f3f661-a933-3h3f-0294-31c4f962ec48',
|
tenantId: 'e7f3f661-a933-3h3f-0294-31c4f962ec48',
|
||||||
clientId: '34509fad-c0r9-45df-9e25-f1ee34af6900',
|
clientId: '34509fad-c0r9-45df-9e25-f1ee34af6900',
|
||||||
clientSecret: undefined,
|
clientSecret: undefined,
|
||||||
defaultSubscriptionId: '44987801-6nn6-49he-9b2d-9106972f9789',
|
|
||||||
},
|
},
|
||||||
azureCloudOptions: [
|
azureCloudOptions: [
|
||||||
{ value: 'azuremonitor', label: 'Azure' },
|
{ value: 'azuremonitor', label: 'Azure' },
|
||||||
@ -45,15 +44,4 @@ describe('AzureCredentialsForm', () => {
|
|||||||
}));
|
}));
|
||||||
expect(await screen.findByLabelText('Client Secret')).toBeDisabled();
|
expect(await screen.findByLabelText('Client Secret')).toBeDisabled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should enable azure monitor load subscriptions button when all required fields are defined', async () => {
|
|
||||||
setup((props) => ({
|
|
||||||
...props,
|
|
||||||
credentials: {
|
|
||||||
...props.credentials,
|
|
||||||
clientSecret: 'e7f3f661-a933-4b3f-8176-51c4f982ec48',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
expect(await screen.findByRole('button', { name: 'Load Subscriptions' })).not.toBeDisabled();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import { cx } from '@emotion/css';
|
import { cx } from '@emotion/css';
|
||||||
import { ChangeEvent, useEffect, useMemo, useReducer, useState } from 'react';
|
import { ChangeEvent, useMemo } from 'react';
|
||||||
|
|
||||||
|
import { AzureAuthType, AzureCredentials } from '@grafana/azure-sdk';
|
||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
import { InlineFormLabel, Button, Select, Input } from '@grafana/ui';
|
import { InlineFormLabel, Button, Select, Input } from '@grafana/ui';
|
||||||
|
|
||||||
import { AzureAuthType, AzureCredentials, isCredentialsComplete } from './AzureCredentials';
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
managedIdentityEnabled: boolean;
|
managedIdentityEnabled: boolean;
|
||||||
workloadIdentityEnabled: boolean;
|
workloadIdentityEnabled: boolean;
|
||||||
@ -22,15 +21,10 @@ export const AzureCredentialsForm = (props: Props) => {
|
|||||||
credentials,
|
credentials,
|
||||||
azureCloudOptions,
|
azureCloudOptions,
|
||||||
onCredentialsChange,
|
onCredentialsChange,
|
||||||
getSubscriptions,
|
|
||||||
disabled,
|
disabled,
|
||||||
managedIdentityEnabled,
|
managedIdentityEnabled,
|
||||||
workloadIdentityEnabled,
|
workloadIdentityEnabled,
|
||||||
} = props;
|
} = props;
|
||||||
const hasRequiredFields = isCredentialsComplete(credentials);
|
|
||||||
|
|
||||||
const [subscriptions, setSubscriptions] = useState<Array<SelectableValue<string>>>([]);
|
|
||||||
const [loadSubscriptionsClicked, onLoadSubscriptions] = useReducer((val) => val + 1, 0);
|
|
||||||
|
|
||||||
const authTypeOptions = useMemo(() => {
|
const authTypeOptions = useMemo(() => {
|
||||||
let opts: Array<SelectableValue<AzureAuthType>> = [
|
let opts: Array<SelectableValue<AzureAuthType>> = [
|
||||||
@ -56,42 +50,7 @@ export const AzureCredentialsForm = (props: Props) => {
|
|||||||
return opts;
|
return opts;
|
||||||
}, [managedIdentityEnabled, workloadIdentityEnabled]);
|
}, [managedIdentityEnabled, workloadIdentityEnabled]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!getSubscriptions || !hasRequiredFields) {
|
|
||||||
updateSubscriptions([]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let canceled = false;
|
|
||||||
getSubscriptions().then((result) => {
|
|
||||||
if (!canceled) {
|
|
||||||
updateSubscriptions(result, loadSubscriptionsClicked);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return () => {
|
|
||||||
canceled = true;
|
|
||||||
};
|
|
||||||
// This effect is intended to be called only once initially and on Load Subscriptions click
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [loadSubscriptionsClicked]);
|
|
||||||
|
|
||||||
const updateSubscriptions = (received: Array<SelectableValue<string>>, autoSelect = false) => {
|
|
||||||
setSubscriptions(received);
|
|
||||||
if (getSubscriptions) {
|
|
||||||
if (autoSelect && !credentials.defaultSubscriptionId && received.length > 0) {
|
|
||||||
// Selecting the default subscription if subscriptions received but no default subscription selected
|
|
||||||
onSubscriptionChange(received[0]);
|
|
||||||
} else if (credentials.defaultSubscriptionId) {
|
|
||||||
const found = received.find((opt) => opt.value === credentials.defaultSubscriptionId);
|
|
||||||
if (!found) {
|
|
||||||
// Unselecting the default subscription if it isn't found among the received subscriptions
|
|
||||||
onSubscriptionChange(undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onAuthTypeChange = (selected: SelectableValue<AzureAuthType>) => {
|
const onAuthTypeChange = (selected: SelectableValue<AzureAuthType>) => {
|
||||||
setSubscriptions([]);
|
|
||||||
const defaultAuthType = managedIdentityEnabled
|
const defaultAuthType = managedIdentityEnabled
|
||||||
? 'msi'
|
? 'msi'
|
||||||
: workloadIdentityEnabled
|
: workloadIdentityEnabled
|
||||||
@ -100,18 +59,15 @@ export const AzureCredentialsForm = (props: Props) => {
|
|||||||
const updated: AzureCredentials = {
|
const updated: AzureCredentials = {
|
||||||
...credentials,
|
...credentials,
|
||||||
authType: selected.value || defaultAuthType,
|
authType: selected.value || defaultAuthType,
|
||||||
defaultSubscriptionId: undefined,
|
|
||||||
};
|
};
|
||||||
onCredentialsChange(updated);
|
onCredentialsChange(updated);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAzureCloudChange = (selected: SelectableValue<string>) => {
|
const onAzureCloudChange = (selected: SelectableValue<string>) => {
|
||||||
if (credentials.authType === 'clientsecret') {
|
if (credentials.authType === 'clientsecret') {
|
||||||
setSubscriptions([]);
|
|
||||||
const updated: AzureCredentials = {
|
const updated: AzureCredentials = {
|
||||||
...credentials,
|
...credentials,
|
||||||
azureCloud: selected.value,
|
azureCloud: selected.value,
|
||||||
defaultSubscriptionId: undefined,
|
|
||||||
};
|
};
|
||||||
onCredentialsChange(updated);
|
onCredentialsChange(updated);
|
||||||
}
|
}
|
||||||
@ -119,11 +75,9 @@ export const AzureCredentialsForm = (props: Props) => {
|
|||||||
|
|
||||||
const onTenantIdChange = (event: ChangeEvent<HTMLInputElement>) => {
|
const onTenantIdChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
if (credentials.authType === 'clientsecret') {
|
if (credentials.authType === 'clientsecret') {
|
||||||
setSubscriptions([]);
|
|
||||||
const updated: AzureCredentials = {
|
const updated: AzureCredentials = {
|
||||||
...credentials,
|
...credentials,
|
||||||
tenantId: event.target.value,
|
tenantId: event.target.value,
|
||||||
defaultSubscriptionId: undefined,
|
|
||||||
};
|
};
|
||||||
onCredentialsChange(updated);
|
onCredentialsChange(updated);
|
||||||
}
|
}
|
||||||
@ -131,11 +85,9 @@ export const AzureCredentialsForm = (props: Props) => {
|
|||||||
|
|
||||||
const onClientIdChange = (event: ChangeEvent<HTMLInputElement>) => {
|
const onClientIdChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
if (credentials.authType === 'clientsecret') {
|
if (credentials.authType === 'clientsecret') {
|
||||||
setSubscriptions([]);
|
|
||||||
const updated: AzureCredentials = {
|
const updated: AzureCredentials = {
|
||||||
...credentials,
|
...credentials,
|
||||||
clientId: event.target.value,
|
clientId: event.target.value,
|
||||||
defaultSubscriptionId: undefined,
|
|
||||||
};
|
};
|
||||||
onCredentialsChange(updated);
|
onCredentialsChange(updated);
|
||||||
}
|
}
|
||||||
@ -143,11 +95,9 @@ export const AzureCredentialsForm = (props: Props) => {
|
|||||||
|
|
||||||
const onClientSecretChange = (event: ChangeEvent<HTMLInputElement>) => {
|
const onClientSecretChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
if (credentials.authType === 'clientsecret') {
|
if (credentials.authType === 'clientsecret') {
|
||||||
setSubscriptions([]);
|
|
||||||
const updated: AzureCredentials = {
|
const updated: AzureCredentials = {
|
||||||
...credentials,
|
...credentials,
|
||||||
clientSecret: event.target.value,
|
clientSecret: event.target.value,
|
||||||
defaultSubscriptionId: undefined,
|
|
||||||
};
|
};
|
||||||
onCredentialsChange(updated);
|
onCredentialsChange(updated);
|
||||||
}
|
}
|
||||||
@ -155,23 +105,14 @@ export const AzureCredentialsForm = (props: Props) => {
|
|||||||
|
|
||||||
const onClientSecretReset = () => {
|
const onClientSecretReset = () => {
|
||||||
if (credentials.authType === 'clientsecret') {
|
if (credentials.authType === 'clientsecret') {
|
||||||
setSubscriptions([]);
|
|
||||||
const updated: AzureCredentials = {
|
const updated: AzureCredentials = {
|
||||||
...credentials,
|
...credentials,
|
||||||
clientSecret: '',
|
clientSecret: '',
|
||||||
defaultSubscriptionId: undefined,
|
|
||||||
};
|
};
|
||||||
onCredentialsChange(updated);
|
onCredentialsChange(updated);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSubscriptionChange = (selected: SelectableValue<string> | undefined) => {
|
|
||||||
const updated: AzureCredentials = {
|
|
||||||
...credentials,
|
|
||||||
defaultSubscriptionId: selected?.value,
|
|
||||||
};
|
|
||||||
onCredentialsChange(updated);
|
|
||||||
};
|
|
||||||
const prometheusConfigOverhaulAuth = config.featureToggles.prometheusConfigOverhaulAuth;
|
const prometheusConfigOverhaulAuth = config.featureToggles.prometheusConfigOverhaulAuth;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -283,42 +224,6 @@ export const AzureCredentialsForm = (props: Props) => {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{getSubscriptions && (
|
|
||||||
<>
|
|
||||||
<div className="gf-form-inline">
|
|
||||||
<div className="gf-form">
|
|
||||||
<InlineFormLabel className="width-12">Default Subscription</InlineFormLabel>
|
|
||||||
<div className={cx(prometheusConfigOverhaulAuth ? 'width-20' : 'width-25')}>
|
|
||||||
<Select
|
|
||||||
value={
|
|
||||||
credentials.defaultSubscriptionId
|
|
||||||
? subscriptions.find((opt) => opt.value === credentials.defaultSubscriptionId)
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
options={subscriptions}
|
|
||||||
onChange={onSubscriptionChange}
|
|
||||||
isDisabled={disabled}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="gf-form-inline">
|
|
||||||
<div className="gf-form">
|
|
||||||
<div className="max-width-30 gf-form-inline">
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
size="sm"
|
|
||||||
type="button"
|
|
||||||
onClick={onLoadSubscriptions}
|
|
||||||
disabled={!hasRequiredFields}
|
|
||||||
>
|
|
||||||
Load Subscriptions
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
|
|
||||||
import { SIGV4ConnectionConfig } from '@grafana/aws-sdk';
|
import { SIGV4ConnectionConfig } from '@grafana/aws-sdk';
|
||||||
import { DataSourcePluginOptionsEditorProps, DataSourceSettings, GrafanaTheme2 } from '@grafana/data';
|
import { hasCredentials } from '@grafana/azure-sdk';
|
||||||
|
import { DataSourcePluginOptionsEditorProps, GrafanaTheme2 } from '@grafana/data';
|
||||||
import { AdvancedHttpSettings, ConfigSection, DataSourceDescription } from '@grafana/experimental';
|
import { AdvancedHttpSettings, ConfigSection, DataSourceDescription } from '@grafana/experimental';
|
||||||
import { AlertingSettingsOverhaul, PromOptions, PromSettings } from '@grafana/prometheus';
|
import { AlertingSettingsOverhaul, PromOptions, PromSettings } from '@grafana/prometheus';
|
||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
import { Alert, FieldValidationMessage, useTheme2 } from '@grafana/ui';
|
import { Alert, FieldValidationMessage, useTheme2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { AzureAuthSettings } from './AzureAuthSettings';
|
import { AzureAuthSettings } from './AzureAuthSettings';
|
||||||
import { hasCredentials, setDefaultCredentials, resetCredentials } from './AzureCredentialsConfig';
|
import { AzurePromDataSourceSettings, setDefaultCredentials, resetCredentials } from './AzureCredentialsConfig';
|
||||||
import { DataSourcehttpSettingsOverhaul } from './DataSourceHttpSettingsOverhaulPackage';
|
import { DataSourcehttpSettingsOverhaul } from './DataSourceHttpSettingsOverhaulPackage';
|
||||||
|
|
||||||
export const PROM_CONFIG_LABEL_WIDTH = 30;
|
export const PROM_CONFIG_LABEL_WIDTH = 30;
|
||||||
@ -20,8 +21,8 @@ export const ConfigEditor = (props: Props) => {
|
|||||||
|
|
||||||
const azureAuthSettings = {
|
const azureAuthSettings = {
|
||||||
azureAuthSupported: config.azureAuthEnabled,
|
azureAuthSupported: config.azureAuthEnabled,
|
||||||
getAzureAuthEnabled: (config: DataSourceSettings): boolean => hasCredentials(config),
|
getAzureAuthEnabled: (config: AzurePromDataSourceSettings): boolean => hasCredentials(config),
|
||||||
setAzureAuthEnabled: (config: DataSourceSettings, enabled: boolean) =>
|
setAzureAuthEnabled: (config: AzurePromDataSourceSettings, enabled: boolean) =>
|
||||||
enabled ? setDefaultCredentials(config) : resetCredentials(config),
|
enabled ? setDefaultCredentials(config) : resetCredentials(config),
|
||||||
azureSettingsUI: AzureAuthSettings,
|
azureSettingsUI: AzureAuthSettings,
|
||||||
};
|
};
|
||||||
|
@ -1,22 +1,17 @@
|
|||||||
import { ReactElement, useState } from 'react';
|
import { ReactElement, useState } from 'react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { DataSourceSettings } from '@grafana/data';
|
|
||||||
import { Auth, ConnectionSettings, convertLegacyAuthProps, AuthMethod } from '@grafana/experimental';
|
import { Auth, ConnectionSettings, convertLegacyAuthProps, AuthMethod } from '@grafana/experimental';
|
||||||
import { PromOptions, docsTip, overhaulStyles } from '@grafana/prometheus';
|
import { docsTip, overhaulStyles } from '@grafana/prometheus';
|
||||||
import { Alert, SecureSocksProxySettings, useTheme2 } from '@grafana/ui';
|
import { Alert, SecureSocksProxySettings, useTheme2 } from '@grafana/ui';
|
||||||
// NEED TO EXPORT THIS FROM GRAFANA/UI FOR EXTERNAL DS
|
// NEED TO EXPORT THIS FROM GRAFANA/UI FOR EXTERNAL DS
|
||||||
import { AzureAuthSettings } from '@grafana/ui/src/components/DataSourceSettings/types';
|
import { AzureAuthSettings } from '@grafana/ui/src/components/DataSourceSettings/types';
|
||||||
|
|
||||||
import type { AzureCredentials } from './AzureCredentials';
|
import { AzurePromDataSourceSettings } from './AzureCredentialsConfig';
|
||||||
|
|
||||||
interface PromOptionsWithCloudAuth extends PromOptions {
|
|
||||||
azureCredentials?: AzureCredentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
options: DataSourceSettings<PromOptionsWithCloudAuth, {}>;
|
options: AzurePromDataSourceSettings;
|
||||||
onOptionsChange: (options: DataSourceSettings<PromOptionsWithCloudAuth, {}>) => void;
|
onOptionsChange: (options: AzurePromDataSourceSettings) => void;
|
||||||
azureAuthSettings: AzureAuthSettings;
|
azureAuthSettings: AzureAuthSettings;
|
||||||
sigV4AuthToggleEnabled: boolean | undefined;
|
sigV4AuthToggleEnabled: boolean | undefined;
|
||||||
renderSigV4Editor: React.ReactNode;
|
renderSigV4Editor: React.ReactNode;
|
||||||
|
Loading…
Reference in New Issue
Block a user