Alerting: Allow testing provisioned contact points (#52824)
This commit is contained in:
@@ -23,7 +23,8 @@ interface Props<R> {
|
||||
secureFields?: Record<string, boolean>;
|
||||
errors?: FieldErrors<R>;
|
||||
onDelete?: () => void;
|
||||
readOnly?: boolean;
|
||||
isEditable?: boolean;
|
||||
isTestable?: boolean;
|
||||
}
|
||||
|
||||
export function ChannelSubForm<R extends ChannelValues>({
|
||||
@@ -36,7 +37,8 @@ export function ChannelSubForm<R extends ChannelValues>({
|
||||
errors,
|
||||
secureFields,
|
||||
commonSettingsComponent: CommonSettingsComponent,
|
||||
readOnly = false,
|
||||
isEditable = true,
|
||||
isTestable,
|
||||
}: Props<R>): JSX.Element {
|
||||
const styles = useStyles2(getStyles);
|
||||
const name = (fieldName: string) => `${pathPrefix}${fieldName}`;
|
||||
@@ -89,6 +91,7 @@ export function ChannelSubForm<R extends ChannelValues>({
|
||||
const optionalOptions = notifier?.options.filter((o) => !o.required);
|
||||
|
||||
const contactPointTypeInputId = `contact-point-type-${pathPrefix}`;
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper} data-testid="item-container">
|
||||
<div className={styles.topRow}>
|
||||
@@ -99,7 +102,7 @@ export function ChannelSubForm<R extends ChannelValues>({
|
||||
defaultValue={defaultValues.type}
|
||||
render={({ field: { ref, onChange, ...field } }) => (
|
||||
<Select
|
||||
disabled={readOnly}
|
||||
disabled={!isEditable}
|
||||
inputId={contactPointTypeInputId}
|
||||
{...field}
|
||||
width={37}
|
||||
@@ -112,37 +115,39 @@ export function ChannelSubForm<R extends ChannelValues>({
|
||||
/>
|
||||
</Field>
|
||||
</div>
|
||||
{!readOnly && (
|
||||
<div className={styles.buttons}>
|
||||
{onTest && (
|
||||
<Button
|
||||
disabled={testingReceiver}
|
||||
size="xs"
|
||||
variant="secondary"
|
||||
type="button"
|
||||
onClick={() => handleTest()}
|
||||
icon={testingReceiver ? 'fa fa-spinner' : 'message'}
|
||||
>
|
||||
Test
|
||||
</Button>
|
||||
)}
|
||||
<Button size="xs" variant="secondary" type="button" onClick={() => onDuplicate()} icon="copy">
|
||||
Duplicate
|
||||
<div className={styles.buttons}>
|
||||
{isTestable && onTest && (
|
||||
<Button
|
||||
disabled={testingReceiver}
|
||||
size="xs"
|
||||
variant="secondary"
|
||||
type="button"
|
||||
onClick={() => handleTest()}
|
||||
icon={testingReceiver ? 'fa fa-spinner' : 'message'}
|
||||
>
|
||||
Test
|
||||
</Button>
|
||||
{onDelete && (
|
||||
<Button
|
||||
data-testid={`${pathPrefix}delete-button`}
|
||||
size="xs"
|
||||
variant="secondary"
|
||||
type="button"
|
||||
onClick={() => onDelete()}
|
||||
icon="trash-alt"
|
||||
>
|
||||
Delete
|
||||
)}
|
||||
{isEditable && (
|
||||
<>
|
||||
<Button size="xs" variant="secondary" type="button" onClick={() => onDuplicate()} icon="copy">
|
||||
Duplicate
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{onDelete && (
|
||||
<Button
|
||||
data-testid={`${pathPrefix}delete-button`}
|
||||
size="xs"
|
||||
variant="secondary"
|
||||
type="button"
|
||||
onClick={() => onDelete()}
|
||||
icon="trash-alt"
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{notifier && (
|
||||
<div className={styles.innerContent}>
|
||||
@@ -153,7 +158,7 @@ export function ChannelSubForm<R extends ChannelValues>({
|
||||
errors={errors}
|
||||
onResetSecureField={onResetSecureField}
|
||||
pathPrefix={pathPrefix}
|
||||
readOnly={readOnly}
|
||||
readOnly={!isEditable}
|
||||
/>
|
||||
{!!(mandatoryOptions?.length && optionalOptions?.length) && (
|
||||
<CollapsibleSection label={`Optional ${notifier.name} settings`}>
|
||||
@@ -169,12 +174,12 @@ export function ChannelSubForm<R extends ChannelValues>({
|
||||
onResetSecureField={onResetSecureField}
|
||||
errors={errors}
|
||||
pathPrefix={pathPrefix}
|
||||
readOnly={readOnly}
|
||||
readOnly={!isEditable}
|
||||
/>
|
||||
</CollapsibleSection>
|
||||
)}
|
||||
<CollapsibleSection label="Notification settings">
|
||||
<CommonSettingsComponent pathPrefix={pathPrefix} readOnly={readOnly} />
|
||||
<CommonSettingsComponent pathPrefix={pathPrefix} readOnly={!isEditable} />
|
||||
</CollapsibleSection>
|
||||
</div>
|
||||
)}
|
||||
|
||||
+5
-2
@@ -62,7 +62,9 @@ export const CloudReceiverForm: FC<Props> = ({ existing, alertManagerSourceName,
|
||||
[config, existing]
|
||||
);
|
||||
|
||||
const readOnly = isVanillaPrometheusAlertManagerDataSource(alertManagerSourceName);
|
||||
// this basically checks if we can manage the selected alert manager data source, either because it's a Grafana Managed one
|
||||
// or a Mimir-based AlertManager
|
||||
const isManageableAlertManagerDataSource = !isVanillaPrometheusAlertManagerDataSource(alertManagerSourceName);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -72,7 +74,8 @@ export const CloudReceiverForm: FC<Props> = ({ existing, alertManagerSourceName,
|
||||
</Alert>
|
||||
)}
|
||||
<ReceiverForm<CloudChannelValues>
|
||||
readOnly={readOnly}
|
||||
isEditable={isManageableAlertManagerDataSource}
|
||||
isTestable={isManageableAlertManagerDataSource}
|
||||
config={config}
|
||||
onSubmit={onSubmit}
|
||||
initialValues={existingValue}
|
||||
|
||||
+8
-2
@@ -114,7 +114,12 @@ export const GrafanaReceiverForm: FC<Props> = ({ existing, alertManagerSourceNam
|
||||
? (existing.grafana_managed_receiver_configs ?? []).some((item) => Boolean(item.provenance))
|
||||
: false;
|
||||
|
||||
const readOnly = isVanillaPrometheusAlertManagerDataSource(alertManagerSourceName) || hasProvisionedItems;
|
||||
// this basically checks if we can manage the selected alert manager data source, either because it's a Grafana Managed one
|
||||
// or a Mimir-based AlertManager
|
||||
const isManageableAlertManagerDataSource = !isVanillaPrometheusAlertManagerDataSource(alertManagerSourceName);
|
||||
|
||||
const isEditable = isManageableAlertManagerDataSource && !hasProvisionedItems;
|
||||
const isTestable = isManageableAlertManagerDataSource || hasProvisionedItems;
|
||||
|
||||
if (grafanaNotifiers.result) {
|
||||
return (
|
||||
@@ -122,7 +127,8 @@ export const GrafanaReceiverForm: FC<Props> = ({ existing, alertManagerSourceNam
|
||||
{hasProvisionedItems && <ProvisioningAlert resource={ProvisionedResource.ContactPoint} />}
|
||||
|
||||
<ReceiverForm<GrafanaChannelValues>
|
||||
readOnly={readOnly}
|
||||
isEditable={isEditable}
|
||||
isTestable={isTestable}
|
||||
config={config}
|
||||
onSubmit={onSubmit}
|
||||
initialValues={existingValue}
|
||||
|
||||
@@ -27,7 +27,8 @@ interface Props<R extends ChannelValues> {
|
||||
takenReceiverNames: string[]; // will validate that user entered receiver name is not one of these
|
||||
commonSettingsComponent: CommonSettingsComponentType;
|
||||
initialValues?: ReceiverFormValues<R>;
|
||||
readOnly: boolean;
|
||||
isEditable: boolean;
|
||||
isTestable?: boolean;
|
||||
}
|
||||
|
||||
export function ReceiverForm<R extends ChannelValues>({
|
||||
@@ -40,7 +41,8 @@ export function ReceiverForm<R extends ChannelValues>({
|
||||
onTestChannel,
|
||||
takenReceiverNames,
|
||||
commonSettingsComponent,
|
||||
readOnly,
|
||||
isEditable,
|
||||
isTestable,
|
||||
}: Props<R>): JSX.Element {
|
||||
const notifyApp = useAppNotification();
|
||||
const styles = useStyles2(getStyles);
|
||||
@@ -101,11 +103,11 @@ export function ReceiverForm<R extends ChannelValues>({
|
||||
)}
|
||||
<form onSubmit={handleSubmit(submitCallback, onInvalid)}>
|
||||
<h4 className={styles.heading}>
|
||||
{readOnly ? 'Contact point' : initialValues ? 'Update contact point' : 'Create contact point'}
|
||||
{!isEditable ? 'Contact point' : initialValues ? 'Update contact point' : 'Create contact point'}
|
||||
</h4>
|
||||
<Field label="Name" invalid={!!errors.name} error={errors.name && errors.name.message} required>
|
||||
<Input
|
||||
readOnly={readOnly}
|
||||
readOnly={!isEditable}
|
||||
id="name"
|
||||
{...register('name', {
|
||||
required: 'Name is required',
|
||||
@@ -143,12 +145,13 @@ export function ReceiverForm<R extends ChannelValues>({
|
||||
secureFields={initialItem?.secureFields}
|
||||
errors={errors?.items?.[index] as FieldErrors<R>}
|
||||
commonSettingsComponent={commonSettingsComponent}
|
||||
readOnly={readOnly}
|
||||
isEditable={isEditable}
|
||||
isTestable={isTestable}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<>
|
||||
{!readOnly && (
|
||||
{isEditable && (
|
||||
<Button
|
||||
type="button"
|
||||
icon="plus"
|
||||
@@ -159,7 +162,7 @@ export function ReceiverForm<R extends ChannelValues>({
|
||||
</Button>
|
||||
)}
|
||||
<div className={styles.buttons}>
|
||||
{!readOnly && (
|
||||
{isEditable && (
|
||||
<>
|
||||
{loading && (
|
||||
<Button disabled={true} icon="fa fa-spinner" variant="primary">
|
||||
|
||||
Reference in New Issue
Block a user