mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Synthetics] add zip url deprecation message to package and Uptime overview (#141679)
* synthetics - add zip url deprecation message to package * add overview deprecation notice * adjust tests * add api integration tests * adjust functional tests * add dismiss logic and tests * adjust test * adjust content * Update x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/browser/source_field.tsx Co-authored-by: florent-leborgne <florent.leborgne@elastic.co> * Update x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/browser/source_field.test.tsx * Update x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/browser/source_field.tsx Co-authored-by: florent-leborgne <florent.leborgne@elastic.co> * Update x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/browser/source_field.tsx Co-authored-by: florent-leborgne <florent.leborgne@elastic.co> * Update x-pack/plugins/synthetics/public/legacy_uptime/components/overview/zip_url_deprecation/index.tsx * Update x-pack/plugins/synthetics/public/legacy_uptime/components/overview/zip_url_deprecation/index.tsx * Update x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/browser/source_field.tsx * add docs links * adjust types * adjust kibana services helper Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: florent-leborgne <florent.leborgne@elastic.co>
This commit is contained in:
parent
bd6893302d
commit
76c234ad54
20 changed files with 567 additions and 114 deletions
|
@ -458,6 +458,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => {
|
|||
userExperience: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/user-experience.html`,
|
||||
createAlerts: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/create-alerts.html`,
|
||||
syntheticsCommandReference: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/synthetics-configuration.html#synthetics-configuration-playwright-options`,
|
||||
syntheticsProjectMonitors: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/synthetic-run-tests.html#synthetic-monitor-choose-project`,
|
||||
},
|
||||
alerting: {
|
||||
guide: `${KIBANA_DOCS}create-and-manage-rules.html`,
|
||||
|
|
|
@ -340,6 +340,7 @@ export interface DocLinks {
|
|||
userExperience: string;
|
||||
createAlerts: string;
|
||||
syntheticsCommandReference: string;
|
||||
syntheticsProjectMonitors: string;
|
||||
}>;
|
||||
readonly alerting: Record<string, string>;
|
||||
readonly maps: Readonly<{
|
||||
|
|
|
@ -45,6 +45,7 @@ export enum API_URLS {
|
|||
TRIGGER_MONITOR = '/internal/uptime/service/monitors/trigger',
|
||||
SERVICE_ALLOWED = '/internal/uptime/service/allowed',
|
||||
SYNTHETICS_APIKEY = '/internal/uptime/service/api_key',
|
||||
SYNTHETICS_HAS_ZIP_URL_MONITORS = '/internal/uptime/fleet/has_zip_url_monitors',
|
||||
|
||||
// Project monitor public endpoint
|
||||
SYNTHETICS_MONITORS_PROJECT = '/api/synthetics/service/project/monitors',
|
||||
|
|
|
@ -8,3 +8,4 @@
|
|||
export * from './monitor_duration';
|
||||
export * from './synthetics_monitor';
|
||||
export * from './monitor_validation';
|
||||
export * from './zip_url_deprecation';
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export interface SyntheticsHasZipUrlMonitorsResponse {
|
||||
hasZipUrlMonitors: boolean;
|
||||
}
|
|
@ -12,4 +12,4 @@ export function setStartServices(core: CoreStart) {
|
|||
coreStart = core;
|
||||
}
|
||||
|
||||
export const getDocLinks = () => coreStart.docLinks;
|
||||
export const getDocLinks = () => coreStart?.docLinks;
|
||||
|
|
|
@ -68,6 +68,9 @@ describe('<SourceField />', () => {
|
|||
render(<WrappedComponent />);
|
||||
const zipUrl = 'test.zip';
|
||||
|
||||
const zip = screen.getByTestId('syntheticsSourceTab__zipUrl');
|
||||
fireEvent.click(zip);
|
||||
|
||||
const zipUrlField = screen.getByTestId('syntheticsBrowserZipUrl');
|
||||
fireEvent.change(zipUrlField, { target: { value: zipUrl } });
|
||||
|
||||
|
@ -79,6 +82,9 @@ describe('<SourceField />', () => {
|
|||
it('calls onBlur', () => {
|
||||
render(<WrappedComponent />);
|
||||
|
||||
const zip = screen.getByTestId('syntheticsSourceTab__zipUrl');
|
||||
fireEvent.click(zip);
|
||||
|
||||
const zipUrlField = screen.getByTestId('syntheticsBrowserZipUrl');
|
||||
fireEvent.click(zipUrlField);
|
||||
fireEvent.blur(zipUrlField);
|
||||
|
@ -86,7 +92,15 @@ describe('<SourceField />', () => {
|
|||
expect(onBlur).toBeCalledWith(ConfigKey.SOURCE_ZIP_URL);
|
||||
});
|
||||
|
||||
it('shows ZipUrl source type by default', async () => {
|
||||
it('selects inline script by default', () => {
|
||||
render(<WrappedComponent />);
|
||||
|
||||
expect(
|
||||
screen.getByText('Runs Synthetic test scripts that are defined inline.')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows zip source type by default', async () => {
|
||||
render(<WrappedComponent />);
|
||||
|
||||
expect(screen.getByTestId('syntheticsSourceTab__zipUrl')).toBeInTheDocument();
|
||||
|
@ -116,4 +130,13 @@ describe('<SourceField />', () => {
|
|||
|
||||
expect(getByText('Parameters')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows deprecated for zip url', () => {
|
||||
const { getByText, getByTestId } = render(<WrappedComponent />);
|
||||
|
||||
const zip = getByTestId('syntheticsSourceTab__zipUrl');
|
||||
fireEvent.click(zip);
|
||||
|
||||
expect(getByText('Zip URL is deprecated')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,6 +10,8 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
EuiCode,
|
||||
EuiCallOut,
|
||||
EuiLink,
|
||||
EuiTabbedContent,
|
||||
EuiTabbedContentTab,
|
||||
EuiFormRow,
|
||||
|
@ -26,6 +28,7 @@ import { CodeEditor } from '../code_editor';
|
|||
import { ScriptRecorderFields } from './script_recorder_fields';
|
||||
import { ZipUrlTLSFields } from './zip_url_tls_fields';
|
||||
import { ConfigKey, MonacoEditorLangId, Validation } from '../types';
|
||||
import { getDocLinks } from '../../../../kibana_services';
|
||||
|
||||
enum SourceType {
|
||||
INLINE = 'syntheticsBrowserInlineConfig',
|
||||
|
@ -64,14 +67,12 @@ export const defaultValues = {
|
|||
fileName: '',
|
||||
};
|
||||
|
||||
const getDefaultTab = (defaultConfig: SourceConfig, isZipUrlSourceEnabled = true) => {
|
||||
const getDefaultTab = (defaultConfig: SourceConfig) => {
|
||||
if (defaultConfig.inlineScript && defaultConfig.isGeneratedScript) {
|
||||
return SourceType.SCRIPT_RECORDER;
|
||||
} else if (defaultConfig.inlineScript) {
|
||||
} else {
|
||||
return SourceType.INLINE;
|
||||
}
|
||||
|
||||
return isZipUrlSourceEnabled ? SourceType.ZIP : SourceType.INLINE;
|
||||
};
|
||||
|
||||
export const SourceField = ({
|
||||
|
@ -81,9 +82,7 @@ export const SourceField = ({
|
|||
validate,
|
||||
}: Props) => {
|
||||
const { isZipUrlSourceEnabled } = usePolicyConfigContext();
|
||||
const [sourceType, setSourceType] = useState<SourceType>(
|
||||
getDefaultTab(defaultConfig, isZipUrlSourceEnabled)
|
||||
);
|
||||
const [sourceType, setSourceType] = useState<SourceType>(getDefaultTab(defaultConfig));
|
||||
const [config, setConfig] = useState<SourceConfig>(defaultConfig);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -145,12 +144,138 @@ export const SourceField = ({
|
|||
|
||||
const zipUrlSourceTabId = 'syntheticsBrowserZipURLConfig';
|
||||
const allTabs = [
|
||||
{
|
||||
id: 'syntheticsBrowserInlineConfig',
|
||||
name: (
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.inlineScript.label"
|
||||
defaultMessage="Inline script"
|
||||
/>
|
||||
),
|
||||
'data-test-subj': `syntheticsSourceTab__inline`,
|
||||
content: (
|
||||
<>
|
||||
<EuiFormRow
|
||||
isInvalid={isSourceInlineInvalid}
|
||||
error={
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.inlineScript.error"
|
||||
defaultMessage="Script is required"
|
||||
/>
|
||||
}
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.inlineScript.helpText"
|
||||
defaultMessage="Runs Synthetic test scripts that are defined inline."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<CodeEditor
|
||||
ariaLabel={i18n.translate(
|
||||
'xpack.synthetics.createPackagePolicy.stepConfigure.requestBody.codeEditor.javascript.ariaLabel',
|
||||
{
|
||||
defaultMessage: 'JavaScript code editor',
|
||||
}
|
||||
)}
|
||||
id="javascript"
|
||||
languageId={MonacoEditorLangId.JAVASCRIPT}
|
||||
onChange={(code) => {
|
||||
setConfig((prevConfig) => ({ ...prevConfig, inlineScript: code }));
|
||||
onFieldBlur(ConfigKey.SOURCE_INLINE);
|
||||
}}
|
||||
value={config.inlineScript}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
{params}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'syntheticsBrowserScriptRecorderConfig',
|
||||
name: (
|
||||
<EuiFlexGroup responsive={false} alignItems="center" gutterSize="xs">
|
||||
<EuiFlexItem grow={false}>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.browser.scriptRecorder.label"
|
||||
defaultMessage="Script recorder"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<StyledBetaBadgeWrapper grow={false}>
|
||||
<EuiBetaBadge
|
||||
label={i18n.translate(
|
||||
'xpack.synthetics.createPackagePolicy.stepConfigure.browser.scriptRecorder.experimentalLabel',
|
||||
{
|
||||
defaultMessage: 'Tech preview',
|
||||
}
|
||||
)}
|
||||
iconType="beaker"
|
||||
tooltipContent={i18n.translate(
|
||||
'xpack.synthetics.createPackagePolicy.stepConfigure.browser.scriptRecorder.experimentalTooltip',
|
||||
{
|
||||
defaultMessage:
|
||||
'Preview the quickest way to create Elastic Synthetics monitoring scripts with our Elastic Synthetics Recorder',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</StyledBetaBadgeWrapper>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
'data-test-subj': 'syntheticsSourceTab__scriptRecorder',
|
||||
content: (
|
||||
<>
|
||||
<ScriptRecorderFields
|
||||
onChange={({ scriptText, fileName }) =>
|
||||
setConfig((prevConfig) => ({
|
||||
...prevConfig,
|
||||
inlineScript: scriptText,
|
||||
isGeneratedScript: true,
|
||||
fileName,
|
||||
}))
|
||||
}
|
||||
script={config.inlineScript}
|
||||
fileName={config.fileName}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
{params}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: zipUrlSourceTabId,
|
||||
name: zipUrlLabel,
|
||||
'data-test-subj': `syntheticsSourceTab__zipUrl`,
|
||||
content: (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiCallOut
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.zipUrl.deprecation.title"
|
||||
defaultMessage="Zip URL is deprecated"
|
||||
/>
|
||||
}
|
||||
size="s"
|
||||
color="warning"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.zipUrl.deprecation.content"
|
||||
defaultMessage="Zip URL is deprecated and will be removed in a future version. Use project monitors instead to create monitors from a remote repository and to migrate existing Zip URL monitors. {link}"
|
||||
values={{
|
||||
link: (
|
||||
<EuiLink
|
||||
target="_blank"
|
||||
href={getDocLinks()?.links?.observability?.syntheticsProjectMonitors}
|
||||
external
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.monitorType.browser.zipUrl.deprecation.link"
|
||||
defaultMessage="Learn more"
|
||||
/>
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiFormRow
|
||||
label={zipUrlLabel}
|
||||
|
@ -278,102 +403,6 @@ export const SourceField = ({
|
|||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'syntheticsBrowserInlineConfig',
|
||||
name: (
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.inlineScript.label"
|
||||
defaultMessage="Inline script"
|
||||
/>
|
||||
),
|
||||
'data-test-subj': `syntheticsSourceTab__inline`,
|
||||
content: (
|
||||
<>
|
||||
<EuiFormRow
|
||||
isInvalid={isSourceInlineInvalid}
|
||||
error={
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.inlineScript.error"
|
||||
defaultMessage="Script is required"
|
||||
/>
|
||||
}
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.monitorIntegrationSettingsSection.browser.inlineScript.helpText"
|
||||
defaultMessage="Runs Synthetic test scripts that are defined inline."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<CodeEditor
|
||||
ariaLabel={i18n.translate(
|
||||
'xpack.synthetics.createPackagePolicy.stepConfigure.requestBody.codeEditor.javascript.ariaLabel',
|
||||
{
|
||||
defaultMessage: 'JavaScript code editor',
|
||||
}
|
||||
)}
|
||||
id="javascript"
|
||||
languageId={MonacoEditorLangId.JAVASCRIPT}
|
||||
onChange={(code) => {
|
||||
setConfig((prevConfig) => ({ ...prevConfig, inlineScript: code }));
|
||||
onFieldBlur(ConfigKey.SOURCE_INLINE);
|
||||
}}
|
||||
value={config.inlineScript}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
{params}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'syntheticsBrowserScriptRecorderConfig',
|
||||
name: (
|
||||
<EuiFlexGroup responsive={false} alignItems="center" gutterSize="xs">
|
||||
<EuiFlexItem grow={false}>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.createPackagePolicy.stepConfigure.browser.scriptRecorder.label"
|
||||
defaultMessage="Script recorder"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<StyledBetaBadgeWrapper grow={false}>
|
||||
<EuiBetaBadge
|
||||
label={i18n.translate(
|
||||
'xpack.synthetics.createPackagePolicy.stepConfigure.browser.scriptRecorder.experimentalLabel',
|
||||
{
|
||||
defaultMessage: 'Tech preview',
|
||||
}
|
||||
)}
|
||||
iconType="beaker"
|
||||
tooltipContent={i18n.translate(
|
||||
'xpack.synthetics.createPackagePolicy.stepConfigure.browser.scriptRecorder.experimentalTooltip',
|
||||
{
|
||||
defaultMessage:
|
||||
'Preview the quickest way to create Elastic Synthetics monitoring scripts with our Elastic Synthetics Recorder',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</StyledBetaBadgeWrapper>
|
||||
</EuiFlexGroup>
|
||||
),
|
||||
'data-test-subj': 'syntheticsSourceTab__scriptRecorder',
|
||||
content: (
|
||||
<>
|
||||
<ScriptRecorderFields
|
||||
onChange={({ scriptText, fileName }) =>
|
||||
setConfig((prevConfig) => ({
|
||||
...prevConfig,
|
||||
inlineScript: scriptText,
|
||||
isGeneratedScript: true,
|
||||
fileName,
|
||||
}))
|
||||
}
|
||||
script={config.inlineScript}
|
||||
fileName={config.fileName}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
{params}
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const tabs = isZipUrlSourceEnabled
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import 'jest-canvas-mock';
|
||||
|
||||
import React from 'react';
|
||||
import { fireEvent, waitFor } from '@testing-library/react';
|
||||
import { screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { render } from '../../lib/helper/rtl_helpers';
|
||||
import {
|
||||
TCPContextProvider,
|
||||
|
@ -247,6 +247,13 @@ describe('<CustomFields />', () => {
|
|||
fireEvent.change(monitorType, { target: { value: DataStream.BROWSER } });
|
||||
|
||||
// expect browser fields to be in the DOM
|
||||
expect(
|
||||
screen.getByText('Runs Synthetic test scripts that are defined inline.')
|
||||
).toBeInTheDocument();
|
||||
|
||||
const zip = screen.getByTestId('syntheticsSourceTab__zipUrl');
|
||||
fireEvent.click(zip);
|
||||
|
||||
getAllByLabelText('Zip URL').forEach((node) => {
|
||||
expect(node).toBeInTheDocument();
|
||||
});
|
||||
|
|
|
@ -702,11 +702,15 @@ describe('<SyntheticsPolicyCreateExtension />', () => {
|
|||
});
|
||||
|
||||
it('handles browser validation', async () => {
|
||||
const { getByText, getByLabelText, queryByText, getByRole } = render(<WrappedComponent />);
|
||||
const { getByText, getByLabelText, queryByText, getByRole, getByTestId } = render(
|
||||
<WrappedComponent />
|
||||
);
|
||||
|
||||
const monitorType = getByLabelText('Monitor Type') as HTMLInputElement;
|
||||
fireEvent.change(monitorType, { target: { value: DataStream.BROWSER } });
|
||||
|
||||
const zip = getByTestId('syntheticsSourceTab__zipUrl');
|
||||
fireEvent.click(zip);
|
||||
const zipUrl = getByRole('textbox', { name: 'Zip URL' }) as HTMLInputElement;
|
||||
const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement;
|
||||
|
||||
|
|
|
@ -636,10 +636,12 @@ describe('<SyntheticsPolicyEditExtension />', () => {
|
|||
},
|
||||
],
|
||||
};
|
||||
const { getByText, getByLabelText, queryByText, getByRole } = render(
|
||||
const { getByText, getByLabelText, queryByText, getByRole, getByTestId } = render(
|
||||
<WrappedComponent policy={currentPolicy} />
|
||||
);
|
||||
|
||||
const zip = getByTestId('syntheticsSourceTab__zipUrl');
|
||||
fireEvent.click(zip);
|
||||
const zipUrl = getByRole('textbox', { name: 'Zip URL' }) as HTMLInputElement;
|
||||
const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement;
|
||||
|
||||
|
@ -1074,9 +1076,11 @@ describe('<SyntheticsPolicyEditExtension />', () => {
|
|||
},
|
||||
],
|
||||
};
|
||||
const { getByLabelText, queryByLabelText, getByRole } = render(
|
||||
const { getByLabelText, queryByLabelText, getByRole, getByTestId } = render(
|
||||
<WrappedComponent policy={currentPolicy} />
|
||||
);
|
||||
const zip = getByTestId('syntheticsSourceTab__zipUrl');
|
||||
fireEvent.click(zip);
|
||||
const zipUrl = getByRole('textbox', { name: 'Zip URL' }) as HTMLInputElement;
|
||||
const monitorIntervalNumber = getByLabelText('Number') as HTMLInputElement;
|
||||
const monitorIntervalUnit = getByLabelText('Unit') as HTMLInputElement;
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiCallOut, EuiLink, EuiButton, EuiFlexItem, EuiFlexGroup, EuiSpacer } from '@elastic/eui';
|
||||
import { useFetcher } from '@kbn/observability-plugin/public';
|
||||
import { getHasZipUrlMonitors } from '../../../state/api/has_zip_url_monitors';
|
||||
import { getDocLinks } from '../../../../kibana_services';
|
||||
|
||||
export const ZIP_URL_DEPRECATION_SESSION_STORAGE_KEY =
|
||||
'SYNTHETICS_ZIP_URL_DEPRECATION_HAS_BEEN_DISMISSED';
|
||||
|
||||
export const ZipUrlDeprecation = () => {
|
||||
const noticeHasBeenDismissed =
|
||||
window.sessionStorage.getItem(ZIP_URL_DEPRECATION_SESSION_STORAGE_KEY) === 'true';
|
||||
const { data, loading } = useFetcher(() => {
|
||||
return getHasZipUrlMonitors();
|
||||
}, []);
|
||||
const hasZipUrlMonitors = !loading && data && data.hasZipUrlMonitors;
|
||||
const [shouldShowNotice, setShouldShowNotice] = useState(
|
||||
Boolean(hasZipUrlMonitors && !noticeHasBeenDismissed)
|
||||
);
|
||||
|
||||
const handleDismissDeprecationNotice = () => {
|
||||
window.sessionStorage.setItem(ZIP_URL_DEPRECATION_SESSION_STORAGE_KEY, 'true');
|
||||
setShouldShowNotice(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setShouldShowNotice(Boolean(hasZipUrlMonitors && !noticeHasBeenDismissed));
|
||||
}, [hasZipUrlMonitors, noticeHasBeenDismissed]);
|
||||
|
||||
return shouldShowNotice ? (
|
||||
<>
|
||||
<EuiCallOut
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.browser.zipUrl.deprecation.title"
|
||||
defaultMessage="Deprecation notice"
|
||||
/>
|
||||
}
|
||||
color="warning"
|
||||
>
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.browser.zipUrl.deprecation.content"
|
||||
defaultMessage="Zip URL is deprecated and will be removed in a future version. Use project monitors instead to create monitors from a remote repository and to migrate existing Zip URL monitors. {link}"
|
||||
values={{
|
||||
link: (
|
||||
<EuiLink
|
||||
target="_blank"
|
||||
href={getDocLinks()?.links?.observability?.syntheticsProjectMonitors}
|
||||
external
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.browser.zipUrl.deprecation.link"
|
||||
defaultMessage="Learn more"
|
||||
/>
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton onClick={handleDismissDeprecationNotice} color="warning">
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.browser.zipUrl.deprecation.dismiss"
|
||||
defaultMessage="Dismiss"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
) : null;
|
||||
};
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { StubBrowserStorage } from '@kbn/test-jest-helpers';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { render } from '../../../lib/helper/rtl_helpers';
|
||||
import { ZipUrlDeprecation, ZIP_URL_DEPRECATION_SESSION_STORAGE_KEY } from '.';
|
||||
import * as observabilityPublic from '@kbn/observability-plugin/public';
|
||||
|
||||
export const mockStorage = new StubBrowserStorage();
|
||||
jest.mock('@kbn/observability-plugin/public');
|
||||
|
||||
describe('ZipUrlDeprecation', () => {
|
||||
const { FETCH_STATUS } = observabilityPublic;
|
||||
it('shows deprecation notice when hasZipUrlMonitors is true', () => {
|
||||
jest.spyOn(observabilityPublic, 'useFetcher').mockReturnValue({
|
||||
status: FETCH_STATUS.SUCCESS,
|
||||
data: { hasZipUrlMonitors: true },
|
||||
refetch: () => null,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
render(<ZipUrlDeprecation />);
|
||||
expect(screen.getByText('Deprecation notice')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show deprecation notice when hasZipUrlMonitors is false', () => {
|
||||
jest.spyOn(observabilityPublic, 'useFetcher').mockReturnValue({
|
||||
status: FETCH_STATUS.SUCCESS,
|
||||
data: { hasZipUrlMonitors: false },
|
||||
refetch: () => null,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
render(<ZipUrlDeprecation />);
|
||||
expect(screen.queryByText('Deprecation notice')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('dismisses notification', () => {
|
||||
jest.spyOn(observabilityPublic, 'useFetcher').mockReturnValue({
|
||||
status: FETCH_STATUS.SUCCESS,
|
||||
data: { hasZipUrlMonitors: true },
|
||||
refetch: () => null,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
render(<ZipUrlDeprecation />);
|
||||
expect(screen.getByText('Deprecation notice')).toBeInTheDocument();
|
||||
userEvent.click(screen.getByText('Dismiss'));
|
||||
expect(screen.queryByText('Deprecation notice')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show notification when session storage key is true', () => {
|
||||
jest.spyOn(observabilityPublic, 'useFetcher').mockReturnValue({
|
||||
status: FETCH_STATUS.SUCCESS,
|
||||
data: { hasZipUrlMonitors: true },
|
||||
refetch: () => null,
|
||||
loading: false,
|
||||
});
|
||||
mockStorage.setItem(ZIP_URL_DEPRECATION_SESSION_STORAGE_KEY, 'true');
|
||||
|
||||
render(<ZipUrlDeprecation />);
|
||||
expect(screen.queryByText('Deprecation notice')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
|
@ -12,6 +12,7 @@ import styled from 'styled-components';
|
|||
import { useTrackPageview } from '@kbn/observability-plugin/public';
|
||||
import { useBreadcrumbs } from '../hooks/use_breadcrumbs';
|
||||
import { MonitorList } from '../components/overview/monitor_list/monitor_list_container';
|
||||
import { ZipUrlDeprecation } from '../components/overview/zip_url_deprecation';
|
||||
import { StatusPanel } from '../components/overview/status_panel';
|
||||
import { QueryBar } from '../components/overview/query_bar/query_bar';
|
||||
import { MONITORING_OVERVIEW_LABEL } from '../routes';
|
||||
|
@ -37,11 +38,18 @@ export const OverviewPageComponent = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<EuiFlexGroup gutterSize="xs" wrap responsive={false}>
|
||||
<QueryBar />
|
||||
<EuiFlexItemStyled grow={true}>
|
||||
<FilterGroup />
|
||||
</EuiFlexItemStyled>
|
||||
<EuiFlexGroup direction="column" gutterSize="none">
|
||||
<EuiFlexItem grow={true}>
|
||||
<ZipUrlDeprecation />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup gutterSize="xs" wrap responsive={false}>
|
||||
<QueryBar />
|
||||
<EuiFlexItemStyled grow={true}>
|
||||
<FilterGroup />
|
||||
</EuiFlexItemStyled>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="xs" />
|
||||
<StatusPanel />
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { API_URLS } from '../../../../common/constants';
|
||||
import { SyntheticsHasZipUrlMonitorsResponse } from '../../../../common/types/zip_url_deprecation';
|
||||
import { apiService } from './utils';
|
||||
|
||||
export const getHasZipUrlMonitors = async (): Promise<SyntheticsHasZipUrlMonitorsResponse> => {
|
||||
return await apiService.get(API_URLS.SYNTHETICS_HAS_ZIP_URL_MONITORS);
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { API_URLS } from '../../../common/constants';
|
||||
import { ConfigKey } from '../../../common/runtime_types';
|
||||
import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types';
|
||||
|
||||
export const getHasZipUrlMonitorRoute: SyntheticsRestApiRouteFactory = () => ({
|
||||
method: 'GET',
|
||||
path: API_URLS.SYNTHETICS_HAS_ZIP_URL_MONITORS,
|
||||
validate: {},
|
||||
handler: async ({ savedObjectsClient, server }): Promise<any> => {
|
||||
const monitors = await server.fleet.packagePolicyService.list(savedObjectsClient, {
|
||||
kuery: 'ingest-package-policies.package.name:synthetics',
|
||||
});
|
||||
const hasZipUrlMonitors = monitors.items.some((item) => {
|
||||
const browserInput = item.inputs.find((input) => input.type === 'synthetics/browser');
|
||||
const streams = browserInput?.streams || [];
|
||||
return streams.find((stream) => stream.data_stream.dataset === 'browser')?.compiled_stream?.[
|
||||
ConfigKey.SOURCE_ZIP_URL
|
||||
];
|
||||
});
|
||||
return {
|
||||
hasZipUrlMonitors,
|
||||
monitors: [],
|
||||
};
|
||||
},
|
||||
});
|
|
@ -31,6 +31,7 @@ import {
|
|||
SyntheticsRestApiRouteFactory,
|
||||
SyntheticsStreamingRouteFactory,
|
||||
} from '../legacy_uptime/routes';
|
||||
import { getHasZipUrlMonitorRoute } from './fleet/get_has_zip_url_monitors';
|
||||
|
||||
export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [
|
||||
addSyntheticsMonitorRoute,
|
||||
|
@ -49,6 +50,7 @@ export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [
|
|||
getServiceAllowedRoute,
|
||||
getAPIKeySyntheticsRoute,
|
||||
syntheticsGetPingsRoute,
|
||||
getHasZipUrlMonitorRoute,
|
||||
createGetCurrentStatusRoute,
|
||||
];
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
|
|||
loadTestFile(require.resolve('./monitor_duration'));
|
||||
loadTestFile(require.resolve('./index_status'));
|
||||
loadTestFile(require.resolve('./monitor_states_real_data'));
|
||||
loadTestFile(require.resolve('./uptime_zip_url_deprecation.ts'));
|
||||
});
|
||||
|
||||
describe('uptime CRUD routes', () => {
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import expect from '@kbn/expect';
|
||||
import uuid from 'uuid/v4';
|
||||
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function (providerContext: FtrProviderContext) {
|
||||
const { getService } = providerContext;
|
||||
|
||||
const supertest = getService('supertest');
|
||||
|
||||
const getBrowserZipInput = (zipUrl?: string) => ({
|
||||
type: 'synthetics/browser',
|
||||
policy_template: 'synthetics',
|
||||
enabled: false,
|
||||
streams: [
|
||||
{
|
||||
enabled: true,
|
||||
release: 'beta',
|
||||
data_stream: { type: 'synthetics', dataset: 'browser' },
|
||||
vars: {
|
||||
__ui: { type: 'yaml' },
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'browser', type: 'text' },
|
||||
name: { type: 'text' },
|
||||
schedule: { value: '"@every 3m"', type: 'text' },
|
||||
'service.name': { type: 'text' },
|
||||
timeout: { type: 'text' },
|
||||
tags: { type: 'yaml' },
|
||||
'source.zip_url.url': { type: 'text', value: zipUrl },
|
||||
'source.zip_url.username': { type: 'text' },
|
||||
'source.zip_url.folder': { type: 'text' },
|
||||
'source.zip_url.password': { type: 'password' },
|
||||
'source.inline.script': { type: 'yaml' },
|
||||
'source.project.content': { type: 'text' },
|
||||
params: { type: 'yaml' },
|
||||
playwright_options: { type: 'yaml' },
|
||||
screenshots: { type: 'text' },
|
||||
synthetics_args: { type: 'text' },
|
||||
ignore_https_errors: { type: 'bool' },
|
||||
'throttling.config': { type: 'text' },
|
||||
'filter_journeys.tags': { type: 'yaml' },
|
||||
'filter_journeys.match': { type: 'text' },
|
||||
'source.zip_url.ssl.certificate_authorities': { type: 'yaml' },
|
||||
'source.zip_url.ssl.certificate': { type: 'yaml' },
|
||||
'source.zip_url.ssl.key': { type: 'yaml' },
|
||||
'source.zip_url.ssl.key_passphrase': { type: 'text' },
|
||||
'source.zip_url.ssl.verification_mode': { type: 'text' },
|
||||
'source.zip_url.ssl.supported_protocols': { type: 'yaml' },
|
||||
'source.zip_url.proxy_url': { type: 'text' },
|
||||
location_name: { value: 'Fleet managed', type: 'text' },
|
||||
id: { type: 'text' },
|
||||
config_id: { type: 'text' },
|
||||
run_once: { value: false, type: 'bool' },
|
||||
origin: { type: 'text' },
|
||||
'monitor.project.id': { type: 'text' },
|
||||
'monitor.project.name': { type: 'text' },
|
||||
},
|
||||
id: 'synthetics/browser-browser-2bfd7da0-22ed-11ed-8c6b-09a2d21dfbc3-27337270-22ed-11ed-8c6b-09a2d21dfbc3-default',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
describe('UptimeZipUrlDeprecation', () => {
|
||||
let agentPolicyId: string;
|
||||
|
||||
before(async function () {
|
||||
const { body: agentPolicyResponse } = await supertest
|
||||
.post(`/api/fleet/agent_policies`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.send({
|
||||
name: `Test policy ${uuid()}`,
|
||||
namespace: 'default',
|
||||
})
|
||||
.expect(200);
|
||||
agentPolicyId = agentPolicyResponse.item.id;
|
||||
|
||||
// create a policy without a zip url
|
||||
await supertest
|
||||
.post(`/api/fleet/package_policies`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.send({
|
||||
name: `synthetics-test ${uuid()}`,
|
||||
description: '',
|
||||
namespace: 'default',
|
||||
policy_id: agentPolicyId,
|
||||
enabled: true,
|
||||
inputs: [getBrowserZipInput()],
|
||||
package: {
|
||||
name: 'synthetics',
|
||||
title: 'For Synthetics Tests',
|
||||
version: '0.10.2',
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await supertest
|
||||
.post(`/api/fleet/agent_policies/delete`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.send({ agentPolicyId });
|
||||
});
|
||||
|
||||
it('should return hasZipUrlMonitors false when there are not any zip url policies', async function () {
|
||||
const { body } = await supertest
|
||||
.get(`/internal/uptime/fleet/has_zip_url_monitors`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
expect(body.hasZipUrlMonitors).to.eql(false);
|
||||
});
|
||||
|
||||
it('should return hasZipUrlMonitors true when there are zip url policies', async function () {
|
||||
const { body } = await supertest
|
||||
.post(`/api/fleet/package_policies`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.send({
|
||||
name: `synthetics-test ${uuid()}`,
|
||||
description: '',
|
||||
namespace: 'default',
|
||||
policy_id: agentPolicyId,
|
||||
enabled: true,
|
||||
inputs: [getBrowserZipInput('testZipUrl')],
|
||||
package: {
|
||||
name: 'synthetics',
|
||||
title: 'For Synthetics Tests',
|
||||
version: '0.10.2',
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const policyId = body.item.id;
|
||||
|
||||
expect(body.item.inputs[0].streams[0].vars['source.zip_url.url'].value).to.eql('testZipUrl');
|
||||
|
||||
const { body: response } = await supertest
|
||||
.get(`/internal/uptime/fleet/has_zip_url_monitors`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
expect(response.hasZipUrlMonitors).to.eql(true);
|
||||
|
||||
// delete policy we just made
|
||||
await supertest
|
||||
.post(`/api/fleet/package_policies/delete`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.send({ force: true, packagePolicyIds: [policyId] })
|
||||
.expect(200);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -329,6 +329,8 @@ export function SyntheticsIntegrationPageProvider({
|
|||
await testSubjects.click('syntheticsSourceTab__inline');
|
||||
await this.fillCodeEditor(inlineScript);
|
||||
return;
|
||||
} else {
|
||||
await testSubjects.click('syntheticsSourceTab__zipUrl');
|
||||
}
|
||||
await this.fillTextInputByTestSubj('syntheticsBrowserZipUrl', zipUrl);
|
||||
await this.fillTextInputByTestSubj('syntheticsBrowserZipUrlFolder', folder);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue