mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Uptime] [Synthetics Integration] Add functional tests for Synthetics Integration (#100161)
* add functional tests for synthetics fleet package
This commit is contained in:
parent
7f9364ac8a
commit
6d4cca29a7
14 changed files with 1052 additions and 4 deletions
|
@ -13,7 +13,7 @@ export interface Props {
|
|||
selectedOptions: string[];
|
||||
}
|
||||
|
||||
export const ComboBox = ({ onChange, selectedOptions }: Props) => {
|
||||
export const ComboBox = ({ onChange, selectedOptions, ...props }: Props) => {
|
||||
const [formattedSelectedOptions, setSelectedOptions] = useState<
|
||||
Array<EuiComboBoxOptionOption<string>>
|
||||
>(selectedOptions.map((option) => ({ label: option, key: option })));
|
||||
|
@ -66,6 +66,7 @@ export const ComboBox = ({ onChange, selectedOptions }: Props) => {
|
|||
onChange={onOptionsChange}
|
||||
onSearchChange={onSearchChange}
|
||||
isInvalid={isInvalid}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -76,6 +76,7 @@ export const CustomFields = memo<Props>(
|
|||
defaultMessage="Configure your monitor with the following options."
|
||||
/>
|
||||
}
|
||||
data-test-subj="monitorSettingsSection"
|
||||
>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
|
@ -104,6 +105,7 @@ export const CustomFields = memo<Props>(
|
|||
configKey: ConfigKeys.MONITOR_TYPE,
|
||||
})
|
||||
}
|
||||
data-test-subj="syntheticsMonitorTypeField"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
)}
|
||||
|
@ -128,6 +130,7 @@ export const CustomFields = memo<Props>(
|
|||
onChange={(event) =>
|
||||
handleInputChange({ value: event.target.value, configKey: ConfigKeys.URLS })
|
||||
}
|
||||
data-test-subj="syntheticsUrlField"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
)}
|
||||
|
@ -155,6 +158,7 @@ export const CustomFields = memo<Props>(
|
|||
configKey: ConfigKeys.HOSTS,
|
||||
})
|
||||
}
|
||||
data-test-subj="syntheticsTCPHostField"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
)}
|
||||
|
@ -182,6 +186,7 @@ export const CustomFields = memo<Props>(
|
|||
configKey: ConfigKeys.HOSTS,
|
||||
})
|
||||
}
|
||||
data-test-subj="syntheticsICMPHostField"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
)}
|
||||
|
@ -268,6 +273,7 @@ export const CustomFields = memo<Props>(
|
|||
configKey: ConfigKeys.APM_SERVICE_NAME,
|
||||
})
|
||||
}
|
||||
data-test-subj="syntheticsAPMServiceName"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
{isHTTP && (
|
||||
|
@ -364,6 +370,7 @@ export const CustomFields = memo<Props>(
|
|||
<ComboBox
|
||||
selectedOptions={fields[ConfigKeys.TAGS]}
|
||||
onChange={(value) => handleInputChange({ value, configKey: ConfigKeys.TAGS })}
|
||||
data-test-subj="syntheticsTags"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
@ -385,6 +392,7 @@ export const CustomFields = memo<Props>(
|
|||
defaultMessage="Configure TLS options, including verification mode, certificate authorities, and client certificates."
|
||||
/>
|
||||
}
|
||||
data-test-subj="syntheticsIsTLSEnabled"
|
||||
>
|
||||
<EuiCheckbox
|
||||
id={'uptimeFleetIsTLSEnabled'}
|
||||
|
|
|
@ -52,6 +52,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
defaultMessage="Advanced HTTP options"
|
||||
/>
|
||||
}
|
||||
data-test-subj="syntheticsHTTPAdvancedFieldsAccordion"
|
||||
>
|
||||
<EuiSpacer size="xl" />
|
||||
<EuiDescribedFormGroup
|
||||
|
@ -69,6 +70,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
defaultMessage="Configure an optional request to send to the remote host including method, body, and headers."
|
||||
/>
|
||||
}
|
||||
data-test-subj="httpAdvancedFieldsSection"
|
||||
>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiFormRow
|
||||
|
@ -94,6 +96,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
configKey: ConfigKeys.USERNAME,
|
||||
})
|
||||
}
|
||||
data-test-subj="syntheticsUsername"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
|
@ -119,6 +122,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
configKey: ConfigKeys.PASSWORD,
|
||||
})
|
||||
}
|
||||
data-test-subj="syntheticsPassword"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
|
@ -144,6 +148,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
configKey: ConfigKeys.PROXY_URL,
|
||||
})
|
||||
}
|
||||
data-test-subj="syntheticsProxyUrl"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
|
@ -169,6 +174,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
configKey: ConfigKeys.REQUEST_METHOD_CHECK,
|
||||
})
|
||||
}
|
||||
data-test-subj="syntheticsRequestMethod"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
|
@ -199,6 +205,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
defaultMessage="A dictionary of additional HTTP headers to send. By default the client will set the User-Agent header to identify itself."
|
||||
/>
|
||||
}
|
||||
data-test-subj="syntheticsRequestHeaders"
|
||||
>
|
||||
<HeaderField
|
||||
contentMode={
|
||||
|
@ -275,6 +282,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
<EuiCode>http.response.body.headers</EuiCode>
|
||||
</>
|
||||
}
|
||||
data-test-subj="syntheticsIndexResponseHeaders"
|
||||
>
|
||||
<EuiCheckbox
|
||||
id={'uptimeFleetIndexResponseHeaders'}
|
||||
|
@ -363,6 +371,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
configKey: ConfigKeys.RESPONSE_STATUS_CHECK,
|
||||
})
|
||||
}
|
||||
data-test-subj="syntheticsResponseStatusCheck"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
|
@ -397,6 +406,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
defaultMessage="A list of expected response headers."
|
||||
/>
|
||||
}
|
||||
data-test-subj="syntheticsResponseHeaders"
|
||||
>
|
||||
<HeaderField
|
||||
defaultValue={fields[ConfigKeys.RESPONSE_HEADERS_CHECK]}
|
||||
|
@ -436,6 +446,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
}),
|
||||
[handleInputChange]
|
||||
)}
|
||||
data-test-subj="syntheticsResponseBodyCheckPositive"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
|
@ -464,6 +475,7 @@ export const HTTPAdvancedFields = memo<Props>(({ validate }) => {
|
|||
}),
|
||||
[handleInputChange]
|
||||
)}
|
||||
data-test-subj="syntheticsResponseBodyCheckNegative"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiDescribedFormGroup>
|
||||
|
|
|
@ -38,7 +38,7 @@ export const ResponseBodyIndexField = ({ defaultValue, onChange }: Props) => {
|
|||
|
||||
return (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexItem data-test-subj="syntheticsIndexResponseBody">
|
||||
<EuiCheckbox
|
||||
id="uptimeFleetIndexResponseBody"
|
||||
checked={checked}
|
||||
|
|
|
@ -131,6 +131,7 @@ export const RequestBodyField = ({ onChange, type, value }: Props) => {
|
|||
{
|
||||
id: Mode.TEXT,
|
||||
name: modeLabels[Mode.TEXT],
|
||||
'data-test-subj': `syntheticsRequestBodyTab__${Mode.TEXT}`,
|
||||
content: (
|
||||
<CodeEditor
|
||||
ariaLabel={i18n.translate(
|
||||
|
@ -151,6 +152,7 @@ export const RequestBodyField = ({ onChange, type, value }: Props) => {
|
|||
{
|
||||
id: Mode.JSON,
|
||||
name: modeLabels[Mode.JSON],
|
||||
'data-test-subj': `syntheticsRequestBodyTab__${Mode.JSON}`,
|
||||
content: (
|
||||
<CodeEditor
|
||||
ariaLabel={i18n.translate(
|
||||
|
@ -171,6 +173,7 @@ export const RequestBodyField = ({ onChange, type, value }: Props) => {
|
|||
{
|
||||
id: Mode.XML,
|
||||
name: modeLabels[Mode.XML],
|
||||
'data-test-subj': `syntheticsRequestBodyTab__${Mode.XML}`,
|
||||
content: (
|
||||
<CodeEditor
|
||||
ariaLabel={i18n.translate(
|
||||
|
@ -191,6 +194,7 @@ export const RequestBodyField = ({ onChange, type, value }: Props) => {
|
|||
{
|
||||
id: Mode.FORM,
|
||||
name: modeLabels[Mode.FORM],
|
||||
'data-test-subj': `syntheticsRequestBodyTab__${Mode.FORM}`,
|
||||
content: (
|
||||
<KeyValuePairsField
|
||||
addPairControlLabel={
|
||||
|
|
|
@ -33,7 +33,11 @@ export const TCPAdvancedFields = () => {
|
|||
);
|
||||
|
||||
return (
|
||||
<EuiAccordion id="uptimeFleetTCPAdvancedOptions" buttonContent="Advanced TCP options">
|
||||
<EuiAccordion
|
||||
id="uptimeFleetTCPAdvancedOptions"
|
||||
buttonContent="Advanced TCP options"
|
||||
data-test-subj="syntheticsTCPAdvancedFieldsAccordion"
|
||||
>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiDescribedFormGroup
|
||||
title={
|
||||
|
@ -75,10 +79,11 @@ export const TCPAdvancedFields = () => {
|
|||
configKey: ConfigKeys.PROXY_URL,
|
||||
})
|
||||
}
|
||||
data-test-subj="syntheticsProxyUrl"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
{!!fields[ConfigKeys.PROXY_URL] && (
|
||||
<EuiFormRow>
|
||||
<EuiFormRow data-test-subj="syntheticsUseLocalResolver">
|
||||
<EuiCheckbox
|
||||
id={'uptimeFleetUseLocalResolverCheckbox'}
|
||||
checked={fields[ConfigKeys.PROXY_USE_LOCAL_RESOLVER]}
|
||||
|
@ -122,6 +127,7 @@ export const TCPAdvancedFields = () => {
|
|||
}),
|
||||
[handleInputChange]
|
||||
)}
|
||||
data-test-subj="syntheticsTCPRequestSendCheck"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiDescribedFormGroup>
|
||||
|
@ -166,6 +172,7 @@ export const TCPAdvancedFields = () => {
|
|||
}),
|
||||
[handleInputChange]
|
||||
)}
|
||||
data-test-subj="syntheticsTCPResponseReceiveCheck"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiDescribedFormGroup>
|
||||
|
|
|
@ -139,6 +139,7 @@ export const TLSFields: React.FunctionComponent<{
|
|||
},
|
||||
}));
|
||||
}}
|
||||
data-test-subj="syntheticsTLSVerificationMode"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
{fields[ConfigKeys.TLS_VERIFICATION_MODE].value === VerificationMode.NONE && (
|
||||
|
@ -229,6 +230,7 @@ export const TLSFields: React.FunctionComponent<{
|
|||
},
|
||||
}));
|
||||
}}
|
||||
data-test-subj="syntheticsTLSCA"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
|
@ -271,6 +273,7 @@ export const TLSFields: React.FunctionComponent<{
|
|||
},
|
||||
}));
|
||||
}}
|
||||
data-test-subj="syntheticsTLSCert"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
|
@ -313,6 +316,7 @@ export const TLSFields: React.FunctionComponent<{
|
|||
},
|
||||
}));
|
||||
}}
|
||||
data-test-subj="syntheticsTLSCertKey"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
|
@ -345,6 +349,7 @@ export const TLSFields: React.FunctionComponent<{
|
|||
},
|
||||
}));
|
||||
}}
|
||||
data-test-subj="syntheticsTLSCertKeyPassphrase"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFormFieldset>
|
||||
|
|
|
@ -59,6 +59,7 @@ export default ({ loadTestFile, getService }: FtrProviderContext) => {
|
|||
loadTestFile(require.resolve('./locations'));
|
||||
loadTestFile(require.resolve('./settings'));
|
||||
loadTestFile(require.resolve('./certificates'));
|
||||
loadTestFile(require.resolve('./synthetics_integration'));
|
||||
});
|
||||
|
||||
describe('with generated data but no data reset', () => {
|
||||
|
|
442
x-pack/test/functional/apps/uptime/synthetics_integration.ts
Normal file
442
x-pack/test/functional/apps/uptime/synthetics_integration.ts
Normal file
|
@ -0,0 +1,442 @@
|
|||
/*
|
||||
* 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 { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { FullAgentPolicy } from '../../../../plugins/fleet/common';
|
||||
|
||||
export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||
const monitorName = 'Sample Synthetics integration';
|
||||
|
||||
const uptimePage = getPageObjects(['syntheticsIntegration']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const uptimeService = getService('uptime');
|
||||
|
||||
const generatePolicy = ({
|
||||
agentFullPolicy,
|
||||
version,
|
||||
monitorType,
|
||||
name,
|
||||
config,
|
||||
}: {
|
||||
agentFullPolicy: FullAgentPolicy;
|
||||
version: string;
|
||||
monitorType: string;
|
||||
name: string;
|
||||
config: Record<string, any>;
|
||||
}) => ({
|
||||
data_stream: {
|
||||
namespace: 'default',
|
||||
},
|
||||
id: agentFullPolicy.inputs[0].id,
|
||||
meta: {
|
||||
package: {
|
||||
name: 'synthetics',
|
||||
version,
|
||||
},
|
||||
},
|
||||
name,
|
||||
revision: 1,
|
||||
streams: [
|
||||
{
|
||||
data_stream: {
|
||||
dataset: monitorType,
|
||||
type: 'synthetics',
|
||||
},
|
||||
id: `${agentFullPolicy.inputs[0]?.streams?.[0]?.id}`,
|
||||
name,
|
||||
type: monitorType,
|
||||
processors: [
|
||||
{
|
||||
add_observer_metadata: {
|
||||
geo: {
|
||||
name: 'Fleet managed',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
add_fields: {
|
||||
fields: {
|
||||
'monitor.fleet_managed': true,
|
||||
},
|
||||
target: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
...config,
|
||||
},
|
||||
],
|
||||
type: `synthetics/${monitorType}`,
|
||||
use_output: 'default',
|
||||
});
|
||||
|
||||
describe('When on the Synthetics Integration Policy Create Page', function () {
|
||||
this.tags(['ciGroup6']);
|
||||
const basicConfig = {
|
||||
name: monitorName,
|
||||
apmServiceName: 'Sample APM Service',
|
||||
tags: 'sample tag',
|
||||
};
|
||||
|
||||
const generateHTTPConfig = (url: string) => ({
|
||||
...basicConfig,
|
||||
url,
|
||||
});
|
||||
|
||||
const generateTCPorICMPConfig = (host: string) => ({
|
||||
...basicConfig,
|
||||
host,
|
||||
});
|
||||
|
||||
describe('displays custom UI', () => {
|
||||
before(async () => {
|
||||
const version = await uptimeService.syntheticsPackage.getSyntheticsPackageVersion();
|
||||
await uptimePage.syntheticsIntegration.navigateToPackagePage(version!);
|
||||
});
|
||||
|
||||
it('should display policy view', async () => {
|
||||
await uptimePage.syntheticsIntegration.ensureIsOnPackagePage();
|
||||
});
|
||||
|
||||
it('prevent saving when integration name, url/host, or schedule is missing', async () => {
|
||||
const saveButton = await uptimePage.syntheticsIntegration.findSaveButton();
|
||||
await saveButton.click();
|
||||
|
||||
await testSubjects.missingOrFail('packagePolicyCreateSuccessToast');
|
||||
});
|
||||
});
|
||||
|
||||
describe('create new policy', () => {
|
||||
let version: string;
|
||||
before(async () => {
|
||||
await uptimeService.syntheticsPackage.deletePolicyByName('system-1');
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
version = (await uptimeService.syntheticsPackage.getSyntheticsPackageVersion())!;
|
||||
await uptimePage.syntheticsIntegration.navigateToPackagePage(version!);
|
||||
await uptimeService.syntheticsPackage.deletePolicyByName(monitorName);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await uptimeService.syntheticsPackage.deletePolicyByName(monitorName);
|
||||
});
|
||||
|
||||
it('allows saving when user enters a valid integration name and url/host', async () => {
|
||||
// This test ensures that updates made to the Synthetics Policy are carried all the way through
|
||||
// to the generated Agent Policy that is dispatch down to the Elastic Agent.
|
||||
const config = generateHTTPConfig('http://elastic.co');
|
||||
await uptimePage.syntheticsIntegration.createBasicHTTPMonitorDetails(config);
|
||||
await uptimePage.syntheticsIntegration.confirmAndSave();
|
||||
|
||||
await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully();
|
||||
|
||||
const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList();
|
||||
const agentPolicyId = agentPolicy.id;
|
||||
const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy(
|
||||
agentPolicyId
|
||||
);
|
||||
|
||||
expect(agentFullPolicy.inputs).to.eql([
|
||||
generatePolicy({
|
||||
agentFullPolicy,
|
||||
version,
|
||||
name: monitorName,
|
||||
monitorType: 'http',
|
||||
config: {
|
||||
max_redirects: 0,
|
||||
'response.include_body': 'on_error',
|
||||
'response.include_headers': true,
|
||||
schedule: '@every 3m',
|
||||
timeout: '16s',
|
||||
urls: config.url,
|
||||
'service.name': config.apmServiceName,
|
||||
tags: [config.tags],
|
||||
'check.request.method': 'GET',
|
||||
},
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows enabling tls with defaults', async () => {
|
||||
// This test ensures that updates made to the Synthetics Policy are carried all the way through
|
||||
// to the generated Agent Policy that is dispatch down to the Elastic Agent.
|
||||
const config = generateHTTPConfig('http://elastic.co');
|
||||
|
||||
await uptimePage.syntheticsIntegration.createBasicHTTPMonitorDetails(config);
|
||||
await uptimePage.syntheticsIntegration.enableTLS();
|
||||
await uptimePage.syntheticsIntegration.confirmAndSave();
|
||||
|
||||
await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully();
|
||||
|
||||
const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList();
|
||||
const agentPolicyId = agentPolicy.id;
|
||||
const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy(
|
||||
agentPolicyId
|
||||
);
|
||||
|
||||
expect(agentFullPolicy.inputs).to.eql([
|
||||
generatePolicy({
|
||||
agentFullPolicy,
|
||||
version,
|
||||
name: monitorName,
|
||||
monitorType: 'http',
|
||||
config: {
|
||||
max_redirects: 0,
|
||||
'check.request.method': 'GET',
|
||||
'response.include_body': 'on_error',
|
||||
'response.include_headers': true,
|
||||
schedule: '@every 3m',
|
||||
'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'],
|
||||
'ssl.verification_mode': 'full',
|
||||
timeout: '16s',
|
||||
urls: config.url,
|
||||
'service.name': config.apmServiceName,
|
||||
tags: [config.tags],
|
||||
},
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows configuring tls', async () => {
|
||||
// This test ensures that updates made to the Synthetics Policy are carried all the way through
|
||||
// to the generated Agent Policy that is dispatch down to the Elastic Agent.
|
||||
const config = generateHTTPConfig('http://elastic.co');
|
||||
|
||||
const tlsConfig = {
|
||||
verificationMode: 'strict',
|
||||
ca: 'ca',
|
||||
cert: 'cert',
|
||||
certKey: 'certKey',
|
||||
certKeyPassphrase: 'certKeyPassphrase',
|
||||
};
|
||||
await uptimePage.syntheticsIntegration.createBasicHTTPMonitorDetails(config);
|
||||
await uptimePage.syntheticsIntegration.configureTLSOptions(tlsConfig);
|
||||
await uptimePage.syntheticsIntegration.confirmAndSave();
|
||||
|
||||
await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully();
|
||||
|
||||
const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList();
|
||||
const agentPolicyId = agentPolicy.id;
|
||||
const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy(
|
||||
agentPolicyId
|
||||
);
|
||||
|
||||
expect(agentFullPolicy.inputs).to.eql([
|
||||
generatePolicy({
|
||||
agentFullPolicy,
|
||||
version,
|
||||
name: monitorName,
|
||||
monitorType: 'http',
|
||||
config: {
|
||||
max_redirects: 0,
|
||||
'check.request.method': 'GET',
|
||||
'response.include_body': 'on_error',
|
||||
'response.include_headers': true,
|
||||
schedule: '@every 3m',
|
||||
'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'],
|
||||
'ssl.verification_mode': tlsConfig.verificationMode,
|
||||
'ssl.certificate': tlsConfig.cert,
|
||||
'ssl.certificate_authorities': tlsConfig.ca,
|
||||
'ssl.key': tlsConfig.certKey,
|
||||
'ssl.key_passphrase': tlsConfig.certKeyPassphrase,
|
||||
timeout: '16s',
|
||||
urls: config.url,
|
||||
'service.name': config.apmServiceName,
|
||||
tags: [config.tags],
|
||||
},
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows configuring http advanced options', async () => {
|
||||
// This test ensures that updates made to the Synthetics Policy are carried all the way through
|
||||
// to the generated Agent Policy that is dispatch down to the Elastic Agent.
|
||||
const config = generateHTTPConfig('http://elastic.co');
|
||||
|
||||
await uptimePage.syntheticsIntegration.createBasicHTTPMonitorDetails(config);
|
||||
const advancedConfig = {
|
||||
username: 'username',
|
||||
password: 'password',
|
||||
proxyUrl: 'proxyUrl',
|
||||
requestMethod: 'POST',
|
||||
responseStatusCheck: '204',
|
||||
responseBodyCheckPositive: 'success',
|
||||
responseBodyCheckNegative: 'failure',
|
||||
requestHeaders: {
|
||||
sampleRequestHeader1: 'sampleRequestKey1',
|
||||
sampleRequestHeader2: 'sampleRequestKey2',
|
||||
},
|
||||
responseHeaders: {
|
||||
sampleResponseHeader1: 'sampleResponseKey1',
|
||||
sampleResponseHeader2: 'sampleResponseKey2',
|
||||
},
|
||||
requestBody: {
|
||||
type: 'xml',
|
||||
value: '<samplexml>samplexml',
|
||||
},
|
||||
indexResponseBody: false,
|
||||
indexResponseHeaders: false,
|
||||
};
|
||||
await uptimePage.syntheticsIntegration.configureHTTPAdvancedOptions(advancedConfig);
|
||||
await uptimePage.syntheticsIntegration.confirmAndSave();
|
||||
|
||||
await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully();
|
||||
|
||||
const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList();
|
||||
const agentPolicyId = agentPolicy.id;
|
||||
const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy(
|
||||
agentPolicyId
|
||||
);
|
||||
|
||||
expect(agentFullPolicy.inputs).to.eql([
|
||||
generatePolicy({
|
||||
agentFullPolicy,
|
||||
version,
|
||||
name: monitorName,
|
||||
monitorType: 'http',
|
||||
config: {
|
||||
max_redirects: 0,
|
||||
'check.request.method': advancedConfig.requestMethod,
|
||||
'check.request.headers': {
|
||||
'Content-Type': 'application/xml',
|
||||
...advancedConfig.requestHeaders,
|
||||
},
|
||||
'check.response.headers': advancedConfig.responseHeaders,
|
||||
'check.response.status': [advancedConfig.responseStatusCheck],
|
||||
'check.request.body': `${advancedConfig.requestBody.value}</samplexml>`, // code editor adds closing tag
|
||||
'check.response.body.positive': [advancedConfig.responseBodyCheckPositive],
|
||||
'check.response.body.negative': [advancedConfig.responseBodyCheckNegative],
|
||||
'response.include_body': advancedConfig.indexResponseBody ? 'on_error' : 'never',
|
||||
'response.include_headers': advancedConfig.indexResponseHeaders,
|
||||
schedule: '@every 3m',
|
||||
timeout: '16s',
|
||||
urls: config.url,
|
||||
proxy_url: advancedConfig.proxyUrl,
|
||||
username: advancedConfig.username,
|
||||
password: advancedConfig.password,
|
||||
'service.name': config.apmServiceName,
|
||||
tags: [config.tags],
|
||||
},
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows saving tcp monitor when user enters a valid integration name and host+port', async () => {
|
||||
// This test ensures that updates made to the Synthetics Policy are carried all the way through
|
||||
// to the generated Agent Policy that is dispatch down to the Elastic Agent.
|
||||
const config = generateTCPorICMPConfig('smtp.gmail.com:587');
|
||||
|
||||
await uptimePage.syntheticsIntegration.createBasicTCPMonitorDetails(config);
|
||||
await uptimePage.syntheticsIntegration.confirmAndSave();
|
||||
|
||||
await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully();
|
||||
|
||||
const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList();
|
||||
const agentPolicyId = agentPolicy.id;
|
||||
const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy(
|
||||
agentPolicyId
|
||||
);
|
||||
|
||||
expect(agentFullPolicy.inputs).to.eql([
|
||||
generatePolicy({
|
||||
agentFullPolicy,
|
||||
version,
|
||||
name: monitorName,
|
||||
monitorType: 'tcp',
|
||||
config: {
|
||||
proxy_use_local_resolver: false,
|
||||
schedule: '@every 3m',
|
||||
timeout: '16s',
|
||||
hosts: config.host,
|
||||
tags: [config.tags],
|
||||
'service.name': config.apmServiceName,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows configuring tcp advanced options', async () => {
|
||||
// This test ensures that updates made to the Synthetics Policy are carried all the way through
|
||||
// to the generated Agent Policy that is dispatch down to the Elastic Agent.
|
||||
const config = generateTCPorICMPConfig('smtp.gmail.com:587');
|
||||
|
||||
await uptimePage.syntheticsIntegration.createBasicTCPMonitorDetails(config);
|
||||
const advancedConfig = {
|
||||
proxyUrl: 'proxyUrl',
|
||||
requestSendCheck: 'body',
|
||||
responseReceiveCheck: 'success',
|
||||
proxyUseLocalResolver: true,
|
||||
};
|
||||
await uptimePage.syntheticsIntegration.configureTCPAdvancedOptions(advancedConfig);
|
||||
await uptimePage.syntheticsIntegration.confirmAndSave();
|
||||
|
||||
await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully();
|
||||
|
||||
const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList();
|
||||
const agentPolicyId = agentPolicy.id;
|
||||
const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy(
|
||||
agentPolicyId
|
||||
);
|
||||
|
||||
expect(agentFullPolicy.inputs).to.eql([
|
||||
generatePolicy({
|
||||
agentFullPolicy,
|
||||
version,
|
||||
name: monitorName,
|
||||
monitorType: 'tcp',
|
||||
config: {
|
||||
schedule: '@every 3m',
|
||||
timeout: '16s',
|
||||
hosts: config.host,
|
||||
proxy_url: advancedConfig.proxyUrl,
|
||||
proxy_use_local_resolver: advancedConfig.proxyUseLocalResolver,
|
||||
'check.receive': advancedConfig.responseReceiveCheck,
|
||||
'check.send': advancedConfig.requestSendCheck,
|
||||
'service.name': config.apmServiceName,
|
||||
tags: [config.tags],
|
||||
},
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows saving icmp monitor when user enters a valid integration name and host', async () => {
|
||||
// This test ensures that updates made to the Synthetics Policy are carried all the way through
|
||||
// to the generated Agent Policy that is dispatch down to the Elastic Agent.
|
||||
const config = generateTCPorICMPConfig('1.1.1.1');
|
||||
|
||||
await uptimePage.syntheticsIntegration.createBasicICMPMonitorDetails(config);
|
||||
await uptimePage.syntheticsIntegration.confirmAndSave();
|
||||
|
||||
await uptimePage.syntheticsIntegration.isPolicyCreatedSuccessfully();
|
||||
|
||||
const [agentPolicy] = await uptimeService.syntheticsPackage.getAgentPolicyList();
|
||||
const agentPolicyId = agentPolicy.id;
|
||||
const agentFullPolicy = await uptimeService.syntheticsPackage.getFullAgentPolicy(
|
||||
agentPolicyId
|
||||
);
|
||||
|
||||
expect(agentFullPolicy.inputs).to.eql([
|
||||
generatePolicy({
|
||||
agentFullPolicy,
|
||||
version,
|
||||
name: monitorName,
|
||||
monitorType: 'icmp',
|
||||
config: {
|
||||
schedule: '@every 3m',
|
||||
timeout: '16s',
|
||||
wait: '1s',
|
||||
hosts: config.host,
|
||||
'service.name': config.apmServiceName,
|
||||
tags: [config.tags],
|
||||
},
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -154,6 +154,9 @@ export default async function ({ readConfigFile }) {
|
|||
uptime: {
|
||||
pathname: '/app/uptime',
|
||||
},
|
||||
fleet: {
|
||||
pathname: '/app/fleet',
|
||||
},
|
||||
ml: {
|
||||
pathname: '/app/ml',
|
||||
},
|
||||
|
|
|
@ -24,6 +24,7 @@ import { StatusPagePageProvider } from './status_page';
|
|||
import { UpgradeAssistantPageProvider } from './upgrade_assistant_page';
|
||||
import { RollupPageProvider } from './rollup_page';
|
||||
import { UptimePageProvider } from './uptime_page';
|
||||
import { SyntheticsIntegrationPageProvider } from './synthetics_integration_page';
|
||||
import { ApiKeysPageProvider } from './api_keys_page';
|
||||
import { LicenseManagementPageProvider } from './license_management_page';
|
||||
import { IndexManagementPageProvider } from './index_management_page';
|
||||
|
@ -64,6 +65,7 @@ export const pageObjects = {
|
|||
statusPage: StatusPagePageProvider,
|
||||
upgradeAssistant: UpgradeAssistantPageProvider,
|
||||
uptime: UptimePageProvider,
|
||||
syntheticsIntegration: SyntheticsIntegrationPageProvider,
|
||||
rollup: RollupPageProvider,
|
||||
apiKeys: ApiKeysPageProvider,
|
||||
licenseManagement: LicenseManagementPageProvider,
|
||||
|
|
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* 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 { WebElementWrapper } from 'test/functional/services/lib/web_element_wrapper';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export function SyntheticsIntegrationPageProvider({
|
||||
getService,
|
||||
getPageObjects,
|
||||
}: FtrProviderContext) {
|
||||
const pageObjects = getPageObjects(['common', 'header']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const comboBox = getService('comboBox');
|
||||
|
||||
return {
|
||||
/**
|
||||
* Navigates to the Synthetics Integration page
|
||||
*
|
||||
*/
|
||||
async navigateToPackagePage(packageVersion: string) {
|
||||
await pageObjects.common.navigateToUrl(
|
||||
'fleet',
|
||||
`/integrations/synthetics-${packageVersion}/add-integration`,
|
||||
{
|
||||
shouldUseHashForSubUrl: true,
|
||||
useActualUrl: true,
|
||||
}
|
||||
);
|
||||
await pageObjects.header.waitUntilLoadingHasFinished();
|
||||
},
|
||||
|
||||
async navigateToPackageEditPage(packageId: string, agentId: string) {
|
||||
await pageObjects.common.navigateToUrl(
|
||||
'fleet',
|
||||
`/policies/${agentId}/edit-integration/${packageId}`,
|
||||
{
|
||||
shouldUseHashForSubUrl: true,
|
||||
useActualUrl: true,
|
||||
}
|
||||
);
|
||||
await pageObjects.header.waitUntilLoadingHasFinished();
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds and returns the Policy Details Page Save button
|
||||
*/
|
||||
async findSaveButton(isEditPage?: boolean) {
|
||||
await this.ensureIsOnPackagePage();
|
||||
return await testSubjects.find(
|
||||
isEditPage ? 'saveIntegration' : 'createPackagePolicySaveButton'
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds and returns the Policy Details Page Cancel Button
|
||||
*/
|
||||
async findCancelButton() {
|
||||
await this.ensureIsOnPackagePage();
|
||||
return await testSubjects.find('policyDetailsCancelButton');
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if the policy was created successfully by looking for the creation success toast
|
||||
*/
|
||||
async isPolicyCreatedSuccessfully() {
|
||||
await testSubjects.existOrFail('packagePolicyCreateSuccessToast');
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects the monitor type
|
||||
* @params {monitorType} the type of monitor, tcp, http, or icmp
|
||||
*/
|
||||
async selectMonitorType(monitorType: string) {
|
||||
await testSubjects.selectValue('syntheticsMonitorTypeField', monitorType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fills a text input
|
||||
* @params {testSubj} the testSubj of the input to fill
|
||||
* @params {value} the value of the input
|
||||
*/
|
||||
async fillTextInputByTestSubj(testSubj: string, value: string) {
|
||||
const field = await testSubjects.find(testSubj, 5000);
|
||||
await field.click();
|
||||
await field.clearValue();
|
||||
await field.type(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fills a text input
|
||||
* @params {testSubj} the testSubj of the input to fill
|
||||
* @params {value} the value of the input
|
||||
*/
|
||||
async fillTextInput(field: WebElementWrapper, value: string) {
|
||||
await field.click();
|
||||
await field.clearValue();
|
||||
await field.type(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fills a text input
|
||||
* @params {testSubj} the testSubj of the comboBox
|
||||
*/
|
||||
async setComboBox(testSubj: string, value: string) {
|
||||
await comboBox.setCustom(`${testSubj} > comboBoxInput`, value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds and returns the HTTP advanced options accordion trigger
|
||||
*/
|
||||
async findHTTPAdvancedOptionsAccordion() {
|
||||
await this.ensureIsOnPackagePage();
|
||||
const accordion = await testSubjects.find('syntheticsHTTPAdvancedFieldsAccordion', 5000);
|
||||
return accordion;
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds and returns the enable TLS checkbox
|
||||
*/
|
||||
async findEnableTLSCheckbox() {
|
||||
await this.ensureIsOnPackagePage();
|
||||
const tlsCheckboxContainer = await testSubjects.find('syntheticsIsTLSEnabled');
|
||||
return await tlsCheckboxContainer.findByCssSelector('label');
|
||||
},
|
||||
|
||||
/**
|
||||
* ensures that the package page is the currently display view
|
||||
*/
|
||||
async ensureIsOnPackagePage() {
|
||||
await testSubjects.existOrFail('monitorSettingsSection');
|
||||
},
|
||||
|
||||
/**
|
||||
* Clicks save button and confirms update on the Policy Details page
|
||||
*/
|
||||
async confirmAndSave(isEditPage?: boolean) {
|
||||
await this.ensureIsOnPackagePage();
|
||||
const saveButton = await this.findSaveButton(isEditPage);
|
||||
saveButton.click();
|
||||
},
|
||||
|
||||
/**
|
||||
* Fills in the username and password field
|
||||
* @params username {string} the value of the username
|
||||
* @params password {string} the value of the password
|
||||
*/
|
||||
async configureUsernameAndPassword({ username, password }: Record<string, string>) {
|
||||
await this.fillTextInputByTestSubj('syntheticsUsername', username);
|
||||
await this.fillTextInputByTestSubj('syntheticsPassword', password);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Configures request headers
|
||||
* @params headers {string} an object containing desired headers
|
||||
*
|
||||
*/
|
||||
async configureRequestHeaders(headers: Record<string, string>) {
|
||||
await this.configureHeaders('syntheticsRequestHeaders', headers);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Configures response headers
|
||||
* @params headers {string} an object containing desired headers
|
||||
*
|
||||
*/
|
||||
async configureResponseHeaders(headers: Record<string, string>) {
|
||||
await this.configureHeaders('syntheticsResponseHeaders', headers);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Configures headers
|
||||
* @params testSubj {string} test subj
|
||||
* @params headers {string} an object containing desired headers
|
||||
*
|
||||
*/
|
||||
async configureHeaders(testSubj: string, headers: Record<string, string>) {
|
||||
const headersContainer = await testSubjects.find(testSubj);
|
||||
const addHeaderButton = await headersContainer.findByCssSelector('button');
|
||||
const keys = Object.keys(headers);
|
||||
|
||||
await Promise.all(
|
||||
keys.map(async (key, index) => {
|
||||
await addHeaderButton.click();
|
||||
const keyField = await headersContainer.findByCssSelector(
|
||||
`[data-test-subj="keyValuePairsKey${index}"]`
|
||||
);
|
||||
const valueField = await headersContainer.findByCssSelector(
|
||||
`[data-test-subj="keyValuePairsValue${index}"]`
|
||||
);
|
||||
await this.fillTextInput(keyField, key);
|
||||
await this.fillTextInput(valueField, headers[key]);
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Configures request body
|
||||
* @params contentType {string} contentType of the request body
|
||||
* @params value {string} value of the request body
|
||||
*
|
||||
*/
|
||||
async configureRequestBody(testSubj: string, value: string) {
|
||||
await testSubjects.click(`syntheticsRequestBodyTab__${testSubj}`);
|
||||
const codeEditorContainer = await testSubjects.find('codeEditorContainer');
|
||||
const textArea = await codeEditorContainer.findByCssSelector('textarea');
|
||||
await textArea.clearValue();
|
||||
await textArea.type(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates basic common monitor details
|
||||
* @params name {string} the name of the monitor
|
||||
* @params url {string} the url of the monitor
|
||||
*
|
||||
*/
|
||||
async createBasicMonitorDetails({ name, apmServiceName, tags }: Record<string, string>) {
|
||||
await this.fillTextInputByTestSubj('packagePolicyNameInput', name);
|
||||
await this.fillTextInputByTestSubj('syntheticsAPMServiceName', apmServiceName);
|
||||
await this.setComboBox('syntheticsTags', tags);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fills in the fields to create a basic HTTP monitor
|
||||
* @params name {string} the name of the monitor
|
||||
* @params url {string} the url of the monitor
|
||||
*
|
||||
*/
|
||||
async createBasicHTTPMonitorDetails({
|
||||
name,
|
||||
url,
|
||||
apmServiceName,
|
||||
tags,
|
||||
}: Record<string, string>) {
|
||||
await this.createBasicMonitorDetails({ name, apmServiceName, tags });
|
||||
await this.fillTextInputByTestSubj('syntheticsUrlField', url);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fills in the fields to create a basic TCP monitor
|
||||
* @params name {string} the name of the monitor
|
||||
* @params host {string} the host (and port) of the monitor
|
||||
*
|
||||
*/
|
||||
async createBasicTCPMonitorDetails({
|
||||
name,
|
||||
host,
|
||||
apmServiceName,
|
||||
tags,
|
||||
}: Record<string, string>) {
|
||||
await this.selectMonitorType('tcp');
|
||||
await this.createBasicMonitorDetails({ name, apmServiceName, tags });
|
||||
await this.fillTextInputByTestSubj('syntheticsTCPHostField', host);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a basic ICMP monitor
|
||||
* @params name {string} the name of the monitor
|
||||
* @params host {string} the host of the monitor
|
||||
*/
|
||||
async createBasicICMPMonitorDetails({
|
||||
name,
|
||||
host,
|
||||
apmServiceName,
|
||||
tags,
|
||||
}: Record<string, string>) {
|
||||
await this.selectMonitorType('icmp');
|
||||
await this.fillTextInputByTestSubj('packagePolicyNameInput', name);
|
||||
await this.createBasicMonitorDetails({ name, apmServiceName, tags });
|
||||
await this.fillTextInputByTestSubj('syntheticsICMPHostField', host);
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables TLS
|
||||
*/
|
||||
async enableTLS() {
|
||||
const tlsCheckbox = await this.findEnableTLSCheckbox();
|
||||
await tlsCheckbox.click();
|
||||
},
|
||||
|
||||
/**
|
||||
* Configures TLS settings
|
||||
* @params verificationMode {string} the name of the monitor
|
||||
*/
|
||||
async configureTLSOptions({
|
||||
verificationMode,
|
||||
ca,
|
||||
cert,
|
||||
certKey,
|
||||
certKeyPassphrase,
|
||||
}: Record<string, string>) {
|
||||
await this.enableTLS();
|
||||
await testSubjects.selectValue('syntheticsTLSVerificationMode', verificationMode);
|
||||
await this.fillTextInputByTestSubj('syntheticsTLSCA', ca);
|
||||
await this.fillTextInputByTestSubj('syntheticsTLSCert', cert);
|
||||
await this.fillTextInputByTestSubj('syntheticsTLSCertKey', certKey);
|
||||
await this.fillTextInputByTestSubj('syntheticsTLSCertKeyPassphrase', certKeyPassphrase);
|
||||
},
|
||||
|
||||
/**
|
||||
* Configure http advanced settings
|
||||
*/
|
||||
async configureHTTPAdvancedOptions({
|
||||
username,
|
||||
password,
|
||||
proxyUrl,
|
||||
requestMethod,
|
||||
requestHeaders,
|
||||
responseStatusCheck,
|
||||
responseBodyCheckPositive,
|
||||
responseBodyCheckNegative,
|
||||
requestBody,
|
||||
responseHeaders,
|
||||
indexResponseBody,
|
||||
indexResponseHeaders,
|
||||
}: {
|
||||
username: string;
|
||||
password: string;
|
||||
proxyUrl: string;
|
||||
requestMethod: string;
|
||||
responseStatusCheck: string;
|
||||
responseBodyCheckPositive: string;
|
||||
responseBodyCheckNegative: string;
|
||||
requestBody: { value: string; type: string };
|
||||
requestHeaders: Record<string, string>;
|
||||
responseHeaders: Record<string, string>;
|
||||
indexResponseBody: boolean;
|
||||
indexResponseHeaders: boolean;
|
||||
}) {
|
||||
await testSubjects.click('syntheticsHTTPAdvancedFieldsAccordion');
|
||||
await this.configureResponseHeaders(responseHeaders);
|
||||
await this.configureRequestHeaders(requestHeaders);
|
||||
await this.configureRequestBody(requestBody.type, requestBody.value);
|
||||
await this.configureUsernameAndPassword({ username, password });
|
||||
await this.setComboBox('syntheticsResponseStatusCheck', responseStatusCheck);
|
||||
await this.setComboBox('syntheticsResponseBodyCheckPositive', responseBodyCheckPositive);
|
||||
await this.setComboBox('syntheticsResponseBodyCheckNegative', responseBodyCheckNegative);
|
||||
await this.fillTextInputByTestSubj('syntheticsProxyUrl', proxyUrl);
|
||||
await testSubjects.selectValue('syntheticsRequestMethod', requestMethod);
|
||||
if (!indexResponseBody) {
|
||||
const field = await testSubjects.find('syntheticsIndexResponseBody');
|
||||
const label = await field.findByCssSelector('label');
|
||||
await label.click();
|
||||
}
|
||||
if (!indexResponseHeaders) {
|
||||
const field = await testSubjects.find('syntheticsIndexResponseHeaders');
|
||||
const label = await field.findByCssSelector('label');
|
||||
await label.click();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Configure tcp advanced settings
|
||||
*/
|
||||
async configureTCPAdvancedOptions({
|
||||
proxyUrl,
|
||||
requestSendCheck,
|
||||
responseReceiveCheck,
|
||||
proxyUseLocalResolver,
|
||||
}: {
|
||||
proxyUrl: string;
|
||||
requestSendCheck: string;
|
||||
responseReceiveCheck: string;
|
||||
proxyUseLocalResolver: boolean;
|
||||
}) {
|
||||
await testSubjects.click('syntheticsTCPAdvancedFieldsAccordion');
|
||||
await this.fillTextInputByTestSubj('syntheticsProxyUrl', proxyUrl);
|
||||
await this.fillTextInputByTestSubj('syntheticsTCPRequestSendCheck', requestSendCheck);
|
||||
await this.fillTextInputByTestSubj('syntheticsTCPResponseReceiveCheck', responseReceiveCheck);
|
||||
if (proxyUseLocalResolver) {
|
||||
const field = await testSubjects.find('syntheticsUseLocalResolver');
|
||||
const label = await field.findByCssSelector('label');
|
||||
await label.click();
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
176
x-pack/test/functional/services/uptime/synthetics_package.ts
Normal file
176
x-pack/test/functional/services/uptime/synthetics_package.ts
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* 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 { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import {
|
||||
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
|
||||
DeletePackagePoliciesRequest,
|
||||
GetPackagePoliciesResponse,
|
||||
GetFullAgentPolicyResponse,
|
||||
GetPackagesResponse,
|
||||
GetAgentPoliciesResponse,
|
||||
} from '../../../../plugins/fleet/common';
|
||||
|
||||
const INGEST_API_ROOT = '/api/fleet';
|
||||
const INGEST_API_AGENT_POLICIES = `${INGEST_API_ROOT}/agent_policies`;
|
||||
const INGEST_API_PACKAGE_POLICIES = `${INGEST_API_ROOT}/package_policies`;
|
||||
const INGEST_API_PACKAGE_POLICIES_DELETE = `${INGEST_API_PACKAGE_POLICIES}/delete`;
|
||||
const INGEST_API_EPM_PACKAGES = `${INGEST_API_ROOT}/epm/packages`;
|
||||
|
||||
export function SyntheticsPackageProvider({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
|
||||
const logSupertestApiErrorAndThrow = (message: string, error: any): never => {
|
||||
const responseBody = error?.response?.body;
|
||||
const responseText = error?.response?.text;
|
||||
log.error(`Error occurred at ${Date.now()} | ${new Date().toISOString()}`);
|
||||
log.error(JSON.stringify(responseBody || responseText, null, 2));
|
||||
log.error(error);
|
||||
throw new Error(message);
|
||||
};
|
||||
const retrieveSyntheticsPackageInfo = (() => {
|
||||
// Retrieve information about the Synthetics package
|
||||
// EPM does not currently have an API to get the "lastest" information for a page given its name,
|
||||
// so we'll retrieve a list of packages and then find the package info in the list.
|
||||
let apiRequest: Promise<GetPackagesResponse['response'][0] | undefined>;
|
||||
|
||||
return () => {
|
||||
if (!apiRequest) {
|
||||
log.info(`Setting up call to retrieve Synthetics package`);
|
||||
|
||||
// Currently (as of 2020-june) the package registry used in CI is the public one and
|
||||
// at times it encounters network connection issues. We use `retry.try` below to see if
|
||||
// subsequent requests get through.
|
||||
apiRequest = retry.try(() => {
|
||||
return supertest
|
||||
.get(INGEST_API_EPM_PACKAGES)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.expect(200)
|
||||
.catch((error) => {
|
||||
return logSupertestApiErrorAndThrow(`Unable to retrieve packages via Ingest!`, error);
|
||||
})
|
||||
.then((response: { body: GetPackagesResponse }) => {
|
||||
const { body } = response;
|
||||
const syntheticsPackageInfo = body.response.find(
|
||||
(epmPackage) => epmPackage.name === 'synthetics'
|
||||
);
|
||||
if (!syntheticsPackageInfo) {
|
||||
throw new Error(
|
||||
`Synthetics package was not in response from ${INGEST_API_EPM_PACKAGES}`
|
||||
);
|
||||
}
|
||||
return Promise.resolve(syntheticsPackageInfo);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
log.info('Using cached retrieval of synthetics package');
|
||||
}
|
||||
return apiRequest;
|
||||
};
|
||||
})();
|
||||
|
||||
return {
|
||||
/**
|
||||
* Returns the synthetics package version for the currently installed package. This version can then
|
||||
* be used to build URLs for Fleet pages or APIs
|
||||
*/
|
||||
async getSyntheticsPackageVersion() {
|
||||
const syntheticsPackage = await retrieveSyntheticsPackageInfo()!;
|
||||
|
||||
return syntheticsPackage?.version;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the full Agent policy by id, which mirrors what the Elastic Agent would get
|
||||
* once they checkin.
|
||||
*/
|
||||
async getFullAgentPolicy(agentPolicyId: string): Promise<GetFullAgentPolicyResponse['item']> {
|
||||
let fullAgentPolicy: GetFullAgentPolicyResponse['item'];
|
||||
try {
|
||||
const apiResponse: { body: GetFullAgentPolicyResponse } = await supertest
|
||||
.get(`${INGEST_API_AGENT_POLICIES}/${agentPolicyId}/full`)
|
||||
.expect(200);
|
||||
|
||||
fullAgentPolicy = apiResponse.body.item;
|
||||
} catch (error) {
|
||||
return logSupertestApiErrorAndThrow('Unable to get full Agent policy', error);
|
||||
}
|
||||
|
||||
return fullAgentPolicy!;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves all the agent policies.
|
||||
*/
|
||||
async getAgentPolicyList(): Promise<GetAgentPoliciesResponse['items']> {
|
||||
let agentPolicyList: GetAgentPoliciesResponse['items'];
|
||||
try {
|
||||
const apiResponse: { body: GetAgentPoliciesResponse } = await supertest
|
||||
.get(INGEST_API_AGENT_POLICIES)
|
||||
.expect(200);
|
||||
|
||||
agentPolicyList = apiResponse.body.items;
|
||||
} catch (error) {
|
||||
return logSupertestApiErrorAndThrow('Unable to get full Agent policy list', error);
|
||||
}
|
||||
|
||||
return agentPolicyList!;
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes a policy (Package Policy) by using the policy name
|
||||
* @param name
|
||||
*/
|
||||
async deletePolicyByName(name: string) {
|
||||
const id = await this.getPackagePolicyIdByName(name);
|
||||
|
||||
if (id) {
|
||||
try {
|
||||
const deletePackagePolicyData: DeletePackagePoliciesRequest['body'] = {
|
||||
packagePolicyIds: [id],
|
||||
};
|
||||
await supertest
|
||||
.post(INGEST_API_PACKAGE_POLICIES_DELETE)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send(deletePackagePolicyData)
|
||||
.expect(200);
|
||||
} catch (error) {
|
||||
logSupertestApiErrorAndThrow(
|
||||
`Unable to delete Package Policy via Ingest! ${name}`,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the policy id (Package Policy) by using the policy name
|
||||
* @param name
|
||||
*/
|
||||
async getPackagePolicyIdByName(name: string) {
|
||||
const {
|
||||
body: packagePoliciesResponse,
|
||||
}: { body: GetPackagePoliciesResponse } = await supertest
|
||||
.get(INGEST_API_PACKAGE_POLICIES)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.query({ kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name: ${name}` })
|
||||
.send()
|
||||
.expect(200);
|
||||
const packagePolicyList: GetPackagePoliciesResponse['items'] = packagePoliciesResponse.items;
|
||||
|
||||
if (packagePolicyList.length > 1) {
|
||||
throw new Error(`Found ${packagePolicyList.length} Policies - was expecting only one!`);
|
||||
}
|
||||
|
||||
if (packagePolicyList.length) {
|
||||
return packagePolicyList[0].id;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
|
@ -15,6 +15,7 @@ import { UptimeAlertsProvider } from './alerts';
|
|||
import { UptimeMLAnomalyProvider } from './ml_anomaly';
|
||||
import { UptimeCertProvider } from './certificates';
|
||||
import { UptimeOverviewProvider } from './overview';
|
||||
import { SyntheticsPackageProvider } from './synthetics_package';
|
||||
|
||||
export function UptimeProvider(context: FtrProviderContext) {
|
||||
const common = UptimeCommonProvider(context);
|
||||
|
@ -25,6 +26,7 @@ export function UptimeProvider(context: FtrProviderContext) {
|
|||
const ml = UptimeMLAnomalyProvider(context);
|
||||
const cert = UptimeCertProvider(context);
|
||||
const overview = UptimeOverviewProvider(context);
|
||||
const syntheticsPackage = SyntheticsPackageProvider(context);
|
||||
|
||||
return {
|
||||
common,
|
||||
|
@ -35,5 +37,6 @@ export function UptimeProvider(context: FtrProviderContext) {
|
|||
ml,
|
||||
cert,
|
||||
overview,
|
||||
syntheticsPackage,
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue