[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:
Dominique Clarke 2022-10-04 15:45:57 -04:00 committed by GitHub
parent bd6893302d
commit 76c234ad54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 567 additions and 114 deletions

View file

@ -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`,

View file

@ -340,6 +340,7 @@ export interface DocLinks {
userExperience: string;
createAlerts: string;
syntheticsCommandReference: string;
syntheticsProjectMonitors: string;
}>;
readonly alerting: Record<string, string>;
readonly maps: Readonly<{

View file

@ -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',

View file

@ -8,3 +8,4 @@
export * from './monitor_duration';
export * from './synthetics_monitor';
export * from './monitor_validation';
export * from './zip_url_deprecation';

View file

@ -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;
}

View file

@ -12,4 +12,4 @@ export function setStartServices(core: CoreStart) {
coreStart = core;
}
export const getDocLinks = () => coreStart.docLinks;
export const getDocLinks = () => coreStart?.docLinks;

View file

@ -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();
});
});

View file

@ -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

View file

@ -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();
});

View file

@ -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;

View file

@ -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;

View file

@ -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;
};

View file

@ -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();
});
});

View file

@ -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 />

View file

@ -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);
};

View file

@ -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: [],
};
},
});

View file

@ -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,
];

View file

@ -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', () => {

View file

@ -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);
});
});
}

View file

@ -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);