mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
# Backport This will backport the following commits from `main` to `8.x`: - [[Synthetics] migrate first set of tests (#198950)](https://github.com/elastic/kibana/pull/198950) <!--- Backport version: 8.9.8 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Dominique Clarke","email":"dominique.clarke@elastic.co"},"sourceCommit":{"committedDate":"2024-12-12T14:41:03Z","message":"[Synthetics] migrate first set of tests (#198950)\n\n## Summary\r\n\r\nRelates to #196229 \r\n\r\nMigrates Synthetics tests to deployment agnostic\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by: Shahzad <shahzad31comp@gmail.com>","sha":"b74b93593cecec34e2745c30811c6929bf8a72c7","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["chore","release_note:skip","v9.0.0","backport:prev-minor","ci:project-deploy-observability","Team:obs-ux-management","v8.17.0"],"number":198950,"url":"https://github.com/elastic/kibana/pull/198950","mergeCommit":{"message":"[Synthetics] migrate first set of tests (#198950)\n\n## Summary\r\n\r\nRelates to #196229 \r\n\r\nMigrates Synthetics tests to deployment agnostic\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by: Shahzad <shahzad31comp@gmail.com>","sha":"b74b93593cecec34e2745c30811c6929bf8a72c7"}},"sourceBranch":"main","suggestedTargetBranches":["8.17"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/198950","number":198950,"mergeCommit":{"message":"[Synthetics] migrate first set of tests (#198950)\n\n## Summary\r\n\r\nRelates to #196229 \r\n\r\nMigrates Synthetics tests to deployment agnostic\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by: Shahzad <shahzad31comp@gmail.com>","sha":"b74b93593cecec34e2745c30811c6929bf8a72c7"}},{"branch":"8.17","label":"v8.17.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
This commit is contained in:
parent
cfe4d8375a
commit
16f761559f
42 changed files with 10420 additions and 4 deletions
5
.github/CODEOWNERS
vendored
5
.github/CODEOWNERS
vendored
|
@ -1220,6 +1220,7 @@ x-pack/test_serverless/**/test_suites/observability/ai_assistant @elastic/obs-ai
|
|||
/x-pack/test/api_integration/apis/infra @elastic/obs-ux-infra_services-team
|
||||
/x-pack/test/functional/apps/infra @elastic/obs-ux-infra_services-team
|
||||
/x-pack/test/functional/apps/infra/logs @elastic/obs-ux-logs-team
|
||||
/x-pack/test_serverless/**/test_suites/observability/infra/ @elastic/obs-ux-infra_services-team
|
||||
|
||||
# Observability UX management team
|
||||
/x-pack/packages/observability/alert_details @elastic/obs-ux-management-team
|
||||
|
@ -1232,7 +1233,9 @@ x-pack/test_serverless/**/test_suites/observability/ai_assistant @elastic/obs-ai
|
|||
/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule @elastic/obs-ux-management-team
|
||||
/x-pack/test/api_integration/deployment_agnostic/services/alerting_api @elastic/obs-ux-management-team
|
||||
/x-pack/test/api_integration/deployment_agnostic/services/slo_api @elastic/obs-ux-management-team
|
||||
/x-pack/test_serverless/**/test_suites/observability/infra/ @elastic/obs-ux-infra_services-team
|
||||
/x-pack/test/api_integration/deployment_agnostic/apis/observability/synthetics/ @elastic/obs-ux-management-team
|
||||
/x-pack/test/api_integration/deployment_agnostic/services/synthetics_monitors @elastic/obs-ux-management-team
|
||||
/x-pack/test/api_integration/deployment_agnostic/services/synthetics_private_location @elastic/obs-ux-management-team
|
||||
|
||||
# Elastic Stack Monitoring
|
||||
/x-pack/test/functional/apps/monitoring @elastic/stack-monitoring
|
||||
|
|
|
@ -95,3 +95,27 @@ From the `~/x-pack` directory:
|
|||
Start the server: `node scripts/functional_tests_server --config test/accessibility/config.ts`
|
||||
|
||||
Run the uptime `a11y` tests: `node scripts/functional_test_runner.js --config test/accessibility/config.ts --grep=uptime`
|
||||
|
||||
|
||||
## Deployment agnostic API Integration Tests
|
||||
The Synthetics tests are located under `x-pack/test/api_integration/deployment_agnostic/apis/observability/synthetics` folder. In order to run the SLO tests of your interest, you can grep accordingly. Use the commands below to run all SLO tests (`grep=SyntheticsAPITests`) on stateful or serverless.
|
||||
|
||||
### Stateful
|
||||
|
||||
```
|
||||
# start server
|
||||
node scripts/functional_tests_server --config x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts
|
||||
|
||||
# run tests
|
||||
node scripts/functional_test_runner --config x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts --grep=SyntheticsAPITests
|
||||
```
|
||||
|
||||
### Serverless
|
||||
|
||||
```
|
||||
# start server
|
||||
node scripts/functional_tests_server --config x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts
|
||||
|
||||
# run tests
|
||||
node scripts/functional_test_runner --config x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts --grep=SyntheticsAPITests
|
||||
```
|
||||
|
|
|
@ -309,9 +309,10 @@ export class SyntheticsService {
|
|||
return this.server.coreStart?.elasticsearch.client.asInternalUser;
|
||||
}
|
||||
|
||||
async getOutput() {
|
||||
async getOutput({ inspect }: { inspect: boolean } = { inspect: false }) {
|
||||
const { apiKey, isValid } = await getAPIKeyForSyntheticsService({ server: this.server });
|
||||
if (!isValid) {
|
||||
// do not check for api key validity if inspecting
|
||||
if (!isValid && !inspect) {
|
||||
this.server.logger.error(
|
||||
'API key is not valid. Cannot push monitor configuration to synthetics public testing locations'
|
||||
);
|
||||
|
@ -332,7 +333,7 @@ export class SyntheticsService {
|
|||
const monitors = this.formatConfigs(config);
|
||||
const license = await this.getLicense();
|
||||
|
||||
const output = await this.getOutput();
|
||||
const output = await this.getOutput({ inspect: true });
|
||||
if (output) {
|
||||
return await this.apiClient.inspect({
|
||||
monitors,
|
||||
|
|
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
* 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 { RoleCredentials, SamlAuthProviderType } from '@kbn/ftr-common-functional-services';
|
||||
import epct from 'expect';
|
||||
import moment from 'moment/moment';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { omit, omitBy } from 'lodash';
|
||||
import {
|
||||
ConfigKey,
|
||||
MonitorTypeEnum,
|
||||
HTTPFields,
|
||||
PrivateLocation,
|
||||
} from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { formatKibanaNamespace } from '@kbn/synthetics-plugin/common/formatters';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import { DEFAULT_FIELDS } from '@kbn/synthetics-plugin/common/constants/monitor_defaults';
|
||||
import {
|
||||
removeMonitorEmptyValues,
|
||||
transformPublicKeys,
|
||||
} from '@kbn/synthetics-plugin/server/routes/monitor_cruds/formatters/saved_object_to_monitor';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { SyntheticsMonitorTestService } from '../../../services/synthetics_monitor';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
|
||||
export const addMonitorAPIHelper = async (
|
||||
supertestAPI: any,
|
||||
monitor: any,
|
||||
statusCode = 200,
|
||||
roleAuthc: RoleCredentials,
|
||||
samlAuth: SamlAuthProviderType
|
||||
) => {
|
||||
const result = await supertestAPI
|
||||
.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.set(roleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor)
|
||||
.expect(statusCode);
|
||||
|
||||
if (statusCode === 200) {
|
||||
const { created_at: createdAt, updated_at: updatedAt, id, config_id: configId } = result.body;
|
||||
expect(id).not.empty();
|
||||
expect(configId).not.empty();
|
||||
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
|
||||
return {
|
||||
rawBody: result.body,
|
||||
body: {
|
||||
...omit(result.body, ['created_at', 'updated_at', 'id', 'config_id', 'form_monitor_type']),
|
||||
},
|
||||
};
|
||||
}
|
||||
return result.body;
|
||||
};
|
||||
|
||||
export const keyToOmitList = [
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'id',
|
||||
'config_id',
|
||||
'form_monitor_type',
|
||||
'spaceId',
|
||||
'private_locations',
|
||||
];
|
||||
|
||||
export const omitMonitorKeys = (monitor: any) => {
|
||||
return omitBy(omit(transformPublicKeys(monitor), keyToOmitList), removeMonitorEmptyValues);
|
||||
};
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('AddNewMonitorsUI', function () {
|
||||
const supertestAPI = getService('supertestWithoutAuth');
|
||||
const samlAuth = getService('samlAuth');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const monitorTestService = new SyntheticsMonitorTestService(getService);
|
||||
const privateLocationsService = new PrivateLocationTestService(getService);
|
||||
|
||||
let privateLocation: PrivateLocation;
|
||||
let _httpMonitorJson: HTTPFields;
|
||||
let httpMonitorJson: HTTPFields;
|
||||
let editorRoleAuthc: RoleCredentials;
|
||||
|
||||
const addMonitorAPI = async (monitor: any, statusCode = 200) => {
|
||||
return addMonitorAPIHelper(supertestAPI, monitor, statusCode, editorRoleAuthc, samlAuth);
|
||||
};
|
||||
|
||||
const deleteMonitor = async (
|
||||
monitorId?: string | string[],
|
||||
statusCode = 200,
|
||||
spaceId?: string
|
||||
) => {
|
||||
return monitorTestService.deleteMonitor(editorRoleAuthc, monitorId, statusCode, spaceId);
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
_httpMonitorJson = getFixtureJson('http_monitor');
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
editorRoleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
privateLocation = await privateLocationsService.addTestPrivateLocation();
|
||||
httpMonitorJson = {
|
||||
..._httpMonitorJson,
|
||||
locations: [privateLocation],
|
||||
};
|
||||
});
|
||||
|
||||
it('returns the newly added monitor', async () => {
|
||||
const newMonitor = httpMonitorJson;
|
||||
|
||||
const { body: apiResponse } = await addMonitorAPI(newMonitor);
|
||||
|
||||
expect(apiResponse).eql(omitMonitorKeys(newMonitor));
|
||||
});
|
||||
|
||||
it('returns bad request if payload is invalid for HTTP monitor', async () => {
|
||||
// Delete a required property to make payload invalid
|
||||
const newMonitor = { ...httpMonitorJson, 'check.request.headers': null };
|
||||
await addMonitorAPI(newMonitor, 400);
|
||||
});
|
||||
|
||||
it('returns bad request if monitor type is invalid', async () => {
|
||||
const newMonitor = { ...httpMonitorJson, type: 'invalid-data-steam' };
|
||||
|
||||
const apiResponse = await addMonitorAPI(newMonitor, 400);
|
||||
|
||||
expect(apiResponse.message).eql('Invalid value "invalid-data-steam" supplied to "type"');
|
||||
});
|
||||
|
||||
it('can create valid monitors without all defaults', async () => {
|
||||
// Delete a required property to make payload invalid
|
||||
const newMonitor = {
|
||||
name: 'Sample name',
|
||||
type: 'http',
|
||||
urls: 'https://elastic.co',
|
||||
locations: [privateLocation],
|
||||
};
|
||||
|
||||
const { body: apiResponse } = await addMonitorAPI(newMonitor);
|
||||
|
||||
expect(apiResponse).eql(
|
||||
omitMonitorKeys({
|
||||
...DEFAULT_FIELDS[MonitorTypeEnum.HTTP],
|
||||
...newMonitor,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('can disable retries', async () => {
|
||||
const maxAttempts = 1;
|
||||
const newMonitor = {
|
||||
max_attempts: maxAttempts,
|
||||
urls: 'https://elastic.co',
|
||||
name: `Sample name ${uuidv4()}`,
|
||||
type: 'http',
|
||||
locations: [privateLocation],
|
||||
};
|
||||
|
||||
const { body: apiResponse } = await addMonitorAPI(newMonitor);
|
||||
|
||||
epct(apiResponse).toEqual(epct.objectContaining({ retest_on_failure: false }));
|
||||
});
|
||||
|
||||
it('can enable retries with max attempts', async () => {
|
||||
const maxAttempts = 2;
|
||||
const newMonitor = {
|
||||
max_attempts: maxAttempts,
|
||||
urls: 'https://elastic.co',
|
||||
name: `Sample name ${uuidv4()}`,
|
||||
type: 'http',
|
||||
locations: [privateLocation],
|
||||
};
|
||||
|
||||
const { body: apiResponse } = await addMonitorAPI(newMonitor);
|
||||
|
||||
epct(apiResponse).toEqual(epct.objectContaining({ retest_on_failure: true }));
|
||||
});
|
||||
|
||||
it('can enable retries', async () => {
|
||||
const newMonitor = {
|
||||
retest_on_failure: false,
|
||||
urls: 'https://elastic.co',
|
||||
name: `Sample name ${uuidv4()}`,
|
||||
type: 'http',
|
||||
locations: [privateLocation],
|
||||
};
|
||||
|
||||
const { body: apiResponse } = await addMonitorAPI(newMonitor);
|
||||
|
||||
epct(apiResponse).toEqual(epct.objectContaining({ retest_on_failure: false }));
|
||||
});
|
||||
|
||||
it('cannot create a invalid monitor without a monitor type', async () => {
|
||||
// Delete a required property to make payload invalid
|
||||
const newMonitor = {
|
||||
name: 'Sample name',
|
||||
url: 'https://elastic.co',
|
||||
locations: [privateLocation],
|
||||
};
|
||||
await addMonitorAPI(newMonitor, 400);
|
||||
});
|
||||
|
||||
it('omits unknown keys', async () => {
|
||||
// Delete a required property to make payload invalid
|
||||
const newMonitor = {
|
||||
name: 'Sample name',
|
||||
url: 'https://elastic.co',
|
||||
unknownKey: 'unknownValue',
|
||||
type: 'http',
|
||||
locations: [privateLocation],
|
||||
};
|
||||
const apiResponse = await addMonitorAPI(newMonitor, 400);
|
||||
expect(apiResponse.message).not.to.have.keys(
|
||||
'Invalid monitor key(s) for http type: unknownKey","attributes":{"details":"Invalid monitor key(s) for http type: unknownKey'
|
||||
);
|
||||
});
|
||||
|
||||
it('sets namespace to Kibana space when not set to a custom namespace', async () => {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
const EXPECTED_NAMESPACE = formatKibanaNamespace(SPACE_ID);
|
||||
privateLocation = await privateLocationsService.addTestPrivateLocation(SPACE_ID);
|
||||
const monitor = {
|
||||
...httpMonitorJson,
|
||||
[ConfigKey.NAMESPACE]: 'default',
|
||||
locations: [privateLocation],
|
||||
};
|
||||
let monitorId = '';
|
||||
|
||||
try {
|
||||
await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
|
||||
const apiResponse = await supertestAPI
|
||||
.post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
.set(editorRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor)
|
||||
.expect(200);
|
||||
monitorId = apiResponse.body.id;
|
||||
expect(apiResponse.body[ConfigKey.NAMESPACE]).eql(EXPECTED_NAMESPACE);
|
||||
} finally {
|
||||
await deleteMonitor(monitorId, 200, SPACE_ID);
|
||||
}
|
||||
});
|
||||
|
||||
it('preserves the passed namespace when preserve_namespace is passed', async () => {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
privateLocation = await privateLocationsService.addTestPrivateLocation(SPACE_ID);
|
||||
const monitor = {
|
||||
...httpMonitorJson,
|
||||
[ConfigKey.NAMESPACE]: 'default',
|
||||
locations: [privateLocation],
|
||||
};
|
||||
let monitorId = '';
|
||||
await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
|
||||
try {
|
||||
const apiResponse = await supertestAPI
|
||||
.post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
.query({ preserve_namespace: true })
|
||||
.set(editorRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor)
|
||||
.expect(200);
|
||||
monitorId = apiResponse.body.id;
|
||||
expect(apiResponse.body[ConfigKey.NAMESPACE]).eql('default');
|
||||
} finally {
|
||||
await deleteMonitor(monitorId, 200, SPACE_ID);
|
||||
}
|
||||
});
|
||||
|
||||
it('sets namespace to custom namespace when set', async () => {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
privateLocation = await privateLocationsService.addTestPrivateLocation(SPACE_ID);
|
||||
const monitor = {
|
||||
...httpMonitorJson,
|
||||
locations: [privateLocation],
|
||||
};
|
||||
let monitorId = '';
|
||||
|
||||
try {
|
||||
await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
|
||||
const apiResponse = await supertestAPI
|
||||
.post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
.set(editorRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor)
|
||||
.expect(200);
|
||||
monitorId = apiResponse.body.id;
|
||||
expect(apiResponse.body[ConfigKey.NAMESPACE]).eql(monitor[ConfigKey.NAMESPACE]);
|
||||
} finally {
|
||||
await deleteMonitor(monitorId, 200, SPACE_ID);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,560 @@
|
|||
/*
|
||||
* 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 moment from 'moment';
|
||||
import semver from 'semver';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import {
|
||||
ConfigKey,
|
||||
HTTPFields,
|
||||
PrivateLocation,
|
||||
ServiceLocation,
|
||||
} from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import { omit } from 'lodash';
|
||||
import { PackagePolicy } from '@kbn/fleet-plugin/common';
|
||||
import expect from '@kbn/expect';
|
||||
import rawExpect from 'expect';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { comparePolicies, getTestSyntheticsPolicy } from './sample_data/test_policy';
|
||||
import {
|
||||
INSTALLED_VERSION,
|
||||
PrivateLocationTestService,
|
||||
} from '../../../services/synthetics_private_location';
|
||||
import { addMonitorAPIHelper, keyToOmitList, omitMonitorKeys } from './create_monitor';
|
||||
import { SyntheticsMonitorTestService } from '../../../services/synthetics_monitor';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('PrivateLocationAddMonitor', function () {
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const supertestAPI = getService('supertestWithoutAuth');
|
||||
const supertestWithAuth = getService('supertest');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
let testFleetPolicyID: string;
|
||||
let editorUser: RoleCredentials;
|
||||
let privateLocations: PrivateLocation[] = [];
|
||||
const testPolicyName = 'Fleet test server policy' + Date.now();
|
||||
|
||||
let _httpMonitorJson: HTTPFields;
|
||||
let httpMonitorJson: HTTPFields;
|
||||
const monitorTestService = new SyntheticsMonitorTestService(getService);
|
||||
const testPrivateLocations = new PrivateLocationTestService(getService);
|
||||
|
||||
const addMonitorAPI = async (monitor: any, statusCode = 200) => {
|
||||
return addMonitorAPIHelper(supertestAPI, monitor, statusCode, editorUser, samlAuth);
|
||||
};
|
||||
|
||||
const deleteMonitor = async (
|
||||
monitorId?: string | string[],
|
||||
statusCode = 200,
|
||||
spaceId?: string
|
||||
) => {
|
||||
return monitorTestService.deleteMonitor(editorUser, monitorId, statusCode, spaceId);
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
await testPrivateLocations.installSyntheticsPackage();
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
|
||||
_httpMonitorJson = getFixtureJson('http_monitor');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
httpMonitorJson = {
|
||||
..._httpMonitorJson,
|
||||
locations: privateLocations ? [privateLocations[0]] : [],
|
||||
};
|
||||
});
|
||||
|
||||
it('adds a test fleet policy', async () => {
|
||||
const apiResponse = await testPrivateLocations.addFleetPolicy(testPolicyName);
|
||||
testFleetPolicyID = apiResponse.body.item.id;
|
||||
});
|
||||
|
||||
it('add a test private location', async () => {
|
||||
privateLocations = await testPrivateLocations.setTestLocations([testFleetPolicyID]);
|
||||
|
||||
const apiResponse = await supertestAPI
|
||||
.get(SYNTHETICS_API_URLS.SERVICE_LOCATIONS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const testResponse: Array<PrivateLocation | ServiceLocation> = [
|
||||
{
|
||||
id: testFleetPolicyID,
|
||||
isServiceManaged: false,
|
||||
isInvalid: false,
|
||||
label: privateLocations[0].label,
|
||||
geo: {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
agentPolicyId: testFleetPolicyID,
|
||||
},
|
||||
];
|
||||
|
||||
rawExpect(apiResponse.body.locations).toEqual(rawExpect.arrayContaining(testResponse));
|
||||
});
|
||||
|
||||
it('does not add a monitor if there is an error in creating integration', async () => {
|
||||
const newMonitor = { ...httpMonitorJson };
|
||||
const invalidName = 'invalid name';
|
||||
|
||||
const location = {
|
||||
id: 'invalidLocation',
|
||||
label: privateLocations[0].label,
|
||||
isServiceManaged: false,
|
||||
geo: {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
};
|
||||
|
||||
newMonitor.name = invalidName;
|
||||
|
||||
const apiResponse = await supertestAPI
|
||||
.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ ...newMonitor, locations: [location] })
|
||||
.expect(400);
|
||||
|
||||
expect(apiResponse.body).eql({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Invalid locations specified. Private Location(s) 'invalidLocation' not found. Available private locations are '${privateLocations[0].label}'`,
|
||||
});
|
||||
|
||||
const apiGetResponse = await supertestAPI
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + `?query="${invalidName}"`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
// verify that no monitor was added
|
||||
expect(apiGetResponse.body.monitors?.length).eql(0);
|
||||
});
|
||||
|
||||
let newMonitorId: string;
|
||||
|
||||
it('adds a monitor in private location', async () => {
|
||||
const newMonitor = {
|
||||
...httpMonitorJson,
|
||||
locations: [privateLocations[0]],
|
||||
};
|
||||
|
||||
const { body, rawBody } = await addMonitorAPI(newMonitor);
|
||||
|
||||
expect(body).eql(omitMonitorKeys(newMonitor));
|
||||
newMonitorId = rawBody.id;
|
||||
});
|
||||
|
||||
it('added an integration for previously added monitor', async () => {
|
||||
const apiResponse = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy = apiResponse.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default'
|
||||
);
|
||||
|
||||
expect(packagePolicy?.policy_id).eql(testFleetPolicyID);
|
||||
|
||||
comparePolicies(
|
||||
packagePolicy,
|
||||
getTestSyntheticsPolicy({
|
||||
name: httpMonitorJson.name,
|
||||
id: newMonitorId,
|
||||
location: { id: testFleetPolicyID, name: privateLocations[0].label },
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
let testFleetPolicyID2: string;
|
||||
let newLocations: PrivateLocation[] = [];
|
||||
|
||||
it('edits a monitor with additional private location', async () => {
|
||||
const resPolicy = await testPrivateLocations.addFleetPolicy(testPolicyName + 1);
|
||||
testFleetPolicyID2 = resPolicy.body.item.id;
|
||||
|
||||
newLocations = await testPrivateLocations.setTestLocations([
|
||||
testFleetPolicyID,
|
||||
testFleetPolicyID2,
|
||||
]);
|
||||
|
||||
httpMonitorJson.locations.push({
|
||||
id: testFleetPolicyID2,
|
||||
agentPolicyId: testFleetPolicyID2,
|
||||
label: newLocations[1].label,
|
||||
isServiceManaged: false,
|
||||
geo: {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const apiResponse = await supertestAPI
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + newMonitorId)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(httpMonitorJson);
|
||||
|
||||
const { created_at: createdAt, updated_at: updatedAt } = apiResponse.body;
|
||||
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
|
||||
|
||||
expect(omit(apiResponse.body, keyToOmitList)).eql(
|
||||
omitMonitorKeys({
|
||||
...omit(httpMonitorJson, ['urls']),
|
||||
url: httpMonitorJson.urls,
|
||||
updated_at: updatedAt,
|
||||
revision: 2,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('added an integration for second location in edit monitor', async () => {
|
||||
const apiResponsePolicy = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
let packagePolicy = apiResponsePolicy.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default'
|
||||
);
|
||||
|
||||
expect(packagePolicy.policy_id).eql(testFleetPolicyID);
|
||||
|
||||
comparePolicies(
|
||||
packagePolicy,
|
||||
getTestSyntheticsPolicy({
|
||||
name: httpMonitorJson.name,
|
||||
id: newMonitorId,
|
||||
location: { id: testFleetPolicyID, name: privateLocations[0].label },
|
||||
})
|
||||
);
|
||||
|
||||
packagePolicy = apiResponsePolicy.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID2 + '-default'
|
||||
);
|
||||
|
||||
expect(packagePolicy.policy_id).eql(testFleetPolicyID2);
|
||||
comparePolicies(
|
||||
packagePolicy,
|
||||
getTestSyntheticsPolicy({
|
||||
name: httpMonitorJson.name,
|
||||
id: newMonitorId,
|
||||
location: {
|
||||
name: newLocations[1].label,
|
||||
id: testFleetPolicyID2,
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('deletes integration for a removed location from monitor', async () => {
|
||||
httpMonitorJson.locations = httpMonitorJson.locations.filter(
|
||||
({ id }) => id !== testFleetPolicyID2
|
||||
);
|
||||
|
||||
await supertestAPI
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + newMonitorId + '?internal=true')
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(httpMonitorJson)
|
||||
.expect(200);
|
||||
|
||||
const apiResponsePolicy = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
let packagePolicy = apiResponsePolicy.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default'
|
||||
);
|
||||
|
||||
expect(packagePolicy.policy_id).eql(testFleetPolicyID);
|
||||
|
||||
comparePolicies(
|
||||
packagePolicy,
|
||||
getTestSyntheticsPolicy({
|
||||
name: httpMonitorJson.name,
|
||||
id: newMonitorId,
|
||||
location: { id: testFleetPolicyID, name: privateLocations[0].label },
|
||||
})
|
||||
);
|
||||
|
||||
packagePolicy = apiResponsePolicy.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID2 + '-default'
|
||||
);
|
||||
|
||||
expect(packagePolicy).eql(undefined);
|
||||
});
|
||||
|
||||
it('deletes integration for a deleted monitor', async () => {
|
||||
await deleteMonitor(newMonitorId);
|
||||
|
||||
const apiResponsePolicy = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy = apiResponsePolicy.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default'
|
||||
);
|
||||
|
||||
expect(packagePolicy).eql(undefined);
|
||||
});
|
||||
|
||||
// it('handles spaces', async () => {
|
||||
// const username = 'admin';
|
||||
// const password = `${username}-password`;
|
||||
// const roleName = 'uptime-role';
|
||||
// const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
// const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
// let monitorId = '';
|
||||
// const monitor = {
|
||||
// ...httpMonitorJson,
|
||||
// name: `Test monitor ${uuidv4()}`,
|
||||
// [ConfigKey.NAMESPACE]: 'default',
|
||||
// locations: [
|
||||
// {
|
||||
// id: testFleetPolicyID,
|
||||
// agentPolicyId: testFleetPolicyID,
|
||||
// label: 'Test private location 0',
|
||||
// isServiceManaged: false,
|
||||
// geo: {
|
||||
// lat: 0,
|
||||
// lon: 0,
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// };
|
||||
|
||||
// try {
|
||||
// await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
// await security.role.create(roleName, {
|
||||
// kibana: [
|
||||
// {
|
||||
// feature: {
|
||||
// uptime: ['all'],
|
||||
// actions: ['all'],
|
||||
// },
|
||||
// spaces: ['*'],
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// await security.user.create(username, {
|
||||
// password,
|
||||
// roles: [roleName],
|
||||
// full_name: 'a kibana user',
|
||||
// });
|
||||
// const apiResponse = await supertestWithoutAuth
|
||||
// .post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
// .auth(username, password)
|
||||
// .set('kbn-xsrf', 'true')
|
||||
// .send(monitor)
|
||||
// .expect(200);
|
||||
|
||||
// const { created_at: createdAt, updated_at: updatedAt } = apiResponse.body;
|
||||
// expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
|
||||
|
||||
// expect(omit(apiResponse.body, keyToOmitList)).eql(
|
||||
// omitMonitorKeys({
|
||||
// ...monitor,
|
||||
// [ConfigKey.NAMESPACE]: formatKibanaNamespace(SPACE_ID),
|
||||
// url: apiResponse.body.url,
|
||||
// })
|
||||
// );
|
||||
// monitorId = apiResponse.body.id;
|
||||
|
||||
// const policyResponse = await supertestWithAuth.get(
|
||||
// '/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
// );
|
||||
|
||||
// const packagePolicy = policyResponse.body.items.find(
|
||||
// (pkgPolicy: PackagePolicy) =>
|
||||
// pkgPolicy.id === monitorId + '-' + testFleetPolicyID + `-${SPACE_ID}`
|
||||
// );
|
||||
|
||||
// expect(packagePolicy.policy_id).eql(testFleetPolicyID);
|
||||
// expect(packagePolicy.name).eql(`${monitor.name}-Test private location 0-${SPACE_ID}`);
|
||||
// comparePolicies(
|
||||
// packagePolicy,
|
||||
// getTestSyntheticsPolicy({
|
||||
// name: monitor.name,
|
||||
// id: monitorId,
|
||||
// location: { id: testFleetPolicyID },
|
||||
// namespace: formatKibanaNamespace(SPACE_ID),
|
||||
// spaceId: SPACE_ID,
|
||||
// })
|
||||
// );
|
||||
// await supertestWithoutAuth
|
||||
// .delete(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
// .auth(username, password)
|
||||
// .set('kbn-xsrf', 'true')
|
||||
// .send({ ids: [monitorId] })
|
||||
// .expect(200);
|
||||
// } finally {
|
||||
// await security.user.delete(username);
|
||||
// await security.role.delete(roleName);
|
||||
// }
|
||||
// });
|
||||
|
||||
it('handles is_tls_enabled true', async () => {
|
||||
let monitorId = '';
|
||||
|
||||
const monitor = {
|
||||
...httpMonitorJson,
|
||||
locations: [
|
||||
{
|
||||
id: testFleetPolicyID,
|
||||
label: privateLocations[0].label,
|
||||
isServiceManaged: false,
|
||||
},
|
||||
],
|
||||
[ConfigKey.METADATA]: {
|
||||
is_tls_enabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const apiResponse = await supertestAPI
|
||||
.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor)
|
||||
.expect(200);
|
||||
|
||||
monitorId = apiResponse.body.id;
|
||||
|
||||
const policyResponse = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy = policyResponse.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === monitorId + '-' + testFleetPolicyID + `-default`
|
||||
);
|
||||
comparePolicies(
|
||||
packagePolicy,
|
||||
getTestSyntheticsPolicy({
|
||||
name: monitor.name,
|
||||
id: monitorId,
|
||||
location: { id: testFleetPolicyID, name: privateLocations[0].label },
|
||||
isTLSEnabled: true,
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
await deleteMonitor(monitorId);
|
||||
}
|
||||
});
|
||||
|
||||
it('handles is_tls_enabled false', async () => {
|
||||
let monitorId = '';
|
||||
|
||||
const monitor = {
|
||||
...httpMonitorJson,
|
||||
locations: [
|
||||
{
|
||||
id: testFleetPolicyID,
|
||||
label: privateLocations[0].label,
|
||||
isServiceManaged: false,
|
||||
},
|
||||
],
|
||||
[ConfigKey.METADATA]: {
|
||||
is_tls_enabled: false,
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
const apiResponse = await supertestAPI
|
||||
.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor)
|
||||
.expect(200);
|
||||
|
||||
monitorId = apiResponse.body.id;
|
||||
|
||||
const policyResponse = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy = policyResponse.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === monitorId + '-' + testFleetPolicyID + `-default`
|
||||
);
|
||||
comparePolicies(
|
||||
packagePolicy,
|
||||
getTestSyntheticsPolicy({
|
||||
name: monitor.name,
|
||||
id: monitorId,
|
||||
location: { id: testFleetPolicyID, name: privateLocations[0].label },
|
||||
})
|
||||
);
|
||||
} finally {
|
||||
await deleteMonitor(monitorId);
|
||||
}
|
||||
});
|
||||
|
||||
it('handles auto upgrading policies', async () => {
|
||||
let monitorId = '';
|
||||
|
||||
const monitor = {
|
||||
...httpMonitorJson,
|
||||
name: `Test monitor ${uuidv4()}`,
|
||||
[ConfigKey.NAMESPACE]: 'default',
|
||||
locations: [
|
||||
{
|
||||
id: testFleetPolicyID,
|
||||
label: privateLocations[0].label,
|
||||
isServiceManaged: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
try {
|
||||
const apiResponse = await supertestAPI
|
||||
.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor)
|
||||
.expect(200);
|
||||
monitorId = apiResponse.body.id;
|
||||
|
||||
const policyResponse = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy = policyResponse.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === monitorId + '-' + testFleetPolicyID + `-default`
|
||||
);
|
||||
|
||||
expect(packagePolicy.package.version).eql(INSTALLED_VERSION);
|
||||
|
||||
await supertestWithAuth.post('/api/fleet/setup').set('kbn-xsrf', 'true').send().expect(200);
|
||||
const policyResponseAfterUpgrade = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
const packagePolicyAfterUpgrade = policyResponseAfterUpgrade.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === monitorId + '-' + testFleetPolicyID + `-default`
|
||||
);
|
||||
expect(semver.gte(packagePolicyAfterUpgrade.package.version, INSTALLED_VERSION)).eql(true);
|
||||
} finally {
|
||||
await deleteMonitor(monitorId);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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 { v4 as uuidv4 } from 'uuid';
|
||||
import expect from '@kbn/expect';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import { ProjectMonitorsRequest } from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
import { SyntheticsMonitorTestService } from '../../../services/synthetics_monitor';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('AddProjectMonitorsPrivateLocations', function () {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
let projectMonitors: ProjectMonitorsRequest;
|
||||
let editorUser: RoleCredentials;
|
||||
|
||||
const monitorTestService = new SyntheticsMonitorTestService(getService);
|
||||
|
||||
let testPolicyId;
|
||||
let testPrivateLocationName: string;
|
||||
const testPolicyName = `Fleet test server policy ${uuidv4()}`;
|
||||
const testPrivateLocationsService = new PrivateLocationTestService(getService);
|
||||
|
||||
const setUniqueIds = (request: ProjectMonitorsRequest) => {
|
||||
return {
|
||||
...request,
|
||||
monitors: request.monitors.map((monitor) => ({ ...monitor, id: uuidv4() })),
|
||||
};
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
await testPrivateLocationsService.installSyntheticsPackage();
|
||||
|
||||
const apiResponse = await testPrivateLocationsService.addFleetPolicy(testPolicyName);
|
||||
testPolicyId = apiResponse.body.item.id;
|
||||
const testPrivateLocations = await testPrivateLocationsService.setTestLocations([
|
||||
testPolicyId,
|
||||
]);
|
||||
testPrivateLocationName = testPrivateLocations[0].label;
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
projectMonitors = setUniqueIds({
|
||||
monitors: getFixtureJson('project_browser_monitor').monitors.map(
|
||||
(monitor: Record<string, unknown>) => {
|
||||
return {
|
||||
...monitor,
|
||||
name: `test-monitor-${uuidv4()}`,
|
||||
type: 'browser',
|
||||
locations: [],
|
||||
privateLocations: [testPrivateLocationName],
|
||||
};
|
||||
}
|
||||
),
|
||||
});
|
||||
});
|
||||
|
||||
it('project monitors - returns a failed monitor when creating integration fails', async () => {
|
||||
const project = `test-project-${uuidv4()}`;
|
||||
|
||||
const secondMonitor = {
|
||||
...projectMonitors.monitors[0],
|
||||
id: 'test-id-2',
|
||||
privateLocations: ['Test private location 7'],
|
||||
};
|
||||
const testMonitors = [
|
||||
projectMonitors.monitors[0],
|
||||
{
|
||||
...secondMonitor,
|
||||
name: '!@#$%^&*()_++[\\-\\]- wow name',
|
||||
},
|
||||
];
|
||||
try {
|
||||
const { body, status } = await monitorTestService.addProjectMonitors(
|
||||
project,
|
||||
testMonitors,
|
||||
editorUser
|
||||
);
|
||||
expect(status).eql(200);
|
||||
expect(body.createdMonitors.length).eql(1);
|
||||
expect(body.failedMonitors[0].reason).eql(
|
||||
"Couldn't save or update monitor because of an invalid configuration."
|
||||
);
|
||||
} finally {
|
||||
await Promise.all([
|
||||
testMonitors.map((monitor) => {
|
||||
return monitorTestService.deleteMonitorByJourney(
|
||||
monitor.id,
|
||||
project,
|
||||
'default',
|
||||
editorUser
|
||||
);
|
||||
}),
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
it('project monitors - returns a failed monitor when editing integration fails', async () => {
|
||||
const project = `test-project-${uuidv4()}`;
|
||||
|
||||
const secondMonitor = {
|
||||
...projectMonitors.monitors[0],
|
||||
id: 'test-id-2',
|
||||
privateLocations: [testPrivateLocationName],
|
||||
};
|
||||
const testMonitors = [projectMonitors.monitors[0], secondMonitor];
|
||||
const { body, status: status0 } = await monitorTestService.addProjectMonitors(
|
||||
project,
|
||||
testMonitors,
|
||||
editorUser
|
||||
);
|
||||
expect(status0).eql(200);
|
||||
|
||||
expect(body.createdMonitors.length).eql(2);
|
||||
const { body: editedBody, status: editedStatus } =
|
||||
await monitorTestService.addProjectMonitors(project, testMonitors, editorUser);
|
||||
expect(editedStatus).eql(200);
|
||||
|
||||
expect(editedBody.createdMonitors.length).eql(0);
|
||||
expect(editedBody.updatedMonitors.length).eql(2);
|
||||
|
||||
testMonitors[1].name = '!@#$%^&*()_++[\\-\\]- wow name';
|
||||
testMonitors[1].privateLocations = ['Test private location 8'];
|
||||
|
||||
const { body: editedBodyError, status } = await monitorTestService.addProjectMonitors(
|
||||
project,
|
||||
testMonitors,
|
||||
editorUser
|
||||
);
|
||||
expect(status).eql(200);
|
||||
expect(editedBodyError.createdMonitors.length).eql(0);
|
||||
expect(editedBodyError.updatedMonitors.length).eql(1);
|
||||
expect(editedBodyError.failedMonitors.length).eql(1);
|
||||
expect(editedBodyError.failedMonitors[0].details).eql(
|
||||
`Invalid locations specified. Private Location(s) 'Test private location 8' not found. Available private locations are '${testPrivateLocationName}'`
|
||||
);
|
||||
expect(editedBodyError.failedMonitors[0].reason).eql(
|
||||
"Couldn't save or update monitor because of an invalid configuration."
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* 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 rawExpect from 'expect';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import { PrivateLocation } from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { DEFAULT_FIELDS } from '@kbn/synthetics-plugin/common/constants/monitor_defaults';
|
||||
import { LOCATION_REQUIRED_ERROR } from '@kbn/synthetics-plugin/server/routes/monitor_cruds/monitor_validation';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { addMonitorAPIHelper, omitMonitorKeys } from './create_monitor';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('AddNewMonitorsPublicAPI', function () {
|
||||
const supertestAPI = getService('supertestWithoutAuth');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const samlAuth = getService('samlAuth');
|
||||
let editorUser: RoleCredentials;
|
||||
let privateLocation: PrivateLocation;
|
||||
const privateLocationTestService = new PrivateLocationTestService(getService);
|
||||
|
||||
async function addMonitorAPI(monitor: any, statusCode: number = 200) {
|
||||
return await addMonitorAPIHelper(supertestAPI, monitor, statusCode, editorUser, samlAuth);
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
privateLocation = await privateLocationTestService.addTestPrivateLocation();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
});
|
||||
|
||||
it('should return error for empty monitor', async function () {
|
||||
const { message } = await addMonitorAPI({}, 400);
|
||||
expect(message).eql('Invalid value "undefined" supplied to "type"');
|
||||
});
|
||||
|
||||
it('return error if no location specified', async () => {
|
||||
const { message } = await addMonitorAPI({ type: 'http' }, 400);
|
||||
expect(message).eql(LOCATION_REQUIRED_ERROR);
|
||||
});
|
||||
|
||||
it('return error if invalid location specified', async () => {
|
||||
const { message } = await addMonitorAPI({ type: 'http', locations: ['mars'] }, 400);
|
||||
rawExpect(message).toContain(
|
||||
"Invalid locations specified. Elastic managed Location(s) 'mars' not found."
|
||||
);
|
||||
});
|
||||
|
||||
it('return error if invalid private location specified', async () => {
|
||||
const { message } = await addMonitorAPI(
|
||||
{
|
||||
type: 'http',
|
||||
locations: ['mars'],
|
||||
privateLocations: ['moon'],
|
||||
},
|
||||
400
|
||||
);
|
||||
expect(message).eql('Invalid monitor key(s) for http type: privateLocations');
|
||||
|
||||
const result = await addMonitorAPI(
|
||||
{
|
||||
type: 'http',
|
||||
locations: ['mars'],
|
||||
private_locations: ['moon'],
|
||||
},
|
||||
400
|
||||
);
|
||||
rawExpect(result.message).toContain("Private Location(s) 'moon' not found.");
|
||||
});
|
||||
|
||||
it('return error for origin project', async () => {
|
||||
const { message } = await addMonitorAPI(
|
||||
{
|
||||
type: 'http',
|
||||
locations: ['dev'],
|
||||
url: 'https://www.google.com',
|
||||
origin: 'project',
|
||||
},
|
||||
400
|
||||
);
|
||||
expect(message).eql('Unsupported origin type project, only ui type is supported via API.');
|
||||
});
|
||||
|
||||
describe('HTTP Monitor', () => {
|
||||
const defaultFields = DEFAULT_FIELDS.http;
|
||||
it('return error empty http', async () => {
|
||||
const { message, attributes } = await addMonitorAPI(
|
||||
{
|
||||
type: 'http',
|
||||
locations: [],
|
||||
private_locations: [privateLocation.id],
|
||||
},
|
||||
400
|
||||
);
|
||||
|
||||
expect(message).eql('Monitor is not a valid monitor of type http');
|
||||
expect(attributes).eql({
|
||||
details:
|
||||
'Invalid field "url", must be a non-empty string. | Invalid value "undefined" supplied to "name"',
|
||||
payload: { type: 'http' },
|
||||
});
|
||||
});
|
||||
|
||||
it('base http monitor', async () => {
|
||||
const monitor = {
|
||||
type: 'http',
|
||||
private_locations: [privateLocation.id],
|
||||
url: 'https://www.google.com',
|
||||
};
|
||||
const { body: result } = await addMonitorAPI(monitor);
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...monitor,
|
||||
locations: [privateLocation],
|
||||
name: 'https://www.google.com',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('can enable retries', async () => {
|
||||
const name = `test name ${uuidv4()}`;
|
||||
const monitor = {
|
||||
type: 'http',
|
||||
private_locations: [privateLocation.id],
|
||||
url: 'https://www.google.com',
|
||||
name,
|
||||
retest_on_failure: true,
|
||||
};
|
||||
const { body: result } = await addMonitorAPI(monitor);
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...monitor,
|
||||
locations: [privateLocation],
|
||||
name,
|
||||
retest_on_failure: true,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('can disable retries', async () => {
|
||||
const name = `test name ${uuidv4()}`;
|
||||
const monitor = {
|
||||
type: 'http',
|
||||
private_locations: [privateLocation.id],
|
||||
url: 'https://www.google.com',
|
||||
name,
|
||||
retest_on_failure: false,
|
||||
};
|
||||
const { body: result } = await addMonitorAPI(monitor);
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...monitor,
|
||||
locations: [privateLocation],
|
||||
name,
|
||||
max_attempts: 1,
|
||||
retest_on_failure: undefined, // this key is not part of the SO and should not be defined
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('TCP Monitor', () => {
|
||||
const defaultFields = DEFAULT_FIELDS.tcp;
|
||||
|
||||
it('base tcp monitor', async () => {
|
||||
const monitor = {
|
||||
type: 'tcp',
|
||||
private_locations: [privateLocation.id],
|
||||
host: 'https://www.google.com/',
|
||||
};
|
||||
const { body: result } = await addMonitorAPI(monitor);
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...monitor,
|
||||
locations: [privateLocation],
|
||||
name: 'https://www.google.com/',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ICMP Monitor', () => {
|
||||
const defaultFields = DEFAULT_FIELDS.icmp;
|
||||
|
||||
it('base icmp monitor', async () => {
|
||||
const monitor = {
|
||||
type: 'icmp',
|
||||
private_locations: [privateLocation.id],
|
||||
host: 'https://8.8.8.8',
|
||||
};
|
||||
const { body: result } = await addMonitorAPI(monitor);
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...monitor,
|
||||
locations: [privateLocation],
|
||||
name: 'https://8.8.8.8',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Browser Monitor', () => {
|
||||
const defaultFields = DEFAULT_FIELDS.browser;
|
||||
|
||||
it('empty browser monitor', async () => {
|
||||
const monitor = {
|
||||
type: 'browser',
|
||||
private_locations: [privateLocation.id],
|
||||
name: 'simple journey',
|
||||
};
|
||||
const result = await addMonitorAPI(monitor, 400);
|
||||
|
||||
expect(result).eql({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'Monitor is not a valid monitor of type browser',
|
||||
attributes: {
|
||||
details: 'source.inline.script: Script is required for browser monitor.',
|
||||
payload: { type: 'browser', name: 'simple journey' },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('base browser monitor', async () => {
|
||||
const monitor = {
|
||||
type: 'browser',
|
||||
private_locations: [privateLocation.id],
|
||||
name: 'simple journey',
|
||||
'source.inline.script': 'step("simple journey", async () => {});',
|
||||
};
|
||||
const { body: result } = await addMonitorAPI(monitor);
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...monitor,
|
||||
locations: [privateLocation],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('base browser monitor with inline_script', async () => {
|
||||
const monitor = {
|
||||
type: 'browser',
|
||||
private_locations: [privateLocation.id],
|
||||
name: 'simple journey inline_script',
|
||||
inline_script: 'step("simple journey", async () => {});',
|
||||
};
|
||||
const { body: result } = await addMonitorAPI(monitor);
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...monitor,
|
||||
locations: [privateLocation],
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
* 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 { v4 as uuidv4 } from 'uuid';
|
||||
import { pick } from 'lodash';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import expect from '@kbn/expect';
|
||||
import { syntheticsParamType } from '@kbn/synthetics-plugin/common/types/saved_objects';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
|
||||
function assertHas(actual: unknown, expected: object) {
|
||||
expect(pick(actual, Object.keys(expected))).eql(expected);
|
||||
}
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe.skip('AddEditParams', function () {
|
||||
const samlAuth = getService('samlAuth');
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
let adminRoleAuthc: RoleCredentials;
|
||||
|
||||
const kServer = getService('kibanaServer');
|
||||
const testParam = {
|
||||
key: 'test',
|
||||
value: 'test',
|
||||
};
|
||||
const testPrivateLocations = new PrivateLocationTestService(getService);
|
||||
|
||||
before(async () => {
|
||||
await testPrivateLocations.installSyntheticsPackage();
|
||||
adminRoleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('admin');
|
||||
await kServer.savedObjects.clean({ types: [syntheticsParamType] });
|
||||
});
|
||||
|
||||
it('adds a test param', async () => {
|
||||
await supertest
|
||||
.post(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(testParam)
|
||||
.expect(200);
|
||||
|
||||
const getResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
assertHas(getResponse.body[0], testParam);
|
||||
});
|
||||
|
||||
it('handles tags and description', async () => {
|
||||
const tagsAndDescription = {
|
||||
tags: ['a tag'],
|
||||
description: 'test description',
|
||||
};
|
||||
const testParam2 = {
|
||||
...testParam,
|
||||
...tagsAndDescription,
|
||||
};
|
||||
await supertest
|
||||
.post(SYNTHETICS_API_URLS.PARAMS)
|
||||
.send(testParam2)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const getResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
assertHas(getResponse.body[0], testParam2);
|
||||
});
|
||||
|
||||
it('handles editing a param', async () => {
|
||||
const expectedUpdatedParam = {
|
||||
key: 'testUpdated',
|
||||
value: 'testUpdated',
|
||||
tags: ['a tag'],
|
||||
description: 'test description',
|
||||
};
|
||||
|
||||
await supertest
|
||||
.post(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(testParam)
|
||||
.expect(200);
|
||||
|
||||
const getResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const param = getResponse.body[0];
|
||||
assertHas(param, testParam);
|
||||
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.PARAMS + '/' + param.id)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({})
|
||||
.expect(400);
|
||||
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.PARAMS + '/' + param.id)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const updatedGetResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const actualUpdatedParam = updatedGetResponse.body[0];
|
||||
assertHas(actualUpdatedParam, expectedUpdatedParam);
|
||||
});
|
||||
|
||||
it('handles partial editing a param', async () => {
|
||||
const newParam = {
|
||||
key: 'testUpdated',
|
||||
value: 'testUpdated',
|
||||
tags: ['a tag'],
|
||||
description: 'test description',
|
||||
};
|
||||
|
||||
const response = await supertest
|
||||
.post(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(newParam)
|
||||
.expect(200);
|
||||
const paramId = response.body.id;
|
||||
|
||||
const getResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.PARAMS + '/' + paramId)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
assertHas(getResponse.body, newParam);
|
||||
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.PARAMS + '/' + paramId)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
key: 'testUpdated',
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.PARAMS + '/' + paramId)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
key: 'testUpdatedAgain',
|
||||
value: 'testUpdatedAgain',
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const updatedGetResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.PARAMS + '/' + paramId)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
assertHas(updatedGetResponse.body, {
|
||||
...newParam,
|
||||
key: 'testUpdatedAgain',
|
||||
value: 'testUpdatedAgain',
|
||||
});
|
||||
});
|
||||
|
||||
it('handles spaces', async () => {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
|
||||
await kServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
|
||||
await supertest
|
||||
.post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(testParam)
|
||||
.expect(200);
|
||||
|
||||
const getResponse = await supertest
|
||||
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(getResponse.body[0].namespaces).eql([SPACE_ID]);
|
||||
assertHas(getResponse.body[0], testParam);
|
||||
});
|
||||
|
||||
it('handles editing a param in spaces', async () => {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
|
||||
await kServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
|
||||
const expectedUpdatedParam = {
|
||||
key: 'testUpdated',
|
||||
value: 'testUpdated',
|
||||
tags: ['a tag'],
|
||||
description: 'test description',
|
||||
};
|
||||
|
||||
await supertest
|
||||
.post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(testParam)
|
||||
.expect(200);
|
||||
|
||||
const getResponse = await supertest
|
||||
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const param = getResponse.body[0];
|
||||
assertHas(param, testParam);
|
||||
|
||||
await supertest
|
||||
.put(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}/${param.id}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(expectedUpdatedParam)
|
||||
.expect(200);
|
||||
|
||||
const updatedGetResponse = await supertest
|
||||
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const actualUpdatedParam = updatedGetResponse.body[0];
|
||||
assertHas(actualUpdatedParam, expectedUpdatedParam);
|
||||
});
|
||||
|
||||
it('does not allow editing a param in created in one space in a different space', async () => {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
const SPACE_ID_TWO = `test-space-${uuidv4()}-two`;
|
||||
const SPACE_NAME_TWO = `test-space-name ${uuidv4()} 2`;
|
||||
|
||||
await kServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
await kServer.spaces.create({ id: SPACE_ID_TWO, name: SPACE_NAME_TWO });
|
||||
|
||||
const updatedParam = {
|
||||
key: 'testUpdated',
|
||||
value: 'testUpdated',
|
||||
tags: ['a tag'],
|
||||
description: 'test description',
|
||||
};
|
||||
|
||||
await supertest
|
||||
.post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(testParam)
|
||||
.expect(200);
|
||||
|
||||
const getResponse = await supertest
|
||||
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const param = getResponse.body[0];
|
||||
assertHas(param, testParam);
|
||||
|
||||
// space does exist so get request should be 200
|
||||
await supertest
|
||||
.get(`/s/${SPACE_ID_TWO}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(`/s/${SPACE_ID_TWO}${SYNTHETICS_API_URLS.PARAMS}/${param.id}}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(updatedParam)
|
||||
.expect(404);
|
||||
|
||||
const updatedGetResponse = await supertest
|
||||
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const actualUpdatedParam = updatedGetResponse.body[0];
|
||||
assertHas(actualUpdatedParam, testParam);
|
||||
});
|
||||
|
||||
it('handles invalid spaces', async () => {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
|
||||
await kServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
|
||||
await supertest
|
||||
.post(`/s/doesnotexist${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(testParam)
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('handles editing with invalid spaces', async () => {
|
||||
const updatedParam = {
|
||||
key: 'testUpdated',
|
||||
value: 'testUpdated',
|
||||
tags: ['a tag'],
|
||||
description: 'test description',
|
||||
};
|
||||
|
||||
await supertest
|
||||
.post(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(testParam)
|
||||
.expect(200);
|
||||
const getResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const param = getResponse.body[0];
|
||||
assertHas(param, testParam);
|
||||
|
||||
await supertest
|
||||
.put(`/s/doesnotexist${SYNTHETICS_API_URLS.PARAMS}/${param.id}}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(updatedParam)
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('handles share across spaces', async () => {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
|
||||
await kServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
|
||||
await supertest
|
||||
.post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ ...testParam, share_across_spaces: true })
|
||||
.expect(200);
|
||||
|
||||
const getResponse = await supertest
|
||||
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(getResponse.body[0].namespaces).eql(['*']);
|
||||
assertHas(getResponse.body[0], testParam);
|
||||
});
|
||||
|
||||
it('should not return values for non admin user', async () => {
|
||||
const resp = await supertest
|
||||
.get(`${SYNTHETICS_API_URLS.PARAMS}`)
|
||||
.set(adminRoleAuthc.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const params = resp.body;
|
||||
expect(params.length).to.eql(6);
|
||||
params.forEach((param: any) => {
|
||||
expect(param.value).to.eql(undefined);
|
||||
expect(param.key).to.not.empty();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* 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 { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import {
|
||||
EncryptedSyntheticsSavedMonitor,
|
||||
HTTPFields,
|
||||
MonitorFields,
|
||||
PrivateLocation,
|
||||
} from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import expect from '@kbn/expect';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
import { SyntheticsMonitorTestService } from '../../../services/synthetics_monitor';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('DeleteMonitorRoute', function () {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
const testPrivateLocations = new PrivateLocationTestService(getService);
|
||||
const monitorTestService = new SyntheticsMonitorTestService(getService);
|
||||
|
||||
let _httpMonitorJson: HTTPFields;
|
||||
let httpMonitorJson: HTTPFields;
|
||||
let editorUser: RoleCredentials;
|
||||
let testPolicyId = '';
|
||||
let privateLocations: PrivateLocation[];
|
||||
|
||||
const saveMonitor = async (
|
||||
monitor: MonitorFields
|
||||
): Promise<EncryptedSyntheticsSavedMonitor> => {
|
||||
const res = await supertest
|
||||
.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor);
|
||||
|
||||
expect(res.status).to.eql(200, JSON.stringify(res.body));
|
||||
|
||||
return res.body;
|
||||
};
|
||||
|
||||
const deleteMonitor = async (monitorId?: string | string[], statusCode = 200) => {
|
||||
return monitorTestService.deleteMonitor(editorUser, monitorId, statusCode, 'default');
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
await testPrivateLocations.installSyntheticsPackage();
|
||||
const testPolicyName = 'Fleet test server policy' + Date.now();
|
||||
const apiResponse = await testPrivateLocations.addFleetPolicy(testPolicyName);
|
||||
testPolicyId = apiResponse.body.item.id;
|
||||
privateLocations = await testPrivateLocations.setTestLocations([testPolicyId]);
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
|
||||
_httpMonitorJson = getFixtureJson('http_monitor');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
httpMonitorJson = {
|
||||
..._httpMonitorJson,
|
||||
locations: [privateLocations[0]],
|
||||
};
|
||||
});
|
||||
|
||||
it('deletes monitor by id', async () => {
|
||||
const { id: monitorId } = await saveMonitor(httpMonitorJson as MonitorFields);
|
||||
|
||||
const deleteResponse = await deleteMonitor(monitorId);
|
||||
|
||||
expect(deleteResponse.body).eql([{ id: monitorId, deleted: true }]);
|
||||
|
||||
// Hit get endpoint and expect 404 as well
|
||||
await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitorId)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('deletes monitor by param id', async () => {
|
||||
const { id: monitorId } = await saveMonitor(httpMonitorJson as MonitorFields);
|
||||
|
||||
const deleteResponse = await monitorTestService.deleteMonitorByIdParam(
|
||||
editorUser,
|
||||
monitorId,
|
||||
200,
|
||||
'default'
|
||||
);
|
||||
|
||||
expect(deleteResponse.body).eql([{ id: monitorId, deleted: true }]);
|
||||
|
||||
// Hit get endpoint and expect 404 as well
|
||||
await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitorId)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('throws error if both body and param are missing', async () => {
|
||||
await supertest
|
||||
.delete(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.send()
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it('deletes multiple monitors by id', async () => {
|
||||
const { id: monitorId } = await saveMonitor(httpMonitorJson as MonitorFields);
|
||||
const { id: monitorId2 } = await saveMonitor({
|
||||
...httpMonitorJson,
|
||||
name: 'another -2',
|
||||
} as MonitorFields);
|
||||
|
||||
const deleteResponse = await deleteMonitor([monitorId2, monitorId]);
|
||||
|
||||
expect(
|
||||
deleteResponse.body.sort((a: { id: string }, b: { id: string }) => (a.id > b.id ? 1 : -1))
|
||||
).eql(
|
||||
[
|
||||
{ id: monitorId2, deleted: true },
|
||||
{ id: monitorId, deleted: true },
|
||||
].sort((a, b) => (a.id > b.id ? 1 : -1))
|
||||
);
|
||||
|
||||
// Hit get endpoint and expect 404 as well
|
||||
await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitorId)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('returns 404 if monitor id is not found', async () => {
|
||||
const invalidMonitorId = 'invalid-id';
|
||||
const expected404Message = `Monitor id ${invalidMonitorId} not found!`;
|
||||
|
||||
const deleteResponse = await deleteMonitor(invalidMonitorId);
|
||||
|
||||
expect(deleteResponse.status).eql(200);
|
||||
expect(deleteResponse.body).eql([
|
||||
{
|
||||
id: invalidMonitorId,
|
||||
deleted: false,
|
||||
error: expected404Message,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('validates empty monitor id', async () => {
|
||||
await deleteMonitor(undefined, 400);
|
||||
await deleteMonitor([], 400);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,521 @@
|
|||
/*
|
||||
* 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 { v4 as uuidv4 } from 'uuid';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import {
|
||||
ConfigKey,
|
||||
ProjectMonitorsRequest,
|
||||
PrivateLocation,
|
||||
} from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { REQUEST_TOO_LARGE } from '@kbn/synthetics-plugin/server/routes/monitor_cruds/delete_monitor_project';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import { PackagePolicy } from '@kbn/fleet-plugin/common';
|
||||
import expect from '@kbn/expect';
|
||||
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('DeleteProjectMonitors', function () {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const supertestWithAuth = getService('supertest');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
let projectMonitors: ProjectMonitorsRequest;
|
||||
let editorUser: RoleCredentials;
|
||||
let privateLocation: PrivateLocation;
|
||||
|
||||
const testPrivateLocationsService = new PrivateLocationTestService(getService);
|
||||
|
||||
const setUniqueIdsAndLocations = (
|
||||
request: ProjectMonitorsRequest,
|
||||
privateLocations: PrivateLocation[] = []
|
||||
) => {
|
||||
return {
|
||||
...request,
|
||||
monitors: request.monitors.map((monitor) => ({
|
||||
...monitor,
|
||||
id: uuidv4(),
|
||||
locations: [],
|
||||
privateLocations: privateLocations.map((location) => location.label),
|
||||
})),
|
||||
};
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
await testPrivateLocationsService.installSyntheticsPackage();
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await kibanaServer.savedObjects.clean({ types: ['synthetics-private-location'] });
|
||||
privateLocation = await testPrivateLocationsService.addTestPrivateLocation();
|
||||
projectMonitors = setUniqueIdsAndLocations(getFixtureJson('project_browser_monitor'), [
|
||||
privateLocation,
|
||||
]);
|
||||
});
|
||||
|
||||
it('only allows 250 requests at a time', async () => {
|
||||
const project = 'test-brower-suite';
|
||||
const monitors = [];
|
||||
for (let i = 0; i < 251; i++) {
|
||||
monitors.push({
|
||||
...projectMonitors.monitors[0],
|
||||
id: `test-id-${i}`,
|
||||
name: `test-name-${i}`,
|
||||
});
|
||||
}
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitors.slice(0, 250) })
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitors.slice(250, 251) })
|
||||
.expect(200);
|
||||
|
||||
const savedObjectsResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const { total } = savedObjectsResponse.body;
|
||||
expect(total).to.eql(251);
|
||||
|
||||
const response = await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(400);
|
||||
const { message } = response.body;
|
||||
expect(message).to.eql(REQUEST_TOO_LARGE);
|
||||
} finally {
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(0, 250) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(250, 251) })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
it('project monitors - handles browser monitors', async () => {
|
||||
const monitorToDelete = 'second-monitor-id';
|
||||
const monitors = [
|
||||
projectMonitors.monitors[0],
|
||||
{
|
||||
...projectMonitors.monitors[0],
|
||||
id: monitorToDelete,
|
||||
},
|
||||
];
|
||||
const project = 'test-brower-suite';
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors })
|
||||
.expect(200);
|
||||
|
||||
const savedObjectsResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const { total } = savedObjectsResponse.body;
|
||||
expect(total).to.eql(2);
|
||||
const monitorsToDelete = [monitorToDelete];
|
||||
|
||||
const response = await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.deleted_monitors).to.eql(monitorsToDelete);
|
||||
|
||||
const responseAfterDeletion = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const { total: totalAfterDeletion } = responseAfterDeletion.body;
|
||||
expect(totalAfterDeletion).to.eql(1);
|
||||
} finally {
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
it('does not delete monitors from a different project', async () => {
|
||||
const monitors = [...projectMonitors.monitors];
|
||||
const project = 'test-brower-suite';
|
||||
const secondProject = 'second-project';
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors })
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace(
|
||||
'{projectName}',
|
||||
secondProject
|
||||
)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors })
|
||||
.expect(200);
|
||||
|
||||
const savedObjectsResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const secondProjectSavedObjectResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${secondProject}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const { total } = savedObjectsResponse.body;
|
||||
const { total: secondProjectTotal } = secondProjectSavedObjectResponse.body;
|
||||
expect(total).to.eql(monitors.length);
|
||||
expect(secondProjectTotal).to.eql(monitors.length);
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
const response = await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.deleted_monitors).to.eql(monitorsToDelete);
|
||||
|
||||
const responseAfterDeletion = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const secondResponseAfterDeletion = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${secondProject}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const { total: totalAfterDeletion } = responseAfterDeletion.body;
|
||||
const { total: secondProjectTotalAfterDeletion } = secondResponseAfterDeletion.body;
|
||||
expect(totalAfterDeletion).to.eql(0);
|
||||
expect(secondProjectTotalAfterDeletion).to.eql(monitors.length);
|
||||
} finally {
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace(
|
||||
'{projectName}',
|
||||
secondProject
|
||||
)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
it('does not delete monitors from the same project in a different space project', async () => {
|
||||
const monitors = [...projectMonitors.monitors];
|
||||
const project = 'test-brower-suite';
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
const spaceScopedPrivateLocation = await testPrivateLocationsService.addTestPrivateLocation(
|
||||
SPACE_ID
|
||||
);
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.map((monitor) => ({
|
||||
...monitor,
|
||||
privateLocations: [privateLocation.label],
|
||||
})),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(
|
||||
`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace(
|
||||
'{projectName}',
|
||||
project
|
||||
)}`
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.map((monitor) => ({
|
||||
...monitor,
|
||||
privateLocations: [spaceScopedPrivateLocation.label],
|
||||
})),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const savedObjectsResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const secondSpaceProjectSavedObjectResponse = await supertest
|
||||
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const { total } = savedObjectsResponse.body;
|
||||
const { total: secondSpaceTotal } = secondSpaceProjectSavedObjectResponse.body;
|
||||
|
||||
expect(total).to.eql(monitors.length);
|
||||
expect(secondSpaceTotal).to.eql(monitors.length);
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
const response = await supertest
|
||||
.delete(
|
||||
`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace(
|
||||
'{projectName}',
|
||||
project
|
||||
)}`
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.deleted_monitors).to.eql(monitorsToDelete);
|
||||
|
||||
const responseAfterDeletion = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const secondSpaceResponseAfterDeletion = await supertest
|
||||
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const { total: totalAfterDeletion } = responseAfterDeletion.body;
|
||||
const { total: secondProjectTotalAfterDeletion } = secondSpaceResponseAfterDeletion.body;
|
||||
expect(totalAfterDeletion).to.eql(monitors.length);
|
||||
expect(secondProjectTotalAfterDeletion).to.eql(0);
|
||||
} finally {
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
await supertest
|
||||
.delete(
|
||||
`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace(
|
||||
'{projectName}',
|
||||
project
|
||||
)}`
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
it('deletes integration policies when project monitors are deleted', async () => {
|
||||
const monitors = [
|
||||
{ ...projectMonitors.monitors[0], privateLocations: [privateLocation.label] },
|
||||
];
|
||||
const project = 'test-brower-suite';
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors })
|
||||
.expect(200);
|
||||
|
||||
const savedObjectsResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const { total } = savedObjectsResponse.body;
|
||||
expect(total).to.eql(monitors.length);
|
||||
const apiResponsePolicy = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy = apiResponsePolicy.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id ===
|
||||
savedObjectsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID] +
|
||||
'-' +
|
||||
privateLocation.id
|
||||
);
|
||||
expect(packagePolicy.policy_id).to.be(privateLocation.id);
|
||||
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
const response = await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.deleted_monitors).to.eql(monitorsToDelete);
|
||||
|
||||
const responseAfterDeletion = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.project_id: "${project}"`,
|
||||
})
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const { total: totalAfterDeletion } = responseAfterDeletion.body;
|
||||
expect(totalAfterDeletion).to.eql(0);
|
||||
const apiResponsePolicy2 = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy2 = apiResponsePolicy2.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id ===
|
||||
savedObjectsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID] +
|
||||
'-' +
|
||||
privateLocation.id
|
||||
);
|
||||
expect(packagePolicy2).to.be(undefined);
|
||||
} finally {
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
* 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 moment from 'moment';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { omit } from 'lodash';
|
||||
import {
|
||||
ConfigKey,
|
||||
EncryptedSyntheticsSavedMonitor,
|
||||
HTTPFields,
|
||||
MonitorFields,
|
||||
PrivateLocation,
|
||||
} from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import expect from '@kbn/expect';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { omitResponseTimestamps, omitEmptyValues } from './helpers/monitor';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
import { SyntheticsMonitorTestService } from '../../../services/synthetics_monitor';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('EditMonitorAPI', function () {
|
||||
const supertestWithAuth = getService('supertest');
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
const testPrivateLocations = new PrivateLocationTestService(getService);
|
||||
const monitorTestService = new SyntheticsMonitorTestService(getService);
|
||||
|
||||
let _httpMonitorJson: HTTPFields;
|
||||
let httpMonitorJson: HTTPFields;
|
||||
let testPolicyId = '';
|
||||
let editorUser: RoleCredentials;
|
||||
let privateLocations: PrivateLocation[];
|
||||
|
||||
const saveMonitor = async (monitor: MonitorFields, spaceId?: string) => {
|
||||
const apiURL = spaceId
|
||||
? `/s/${spaceId}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`
|
||||
: SYNTHETICS_API_URLS.SYNTHETICS_MONITORS;
|
||||
const res = await supertest
|
||||
.post(apiURL + '?internal=true')
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor)
|
||||
.expect(200);
|
||||
|
||||
const { url, created_at: createdAt, updated_at: updatedAt, ...rest } = res.body;
|
||||
|
||||
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
|
||||
|
||||
return rest as EncryptedSyntheticsSavedMonitor;
|
||||
};
|
||||
|
||||
const editMonitor = async (modifiedMonitor: MonitorFields, monitorId: string) => {
|
||||
const res = await supertest
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitorId + '?internal=true')
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(modifiedMonitor);
|
||||
|
||||
expect(res.status).eql(200, JSON.stringify(res.body));
|
||||
|
||||
const { created_at: createdAt, updated_at: updatedAt } = res.body;
|
||||
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
|
||||
|
||||
return omit(res.body, ['created_at', 'updated_at']);
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
await supertestWithAuth.post('/api/fleet/setup').set('kbn-xsrf', 'true').send().expect(200);
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const testPolicyName = 'Fleet test server policy' + Date.now();
|
||||
const apiResponse = await testPrivateLocations.addFleetPolicy(testPolicyName);
|
||||
testPolicyId = apiResponse.body.item.id;
|
||||
privateLocations = await testPrivateLocations.setTestLocations([testPolicyId]);
|
||||
_httpMonitorJson = getFixtureJson('http_monitor');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
httpMonitorJson = { ..._httpMonitorJson, locations: [privateLocations[0]] };
|
||||
});
|
||||
|
||||
it('edits the monitor', async () => {
|
||||
const newMonitor = httpMonitorJson;
|
||||
|
||||
const savedMonitor = await saveMonitor(newMonitor as MonitorFields);
|
||||
const monitorId = savedMonitor[ConfigKey.CONFIG_ID];
|
||||
|
||||
expect(omitResponseTimestamps(savedMonitor)).eql(
|
||||
omitEmptyValues({
|
||||
...newMonitor,
|
||||
[ConfigKey.MONITOR_QUERY_ID]: monitorId,
|
||||
[ConfigKey.CONFIG_ID]: monitorId,
|
||||
})
|
||||
);
|
||||
|
||||
const updates: Partial<HTTPFields> = {
|
||||
[ConfigKey.URLS]: 'https://modified-host.com',
|
||||
[ConfigKey.NAME]: 'Modified name',
|
||||
[ConfigKey.LOCATIONS]: [privateLocations[0]],
|
||||
[ConfigKey.REQUEST_HEADERS_CHECK]: {
|
||||
sampleHeader2: 'sampleValue2',
|
||||
},
|
||||
[ConfigKey.METADATA]: {
|
||||
script_source: {
|
||||
is_generated_script: false,
|
||||
file_name: 'test-file.name',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const modifiedMonitor = {
|
||||
...savedMonitor,
|
||||
...updates,
|
||||
[ConfigKey.METADATA]: {
|
||||
...newMonitor[ConfigKey.METADATA],
|
||||
...updates[ConfigKey.METADATA],
|
||||
},
|
||||
} as any;
|
||||
|
||||
const editResponse = await editMonitor(modifiedMonitor, monitorId);
|
||||
|
||||
expect(editResponse).eql(
|
||||
omitEmptyValues({
|
||||
...modifiedMonitor,
|
||||
revision: 2,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('strips unknown keys from monitor edits', async () => {
|
||||
const newMonitor = { ...httpMonitorJson, name: 'yet another' };
|
||||
|
||||
const savedMonitor = await saveMonitor(newMonitor as MonitorFields);
|
||||
const monitorId = savedMonitor[ConfigKey.CONFIG_ID];
|
||||
|
||||
const { created_at: createdAt, updated_at: updatedAt } = savedMonitor;
|
||||
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
|
||||
|
||||
expect(omitResponseTimestamps(savedMonitor)).eql(
|
||||
omitEmptyValues({
|
||||
...newMonitor,
|
||||
[ConfigKey.MONITOR_QUERY_ID]: monitorId,
|
||||
[ConfigKey.CONFIG_ID]: monitorId,
|
||||
})
|
||||
);
|
||||
|
||||
const updates: Partial<HTTPFields> = {
|
||||
[ConfigKey.URLS]: 'https://modified-host.com',
|
||||
[ConfigKey.NAME]: 'Modified name like that',
|
||||
[ConfigKey.LOCATIONS]: [privateLocations[0]],
|
||||
[ConfigKey.REQUEST_HEADERS_CHECK]: {
|
||||
sampleHeader2: 'sampleValue2',
|
||||
},
|
||||
[ConfigKey.METADATA]: {
|
||||
script_source: {
|
||||
is_generated_script: false,
|
||||
file_name: 'test-file.name',
|
||||
},
|
||||
},
|
||||
unknownkey: 'unknownvalue',
|
||||
} as Partial<HTTPFields>;
|
||||
|
||||
const modifiedMonitor = omit(
|
||||
{
|
||||
...updates,
|
||||
[ConfigKey.METADATA]: {
|
||||
...newMonitor[ConfigKey.METADATA],
|
||||
...updates[ConfigKey.METADATA],
|
||||
},
|
||||
},
|
||||
['unknownkey']
|
||||
);
|
||||
|
||||
const editResponse = await editMonitor(modifiedMonitor as MonitorFields, monitorId);
|
||||
|
||||
expect(editResponse).eql(
|
||||
omitEmptyValues({
|
||||
...savedMonitor,
|
||||
...modifiedMonitor,
|
||||
revision: 2,
|
||||
})
|
||||
);
|
||||
expect(editResponse).not.to.have.keys('unknownkey');
|
||||
});
|
||||
|
||||
it('returns 404 if monitor id is not present', async () => {
|
||||
const invalidMonitorId = 'invalid-id';
|
||||
const expected404Message = `Monitor id ${invalidMonitorId} not found!`;
|
||||
|
||||
const editResponse = await supertest
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + invalidMonitorId)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(httpMonitorJson)
|
||||
.expect(404);
|
||||
|
||||
expect(editResponse.body.message).eql(expected404Message);
|
||||
});
|
||||
|
||||
it('returns bad request if payload is invalid for HTTP monitor', async () => {
|
||||
const { id: monitorId, ...savedMonitor } = await saveMonitor(
|
||||
httpMonitorJson as MonitorFields
|
||||
);
|
||||
|
||||
// Delete a required property to make payload invalid
|
||||
const toUpdate = { ...savedMonitor, 'check.request.headers': null };
|
||||
|
||||
const apiResponse = await supertest
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitorId)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(toUpdate);
|
||||
|
||||
expect(apiResponse.status).eql(400);
|
||||
});
|
||||
|
||||
it('returns bad request if monitor type is invalid', async () => {
|
||||
const { id: monitorId, ...savedMonitor } = await saveMonitor({
|
||||
...httpMonitorJson,
|
||||
name: 'test monitor - 11',
|
||||
} as MonitorFields);
|
||||
|
||||
const toUpdate = { ...savedMonitor, type: 'invalid-data-steam' };
|
||||
|
||||
const apiResponse = await supertest
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitorId)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(toUpdate);
|
||||
|
||||
expect(apiResponse.status).eql(400);
|
||||
expect(apiResponse.body.message).eql(
|
||||
'Monitor type cannot be changed from http to invalid-data-steam.'
|
||||
);
|
||||
});
|
||||
|
||||
it('sets config hash to empty string on edits', async () => {
|
||||
const newMonitor = httpMonitorJson;
|
||||
const configHash = 'djrhefje';
|
||||
|
||||
const savedMonitor = await saveMonitor({
|
||||
...(newMonitor as MonitorFields),
|
||||
[ConfigKey.CONFIG_HASH]: configHash,
|
||||
name: 'test monitor - 12',
|
||||
});
|
||||
const monitorId = savedMonitor[ConfigKey.CONFIG_ID];
|
||||
const { created_at: createdAt, updated_at: updatedAt } = savedMonitor;
|
||||
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
|
||||
|
||||
expect(savedMonitor).eql(
|
||||
omitEmptyValues({
|
||||
...newMonitor,
|
||||
[ConfigKey.CONFIG_ID]: monitorId,
|
||||
[ConfigKey.MONITOR_QUERY_ID]: monitorId,
|
||||
name: 'test monitor - 12',
|
||||
hash: configHash,
|
||||
})
|
||||
);
|
||||
|
||||
const updates: Partial<HTTPFields> = {
|
||||
[ConfigKey.URLS]: 'https://modified-host.com',
|
||||
name: 'test monitor - 12',
|
||||
} as Partial<HTTPFields>;
|
||||
|
||||
const modifiedMonitor = {
|
||||
...newMonitor,
|
||||
...updates,
|
||||
[ConfigKey.METADATA]: {
|
||||
...newMonitor[ConfigKey.METADATA],
|
||||
...updates[ConfigKey.METADATA],
|
||||
},
|
||||
};
|
||||
|
||||
const editResponse = await editMonitor(modifiedMonitor as MonitorFields, monitorId);
|
||||
|
||||
expect(editResponse).eql(
|
||||
omitEmptyValues({
|
||||
...modifiedMonitor,
|
||||
[ConfigKey.CONFIG_ID]: monitorId,
|
||||
[ConfigKey.MONITOR_QUERY_ID]: monitorId,
|
||||
[ConfigKey.CONFIG_HASH]: '',
|
||||
revision: 2,
|
||||
})
|
||||
);
|
||||
expect(editResponse).not.to.have.keys('unknownkey');
|
||||
});
|
||||
|
||||
it('handles spaces', async () => {
|
||||
const name = 'Monitor with private location';
|
||||
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
|
||||
await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
|
||||
const spaceScopedPrivateLocation = await testPrivateLocations.addTestPrivateLocation(
|
||||
SPACE_ID
|
||||
);
|
||||
const newMonitor = {
|
||||
name,
|
||||
type: 'http',
|
||||
urls: 'https://elastic.co',
|
||||
locations: [spaceScopedPrivateLocation],
|
||||
};
|
||||
|
||||
const savedMonitor = await saveMonitor(newMonitor as MonitorFields, SPACE_ID);
|
||||
|
||||
const monitorId = savedMonitor[ConfigKey.CONFIG_ID];
|
||||
const toUpdate = {
|
||||
...savedMonitor,
|
||||
urls: 'https://google.com',
|
||||
};
|
||||
await supertest
|
||||
.put(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}/${monitorId}`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(toUpdate)
|
||||
.expect(200);
|
||||
|
||||
const updatedResponse = await monitorTestService.getMonitor(monitorId, {
|
||||
space: SPACE_ID,
|
||||
internal: true,
|
||||
user: editorUser,
|
||||
});
|
||||
|
||||
// ensure monitor was updated
|
||||
expect(updatedResponse.body.urls).eql(toUpdate.urls);
|
||||
|
||||
// update a second time, ensures AAD was not corrupted
|
||||
const toUpdate2 = {
|
||||
...savedMonitor,
|
||||
urls: 'https://google.com',
|
||||
};
|
||||
|
||||
await supertest
|
||||
.put(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}/${monitorId}`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(toUpdate2)
|
||||
.expect(200);
|
||||
|
||||
const updatedResponse2 = await monitorTestService.getMonitor(monitorId, {
|
||||
space: SPACE_ID,
|
||||
internal: true,
|
||||
user: editorUser,
|
||||
});
|
||||
|
||||
// ensure monitor was updated
|
||||
expect(updatedResponse2.body.urls).eql(toUpdate2.urls);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* 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 rawExpect from 'expect';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { omit } from 'lodash';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import { DEFAULT_FIELDS } from '@kbn/synthetics-plugin/common/constants/monitor_defaults';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import moment from 'moment';
|
||||
import { PrivateLocation } from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { LOCATION_REQUIRED_ERROR } from '@kbn/synthetics-plugin/server/routes/monitor_cruds/monitor_validation';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { addMonitorAPIHelper, omitMonitorKeys } from './create_monitor';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('EditMonitorsPublicAPI', function () {
|
||||
const supertestAPI = getService('supertestWithoutAuth');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const samlAuth = getService('samlAuth');
|
||||
const testPrivateLocations = new PrivateLocationTestService(getService);
|
||||
let editorUser: RoleCredentials;
|
||||
let privateLocation1: PrivateLocation;
|
||||
let privateLocation2: PrivateLocation;
|
||||
|
||||
async function addMonitorAPI(monitor: any, statusCode: number = 200) {
|
||||
return await addMonitorAPIHelper(supertestAPI, monitor, statusCode, editorUser, samlAuth);
|
||||
}
|
||||
|
||||
async function editMonitorAPI(id: string, monitor: any, statusCode: number = 200) {
|
||||
return await editMonitorAPIHelper(id, monitor, statusCode);
|
||||
}
|
||||
|
||||
async function editMonitorAPIHelper(monitorId: string, monitor: any, statusCode = 200) {
|
||||
const result = await supertestAPI
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + `/${monitorId}`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor);
|
||||
|
||||
expect(result.status).eql(statusCode, JSON.stringify(result.body));
|
||||
|
||||
if (statusCode === 200) {
|
||||
const {
|
||||
created_at: createdAt,
|
||||
updated_at: updatedAt,
|
||||
id,
|
||||
config_id: configId,
|
||||
} = result.body;
|
||||
expect(id).not.empty();
|
||||
expect(configId).not.empty();
|
||||
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
|
||||
return {
|
||||
rawBody: result.body,
|
||||
body: {
|
||||
...omit(result.body, [
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'id',
|
||||
'config_id',
|
||||
'form_monitor_type',
|
||||
]),
|
||||
},
|
||||
};
|
||||
}
|
||||
return result.body;
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
await testPrivateLocations.installSyntheticsPackage();
|
||||
privateLocation1 = await testPrivateLocations.addTestPrivateLocation();
|
||||
privateLocation2 = await testPrivateLocations.addTestPrivateLocation();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
});
|
||||
let monitorId = 'test-id';
|
||||
|
||||
const defaultFields = DEFAULT_FIELDS.http;
|
||||
|
||||
it('adds test monitor', async () => {
|
||||
const monitor = {
|
||||
type: 'http',
|
||||
private_locations: [privateLocation1.id],
|
||||
url: 'https://www.google.com',
|
||||
};
|
||||
const { body: result, rawBody } = await addMonitorAPI(monitor);
|
||||
monitorId = rawBody.id;
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...monitor,
|
||||
locations: [privateLocation1],
|
||||
name: 'https://www.google.com',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should return error for empty monitor', async function () {
|
||||
const errMessage = 'Monitor must be a non-empty object';
|
||||
const testCases = [{}, null, undefined, false, [], ''];
|
||||
for (const testCase of testCases) {
|
||||
const { message } = await editMonitorAPI(monitorId, testCase, 400);
|
||||
expect(message).eql(errMessage);
|
||||
}
|
||||
});
|
||||
|
||||
it('return error if type is being changed', async () => {
|
||||
const { message } = await editMonitorAPI(monitorId, { type: 'tcp' }, 400);
|
||||
expect(message).eql('Monitor type cannot be changed from http to tcp.');
|
||||
});
|
||||
|
||||
it('return error if monitor not found', async () => {
|
||||
const { message } = await editMonitorAPI('invalid-monitor-id', { type: 'tcp' }, 404);
|
||||
expect(message).eql('Monitor id invalid-monitor-id not found!');
|
||||
});
|
||||
|
||||
it('return error if invalid location specified', async () => {
|
||||
const { message } = await editMonitorAPI(
|
||||
monitorId,
|
||||
{ type: 'http', locations: ['mars'] },
|
||||
400
|
||||
);
|
||||
rawExpect(message).toContain(
|
||||
"Invalid locations specified. Elastic managed Location(s) 'mars' not found."
|
||||
);
|
||||
});
|
||||
|
||||
it('return error if invalid private location specified', async () => {
|
||||
const { message } = await editMonitorAPI(
|
||||
monitorId,
|
||||
{
|
||||
type: 'http',
|
||||
locations: ['mars'],
|
||||
privateLocations: ['moon'],
|
||||
},
|
||||
400
|
||||
);
|
||||
expect(message).eql('Invalid monitor key(s) for http type: privateLocations');
|
||||
|
||||
const result = await editMonitorAPI(
|
||||
monitorId,
|
||||
{
|
||||
type: 'http',
|
||||
locations: ['mars'],
|
||||
private_locations: ['moon'],
|
||||
},
|
||||
400
|
||||
);
|
||||
rawExpect(result.message).toContain("Private Location(s) 'moon' not found.");
|
||||
});
|
||||
|
||||
it('throws an error if empty locations', async () => {
|
||||
const monitor = {
|
||||
locations: [],
|
||||
private_locations: [],
|
||||
};
|
||||
const { message } = await editMonitorAPI(monitorId, monitor, 400);
|
||||
|
||||
expect(message).eql(LOCATION_REQUIRED_ERROR);
|
||||
});
|
||||
|
||||
it('cannot change origin type', async () => {
|
||||
const monitor = {
|
||||
origin: 'project',
|
||||
};
|
||||
const result = await editMonitorAPI(monitorId, monitor, 400);
|
||||
|
||||
expect(result).eql({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'Unsupported origin type project, only ui type is supported via API.',
|
||||
attributes: {
|
||||
details: 'Unsupported origin type project, only ui type is supported via API.',
|
||||
payload: { origin: 'project' },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const updates: any = {};
|
||||
|
||||
it('can change name of monitor', async () => {
|
||||
updates.name = `updated name ${uuidv4()}`;
|
||||
const monitor = {
|
||||
name: updates.name,
|
||||
};
|
||||
const { body: result } = await editMonitorAPI(monitorId, monitor);
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...monitor,
|
||||
...updates,
|
||||
locations: [privateLocation1],
|
||||
revision: 2,
|
||||
url: 'https://www.google.com',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('prevents duplicate name of monitor', async () => {
|
||||
const name = `test name ${uuidv4()}`;
|
||||
const monitor = {
|
||||
name,
|
||||
type: 'http',
|
||||
private_locations: [privateLocation1.id],
|
||||
url: 'https://www.google.com',
|
||||
};
|
||||
// create one monitor with one name
|
||||
await addMonitorAPI(monitor);
|
||||
// create another monitor with a different name
|
||||
const { body: result, rawBody } = await addMonitorAPI({
|
||||
...monitor,
|
||||
name: 'test name',
|
||||
});
|
||||
const newMonitorId = rawBody.id;
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...monitor,
|
||||
locations: [privateLocation1],
|
||||
name: 'test name',
|
||||
})
|
||||
);
|
||||
|
||||
const editResult = await editMonitorAPI(
|
||||
newMonitorId,
|
||||
{
|
||||
name,
|
||||
},
|
||||
400
|
||||
);
|
||||
|
||||
expect(editResult).eql({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: `Monitor name must be unique, "${name}" already exists.`,
|
||||
attributes: {
|
||||
details: `Monitor name must be unique, "${name}" already exists.`,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('can add a second private location to existing monitor', async () => {
|
||||
const monitor = {
|
||||
private_locations: [privateLocation1.id, privateLocation2.id],
|
||||
};
|
||||
|
||||
const { body: result } = await editMonitorAPI(monitorId, monitor);
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...updates,
|
||||
revision: 3,
|
||||
url: 'https://www.google.com',
|
||||
locations: [privateLocation1, privateLocation2],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('can remove private location from existing monitor', async () => {
|
||||
const monitor = {
|
||||
private_locations: [privateLocation2.id],
|
||||
};
|
||||
|
||||
const { body: result } = await editMonitorAPI(monitorId, monitor);
|
||||
|
||||
expect(result).eql(
|
||||
omitMonitorKeys({
|
||||
...defaultFields,
|
||||
...updates,
|
||||
revision: 4,
|
||||
url: 'https://www.google.com',
|
||||
locations: [privateLocation2],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('can not remove all locations', async () => {
|
||||
const monitor = {
|
||||
locations: [],
|
||||
private_locations: [],
|
||||
};
|
||||
|
||||
const { message } = await editMonitorAPI(monitorId, monitor, 400);
|
||||
|
||||
expect(message).eql(LOCATION_REQUIRED_ERROR);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
* 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 rawExpect from 'expect';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import { omit } from 'lodash';
|
||||
import { HTTPFields, PrivateLocation } from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import { DYNAMIC_SETTINGS_DEFAULTS } from '@kbn/synthetics-plugin/common/constants/settings_defaults';
|
||||
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { addMonitorAPIHelper, omitMonitorKeys } from './create_monitor';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('EnableDefaultAlerting', function () {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const retry = getService('retry');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
let _httpMonitorJson: HTTPFields;
|
||||
let httpMonitorJson: HTTPFields;
|
||||
let editorUser: RoleCredentials;
|
||||
let privateLocation: PrivateLocation;
|
||||
|
||||
const privateLocationTestService = new PrivateLocationTestService(getService);
|
||||
|
||||
const addMonitorAPI = async (monitor: any, statusCode = 200) => {
|
||||
return addMonitorAPIHelper(supertest, monitor, statusCode, editorUser, samlAuth);
|
||||
};
|
||||
|
||||
after(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
});
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
_httpMonitorJson = getFixtureJson('http_monitor');
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
privateLocation = await privateLocationTestService.addTestPrivateLocation();
|
||||
httpMonitorJson = {
|
||||
..._httpMonitorJson,
|
||||
locations: [privateLocation],
|
||||
};
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.DYNAMIC_SETTINGS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(DYNAMIC_SETTINGS_DEFAULTS)
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('returns the created alerted when called', async () => {
|
||||
const apiResponse = await supertest
|
||||
.post(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const omitFields = [
|
||||
'apiKeyOwner',
|
||||
'createdBy',
|
||||
'updatedBy',
|
||||
'id',
|
||||
'updatedAt',
|
||||
'createdAt',
|
||||
'scheduledTaskId',
|
||||
'executionStatus',
|
||||
'monitoring',
|
||||
'nextRun',
|
||||
'lastRun',
|
||||
'snoozeSchedule',
|
||||
'viewInAppRelativeUrl',
|
||||
];
|
||||
|
||||
const statusRule = apiResponse.body.statusRule;
|
||||
const tlsRule = apiResponse.body.tlsRule;
|
||||
|
||||
rawExpect(omit(statusRule, omitFields)).toEqual(
|
||||
omit(defaultAlertRules.statusRule, omitFields)
|
||||
);
|
||||
rawExpect(omit(tlsRule, omitFields)).toEqual(omit(defaultAlertRules.tlsRule, omitFields));
|
||||
});
|
||||
|
||||
it('enables alert when new monitor is added', async () => {
|
||||
const newMonitor = httpMonitorJson;
|
||||
|
||||
const { body: apiResponse } = await addMonitorAPI(newMonitor);
|
||||
|
||||
expect(apiResponse).eql(omitMonitorKeys({ ...newMonitor, spaceId: 'default' }));
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule.ruleTypeId).eql('xpack.synthetics.alerts.monitorStatus');
|
||||
expect(res.body.tlsRule.ruleTypeId).eql('xpack.synthetics.alerts.tls');
|
||||
});
|
||||
});
|
||||
|
||||
it('deletes (and recreates) the default rule when settings are updated', async () => {
|
||||
const newMonitor = httpMonitorJson;
|
||||
|
||||
const { body: apiResponse } = await addMonitorAPI(newMonitor);
|
||||
|
||||
expect(apiResponse).eql(omitMonitorKeys(newMonitor));
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule.ruleTypeId).eql('xpack.synthetics.alerts.monitorStatus');
|
||||
expect(res.body.tlsRule.ruleTypeId).eql('xpack.synthetics.alerts.tls');
|
||||
});
|
||||
const settings = await supertest
|
||||
.put(SYNTHETICS_API_URLS.DYNAMIC_SETTINGS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
defaultStatusRuleEnabled: false,
|
||||
defaultTLSRuleEnabled: false,
|
||||
});
|
||||
|
||||
expect(settings.body.defaultStatusRuleEnabled).eql(false);
|
||||
expect(settings.body.defaultTLSRuleEnabled).eql(false);
|
||||
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule).eql(null);
|
||||
expect(res.body.tlsRule).eql(null);
|
||||
});
|
||||
|
||||
const settings2 = await supertest
|
||||
.put(SYNTHETICS_API_URLS.DYNAMIC_SETTINGS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
defaultStatusRuleEnabled: true,
|
||||
defaultTLSRuleEnabled: true,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(settings2.body.defaultStatusRuleEnabled).eql(true);
|
||||
expect(settings2.body.defaultTLSRuleEnabled).eql(true);
|
||||
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule.ruleTypeId).eql('xpack.synthetics.alerts.monitorStatus');
|
||||
expect(res.body.tlsRule.ruleTypeId).eql('xpack.synthetics.alerts.tls');
|
||||
});
|
||||
});
|
||||
|
||||
it('doesnt throw errors when rule has already been deleted', async () => {
|
||||
const newMonitor = httpMonitorJson;
|
||||
|
||||
const { body: apiResponse } = await addMonitorAPI(newMonitor);
|
||||
|
||||
expect(apiResponse).eql(omitMonitorKeys(newMonitor));
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule.ruleTypeId).eql('xpack.synthetics.alerts.monitorStatus');
|
||||
expect(res.body.tlsRule.ruleTypeId).eql('xpack.synthetics.alerts.tls');
|
||||
});
|
||||
|
||||
const settings = await supertest
|
||||
.put(SYNTHETICS_API_URLS.DYNAMIC_SETTINGS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
defaultStatusRuleEnabled: false,
|
||||
defaultTLSRuleEnabled: false,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(settings.body.defaultStatusRuleEnabled).eql(false);
|
||||
expect(settings.body.defaultTLSRuleEnabled).eql(false);
|
||||
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule).eql(null);
|
||||
expect(res.body.tlsRule).eql(null);
|
||||
});
|
||||
|
||||
// call api again with the same settings, make sure its 200
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule).eql(null);
|
||||
expect(res.body.tlsRule).eql(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const defaultAlertRules = {
|
||||
statusRule: {
|
||||
id: '574e82f0-1672-11ee-8e7d-c985c0ef6c2e',
|
||||
notifyWhen: null,
|
||||
consumer: 'uptime',
|
||||
alertTypeId: 'xpack.synthetics.alerts.monitorStatus',
|
||||
tags: ['SYNTHETICS_DEFAULT_ALERT'],
|
||||
name: 'Synthetics status internal rule',
|
||||
enabled: true,
|
||||
throttle: null,
|
||||
apiKeyOwner: 'any',
|
||||
apiKeyCreatedByUser: true,
|
||||
createdBy: 'any',
|
||||
updatedBy: 'any',
|
||||
muteAll: false,
|
||||
mutedInstanceIds: [],
|
||||
revision: 0,
|
||||
running: false,
|
||||
schedule: { interval: '1m' },
|
||||
actions: [],
|
||||
params: {},
|
||||
snoozeSchedule: [],
|
||||
updatedAt: '2023-06-29T11:44:44.488Z',
|
||||
createdAt: '2023-06-29T11:44:44.488Z',
|
||||
scheduledTaskId: '574e82f0-1672-11ee-8e7d-c985c0ef6c2e',
|
||||
executionStatus: {
|
||||
status: 'ok',
|
||||
lastExecutionDate: '2023-06-29T11:47:55.331Z',
|
||||
lastDuration: 64,
|
||||
},
|
||||
ruleTypeId: 'xpack.synthetics.alerts.monitorStatus',
|
||||
viewInAppRelativeUrl: '/app/observability/alerts/rules/574e82f0-1672-11ee-8e7d-c985c0ef6c2e',
|
||||
},
|
||||
tlsRule: {
|
||||
id: '574eaa00-1672-11ee-8e7d-c985c0ef6c2e',
|
||||
notifyWhen: null,
|
||||
consumer: 'uptime',
|
||||
alertTypeId: 'xpack.synthetics.alerts.tls',
|
||||
tags: ['SYNTHETICS_DEFAULT_ALERT'],
|
||||
name: 'Synthetics internal TLS rule',
|
||||
enabled: true,
|
||||
throttle: null,
|
||||
apiKeyOwner: 'elastic_admin',
|
||||
apiKeyCreatedByUser: true,
|
||||
createdBy: 'elastic_admin',
|
||||
updatedBy: 'elastic_admin',
|
||||
muteAll: false,
|
||||
mutedInstanceIds: [],
|
||||
revision: 0,
|
||||
running: false,
|
||||
schedule: { interval: '1m' },
|
||||
actions: [],
|
||||
params: {},
|
||||
snoozeSchedule: [],
|
||||
updatedAt: '2023-06-29T11:44:44.489Z',
|
||||
createdAt: '2023-06-29T11:44:44.489Z',
|
||||
scheduledTaskId: '574eaa00-1672-11ee-8e7d-c985c0ef6c2e',
|
||||
executionStatus: {
|
||||
status: 'ok',
|
||||
lastExecutionDate: '2023-06-29T11:44:46.214Z',
|
||||
lastDuration: 193,
|
||||
},
|
||||
ruleTypeId: 'xpack.synthetics.alerts.tls',
|
||||
viewInAppRelativeUrl: '/app/observability/alerts/rules/574e82f0-1672-11ee-8e7d-c985c0ef6c2e',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
"type": "browser",
|
||||
"enabled": true,
|
||||
"alert": {
|
||||
"status": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"journey_id": "",
|
||||
"project_id": "",
|
||||
"schedule": {
|
||||
"number": "3",
|
||||
"unit": "m"
|
||||
},
|
||||
"service.name": "",
|
||||
"config_id": "",
|
||||
"tags": ["cookie-test", "browser"],
|
||||
"timeout": "16",
|
||||
"__ui": {
|
||||
"script_source": {
|
||||
"is_generated_script": false,
|
||||
"file_name": ""
|
||||
},
|
||||
"is_tls_enabled": false
|
||||
},
|
||||
"source.inline.script": "step(\"Visit /users api route\", async () => {\\n const response = await page.goto('https://nextjs-test-synthetics.vercel.app/api/users');\\n expect(response.status()).toEqual(200);\\n});",
|
||||
"source.project.content": "",
|
||||
"params": "",
|
||||
"screenshots": "on",
|
||||
"synthetics_args": [],
|
||||
"filter_journeys.match": "",
|
||||
"filter_journeys.tags": [],
|
||||
"ignore_https_errors": false,
|
||||
"throttling": {
|
||||
"value": {
|
||||
"download": "5",
|
||||
"latency": "20",
|
||||
"upload": "3"
|
||||
},
|
||||
"id": "default",
|
||||
"label": "Default"
|
||||
},
|
||||
"locations": ["dev"],
|
||||
"name": "Test HTTP Monitor 03",
|
||||
"namespace": "testnamespace",
|
||||
"origin": "ui",
|
||||
"form_monitor_type": "multistep",
|
||||
"url.port": null,
|
||||
"id": "",
|
||||
"hash": "",
|
||||
"playwright_options": "",
|
||||
"playwright_text_assertion": "",
|
||||
"ssl.certificate": "",
|
||||
"ssl.certificate_authorities": "",
|
||||
"ssl.supported_protocols": ["TLSv1.1", "TLSv1.2", "TLSv1.3"],
|
||||
"ssl.verification_mode": "full",
|
||||
"revision": 1,
|
||||
"max_attempts": 2,
|
||||
"labels": {}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"type": "http",
|
||||
"enabled": true,
|
||||
"alert": {
|
||||
"status": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"tag1",
|
||||
"tag2"
|
||||
],
|
||||
"schedule": {
|
||||
"number": "5",
|
||||
"unit": "m"
|
||||
},
|
||||
"service.name": "",
|
||||
"config_id": "",
|
||||
"timeout": "180",
|
||||
"__ui": {
|
||||
"is_tls_enabled": false
|
||||
},
|
||||
"max_attempts": 2,
|
||||
"max_redirects": "3",
|
||||
"password": "test",
|
||||
"urls": "https://nextjs-test-synthetics.vercel.app/api/users",
|
||||
"url.port": null,
|
||||
"proxy_url": "http://proxy.com",
|
||||
"proxy_headers": {},
|
||||
"check.response.body.negative": [],
|
||||
"check.response.body.positive": [],
|
||||
"check.response.json": [],
|
||||
"response.include_body": "never",
|
||||
"response.include_body_max_bytes": "1024",
|
||||
"check.request.headers": {
|
||||
"sampleHeader": "sampleHeaderValue"
|
||||
},
|
||||
"response.include_headers": true,
|
||||
"check.response.status": [
|
||||
"200",
|
||||
"201"
|
||||
],
|
||||
"check.request.body": {
|
||||
"value": "testValue",
|
||||
"type": "json"
|
||||
},
|
||||
"check.response.headers": {},
|
||||
"check.request.method": "",
|
||||
"username": "test-username",
|
||||
"ssl.certificate_authorities": "t.string",
|
||||
"ssl.certificate": "t.string",
|
||||
"ssl.key": "t.string",
|
||||
"ssl.key_passphrase": "t.string",
|
||||
"ssl.verification_mode": "certificate",
|
||||
"ssl.supported_protocols": [
|
||||
"TLSv1.1",
|
||||
"TLSv1.2"
|
||||
],
|
||||
"name": "test-monitor-name",
|
||||
"locations": [
|
||||
{
|
||||
"id": "dev",
|
||||
"label": "Dev Service",
|
||||
"geo": {
|
||||
"lat": 0,
|
||||
"lon": 0
|
||||
},
|
||||
"isServiceManaged": true
|
||||
}
|
||||
],
|
||||
"namespace": "testnamespace",
|
||||
"revision": 1,
|
||||
"origin": "ui",
|
||||
"form_monitor_type": "http",
|
||||
"journey_id": "",
|
||||
"id": "",
|
||||
"hash": "",
|
||||
"mode": "any",
|
||||
"ipv4": true,
|
||||
"ipv6": true,
|
||||
"params": "",
|
||||
"labels": {}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"type": "icmp",
|
||||
"locations": ["dev"],
|
||||
"journey_id": "",
|
||||
"enabled": true,
|
||||
"alert": {
|
||||
"status": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"schedule": {
|
||||
"number": "3",
|
||||
"unit": "m"
|
||||
},
|
||||
"config_id": "",
|
||||
"service.name": "example-service-name",
|
||||
"tags": [
|
||||
"tagT1",
|
||||
"tagT2"
|
||||
],
|
||||
"timeout": "16",
|
||||
"hosts": "192.33.22.111:3333",
|
||||
"wait": "1",
|
||||
"name": "Test HTTP Monitor 04",
|
||||
"namespace": "testnamespace",
|
||||
"origin": "ui",
|
||||
"form_monitor_type": "icmp",
|
||||
"id": "",
|
||||
"hash": "",
|
||||
"mode": "any",
|
||||
"ipv4": true,
|
||||
"ipv6": true,
|
||||
"params": "",
|
||||
"max_attempts": 2
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
{
|
||||
"type": "browser",
|
||||
"form_monitor_type": "multistep",
|
||||
"enabled": true,
|
||||
"alert": {
|
||||
"status": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"schedule": {
|
||||
"number": "10",
|
||||
"unit": "m"
|
||||
},
|
||||
"service.name": "",
|
||||
"config_id": "0088b13c-9bb0-4fc6-a0b5-63b9b024eabb",
|
||||
"tags": [],
|
||||
"timeout": null,
|
||||
"name": "check if title is present",
|
||||
"locations": [
|
||||
{
|
||||
"id": "dev",
|
||||
"label": "Dev Service",
|
||||
"geo": {
|
||||
"lat": 0,
|
||||
"lon": 0
|
||||
},
|
||||
"isServiceManaged": true
|
||||
}
|
||||
],
|
||||
"namespace": "default",
|
||||
"origin": "project",
|
||||
"journey_id": "bb82f7de-d832-4b14-8097-38a464d5fe49",
|
||||
"hash": "ekrjelkjrelkjre",
|
||||
"id": "bb82f7de-d832-4b14-8097-38a464d5fe49-test-project-cb47c83a-45e7-416a-9301-cb476b5bff01-default",
|
||||
"params": "",
|
||||
"project_id": "test-project-cb47c83a-45e7-416a-9301-cb476b5bff01",
|
||||
"playwright_options": "{\"headless\":true,\"chromiumSandbox\":false}",
|
||||
"__ui": {
|
||||
"script_source": {
|
||||
"is_generated_script": false,
|
||||
"file_name": ""
|
||||
}
|
||||
},
|
||||
"url.port": null,
|
||||
"source.inline.script": "",
|
||||
"source.project.content": "UEsDBBQACAAIAON5qVQAAAAAAAAAAAAAAAAfAAAAZXhhbXBsZXMvdG9kb3MvYmFzaWMuam91cm5leS50c22Q0WrDMAxF3/sVF7MHB0LMXlc6RvcN+wDPVWNviW0sdUsp/fe5SSiD7UFCWFfHujIGlpnkybwxFTZfoY/E3hsaLEtwhs9RPNWKDU12zAOxkXRIbN4tB9d9pFOJdO6EN2HMqQguWN9asFBuQVMmJ7jiWNII9fIXrbabdUYr58l9IhwhQQZCYORCTFFUC31Btj21NRc7Mq4Nds+4bDD/pNVgT9F52Jyr2Fa+g75LAPttg8yErk+S9ELpTmVotlVwnfNCuh2lepl3+JflUmSBJ3uggt1v9INW/lHNLKze9dJe1J3QJK8pSvWkm6aTtCet5puq+x63+AFQSwcIAPQ3VfcAAACcAQAAUEsBAi0DFAAIAAgA43mpVAD0N1X3AAAAnAEAAB8AAAAAAAAAAAAgAKSBAAAAAGV4YW1wbGVzL3RvZG9zL2Jhc2ljLmpvdXJuZXkudHNQSwUGAAAAAAEAAQBNAAAARAEAAAAA",
|
||||
"playwright_text_assertion": "",
|
||||
"urls": "",
|
||||
"screenshots": "on",
|
||||
"synthetics_args": [],
|
||||
"filter_journeys.match": "check if title is present",
|
||||
"filter_journeys.tags": [],
|
||||
"ignore_https_errors": false,
|
||||
"throttling": {
|
||||
"value": {
|
||||
"download": "5",
|
||||
"upload": "3",
|
||||
"latency": "20"
|
||||
},
|
||||
"id": "default",
|
||||
"label": "Default"
|
||||
},
|
||||
"ssl.certificate_authorities": "",
|
||||
"ssl.certificate": "",
|
||||
"ssl.key": "",
|
||||
"ssl.key_passphrase": "",
|
||||
"ssl.verification_mode": "full",
|
||||
"ssl.supported_protocols": [
|
||||
"TLSv1.1",
|
||||
"TLSv1.2",
|
||||
"TLSv1.3"
|
||||
],
|
||||
"original_space": "default",
|
||||
"custom_heartbeat_id": "bb82f7de-d832-4b14-8097-38a464d5fe49-test-project-cb47c83a-45e7-416a-9301-cb476b5bff01-default",
|
||||
"revision": 1,
|
||||
"source.inline": {
|
||||
"type": "inline",
|
||||
"script": "",
|
||||
"fileName": ""
|
||||
},
|
||||
"service": {
|
||||
"name": ""
|
||||
},
|
||||
"max_attempts": 2
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"keep_stale": true,
|
||||
"project": "test-suite",
|
||||
"monitors": [{
|
||||
"throttling": {
|
||||
"download": 5,
|
||||
"upload": 3,
|
||||
"latency": 20
|
||||
},
|
||||
"schedule": 10,
|
||||
"locations": [
|
||||
"dev"
|
||||
],
|
||||
"params": {},
|
||||
"playwrightOptions": {
|
||||
"headless": true,
|
||||
"chromiumSandbox": false
|
||||
},
|
||||
"name": "check if title is present",
|
||||
"id": "check-if-title-is-present",
|
||||
"tags": [],
|
||||
"content": "UEsDBBQACAAIAON5qVQAAAAAAAAAAAAAAAAfAAAAZXhhbXBsZXMvdG9kb3MvYmFzaWMuam91cm5leS50c22Q0WrDMAxF3/sVF7MHB0LMXlc6RvcN+wDPVWNviW0sdUsp/fe5SSiD7UFCWFfHujIGlpnkybwxFTZfoY/E3hsaLEtwhs9RPNWKDU12zAOxkXRIbN4tB9d9pFOJdO6EN2HMqQguWN9asFBuQVMmJ7jiWNII9fIXrbabdUYr58l9IhwhQQZCYORCTFFUC31Btj21NRc7Mq4Nds+4bDD/pNVgT9F52Jyr2Fa+g75LAPttg8yErk+S9ELpTmVotlVwnfNCuh2lepl3+JflUmSBJ3uggt1v9INW/lHNLKze9dJe1J3QJK8pSvWkm6aTtCet5puq+x63+AFQSwcIAPQ3VfcAAACcAQAAUEsBAi0DFAAIAAgA43mpVAD0N1X3AAAAnAEAAB8AAAAAAAAAAAAgAKSBAAAAAGV4YW1wbGVzL3RvZG9zL2Jhc2ljLmpvdXJuZXkudHNQSwUGAAAAAAEAAQBNAAAARAEAAAAA",
|
||||
"filter": {
|
||||
"match": "check if title is present"
|
||||
},
|
||||
"hash": "ekrjelkjrelkjre",
|
||||
"max_attempts": 2,
|
||||
"type": "browser"
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
{
|
||||
"project": "test-suite",
|
||||
"keep_stale": false,
|
||||
"monitors": [
|
||||
{
|
||||
"locations": ["dev"],
|
||||
"type": "http",
|
||||
"enabled": false,
|
||||
"id": "my-monitor-2",
|
||||
"name": "My Monitor 2",
|
||||
"urls": [
|
||||
"http://localhost:9200",
|
||||
"http://anotherurl:9200"
|
||||
],
|
||||
"schedule": 60,
|
||||
"timeout": "80s",
|
||||
"check.request": {
|
||||
"method": "POST",
|
||||
"headers": {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"include_body": "always"
|
||||
},
|
||||
"response.include_headers": false,
|
||||
"check.response": {
|
||||
"status": [
|
||||
200
|
||||
],
|
||||
"body": [
|
||||
"Saved",
|
||||
"saved"
|
||||
]
|
||||
},
|
||||
"unsupportedKey": {
|
||||
"nestedUnsupportedKey": "unsupportedValue"
|
||||
},
|
||||
"hash": "ekrjelkjrelkjre"
|
||||
},
|
||||
{
|
||||
"locations": ["dev"],
|
||||
"type": "http",
|
||||
"enabled": false,
|
||||
"id": "my-monitor-3",
|
||||
"name": "My Monitor 3",
|
||||
"proxy_url": "${testGlobalParam2}",
|
||||
"urls": [
|
||||
"http://localhost:9200"
|
||||
],
|
||||
"schedule": 60,
|
||||
"timeout": "80s",
|
||||
"check.request": {
|
||||
"method": "POST",
|
||||
"headers": {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"include_body": "always",
|
||||
"include_body_max_bytes": 900
|
||||
},
|
||||
"tags": "tag2,tag2",
|
||||
"response.include_headers": false,
|
||||
"check.response": {
|
||||
"status": [
|
||||
200
|
||||
],
|
||||
"body":{
|
||||
"positive": [
|
||||
"${testLocal1}",
|
||||
"saved"
|
||||
]
|
||||
},
|
||||
"json": [{"description":"check status","expression":"foo.bar == \"myValue\""}]
|
||||
},
|
||||
"hash": "ekrjelkjrelkjre",
|
||||
"ssl.verification_mode": "strict",
|
||||
"params": {
|
||||
"testLocal1": "testLocalParamsValue",
|
||||
"testGlobalParam2": "testGlobalParamOverwrite"
|
||||
},
|
||||
"max_attempts": 2
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
|
||||
|
||||
{
|
||||
"project": "test-suite",
|
||||
"keep_stale": true,
|
||||
"monitors": [
|
||||
{
|
||||
"locations": [ "dev" ],
|
||||
"type": "icmp",
|
||||
"id": "Cloudflare-DNS",
|
||||
"name": "Cloudflare DNS",
|
||||
"hosts": [ "1.1.1.1" ],
|
||||
"schedule": 1,
|
||||
"tags": [ "service:smtp", "org:google" ],
|
||||
"privateLocations": [ "Test private location 0" ],
|
||||
"wait": "30s",
|
||||
"hash": "ekrjelkjrelkjre"
|
||||
},
|
||||
{
|
||||
"locations": [ "dev" ],
|
||||
"type": "icmp",
|
||||
"id": "Cloudflare-DNS-2",
|
||||
"name": "Cloudflare DNS 2",
|
||||
"hosts": "1.1.1.1",
|
||||
"schedule": 1,
|
||||
"tags": "tag1,tag2",
|
||||
"privateLocations": [ "Test private location 0" ],
|
||||
"wait": "1m",
|
||||
"hash": "ekrjelkjrelkjre"
|
||||
},
|
||||
{
|
||||
"locations": [ "dev" ],
|
||||
"type": "icmp",
|
||||
"id": "Cloudflare-DNS-3",
|
||||
"name": "Cloudflare DNS 3",
|
||||
"hosts": "1.1.1.1,2.2.2.2",
|
||||
"schedule": 1,
|
||||
"tags": "tag1,tag2",
|
||||
"privateLocations": [ "Test private location 0" ],
|
||||
"unsupportedKey": {
|
||||
"nestedUnsupportedKey": "unnsuportedValue"
|
||||
},
|
||||
"hash": "ekrjelkjrelkjre"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"project": "test-suite",
|
||||
"keep_stale": true,
|
||||
"monitors": [
|
||||
{
|
||||
"locations": [ "dev" ],
|
||||
"type": "tcp",
|
||||
"id": "gmail-smtp",
|
||||
"name": "GMail SMTP",
|
||||
"hosts": [ "smtp.gmail.com:587" ],
|
||||
"schedule": 1,
|
||||
"tags": [ "service:smtp", "org:google" ],
|
||||
"privateLocations": [ ],
|
||||
"hash": "ekrjelkjrelkjre",
|
||||
"ssl.verification_mode": "strict"
|
||||
},
|
||||
{
|
||||
"locations": [ "dev" ],
|
||||
"type": "tcp",
|
||||
"id": "always-down",
|
||||
"name": "Always Down",
|
||||
"hosts": "localhost:18278",
|
||||
"schedule": 1,
|
||||
"tags": "tag1,tag2",
|
||||
"privateLocations": [ ],
|
||||
"hash": "ekrjelkjrelkjre"
|
||||
},
|
||||
{
|
||||
"locations": [ "dev" ],
|
||||
"type": "tcp",
|
||||
"id": "always-down",
|
||||
"name": "Always Down",
|
||||
"hosts": ["localhost", "anotherhost"],
|
||||
"ports": ["5698"],
|
||||
"schedule": 1,
|
||||
"tags": "tag1,tag2",
|
||||
"privateLocations": [ ],
|
||||
"unsupportedKey": {
|
||||
"nestedUnsupportedKey": "unnsuportedValue"
|
||||
},
|
||||
"hash": "ekrjelkjrelkjre"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"type": "tcp",
|
||||
"locations": ["dev"],
|
||||
"enabled": true,
|
||||
"config_id": "",
|
||||
"schedule": {
|
||||
"number": "3",
|
||||
"unit": "m"
|
||||
},
|
||||
"service.name": "",
|
||||
"tags": [],
|
||||
"timeout": "16",
|
||||
"__ui": {
|
||||
"is_tls_enabled": true
|
||||
},
|
||||
"hosts": "example-host:40",
|
||||
"urls": "example-host:40",
|
||||
"url.port": null,
|
||||
"proxy_url": "",
|
||||
"proxy_use_local_resolver": false,
|
||||
"check.receive": "",
|
||||
"check.send": "",
|
||||
"ssl.certificate_authorities": "",
|
||||
"ssl.certificate": "",
|
||||
"ssl.key": "",
|
||||
"ssl.key_passphrase": "examplepassphrase",
|
||||
"ssl.verification_mode": "full",
|
||||
"ssl.supported_protocols": [
|
||||
"TLSv1.1",
|
||||
"TLSv1.3"
|
||||
],
|
||||
"name": "Test HTTP Monitor 04",
|
||||
"namespace": "testnamespace",
|
||||
"origin": "ui",
|
||||
"form_monitor_type": "tcp",
|
||||
"id": "",
|
||||
"hash": "",
|
||||
"mode": "any",
|
||||
"ipv4": true,
|
||||
"ipv6": true,
|
||||
"params": "",
|
||||
"max_attempts": 2
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import expect from '@kbn/expect';
|
||||
import { PrivateLocation } from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('getMonitorFilters', function () {
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
const privateLocationTestService = new PrivateLocationTestService(getService);
|
||||
|
||||
let editorUser: RoleCredentials;
|
||||
let privateLocation: PrivateLocation;
|
||||
|
||||
after(async () => {
|
||||
await kibanaServer.savedObjects.clean({ types: [syntheticsMonitorType] });
|
||||
});
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.clean({ types: [syntheticsMonitorType] });
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
privateLocation = await privateLocationTestService.addTestPrivateLocation();
|
||||
});
|
||||
|
||||
it('get list of filters', async () => {
|
||||
const apiResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.FILTERS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body).eql({
|
||||
monitorTypes: [],
|
||||
tags: [],
|
||||
locations: [],
|
||||
projects: [],
|
||||
schedules: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('get list of filters with monitorTypes', async () => {
|
||||
const newMonitor = {
|
||||
name: 'Sample name',
|
||||
type: 'http',
|
||||
urls: 'https://elastic.co',
|
||||
tags: ['apm', 'synthetics'],
|
||||
locations: [privateLocation],
|
||||
};
|
||||
|
||||
await supertest
|
||||
.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(newMonitor)
|
||||
.expect(200);
|
||||
|
||||
const apiResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.FILTERS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body).eql({
|
||||
monitorTypes: [{ label: 'http', count: 1 }],
|
||||
tags: [
|
||||
{ label: 'apm', count: 1 },
|
||||
{ label: 'synthetics', count: 1 },
|
||||
],
|
||||
locations: [{ label: privateLocation.id, count: 1 }],
|
||||
projects: [],
|
||||
schedules: [{ label: '3', count: 1 }],
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* 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 { omit } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import {
|
||||
ConfigKey,
|
||||
EncryptedSyntheticsSavedMonitor,
|
||||
MonitorFields,
|
||||
PrivateLocation,
|
||||
} from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import expect from '@kbn/expect';
|
||||
import { secretKeys } from '@kbn/synthetics-plugin/common/constants/monitor_management';
|
||||
import { SyntheticsMonitorTestService } from '../../../services/synthetics_monitor';
|
||||
import { omitMonitorKeys } from './create_monitor';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('getSyntheticsMonitors', function () {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const retry = getService('retry');
|
||||
const samlAuth = getService('samlAuth');
|
||||
const monitorTestService = new SyntheticsMonitorTestService(getService);
|
||||
const privateLocationTestService = new PrivateLocationTestService(getService);
|
||||
|
||||
let _monitors: MonitorFields[];
|
||||
let monitors: MonitorFields[];
|
||||
let editorUser: RoleCredentials;
|
||||
let privateLocation: PrivateLocation;
|
||||
|
||||
const saveMonitor = async (monitor: MonitorFields, spaceId?: string) => {
|
||||
let url = SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '?internal=true';
|
||||
if (spaceId) {
|
||||
url = '/s/' + spaceId + url;
|
||||
}
|
||||
const res = await supertest
|
||||
.post(url)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor);
|
||||
|
||||
expect(res.status).eql(200, JSON.stringify(res.body));
|
||||
|
||||
return res.body as EncryptedSyntheticsSavedMonitor;
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
privateLocation = await privateLocationTestService.addTestPrivateLocation();
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
_monitors = [
|
||||
getFixtureJson('icmp_monitor'),
|
||||
getFixtureJson('tcp_monitor'),
|
||||
getFixtureJson('http_monitor'),
|
||||
getFixtureJson('browser_monitor'),
|
||||
].map((mon) => ({
|
||||
...mon,
|
||||
locations: [privateLocation],
|
||||
}));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
monitors = _monitors;
|
||||
});
|
||||
|
||||
describe('get many monitors', () => {
|
||||
it('without params', async () => {
|
||||
const uuid = uuidv4();
|
||||
const [mon1, mon2] = await Promise.all(
|
||||
monitors.map((mon, i) => saveMonitor({ ...mon, name: `${mon.name}-${uuid}-${i}` }))
|
||||
);
|
||||
|
||||
const apiResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '?perPage=1000&internal=true') // 1000 to sort of load all saved monitors
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const found: MonitorFields[] = apiResponse.body.monitors.filter(({ id }: MonitorFields) =>
|
||||
[mon1.id, mon2.id].includes(id)
|
||||
);
|
||||
found.sort(({ id: a }) => (a === mon2.id ? 1 : a === mon1.id ? -1 : 0));
|
||||
const foundMonitors = found.map(
|
||||
(fields) => fields as unknown as EncryptedSyntheticsSavedMonitor
|
||||
);
|
||||
|
||||
const expected = [mon1, mon2];
|
||||
|
||||
/**
|
||||
* These dates are dynamically generated by the server, so we can't
|
||||
* compare them directly. Instead, we'll just check that they're valid.
|
||||
*/
|
||||
foundMonitors.forEach(({ updated_at: updatedAt, created_at: createdAt }) => {
|
||||
expect(moment(createdAt).isValid()).to.be(true);
|
||||
expect(moment(updatedAt).isValid()).to.be(true);
|
||||
});
|
||||
|
||||
expect(foundMonitors.map((fm) => omit(fm, 'updated_at', 'created_at', 'spaceId'))).eql(
|
||||
expected.map((expectedMon) =>
|
||||
omit(expectedMon, ['updated_at', 'created_at', ...secretKeys])
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('with page params', async () => {
|
||||
const allMonitors = [...monitors, ...monitors];
|
||||
for (const mon of allMonitors) {
|
||||
await saveMonitor({ ...mon, name: mon.name + Date.now() });
|
||||
}
|
||||
|
||||
await retry.try(async () => {
|
||||
const firstPageResp = await supertest
|
||||
.get(`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}?page=1&perPage=2`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const secondPageResp = await supertest
|
||||
.get(`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}?page=2&perPage=3`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(firstPageResp.body.total).greaterThan(6);
|
||||
expect(firstPageResp.body.monitors.length).eql(2);
|
||||
expect(secondPageResp.body.monitors.length).eql(3);
|
||||
|
||||
expect(firstPageResp.body.monitors[0].id).not.eql(secondPageResp.body.monitors[0].id);
|
||||
});
|
||||
});
|
||||
|
||||
it('with single monitorQueryId filter', async () => {
|
||||
const uuid = uuidv4();
|
||||
const [_, { id: id2 }] = await Promise.all(
|
||||
monitors
|
||||
.map((mon, i) => ({ ...mon, name: `mon.name-${uuid}-${i}` }))
|
||||
.map((mon) => saveMonitor(mon))
|
||||
);
|
||||
|
||||
const resp = await supertest
|
||||
.get(
|
||||
`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}?page=1&perPage=10&monitorQueryIds=${id2}`
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const resultMonitorIds = resp.body.monitors.map(({ id }: Partial<MonitorFields>) => id);
|
||||
expect(resultMonitorIds.length).eql(1);
|
||||
expect(resultMonitorIds).eql([id2]);
|
||||
});
|
||||
|
||||
it('with multiple monitorQueryId filter', async () => {
|
||||
const uuid = uuidv4();
|
||||
const [_, { id: id2 }, { id: id3 }] = await Promise.all(
|
||||
monitors
|
||||
.map((mon, i) => ({ ...mon, name: `${mon.name}-${uuid}-${i}` }))
|
||||
.map((monT) => saveMonitor(monT))
|
||||
);
|
||||
|
||||
const resp = await supertest
|
||||
.get(
|
||||
`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}?page=1&perPage=10&sortField=name.keyword&sortOrder=asc&monitorQueryIds=${id2}&monitorQueryIds=${id3}`
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const resultMonitorIds = resp.body.monitors.map(({ id }: Partial<MonitorFields>) => id);
|
||||
|
||||
expect(resultMonitorIds.length).eql(2);
|
||||
expect(resultMonitorIds).eql([id2, id3]);
|
||||
});
|
||||
|
||||
it('monitorQueryId respects custom_heartbeat_id while filtering', async () => {
|
||||
const customHeartbeatId0 = 'custom-heartbeat-id-test-01';
|
||||
const customHeartbeatId1 = 'custom-heartbeat-id-test-02';
|
||||
await Promise.all(
|
||||
[
|
||||
{
|
||||
...monitors[0],
|
||||
[ConfigKey.CUSTOM_HEARTBEAT_ID]: customHeartbeatId0,
|
||||
[ConfigKey.NAME]: `NAME-${customHeartbeatId0}`,
|
||||
},
|
||||
{
|
||||
...monitors[1],
|
||||
[ConfigKey.CUSTOM_HEARTBEAT_ID]: customHeartbeatId1,
|
||||
[ConfigKey.NAME]: `NAME-${customHeartbeatId1}`,
|
||||
},
|
||||
].map((monT) => saveMonitor(monT))
|
||||
);
|
||||
|
||||
const resp = await supertest
|
||||
.get(
|
||||
`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}?page=1&perPage=10&sortField=name.keyword&sortOrder=asc&monitorQueryIds=${customHeartbeatId0}&monitorQueryIds=${customHeartbeatId1}`
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const resultMonitorIds = resp.body.monitors
|
||||
.map(({ id }: Partial<MonitorFields>) => id)
|
||||
.filter((id: string, index: number, arr: string[]) => arr.indexOf(id) === index); // Filter only unique
|
||||
expect(resultMonitorIds.length).eql(2);
|
||||
expect(resultMonitorIds).eql([customHeartbeatId0, customHeartbeatId1]);
|
||||
});
|
||||
|
||||
it('gets monitors from all spaces', async () => {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
const spaceScopedPrivateLocation = await privateLocationTestService.addTestPrivateLocation(
|
||||
SPACE_ID
|
||||
);
|
||||
|
||||
const allMonitors = [...monitors, ...monitors];
|
||||
for (const mon of allMonitors) {
|
||||
await saveMonitor(
|
||||
{ ...mon, name: mon.name + Date.now(), locations: [spaceScopedPrivateLocation] },
|
||||
SPACE_ID
|
||||
);
|
||||
}
|
||||
|
||||
const firstPageResp = await supertest
|
||||
.get(`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}?page=1&perPage=1000`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const defaultSpaceMons = firstPageResp.body.monitors.filter(
|
||||
({ spaceId }: { spaceId: string }) => spaceId === 'default'
|
||||
);
|
||||
const testSpaceMons = firstPageResp.body.monitors.filter(
|
||||
({ spaceId }: { spaceId: string }) => spaceId === SPACE_ID
|
||||
);
|
||||
|
||||
expect(defaultSpaceMons.length).to.eql(22);
|
||||
expect(testSpaceMons.length).to.eql(0);
|
||||
|
||||
const res = await supertest
|
||||
.get(
|
||||
`${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}?page=1&perPage=1000&showFromAllSpaces=true`
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const defaultSpaceMons1 = res.body.monitors.filter(
|
||||
({ spaceId }: { spaceId: string }) => spaceId === 'default'
|
||||
);
|
||||
const testSpaceMons1 = res.body.monitors.filter(
|
||||
({ spaceId }: { spaceId: string }) => spaceId === SPACE_ID
|
||||
);
|
||||
|
||||
expect(defaultSpaceMons1.length).to.eql(22);
|
||||
expect(testSpaceMons1.length).to.eql(8);
|
||||
});
|
||||
});
|
||||
|
||||
describe('get one monitor', () => {
|
||||
it('should get by id', async () => {
|
||||
const uuid = uuidv4();
|
||||
const [{ id: id1 }] = await Promise.all(
|
||||
monitors
|
||||
.map((mon, i) => ({ ...mon, name: `${mon.name}-${uuid}-${i}` }))
|
||||
.map((monT) => saveMonitor(monT))
|
||||
);
|
||||
|
||||
const apiResponse = await monitorTestService.getMonitor(id1, { user: editorUser });
|
||||
|
||||
expect(apiResponse.body).eql(
|
||||
omitMonitorKeys({
|
||||
...monitors[0],
|
||||
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
|
||||
[ConfigKey.CONFIG_ID]: apiResponse.body.id,
|
||||
revision: 1,
|
||||
locations: [privateLocation],
|
||||
name: `${monitors[0].name}-${uuid}-0`,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should get by id with ui query param', async () => {
|
||||
const uuid = uuidv4();
|
||||
const [{ id: id1 }] = await Promise.all(
|
||||
monitors
|
||||
.map((mon, i) => ({ ...mon, name: `${mon.name}-${uuid}-${i}` }))
|
||||
.map((monT) => saveMonitor(monT))
|
||||
);
|
||||
|
||||
const apiResponse = await monitorTestService.getMonitor(id1, {
|
||||
internal: true,
|
||||
user: editorUser,
|
||||
});
|
||||
|
||||
expect(apiResponse.body).eql(
|
||||
omit(
|
||||
{
|
||||
...monitors[0],
|
||||
form_monitor_type: 'icmp',
|
||||
revision: 1,
|
||||
locations: [privateLocation],
|
||||
name: `${monitors[0].name}-${uuid}-0`,
|
||||
hosts: '192.33.22.111:3333',
|
||||
hash: '',
|
||||
journey_id: '',
|
||||
max_attempts: 2,
|
||||
labels: {},
|
||||
},
|
||||
['config_id', 'id', 'form_monitor_type']
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('returns 404 if monitor id is not found', async () => {
|
||||
const invalidMonitorId = 'invalid-id';
|
||||
const expected404Message = `Monitor id ${invalidMonitorId} not found!`;
|
||||
|
||||
const getResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.GET_SYNTHETICS_MONITOR.replace('{monitorId}', invalidMonitorId))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(404);
|
||||
|
||||
expect(getResponse.body.message).eql(expected404Message);
|
||||
});
|
||||
|
||||
it('validates param length', async () => {
|
||||
const veryLargeMonId = new Array(1050).fill('1').join('');
|
||||
|
||||
await supertest
|
||||
.get(SYNTHETICS_API_URLS.GET_SYNTHETICS_MONITOR.replace('{monitorId}', veryLargeMonId))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(400);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,741 @@
|
|||
/*
|
||||
* 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 { v4 as uuidv4 } from 'uuid';
|
||||
import type SuperTest from 'supertest';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import {
|
||||
LegacyProjectMonitorsRequest,
|
||||
ProjectMonitor,
|
||||
ProjectMonitorMetaData,
|
||||
PrivateLocation,
|
||||
} from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import expect from '@kbn/expect';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('GetProjectMonitors', function () {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
let projectMonitors: LegacyProjectMonitorsRequest;
|
||||
let httpProjectMonitors: LegacyProjectMonitorsRequest;
|
||||
let tcpProjectMonitors: LegacyProjectMonitorsRequest;
|
||||
let icmpProjectMonitors: LegacyProjectMonitorsRequest;
|
||||
let testPolicyId = '';
|
||||
let editorUser: RoleCredentials;
|
||||
let testPrivateLocations: PrivateLocation[] = [];
|
||||
|
||||
const testPrivateLocationsService = new PrivateLocationTestService(getService);
|
||||
|
||||
const setUniqueIds = (
|
||||
request: LegacyProjectMonitorsRequest,
|
||||
privateLocations: PrivateLocation[] = []
|
||||
) => {
|
||||
return {
|
||||
...request,
|
||||
monitors: request.monitors.map((monitor) => ({
|
||||
...monitor,
|
||||
id: uuidv4(),
|
||||
locations: [],
|
||||
privateLocations: privateLocations.map((location) => location.label),
|
||||
})),
|
||||
};
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
await testPrivateLocationsService.installSyntheticsPackage();
|
||||
|
||||
const testPolicyName = 'Fleet test server policy' + Date.now();
|
||||
const apiResponse = await testPrivateLocationsService.addFleetPolicy(testPolicyName);
|
||||
testPolicyId = apiResponse.body.item.id;
|
||||
testPrivateLocations = await testPrivateLocationsService.setTestLocations([testPolicyId]);
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
projectMonitors = setUniqueIds(
|
||||
getFixtureJson('project_browser_monitor'),
|
||||
testPrivateLocations
|
||||
);
|
||||
httpProjectMonitors = setUniqueIds(
|
||||
getFixtureJson('project_http_monitor'),
|
||||
testPrivateLocations
|
||||
);
|
||||
tcpProjectMonitors = setUniqueIds(
|
||||
getFixtureJson('project_tcp_monitor'),
|
||||
testPrivateLocations
|
||||
);
|
||||
icmpProjectMonitors = setUniqueIds(
|
||||
getFixtureJson('project_icmp_monitor'),
|
||||
testPrivateLocations
|
||||
);
|
||||
});
|
||||
|
||||
it('project monitors - fetches all monitors - browser', async () => {
|
||||
const monitors = [];
|
||||
const project = 'test-brower-suite';
|
||||
for (let i = 0; i < 600; i++) {
|
||||
monitors.push({
|
||||
...projectMonitors.monitors[0],
|
||||
id: `test browser id ${i}`,
|
||||
name: `test name ${i}`,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(0, 250),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(250, 500),
|
||||
})
|
||||
.expect(200);
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(500, 600),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const firstPageResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.query({ per_page: 500 })
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const { monitors: firstPageMonitors, total, after_key: afterKey } = firstPageResponse.body;
|
||||
expect(firstPageMonitors.length).to.eql(500);
|
||||
expect(total).to.eql(600);
|
||||
expect(afterKey).to.eql('test browser id 548');
|
||||
|
||||
const secondPageResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.query({
|
||||
search_after: afterKey,
|
||||
per_page: 500,
|
||||
})
|
||||
.send()
|
||||
.expect(200);
|
||||
const { monitors: secondPageMonitors } = secondPageResponse.body;
|
||||
expect(secondPageMonitors.length).to.eql(100);
|
||||
checkFields([...firstPageMonitors, ...secondPageMonitors], monitors);
|
||||
} finally {
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(0, 250) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(250, 500) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(500, 600) })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
it('project monitors - fetches all monitors - http', async () => {
|
||||
const monitors = [];
|
||||
const project = 'test-http-suite';
|
||||
for (let i = 0; i < 600; i++) {
|
||||
monitors.push({
|
||||
...httpProjectMonitors.monitors[1],
|
||||
id: `test http id ${i}`,
|
||||
name: `test name ${i}`,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(0, 250),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(250, 500),
|
||||
})
|
||||
.expect(200);
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(500, 600),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const firstPageResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.query({ per_page: 500 })
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const {
|
||||
monitors: firstPageProjectMonitors,
|
||||
after_key: afterKey,
|
||||
total,
|
||||
} = firstPageResponse.body;
|
||||
expect(firstPageProjectMonitors.length).to.eql(500);
|
||||
expect(total).to.eql(600);
|
||||
expect(afterKey).to.eql('test http id 548');
|
||||
|
||||
const secondPageResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.query({
|
||||
search_after: afterKey,
|
||||
per_page: 500,
|
||||
})
|
||||
.send()
|
||||
.expect(200);
|
||||
const { monitors: secondPageProjectMonitors } = secondPageResponse.body;
|
||||
expect(secondPageProjectMonitors.length).to.eql(100);
|
||||
checkFields([...firstPageProjectMonitors, ...secondPageProjectMonitors], monitors);
|
||||
} finally {
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(0, 250) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(250, 500) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(500, 600) })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
it('project monitors - fetches all monitors - tcp', async () => {
|
||||
const monitors = [];
|
||||
const project = 'test-tcp-suite';
|
||||
for (let i = 0; i < 600; i++) {
|
||||
monitors.push({
|
||||
...tcpProjectMonitors.monitors[0],
|
||||
id: `test tcp id ${i}`,
|
||||
name: `test name ${i}`,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(0, 250),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(250, 500),
|
||||
})
|
||||
.expect(200);
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(500, 600),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const firstPageResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.query({ per_page: 500 })
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const {
|
||||
monitors: firstPageProjectMonitors,
|
||||
after_key: afterKey,
|
||||
total,
|
||||
} = firstPageResponse.body;
|
||||
expect(firstPageProjectMonitors.length).to.eql(500);
|
||||
expect(total).to.eql(600);
|
||||
expect(afterKey).to.eql('test tcp id 548');
|
||||
|
||||
const secondPageResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.query({
|
||||
search_after: afterKey,
|
||||
per_page: 500,
|
||||
})
|
||||
.send()
|
||||
.expect(200);
|
||||
const { monitors: secondPageProjectMonitors } = secondPageResponse.body;
|
||||
expect(secondPageProjectMonitors.length).to.eql(100);
|
||||
checkFields([...firstPageProjectMonitors, ...secondPageProjectMonitors], monitors);
|
||||
} finally {
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(0, 250) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(250, 500) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(500, 600) })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
it('project monitors - fetches all monitors - icmp', async () => {
|
||||
const monitors = [];
|
||||
const project = 'test-icmp-suite';
|
||||
for (let i = 0; i < 600; i++) {
|
||||
monitors.push({
|
||||
...icmpProjectMonitors.monitors[0],
|
||||
id: `test icmp id ${i}`,
|
||||
name: `test name ${i}`,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(0, 250),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(250, 500),
|
||||
})
|
||||
.expect(200);
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(500, 600),
|
||||
})
|
||||
.expect(200);
|
||||
const firstPageResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.query({ per_page: 500 })
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const {
|
||||
monitors: firstPageProjectMonitors,
|
||||
after_key: afterKey,
|
||||
total,
|
||||
} = firstPageResponse.body;
|
||||
expect(firstPageProjectMonitors.length).to.eql(500);
|
||||
expect(total).to.eql(600);
|
||||
expect(afterKey).to.eql('test icmp id 548');
|
||||
|
||||
const secondPageResponse = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.query({
|
||||
search_after: afterKey,
|
||||
per_page: 500,
|
||||
})
|
||||
.send()
|
||||
.expect(200);
|
||||
const { monitors: secondPageProjectMonitors } = secondPageResponse.body;
|
||||
expect(secondPageProjectMonitors.length).to.eql(100);
|
||||
|
||||
checkFields([...firstPageProjectMonitors, ...secondPageProjectMonitors], monitors);
|
||||
} finally {
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(0, 250) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(250, 500) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(500, 600) })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
it('project monitors - handles url ecoded project names', async () => {
|
||||
const monitors = [];
|
||||
const projectName = 'Test project';
|
||||
for (let i = 0; i < 600; i++) {
|
||||
monitors.push({
|
||||
...icmpProjectMonitors.monitors[0],
|
||||
id: `test url id ${i}`,
|
||||
name: `test name ${i}`,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace(
|
||||
'{projectName}',
|
||||
projectName
|
||||
)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(0, 250),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace(
|
||||
'{projectName}',
|
||||
projectName
|
||||
)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(250, 500),
|
||||
})
|
||||
.expect(200);
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace(
|
||||
'{projectName}',
|
||||
projectName
|
||||
)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(500, 600),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const firstPageResponse = await supertest
|
||||
.get(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace(
|
||||
'{projectName}',
|
||||
encodeURI(projectName)
|
||||
)
|
||||
)
|
||||
.query({ per_page: 500 })
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const {
|
||||
monitors: firstPageProjectMonitors,
|
||||
after_key: afterKey,
|
||||
total,
|
||||
} = firstPageResponse.body;
|
||||
expect(firstPageProjectMonitors.length).to.eql(500);
|
||||
expect(total).to.eql(600);
|
||||
expect(afterKey).to.eql('test url id 548');
|
||||
|
||||
const secondPageResponse = await supertest
|
||||
.get(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace(
|
||||
'{projectName}',
|
||||
encodeURI(projectName)
|
||||
)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.query({
|
||||
search_after: afterKey,
|
||||
per_page: 500,
|
||||
})
|
||||
.send()
|
||||
.expect(200);
|
||||
const { monitors: secondPageProjectMonitors } = secondPageResponse.body;
|
||||
expect(secondPageProjectMonitors.length).to.eql(100);
|
||||
|
||||
checkFields([...firstPageProjectMonitors, ...secondPageProjectMonitors], monitors);
|
||||
} finally {
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace(
|
||||
'{projectName}',
|
||||
encodeURI(projectName)
|
||||
)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(0, 250) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace(
|
||||
'{projectName}',
|
||||
encodeURI(projectName)
|
||||
)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(250, 500) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace(
|
||||
'{projectName}',
|
||||
encodeURI(projectName)
|
||||
)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(500, 600) })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
it('project monitors - handles per_page parameter', async () => {
|
||||
const monitors = [];
|
||||
const project = 'test-suite';
|
||||
const perPage = 250;
|
||||
for (let i = 0; i < 600; i++) {
|
||||
monitors.push({
|
||||
...icmpProjectMonitors.monitors[0],
|
||||
id: `test-id-${i}`,
|
||||
name: `test-name-${i}`,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(0, 250),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(250, 500),
|
||||
})
|
||||
.expect(200);
|
||||
await supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({
|
||||
monitors: monitors.slice(500, 600),
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
let count = Number.MAX_VALUE;
|
||||
let afterId;
|
||||
const fullResponse: ProjectMonitorMetaData[] = [];
|
||||
let page = 1;
|
||||
while (count >= 250) {
|
||||
const response: SuperTest.Response = await supertest
|
||||
.get(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project))
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.query({
|
||||
per_page: perPage,
|
||||
search_after: afterId,
|
||||
})
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const { monitors: monitorsResponse, after_key: afterKey, total } = response.body;
|
||||
expect(total).to.eql(600);
|
||||
count = monitorsResponse.length;
|
||||
fullResponse.push(...monitorsResponse);
|
||||
if (page < 3) {
|
||||
expect(count).to.eql(perPage);
|
||||
} else {
|
||||
expect(count).to.eql(100);
|
||||
}
|
||||
page++;
|
||||
|
||||
afterId = afterKey;
|
||||
}
|
||||
// expect(fullResponse.length).to.eql(600);
|
||||
// checkFields(fullResponse, monitors);
|
||||
} finally {
|
||||
const monitorsToDelete = monitors.map((monitor) => monitor.id);
|
||||
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(0, 250) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(250, 500) })
|
||||
.expect(200);
|
||||
await supertest
|
||||
.delete(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_DELETE.replace('{projectName}', project)
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors: monitorsToDelete.slice(500, 600) })
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const checkFields = (monitorMetaData: ProjectMonitorMetaData[], monitors: ProjectMonitor[]) => {
|
||||
monitors.forEach((monitor) => {
|
||||
const configIsCorrect = monitorMetaData.some((ndjson: Record<string, unknown>) => {
|
||||
return ndjson.journey_id === monitor.id && ndjson.hash === monitor.hash;
|
||||
});
|
||||
expect(configIsCorrect).to.eql(true);
|
||||
});
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 fs from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const fixturesDir = join(__dirname, '..', 'fixtures');
|
||||
|
||||
export function getFixtureJson(fixtureName: string) {
|
||||
try {
|
||||
const fixturePath = join(fixturesDir, `${fixtureName}.json`);
|
||||
const fileContents = fs.readFileSync(fixturePath, 'utf8');
|
||||
return JSON.parse(fileContents);
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 { omit } from 'lodash';
|
||||
|
||||
export function omitResponseTimestamps(monitor: object) {
|
||||
return omit(monitor, ['created_at', 'updated_at']);
|
||||
}
|
||||
|
||||
export function omitEmptyValues(monitor: object) {
|
||||
const { url, ...rest } = omit(monitor, ['created_at', 'updated_at']) as any;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
...(url ? { url } : {}),
|
||||
};
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('SyntheticsAPITests', () => {
|
||||
loadTestFile(require.resolve('./create_monitor'));
|
||||
loadTestFile(require.resolve('./create_monitor_private_location'));
|
||||
loadTestFile(require.resolve('./create_monitor_project'));
|
||||
loadTestFile(require.resolve('./create_monitor_project_private_location'));
|
||||
loadTestFile(require.resolve('./create_monitor_public_api'));
|
||||
loadTestFile(require.resolve('./create_update_params'));
|
||||
loadTestFile(require.resolve('./delete_monitor_project'));
|
||||
loadTestFile(require.resolve('./delete_monitor'));
|
||||
loadTestFile(require.resolve('./edit_monitor'));
|
||||
loadTestFile(require.resolve('./edit_monitor_public_api'));
|
||||
loadTestFile(require.resolve('./enable_default_alerting'));
|
||||
loadTestFile(require.resolve('./get_filters'));
|
||||
loadTestFile(require.resolve('./get_monitor_project'));
|
||||
loadTestFile(require.resolve('./get_monitor'));
|
||||
loadTestFile(require.resolve('./synthetics_enablement'));
|
||||
loadTestFile(require.resolve('./inspect_monitor'));
|
||||
loadTestFile(require.resolve('./suggestions.ts'));
|
||||
loadTestFile(require.resolve('./sync_global_params'));
|
||||
loadTestFile(require.resolve('./test_now_monitor'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* 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 { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import { MonitorFields } from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import rawExpect from 'expect';
|
||||
import expect from '@kbn/expect';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { SyntheticsMonitorTestService } from '../../../services/synthetics_monitor';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('inspectSyntheticsMonitor', function () {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
|
||||
const monitorTestService = new SyntheticsMonitorTestService(getService);
|
||||
const testPrivateLocations = new PrivateLocationTestService(getService);
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
let _monitors: MonitorFields[];
|
||||
let editorUser: RoleCredentials;
|
||||
let adminUser: RoleCredentials;
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
await kibanaServer.savedObjects.clean({ types: ['synthetics-param'] });
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
adminUser = await samlAuth.createM2mApiKeyWithRoleScope('admin');
|
||||
await testPrivateLocations.installSyntheticsPackage();
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
_monitors = [getFixtureJson('http_monitor'), getFixtureJson('inspect_browser_monitor')];
|
||||
});
|
||||
|
||||
// tests public locations which fails in MKI
|
||||
it.skip('inspect http monitor', async () => {
|
||||
const apiResponse = await monitorTestService.inspectMonitor(adminUser, {
|
||||
..._monitors[0],
|
||||
locations: [
|
||||
{
|
||||
id: 'dev',
|
||||
label: 'Dev Service',
|
||||
isServiceManaged: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
rawExpect(apiResponse).toEqual({
|
||||
result: {
|
||||
publicConfigs: [
|
||||
rawExpect.objectContaining({
|
||||
monitors: [
|
||||
{
|
||||
type: 'http',
|
||||
schedule: '@every 5m',
|
||||
enabled: true,
|
||||
data_stream: { namespace: 'testnamespace' },
|
||||
streams: [
|
||||
{
|
||||
data_stream: { dataset: 'http', type: 'synthetics' },
|
||||
type: 'http',
|
||||
enabled: true,
|
||||
schedule: '@every 5m',
|
||||
tags: ['tag1', 'tag2'],
|
||||
timeout: '180s',
|
||||
name: 'test-monitor-name',
|
||||
namespace: 'testnamespace',
|
||||
origin: 'ui',
|
||||
urls: 'https://nextjs-test-synthetics.vercel.app/api/users',
|
||||
max_redirects: '3',
|
||||
max_attempts: 2,
|
||||
password: 'test',
|
||||
proxy_url: 'http://proxy.com',
|
||||
'response.include_body': 'never',
|
||||
'response.include_headers': true,
|
||||
'check.response.status': ['200', '201'],
|
||||
'check.request.body': 'testValue',
|
||||
'check.request.headers': { sampleHeader: 'sampleHeaderValue' },
|
||||
username: 'test-username',
|
||||
mode: 'any',
|
||||
'response.include_body_max_bytes': '1024',
|
||||
ipv4: true,
|
||||
ipv6: true,
|
||||
fields: {
|
||||
meta: { space_id: 'default' },
|
||||
},
|
||||
fields_under_root: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
output: { hosts: [] },
|
||||
}),
|
||||
],
|
||||
privateConfig: null,
|
||||
},
|
||||
decodedCode: '',
|
||||
});
|
||||
});
|
||||
|
||||
// tests public locations which fails in MKI
|
||||
it.skip('inspect project browser monitor', async () => {
|
||||
const apiResponse = await monitorTestService.inspectMonitor(editorUser, {
|
||||
..._monitors[1],
|
||||
params: JSON.stringify({
|
||||
username: 'elastic',
|
||||
password: 'changeme',
|
||||
}),
|
||||
locations: [
|
||||
{
|
||||
id: 'dev',
|
||||
label: 'Dev Service',
|
||||
isServiceManaged: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
rawExpect(apiResponse).toEqual({
|
||||
result: {
|
||||
publicConfigs: [
|
||||
rawExpect.objectContaining({
|
||||
monitors: [
|
||||
{
|
||||
type: 'browser',
|
||||
schedule: '@every 10m',
|
||||
enabled: true,
|
||||
data_stream: { namespace: 'default' },
|
||||
streams: [
|
||||
{
|
||||
data_stream: { dataset: 'browser', type: 'synthetics' },
|
||||
type: 'browser',
|
||||
enabled: true,
|
||||
schedule: '@every 10m',
|
||||
name: 'check if title is present',
|
||||
namespace: 'default',
|
||||
origin: 'project',
|
||||
params: {
|
||||
username: '"********"',
|
||||
password: '"********"',
|
||||
},
|
||||
playwright_options: { headless: true, chromiumSandbox: false },
|
||||
'source.project.content':
|
||||
'UEsDBBQACAAIAON5qVQAAAAAAAAAAAAAAAAfAAAAZXhhbXBsZXMvdG9kb3MvYmFzaWMuam91cm5leS50c22Q0WrDMAxF3/sVF7MHB0LMXlc6RvcN+wDPVWNviW0sdUsp/fe5SSiD7UFCWFfHujIGlpnkybwxFTZfoY/E3hsaLEtwhs9RPNWKDU12zAOxkXRIbN4tB9d9pFOJdO6EN2HMqQguWN9asFBuQVMmJ7jiWNII9fIXrbabdUYr58l9IhwhQQZCYORCTFFUC31Btj21NRc7Mq4Nds+4bDD/pNVgT9F52Jyr2Fa+g75LAPttg8yErk+S9ELpTmVotlVwnfNCuh2lepl3+JflUmSBJ3uggt1v9INW/lHNLKze9dJe1J3QJK8pSvWkm6aTtCet5puq+x63+AFQSwcIAPQ3VfcAAACcAQAAUEsBAi0DFAAIAAgA43mpVAD0N1X3AAAAnAEAAB8AAAAAAAAAAAAgAKSBAAAAAGV4YW1wbGVzL3RvZG9zL2Jhc2ljLmpvdXJuZXkudHNQSwUGAAAAAAEAAQBNAAAARAEAAAAA',
|
||||
screenshots: 'on',
|
||||
'filter_journeys.match': 'check if title is present',
|
||||
ignore_https_errors: false,
|
||||
throttling: { download: 5, upload: 3, latency: 20 },
|
||||
original_space: 'default',
|
||||
fields: {
|
||||
meta: { space_id: 'default' },
|
||||
'monitor.project.name': 'test-project-cb47c83a-45e7-416a-9301-cb476b5bff01',
|
||||
'monitor.project.id': 'test-project-cb47c83a-45e7-416a-9301-cb476b5bff01',
|
||||
},
|
||||
fields_under_root: true,
|
||||
max_attempts: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
license_level: rawExpect.any(String),
|
||||
cloud_id: 'ftr_fake_cloud_id',
|
||||
output: { hosts: [] },
|
||||
}),
|
||||
],
|
||||
privateConfig: null,
|
||||
},
|
||||
decodedCode:
|
||||
'// asset:/Users/vigneshh/elastic/synthetics/examples/todos/basic.journey.ts\nimport { journey, step, expect } from "@elastic/synthetics";\njourney("check if title is present", ({ page, params }) => {\n step("launch app", async () => {\n await page.goto(params.url);\n });\n step("assert title", async () => {\n const header = await page.$("h1");\n expect(await header.textContent()).toBe("todos");\n });\n});\n',
|
||||
});
|
||||
});
|
||||
|
||||
it('inspect http monitor in private location', async () => {
|
||||
const location = await testPrivateLocations.addTestPrivateLocation();
|
||||
const apiResponse = await monitorTestService.inspectMonitor(editorUser, {
|
||||
..._monitors[0],
|
||||
locations: [
|
||||
{
|
||||
id: location.id,
|
||||
label: location.label,
|
||||
isServiceManaged: false,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const privateConfig = apiResponse.result.privateConfig!;
|
||||
|
||||
const enabledStream = privateConfig.inputs
|
||||
.find((input) => input.enabled)
|
||||
?.streams.find((stream) => stream.enabled);
|
||||
|
||||
const compiledStream = enabledStream?.compiled_stream;
|
||||
|
||||
delete compiledStream.id;
|
||||
delete compiledStream.processors[0].add_fields.fields.config_id;
|
||||
|
||||
expect(enabledStream?.compiled_stream).eql({
|
||||
__ui: { is_tls_enabled: false },
|
||||
type: 'http',
|
||||
name: 'test-monitor-name',
|
||||
origin: 'ui',
|
||||
'run_from.id': location.id,
|
||||
'run_from.geo.name': location.label,
|
||||
enabled: true,
|
||||
urls: 'https://nextjs-test-synthetics.vercel.app/api/users',
|
||||
schedule: '@every 5m',
|
||||
timeout: '180s',
|
||||
max_redirects: 3,
|
||||
max_attempts: 2,
|
||||
proxy_url: 'http://proxy.com',
|
||||
tags: ['tag1', 'tag2'],
|
||||
username: 'test-username',
|
||||
password: 'test',
|
||||
'response.include_headers': true,
|
||||
'response.include_body': 'never',
|
||||
'response.include_body_max_bytes': 1024,
|
||||
'check.request.method': null,
|
||||
'check.request.headers': { sampleHeader: 'sampleHeaderValue' },
|
||||
'check.request.body': 'testValue',
|
||||
'check.response.status': ['200', '201'],
|
||||
mode: 'any',
|
||||
ipv4: true,
|
||||
ipv6: true,
|
||||
processors: [
|
||||
{
|
||||
add_fields: {
|
||||
target: '',
|
||||
fields: {
|
||||
meta: { space_id: 'default' },
|
||||
'monitor.fleet_managed': true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,575 @@
|
|||
/*
|
||||
* 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 'expect';
|
||||
import { omit, sortBy } from 'lodash';
|
||||
import { PackagePolicy, PackagePolicyConfigRecord } from '@kbn/fleet-plugin/common';
|
||||
import { INSTALLED_VERSION } from '../../../../services/synthetics_private_location';
|
||||
import { commonVars } from './test_project_monitor_policy';
|
||||
|
||||
interface PolicyProps {
|
||||
name?: string;
|
||||
id: string;
|
||||
configId?: string;
|
||||
projectId?: string;
|
||||
location: { name?: string; id?: string };
|
||||
namespace?: string;
|
||||
isTLSEnabled?: boolean;
|
||||
proxyUrl?: string;
|
||||
params?: Record<string, any>;
|
||||
isBrowser?: boolean;
|
||||
spaceId?: string;
|
||||
}
|
||||
|
||||
export const getTestSyntheticsPolicy = (props: PolicyProps): PackagePolicy => {
|
||||
const { namespace } = props;
|
||||
return {
|
||||
id: '2bfd7da0-22ed-11ed-8c6b-09a2d21dfbc3-27337270-22ed-11ed-8c6b-09a2d21dfbc3-default',
|
||||
version: 'WzE2MjYsMV0=',
|
||||
name: 'test-monitor-name-Test private location 0-default',
|
||||
namespace: namespace ?? 'testnamespace',
|
||||
package: { name: 'synthetics', title: 'Elastic Synthetics', version: INSTALLED_VERSION },
|
||||
enabled: true,
|
||||
policy_id: '5347cd10-0368-11ed-8df7-a7424c6f5167',
|
||||
policy_ids: ['5347cd10-0368-11ed-8df7-a7424c6f5167'],
|
||||
inputs: [
|
||||
getHttpInput(props),
|
||||
{
|
||||
type: 'synthetics/tcp',
|
||||
policy_template: 'synthetics',
|
||||
enabled: false,
|
||||
streams: [
|
||||
{
|
||||
enabled: false,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'tcp',
|
||||
},
|
||||
vars: {
|
||||
__ui: { type: 'yaml' },
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'tcp', type: 'text' },
|
||||
name: { type: 'text' },
|
||||
schedule: { value: '"@every 3m"', type: 'text' },
|
||||
hosts: { type: 'text' },
|
||||
'service.name': { type: 'text' },
|
||||
timeout: { type: 'text' },
|
||||
proxy_url: { type: 'text' },
|
||||
processors: { type: 'yaml' },
|
||||
proxy_use_local_resolver: { value: false, type: 'bool' },
|
||||
tags: { type: 'yaml' },
|
||||
'check.send': { type: 'text' },
|
||||
'check.receive': { type: 'text' },
|
||||
'ssl.certificate_authorities': { type: 'yaml' },
|
||||
'ssl.certificate': { type: 'yaml' },
|
||||
'ssl.key': { type: 'yaml' },
|
||||
'ssl.key_passphrase': { type: 'text' },
|
||||
'ssl.verification_mode': { type: 'text' },
|
||||
'ssl.supported_protocols': { type: 'yaml' },
|
||||
location_name: { value: 'Fleet managed', type: 'text' },
|
||||
id: { type: 'text' },
|
||||
origin: { type: 'text' },
|
||||
ipv4: { type: 'bool', value: true },
|
||||
ipv6: { type: 'bool', value: true },
|
||||
mode: { type: 'text' },
|
||||
},
|
||||
id: 'synthetics/tcp-tcp-2bfd7da0-22ed-11ed-8c6b-09a2d21dfbc3-27337270-22ed-11ed-8c6b-09a2d21dfbc3-default',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'synthetics/icmp',
|
||||
policy_template: 'synthetics',
|
||||
enabled: false,
|
||||
streams: [
|
||||
{
|
||||
enabled: false,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'icmp',
|
||||
},
|
||||
vars: {
|
||||
__ui: { type: 'yaml' },
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'icmp', type: 'text' },
|
||||
name: { type: 'text' },
|
||||
schedule: { value: '"@every 3m"', type: 'text' },
|
||||
wait: { value: '1s', type: 'text' },
|
||||
hosts: { type: 'text' },
|
||||
'service.name': { type: 'text' },
|
||||
timeout: { type: 'text' },
|
||||
tags: { type: 'yaml' },
|
||||
location_name: { value: 'Fleet managed', type: 'text' },
|
||||
id: { type: 'text' },
|
||||
origin: { type: 'text' },
|
||||
ipv4: { type: 'bool', value: true },
|
||||
ipv6: { type: 'bool', value: true },
|
||||
mode: { type: 'text' },
|
||||
},
|
||||
id: 'synthetics/icmp-icmp-2bfd7da0-22ed-11ed-8c6b-09a2d21dfbc3-27337270-22ed-11ed-8c6b-09a2d21dfbc3-default',
|
||||
},
|
||||
],
|
||||
},
|
||||
getBrowserInput(props),
|
||||
],
|
||||
is_managed: true,
|
||||
revision: 1,
|
||||
created_at: '2022-08-23T14:09:17.176Z',
|
||||
created_by: 'system',
|
||||
updated_at: '2022-08-23T14:09:17.176Z',
|
||||
updated_by: 'system',
|
||||
};
|
||||
};
|
||||
|
||||
export const getHttpInput = ({
|
||||
projectId,
|
||||
id,
|
||||
location,
|
||||
proxyUrl,
|
||||
isTLSEnabled,
|
||||
isBrowser,
|
||||
spaceId,
|
||||
namespace,
|
||||
name = 'check if title is present-Test private location 0',
|
||||
}: PolicyProps) => {
|
||||
const enabled = !isBrowser;
|
||||
const baseVars: PackagePolicyConfigRecord = {
|
||||
__ui: { type: 'yaml' },
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'http', type: 'text' },
|
||||
name: { type: 'text' },
|
||||
schedule: { value: '"@every 3m"', type: 'text' },
|
||||
urls: { type: 'text' },
|
||||
'service.name': { type: 'text' },
|
||||
timeout: { type: 'text' },
|
||||
max_redirects: { type: 'integer' },
|
||||
proxy_url: { type: 'text' },
|
||||
processors: { type: 'yaml' },
|
||||
proxy_headers: { type: 'yaml' },
|
||||
tags: { type: 'yaml' },
|
||||
username: { type: 'text' },
|
||||
password: { type: 'password' },
|
||||
'response.include_headers': { type: 'bool' },
|
||||
'response.include_body': { type: 'text' },
|
||||
'response.include_body_max_bytes': { type: 'text' },
|
||||
'check.request.method': { type: 'text' },
|
||||
'check.request.headers': { type: 'yaml' },
|
||||
'check.request.body': { type: 'yaml' },
|
||||
'check.response.status': { type: 'yaml' },
|
||||
'check.response.headers': { type: 'yaml' },
|
||||
'check.response.body.positive': { type: 'yaml' },
|
||||
'check.response.body.negative': { type: 'yaml' },
|
||||
'check.response.json': { type: 'yaml' },
|
||||
'ssl.certificate_authorities': { type: 'yaml' },
|
||||
'ssl.certificate': { type: 'yaml' },
|
||||
'ssl.key': { type: 'yaml' },
|
||||
'ssl.key_passphrase': { type: 'text' },
|
||||
'ssl.verification_mode': { type: 'text' },
|
||||
'ssl.supported_protocols': { type: 'yaml' },
|
||||
location_id: { value: 'fleet_managed', type: 'text' },
|
||||
location_name: { value: 'Fleet managed', type: 'text' },
|
||||
...commonVars,
|
||||
id: { type: 'text' },
|
||||
origin: { type: 'text' },
|
||||
ipv4: { type: 'bool', value: true },
|
||||
ipv6: { type: 'bool', value: true },
|
||||
mode: { type: 'text' },
|
||||
};
|
||||
|
||||
const enabledVars = {
|
||||
__ui: {
|
||||
value: `{"is_tls_enabled":${isTLSEnabled || false}}`,
|
||||
type: 'yaml',
|
||||
},
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'http', type: 'text' },
|
||||
name: { value: JSON.stringify(name), type: 'text' },
|
||||
schedule: { value: '"@every 5m"', type: 'text' },
|
||||
urls: { value: '"https://nextjs-test-synthetics.vercel.app/api/users"', type: 'text' },
|
||||
'service.name': { value: null, type: 'text' },
|
||||
timeout: { value: '180s', type: 'text' },
|
||||
max_redirects: { value: '3', type: 'integer' },
|
||||
processors: {
|
||||
type: 'yaml',
|
||||
value: JSON.stringify([
|
||||
{
|
||||
add_fields: {
|
||||
fields: {
|
||||
'monitor.fleet_managed': true,
|
||||
config_id: id,
|
||||
meta: { space_id: spaceId ?? 'default' },
|
||||
'monitor.project.name': projectId,
|
||||
'monitor.project.id': projectId,
|
||||
},
|
||||
target: '',
|
||||
},
|
||||
},
|
||||
]),
|
||||
},
|
||||
proxy_url: { value: proxyUrl ?? '"http://proxy.com"', type: 'text' },
|
||||
proxy_headers: { value: null, type: 'yaml' },
|
||||
tags: { value: '["tag1","tag2"]', type: 'yaml' },
|
||||
username: { value: '"test-username"', type: 'text' },
|
||||
password: { value: '"test"', type: 'password' },
|
||||
'response.include_headers': { value: true, type: 'bool' },
|
||||
'response.include_body': { value: 'never', type: 'text' },
|
||||
'response.include_body_max_bytes': { value: '1024', type: 'text' },
|
||||
'check.request.method': { value: '', type: 'text' },
|
||||
'check.request.headers': {
|
||||
value: '{"sampleHeader":"sampleHeaderValue"}',
|
||||
type: 'yaml',
|
||||
},
|
||||
'check.request.body': { value: '"testValue"', type: 'yaml' },
|
||||
'check.response.status': { value: '["200","201"]', type: 'yaml' },
|
||||
'check.response.headers': { value: null, type: 'yaml' },
|
||||
'check.response.body.positive': { value: null, type: 'yaml' },
|
||||
'check.response.body.negative': { value: null, type: 'yaml' },
|
||||
'check.response.json': { value: null, type: 'yaml' },
|
||||
'ssl.certificate_authorities': {
|
||||
value: isTLSEnabled ? '"t.string"' : null,
|
||||
type: 'yaml',
|
||||
},
|
||||
'ssl.certificate': { value: isTLSEnabled ? '"t.string"' : null, type: 'yaml' },
|
||||
'ssl.key': { value: isTLSEnabled ? '"t.string"' : null, type: 'yaml' },
|
||||
'ssl.key_passphrase': { value: isTLSEnabled ? 't.string' : null, type: 'text' },
|
||||
'ssl.verification_mode': { value: isTLSEnabled ? 'certificate' : null, type: 'text' },
|
||||
'ssl.supported_protocols': {
|
||||
value: isTLSEnabled ? '["TLSv1.1","TLSv1.2"]' : null,
|
||||
type: 'yaml',
|
||||
},
|
||||
location_id: {
|
||||
type: 'text',
|
||||
value: location.id ?? 'aaa3c150-f94d-11ed-9895-d36d5472fafd',
|
||||
},
|
||||
location_name: {
|
||||
value: JSON.stringify(location.name) ?? '"Test private location 0"',
|
||||
type: 'text',
|
||||
},
|
||||
...commonVars,
|
||||
id: { value: JSON.stringify(id), type: 'text' },
|
||||
origin: { value: projectId ? 'project' : 'ui', type: 'text' },
|
||||
ipv4: { type: 'bool', value: true },
|
||||
ipv6: { type: 'bool', value: true },
|
||||
mode: { type: 'text', value: 'any' },
|
||||
};
|
||||
|
||||
const compiledHttpStream = {
|
||||
__ui: {
|
||||
is_tls_enabled: isTLSEnabled || false,
|
||||
},
|
||||
type: 'http',
|
||||
name,
|
||||
id,
|
||||
origin: projectId ? 'project' : 'ui',
|
||||
enabled: true,
|
||||
urls: 'https://nextjs-test-synthetics.vercel.app/api/users',
|
||||
schedule: '@every 5m',
|
||||
timeout: '180s',
|
||||
max_redirects: 3,
|
||||
max_attempts: 2,
|
||||
proxy_url: proxyUrl ?? 'http://proxy.com',
|
||||
tags: ['tag1', 'tag2'],
|
||||
username: 'test-username',
|
||||
password: 'test',
|
||||
'run_from.geo.name': location?.name ?? 'Test private location 0',
|
||||
'run_from.id': location?.id ?? 'Test private location 0',
|
||||
'response.include_headers': true,
|
||||
'response.include_body': 'never',
|
||||
'response.include_body_max_bytes': 1024,
|
||||
'check.request.method': null,
|
||||
'check.request.headers': { sampleHeader: 'sampleHeaderValue' },
|
||||
'check.request.body': 'testValue',
|
||||
'check.response.status': ['200', '201'],
|
||||
ipv4: true,
|
||||
ipv6: true,
|
||||
mode: 'any',
|
||||
...(isTLSEnabled
|
||||
? {
|
||||
'ssl.certificate': 't.string',
|
||||
'ssl.certificate_authorities': 't.string',
|
||||
'ssl.key': 't.string',
|
||||
'ssl.key_passphrase': 't.string',
|
||||
'ssl.verification_mode': 'certificate',
|
||||
'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2'],
|
||||
}
|
||||
: {}),
|
||||
processors: [
|
||||
{
|
||||
add_fields: {
|
||||
fields: {
|
||||
config_id: id,
|
||||
meta: {
|
||||
space_id: spaceId ?? 'default',
|
||||
},
|
||||
'monitor.fleet_managed': true,
|
||||
...(projectId
|
||||
? { 'monitor.project.id': projectId, 'monitor.project.name': projectId }
|
||||
: {}),
|
||||
},
|
||||
target: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return {
|
||||
type: 'synthetics/http',
|
||||
policy_template: 'synthetics',
|
||||
enabled,
|
||||
streams: [
|
||||
{
|
||||
enabled,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'http',
|
||||
...(enabled
|
||||
? {
|
||||
elasticsearch: {
|
||||
privileges: {
|
||||
indices: ['auto_configure', 'create_doc', 'read'],
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
vars: enabled ? enabledVars : baseVars,
|
||||
id: 'synthetics/http-http-2bfd7da0-22ed-11ed-8c6b-09a2d21dfbc3-27337270-22ed-11ed-8c6b-09a2d21dfbc3-default',
|
||||
...(enabled ? { compiled_stream: compiledHttpStream } : {}),
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
export const getBrowserInput = ({ id, params, isBrowser, projectId }: PolicyProps) => {
|
||||
const compiledBrowser = isBrowser
|
||||
? {
|
||||
__ui: {
|
||||
script_source: { is_generated_script: false, file_name: '' },
|
||||
is_tls_enabled: false,
|
||||
},
|
||||
type: 'browser',
|
||||
name: 'Test HTTP Monitor 03',
|
||||
id,
|
||||
origin: 'ui',
|
||||
'run_from.id': 'Test private location 0',
|
||||
'run_from.geo.name': 'Test private location 0',
|
||||
enabled: true,
|
||||
schedule: '@every 3m',
|
||||
timeout: '16s',
|
||||
throttling: { download: 5, upload: 3, latency: 20 },
|
||||
tags: ['cookie-test', 'browser'],
|
||||
'source.inline.script':
|
||||
'step("Visit /users api route", async () => {\\n const response = await page.goto(\'https://nextjs-test-synthetics.vercel.app/api/users\');\\n expect(response.status()).toEqual(200);\\n});',
|
||||
...(params ? { params } : {}),
|
||||
screenshots: 'on',
|
||||
processors: [
|
||||
{
|
||||
add_fields: {
|
||||
target: '',
|
||||
fields: {
|
||||
'monitor.fleet_managed': true,
|
||||
config_id: id,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
: {
|
||||
__ui: null,
|
||||
type: 'browser',
|
||||
name: null,
|
||||
enabled: true,
|
||||
schedule: '@every 3m',
|
||||
'run_from.id': 'Fleet managed',
|
||||
'run_from.geo.name': 'Fleet managed',
|
||||
timeout: null,
|
||||
throttling: null,
|
||||
processors: [{ add_fields: { target: '', fields: { 'monitor.fleet_managed': true } } }],
|
||||
};
|
||||
|
||||
const browserVars = isBrowser
|
||||
? {
|
||||
__ui: {
|
||||
value:
|
||||
'{"script_source":{"is_generated_script":false,"file_name":""},"is_tls_enabled":false}',
|
||||
type: 'yaml',
|
||||
},
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'browser', type: 'text' },
|
||||
name: { value: 'Test HTTP Monitor 03', type: 'text' },
|
||||
schedule: { value: '"@every 3m"', type: 'text' },
|
||||
'service.name': { value: '', type: 'text' },
|
||||
timeout: { value: '16s', type: 'text' },
|
||||
tags: { value: '["cookie-test","browser"]', type: 'yaml' },
|
||||
'source.zip_url.url': { type: 'text' },
|
||||
'source.zip_url.username': { type: 'text' },
|
||||
'source.zip_url.folder': { type: 'text' },
|
||||
'source.zip_url.password': { type: 'password' },
|
||||
'source.inline.script': {
|
||||
value:
|
||||
'"step(\\"Visit /users api route\\", async () => {\\\\n const response = await page.goto(\'https://nextjs-test-synthetics.vercel.app/api/users\');\\\\n expect(response.status()).toEqual(200);\\\\n});"',
|
||||
type: 'yaml',
|
||||
},
|
||||
'source.project.content': { value: '', type: 'text' },
|
||||
params: { value: params ? JSON.stringify(params) : '', type: 'yaml' },
|
||||
playwright_options: { value: '', type: 'yaml' },
|
||||
screenshots: { value: 'on', type: 'text' },
|
||||
synthetics_args: { value: null, type: 'text' },
|
||||
ignore_https_errors: { value: false, type: 'bool' },
|
||||
'throttling.config': {
|
||||
value: JSON.stringify({ download: 5, upload: 3, latency: 20 }),
|
||||
type: 'text',
|
||||
},
|
||||
'filter_journeys.tags': { value: null, type: 'yaml' },
|
||||
'filter_journeys.match': { value: null, 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_id: {
|
||||
type: 'text',
|
||||
value: 'fleet_managed',
|
||||
},
|
||||
location_name: { value: 'Test private location 0', type: 'text' },
|
||||
id: { value: id, type: 'text' },
|
||||
origin: { value: 'ui', type: 'text' },
|
||||
}
|
||||
: {
|
||||
__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' },
|
||||
'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' },
|
||||
location_id: { value: 'Fleet managed', type: 'text' },
|
||||
id: { type: 'text' },
|
||||
origin: { type: 'text' },
|
||||
};
|
||||
|
||||
return {
|
||||
type: 'synthetics/browser',
|
||||
policy_template: 'synthetics',
|
||||
enabled: false,
|
||||
streams: [
|
||||
{
|
||||
enabled: true,
|
||||
data_stream: getDataStream('browser'),
|
||||
vars: browserVars,
|
||||
id: 'synthetics/browser-browser-2bfd7da0-22ed-11ed-8c6b-09a2d21dfbc3-27337270-22ed-11ed-8c6b-09a2d21dfbc3-default',
|
||||
compiled_stream: compiledBrowser,
|
||||
},
|
||||
{
|
||||
enabled: true,
|
||||
data_stream: getDataStream('browser.network'),
|
||||
id: 'synthetics/browser-browser.network-2bfd7da0-22ed-11ed-8c6b-09a2d21dfbc3-27337270-22ed-11ed-8c6b-09a2d21dfbc3-default',
|
||||
compiled_stream: {
|
||||
processors: [{ add_fields: { target: '', fields: { 'monitor.fleet_managed': true } } }],
|
||||
},
|
||||
},
|
||||
{
|
||||
enabled: true,
|
||||
data_stream: getDataStream('browser.screenshot'),
|
||||
id: 'synthetics/browser-browser.screenshot-2bfd7da0-22ed-11ed-8c6b-09a2d21dfbc3-27337270-22ed-11ed-8c6b-09a2d21dfbc3-default',
|
||||
compiled_stream: {
|
||||
processors: [{ add_fields: { target: '', fields: { 'monitor.fleet_managed': true } } }],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
export const getDataStream = (dataset: string) => ({
|
||||
dataset,
|
||||
type: 'synthetics',
|
||||
elasticsearch: {
|
||||
privileges: {
|
||||
indices: ['auto_configure', 'create_doc', 'read'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const omitIds = (policy: PackagePolicy) => {
|
||||
policy.inputs = sortBy(policy.inputs, 'type');
|
||||
|
||||
policy.inputs.forEach((input) => {
|
||||
input.streams = sortBy(input.streams, 'data_stream.dataset');
|
||||
input.streams.forEach((stream) => {
|
||||
stream.id = '';
|
||||
});
|
||||
});
|
||||
|
||||
return omit(policy, ignoreTestFields);
|
||||
};
|
||||
|
||||
export const comparePolicies = (aPolicy: PackagePolicy, bPolicy: PackagePolicy) => {
|
||||
const a = omitIds(aPolicy);
|
||||
const b = omitIds(bPolicy);
|
||||
|
||||
const aHttpInput = a.inputs?.find((input) => input.type === 'synthetics/http');
|
||||
const aTcpInput = b.inputs?.find((input) => input.type === 'synthetics/tcp');
|
||||
const aIcmpInput = b.inputs?.find((input) => input.type === 'synthetics/icmp');
|
||||
const aBrowserInput = b.inputs?.find((input) => input.type === 'synthetics/browser');
|
||||
|
||||
const bHttpInput = b.inputs?.find((input) => input.type === 'synthetics/http');
|
||||
const bTcpInput = b.inputs?.find((input) => input.type === 'synthetics/tcp');
|
||||
const bIcmpInput = b.inputs?.find((input) => input.type === 'synthetics/icmp');
|
||||
const bBrowserInput = b.inputs?.find((input) => input.type === 'synthetics/browser');
|
||||
|
||||
expect(aHttpInput).toEqual(bHttpInput);
|
||||
expect(aTcpInput).toEqual(bTcpInput);
|
||||
expect(aIcmpInput).toEqual(bIcmpInput);
|
||||
expect(aBrowserInput).toEqual(bBrowserInput);
|
||||
|
||||
// delete inputs to compare rest of policy
|
||||
delete a.inputs;
|
||||
delete b.inputs;
|
||||
|
||||
// delete package to compare rest of policy
|
||||
delete a.package;
|
||||
delete b.package;
|
||||
|
||||
expect(a).toEqual(b);
|
||||
};
|
||||
|
||||
export const ignoreTestFields = [
|
||||
'id',
|
||||
'name',
|
||||
'created_at',
|
||||
'created_by',
|
||||
'updated_at',
|
||||
'updated_by',
|
||||
'policy_id',
|
||||
'policy_ids',
|
||||
'version',
|
||||
'revision',
|
||||
];
|
|
@ -0,0 +1,803 @@
|
|||
/*
|
||||
* 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 { PackagePolicy } from '@kbn/fleet-plugin/common';
|
||||
import { INSTALLED_VERSION } from '../../../../services/synthetics_private_location';
|
||||
import { getDataStream } from './test_policy';
|
||||
|
||||
export const commonVars = {
|
||||
max_attempts: {
|
||||
type: 'integer',
|
||||
value: 2,
|
||||
},
|
||||
};
|
||||
|
||||
export const getTestProjectSyntheticsPolicyLightweight = (
|
||||
{
|
||||
name,
|
||||
inputs = {},
|
||||
configId,
|
||||
id,
|
||||
locationId,
|
||||
projectId = 'test-suite',
|
||||
locationName = 'Fleet Managed',
|
||||
namespace,
|
||||
}: {
|
||||
name?: string;
|
||||
inputs: Record<string, { value: string | boolean; type: string }>;
|
||||
configId: string;
|
||||
id: string;
|
||||
projectId?: string;
|
||||
locationId: string;
|
||||
locationName?: string;
|
||||
namespace?: string;
|
||||
} = {
|
||||
name: 'My Monitor 3',
|
||||
inputs: {},
|
||||
configId: '',
|
||||
id: '',
|
||||
locationId: 'fleet_managed',
|
||||
locationName: 'Fleet Managed',
|
||||
}
|
||||
): PackagePolicy => ({
|
||||
id: `4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
version: 'WzEzMDksMV0=',
|
||||
name: `4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-${locationName}`,
|
||||
namespace: namespace || undefined,
|
||||
package: { name: 'synthetics', title: 'Elastic Synthetics', version: INSTALLED_VERSION },
|
||||
enabled: true,
|
||||
policy_id: '46034710-0ba6-11ed-ba04-5f123b9faa8b',
|
||||
policy_ids: ['46034710-0ba6-11ed-ba04-5f123b9faa8b'],
|
||||
inputs: [
|
||||
{
|
||||
type: 'synthetics/http',
|
||||
policy_template: 'synthetics',
|
||||
enabled: true,
|
||||
streams: [
|
||||
{
|
||||
enabled: true,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'http',
|
||||
elasticsearch: {
|
||||
privileges: {
|
||||
indices: ['auto_configure', 'create_doc', 'read'],
|
||||
},
|
||||
},
|
||||
},
|
||||
vars: {
|
||||
__ui: {
|
||||
type: 'yaml',
|
||||
value: '{"is_tls_enabled":true}',
|
||||
},
|
||||
'check.request.body': {
|
||||
type: 'yaml',
|
||||
value: '"testGlobalParamValue"',
|
||||
},
|
||||
'check.request.headers': {
|
||||
type: 'yaml',
|
||||
value: '{"Content-Type":"application/x-www-form-urlencoded"}',
|
||||
},
|
||||
'check.request.method': {
|
||||
type: 'text',
|
||||
value: 'POST',
|
||||
},
|
||||
'check.response.body.negative': {
|
||||
type: 'yaml',
|
||||
value: null,
|
||||
},
|
||||
'check.response.body.positive': {
|
||||
type: 'yaml',
|
||||
value: '["testLocalParamsValue","saved"]',
|
||||
},
|
||||
'check.response.headers': {
|
||||
type: 'yaml',
|
||||
value: null,
|
||||
},
|
||||
'check.response.json': {
|
||||
type: 'yaml',
|
||||
value: '[{"description":"check status","expression":"foo.bar == \\"myValue\\""}]',
|
||||
},
|
||||
'check.response.status': {
|
||||
type: 'yaml',
|
||||
value: '["200"]',
|
||||
},
|
||||
enabled: {
|
||||
type: 'bool',
|
||||
value: false,
|
||||
},
|
||||
id: {
|
||||
type: 'text',
|
||||
value: JSON.stringify(id),
|
||||
},
|
||||
ipv4: {
|
||||
type: 'bool',
|
||||
value: true,
|
||||
},
|
||||
ipv6: {
|
||||
type: 'bool',
|
||||
value: true,
|
||||
},
|
||||
location_id: {
|
||||
type: 'text',
|
||||
value: locationId ?? 'fleet_managed',
|
||||
},
|
||||
location_name: {
|
||||
type: 'text',
|
||||
value: `"${locationName}"`,
|
||||
},
|
||||
max_redirects: {
|
||||
type: 'integer',
|
||||
value: '0',
|
||||
},
|
||||
...commonVars,
|
||||
mode: {
|
||||
type: 'text',
|
||||
value: 'any',
|
||||
},
|
||||
name: {
|
||||
type: 'text',
|
||||
value: JSON.stringify(name),
|
||||
},
|
||||
origin: {
|
||||
type: 'text',
|
||||
value: 'project',
|
||||
},
|
||||
password: {
|
||||
type: 'password',
|
||||
value: null,
|
||||
},
|
||||
processors: {
|
||||
type: 'yaml',
|
||||
value: JSON.stringify([
|
||||
{
|
||||
add_fields: {
|
||||
fields: {
|
||||
'monitor.fleet_managed': true,
|
||||
config_id: configId,
|
||||
'monitor.project.name': projectId,
|
||||
'monitor.project.id': projectId,
|
||||
meta: { space_id: 'default' },
|
||||
},
|
||||
target: '',
|
||||
},
|
||||
},
|
||||
]),
|
||||
},
|
||||
proxy_headers: {
|
||||
type: 'yaml',
|
||||
value: null,
|
||||
},
|
||||
proxy_url: {
|
||||
type: 'text',
|
||||
value: JSON.stringify('testGlobalParamOverwrite'),
|
||||
},
|
||||
'response.include_body': {
|
||||
type: 'text',
|
||||
value: 'always',
|
||||
},
|
||||
'response.include_body_max_bytes': {
|
||||
type: 'text',
|
||||
value: '900',
|
||||
},
|
||||
'response.include_headers': {
|
||||
type: 'bool',
|
||||
value: false,
|
||||
},
|
||||
schedule: {
|
||||
type: 'text',
|
||||
value: '"@every 60m"',
|
||||
},
|
||||
'service.name': {
|
||||
type: 'text',
|
||||
value: null,
|
||||
},
|
||||
'ssl.certificate': {
|
||||
type: 'yaml',
|
||||
value: null,
|
||||
},
|
||||
'ssl.certificate_authorities': {
|
||||
type: 'yaml',
|
||||
value: null,
|
||||
},
|
||||
'ssl.key': {
|
||||
type: 'yaml',
|
||||
value: null,
|
||||
},
|
||||
'ssl.key_passphrase': {
|
||||
type: 'text',
|
||||
value: null,
|
||||
},
|
||||
'ssl.supported_protocols': {
|
||||
type: 'yaml',
|
||||
value: '["TLSv1.1","TLSv1.2","TLSv1.3"]',
|
||||
},
|
||||
'ssl.verification_mode': {
|
||||
type: 'text',
|
||||
value: 'strict',
|
||||
},
|
||||
tags: {
|
||||
type: 'yaml',
|
||||
value: '["tag2","tag2"]',
|
||||
},
|
||||
timeout: {
|
||||
type: 'text',
|
||||
value: '80s',
|
||||
},
|
||||
type: {
|
||||
type: 'text',
|
||||
value: 'http',
|
||||
},
|
||||
urls: {
|
||||
type: 'text',
|
||||
value: '"http://localhost:9200"',
|
||||
},
|
||||
username: {
|
||||
type: 'text',
|
||||
value: null,
|
||||
},
|
||||
},
|
||||
compiled_stream: {
|
||||
__ui: {
|
||||
is_tls_enabled: true,
|
||||
},
|
||||
type: 'http',
|
||||
name,
|
||||
id,
|
||||
origin: 'project',
|
||||
enabled: false,
|
||||
urls: 'http://localhost:9200',
|
||||
schedule: '@every 60m',
|
||||
timeout: '80s',
|
||||
max_redirects: 0,
|
||||
max_attempts: 2,
|
||||
tags: ['tag2', 'tag2'],
|
||||
proxy_url: 'testGlobalParamOverwrite',
|
||||
'run_from.geo.name': locationName ?? 'Test private location 0',
|
||||
'run_from.id': locationId ?? 'Test private location 0',
|
||||
'response.include_headers': false,
|
||||
'response.include_body': 'always',
|
||||
'response.include_body_max_bytes': 900,
|
||||
'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'],
|
||||
'ssl.verification_mode': 'strict',
|
||||
'check.request.method': 'POST',
|
||||
'check.request.headers': { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
'check.response.body.positive': ['testLocalParamsValue', 'saved'],
|
||||
'check.response.json': [
|
||||
{
|
||||
description: 'check status',
|
||||
expression: 'foo.bar == "myValue"',
|
||||
},
|
||||
],
|
||||
'check.response.status': ['200'],
|
||||
'check.request.body': 'testGlobalParamValue',
|
||||
ipv4: true,
|
||||
ipv6: true,
|
||||
mode: 'any',
|
||||
processors: [
|
||||
{
|
||||
add_fields: {
|
||||
fields: {
|
||||
config_id: configId,
|
||||
'monitor.fleet_managed': true,
|
||||
'monitor.project.id': projectId,
|
||||
'monitor.project.name': projectId,
|
||||
meta: { space_id: 'default' },
|
||||
},
|
||||
target: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
id: `synthetics/http-http-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'synthetics/tcp',
|
||||
policy_template: 'synthetics',
|
||||
enabled: false,
|
||||
streams: [
|
||||
{
|
||||
enabled: false,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'tcp',
|
||||
},
|
||||
vars: {
|
||||
__ui: { type: 'yaml' },
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'tcp', type: 'text' },
|
||||
name: { type: 'text' },
|
||||
schedule: { value: '"@every 3m"', type: 'text' },
|
||||
hosts: { type: 'text' },
|
||||
'service.name': { type: 'text' },
|
||||
timeout: { type: 'text' },
|
||||
proxy_url: { type: 'text' },
|
||||
proxy_use_local_resolver: { value: false, type: 'bool' },
|
||||
tags: { type: 'yaml' },
|
||||
'check.send': { type: 'text' },
|
||||
'check.receive': { type: 'text' },
|
||||
'ssl.certificate_authorities': { type: 'yaml' },
|
||||
'ssl.certificate': { type: 'yaml' },
|
||||
'ssl.key': { type: 'yaml' },
|
||||
'ssl.key_passphrase': { type: 'text' },
|
||||
'ssl.verification_mode': { type: 'text' },
|
||||
'ssl.supported_protocols': { type: 'yaml' },
|
||||
location_id: { value: 'fleet_managed', type: 'text' },
|
||||
location_name: { value: 'Fleet managed', type: 'text' },
|
||||
...commonVars,
|
||||
id: { type: 'text' },
|
||||
origin: { type: 'text' },
|
||||
ipv4: { type: 'bool', value: true },
|
||||
ipv6: { type: 'bool', value: true },
|
||||
mode: { type: 'text' },
|
||||
},
|
||||
id: `synthetics/tcp-tcp-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'synthetics/icmp',
|
||||
policy_template: 'synthetics',
|
||||
enabled: false,
|
||||
streams: [
|
||||
{
|
||||
enabled: false,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'icmp',
|
||||
},
|
||||
vars: {
|
||||
__ui: { type: 'yaml' },
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'icmp', type: 'text' },
|
||||
name: { type: 'text' },
|
||||
schedule: { value: '"@every 3m"', type: 'text' },
|
||||
wait: { value: '1s', type: 'text' },
|
||||
hosts: { type: 'text' },
|
||||
'service.name': { type: 'text' },
|
||||
timeout: { type: 'text' },
|
||||
tags: { type: 'yaml' },
|
||||
location_id: { value: 'fleet_managed', type: 'text' },
|
||||
location_name: { value: 'Fleet managed', type: 'text' },
|
||||
...commonVars,
|
||||
id: { type: 'text' },
|
||||
origin: { type: 'text' },
|
||||
ipv4: { type: 'bool', value: true },
|
||||
ipv6: { type: 'bool', value: true },
|
||||
mode: { type: 'text' },
|
||||
},
|
||||
id: `synthetics/icmp-icmp-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'synthetics/browser',
|
||||
policy_template: 'synthetics',
|
||||
enabled: false,
|
||||
streams: [
|
||||
{
|
||||
enabled: true,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'browser',
|
||||
elasticsearch: {
|
||||
privileges: {
|
||||
indices: ['auto_configure', 'create_doc', 'read'],
|
||||
},
|
||||
},
|
||||
},
|
||||
vars: {
|
||||
__ui: {
|
||||
type: 'yaml',
|
||||
},
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'browser', type: 'text' },
|
||||
name: { type: 'text' },
|
||||
schedule: { value: JSON.stringify('@every 3m'), type: 'text' },
|
||||
'service.name': { type: 'text' },
|
||||
timeout: { type: 'text' },
|
||||
tags: { type: 'yaml' },
|
||||
'source.zip_url.url': { type: 'text' },
|
||||
'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_id: { value: 'fleet_managed', type: 'text' },
|
||||
location_name: { value: 'Fleet managed', type: 'text' },
|
||||
...commonVars,
|
||||
id: { type: 'text' },
|
||||
origin: { type: 'text' },
|
||||
...inputs,
|
||||
},
|
||||
id: `synthetics/browser-browser-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
compiled_stream: {
|
||||
__ui: null,
|
||||
type: 'browser',
|
||||
name: null,
|
||||
enabled: true,
|
||||
schedule: '@every 3m',
|
||||
timeout: null,
|
||||
throttling: null,
|
||||
processors: [
|
||||
{
|
||||
add_fields: {
|
||||
target: '',
|
||||
fields: {
|
||||
'monitor.fleet_managed': true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
'run_from.geo.name': 'Fleet managed',
|
||||
'run_from.id': 'Fleet managed',
|
||||
...Object.keys(inputs).reduce((acc: Record<string, unknown>, key) => {
|
||||
acc[key] = inputs[key].value;
|
||||
return acc;
|
||||
}, {}),
|
||||
},
|
||||
},
|
||||
{
|
||||
enabled: true,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'browser.network',
|
||||
elasticsearch: {
|
||||
privileges: {
|
||||
indices: ['auto_configure', 'create_doc', 'read'],
|
||||
},
|
||||
},
|
||||
},
|
||||
id: `synthetics/browser-browser.network-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
compiled_stream: {
|
||||
processors: [{ add_fields: { target: '', fields: { 'monitor.fleet_managed': true } } }],
|
||||
},
|
||||
},
|
||||
{
|
||||
enabled: true,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'browser.screenshot',
|
||||
elasticsearch: {
|
||||
privileges: {
|
||||
indices: ['auto_configure', 'create_doc', 'read'],
|
||||
},
|
||||
},
|
||||
},
|
||||
id: `synthetics/browser-browser.screenshot-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
compiled_stream: {
|
||||
processors: [{ add_fields: { target: '', fields: { 'monitor.fleet_managed': true } } }],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
is_managed: true,
|
||||
revision: 1,
|
||||
created_at: '2022-08-23T13:52:42.531Z',
|
||||
created_by: 'system',
|
||||
updated_at: '2022-08-23T13:52:42.531Z',
|
||||
updated_by: 'system',
|
||||
});
|
||||
|
||||
export const getTestProjectSyntheticsPolicy = (
|
||||
{
|
||||
name,
|
||||
inputs = {},
|
||||
configId,
|
||||
id,
|
||||
projectId = 'test-suite',
|
||||
locationId,
|
||||
locationName = 'Fleet Managed',
|
||||
namespace,
|
||||
}: {
|
||||
name?: string;
|
||||
inputs: Record<string, { value: string | boolean; type: string }>;
|
||||
configId: string;
|
||||
id: string;
|
||||
projectId?: string;
|
||||
locationName?: string;
|
||||
locationId: string;
|
||||
namespace?: string;
|
||||
} = {
|
||||
name: 'check if title is present-Test private location 0',
|
||||
inputs: {},
|
||||
configId: '',
|
||||
id: '',
|
||||
locationId: 'fleet_managed',
|
||||
locationName: 'Fleet Managed',
|
||||
}
|
||||
): PackagePolicy => ({
|
||||
id: `4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
version: 'WzEzMDksMV0=',
|
||||
name: `4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-Test private location 0`,
|
||||
namespace: namespace || undefined,
|
||||
package: { name: 'synthetics', title: 'Elastic Synthetics', version: INSTALLED_VERSION },
|
||||
enabled: true,
|
||||
policy_id: '46034710-0ba6-11ed-ba04-5f123b9faa8b',
|
||||
policy_ids: ['46034710-0ba6-11ed-ba04-5f123b9faa8b'],
|
||||
inputs: [
|
||||
{
|
||||
type: 'synthetics/http',
|
||||
policy_template: 'synthetics',
|
||||
enabled: false,
|
||||
streams: [
|
||||
{
|
||||
enabled: false,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'http',
|
||||
},
|
||||
vars: {
|
||||
__ui: { type: 'yaml' },
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'http', type: 'text' },
|
||||
name: { type: 'text' },
|
||||
schedule: { value: '"@every 3m"', type: 'text' },
|
||||
urls: { type: 'text' },
|
||||
'service.name': { type: 'text' },
|
||||
timeout: { type: 'text' },
|
||||
max_redirects: { type: 'integer' },
|
||||
proxy_url: { type: 'text' },
|
||||
processors: { type: 'yaml' },
|
||||
proxy_headers: { type: 'yaml' },
|
||||
tags: { type: 'yaml' },
|
||||
username: { type: 'text' },
|
||||
password: { type: 'password' },
|
||||
'response.include_headers': { type: 'bool' },
|
||||
'response.include_body': { type: 'text' },
|
||||
'response.include_body_max_bytes': { type: 'text' },
|
||||
'check.request.method': { type: 'text' },
|
||||
'check.request.headers': { type: 'yaml' },
|
||||
'check.request.body': { type: 'yaml' },
|
||||
'check.response.status': { type: 'yaml' },
|
||||
'check.response.headers': { type: 'yaml' },
|
||||
'check.response.body.positive': { type: 'yaml' },
|
||||
'check.response.body.negative': { type: 'yaml' },
|
||||
'check.response.json': { type: 'yaml' },
|
||||
'ssl.certificate_authorities': { type: 'yaml' },
|
||||
'ssl.certificate': { type: 'yaml' },
|
||||
'ssl.key': { type: 'yaml' },
|
||||
'ssl.key_passphrase': { type: 'text' },
|
||||
'ssl.verification_mode': { type: 'text' },
|
||||
'ssl.supported_protocols': { type: 'yaml' },
|
||||
location_id: { value: 'fleet_managed', type: 'text' },
|
||||
location_name: { value: 'Fleet managed', type: 'text' },
|
||||
...commonVars,
|
||||
id: { type: 'text' },
|
||||
origin: { type: 'text' },
|
||||
ipv4: { type: 'bool', value: true },
|
||||
ipv6: { type: 'bool', value: true },
|
||||
mode: { type: 'text' },
|
||||
},
|
||||
id: `synthetics/http-http-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'synthetics/tcp',
|
||||
policy_template: 'synthetics',
|
||||
enabled: false,
|
||||
streams: [
|
||||
{
|
||||
enabled: false,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'tcp',
|
||||
},
|
||||
vars: {
|
||||
__ui: { type: 'yaml' },
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'tcp', type: 'text' },
|
||||
name: { type: 'text' },
|
||||
schedule: { value: '"@every 3m"', type: 'text' },
|
||||
hosts: { type: 'text' },
|
||||
'service.name': { type: 'text' },
|
||||
timeout: { type: 'text' },
|
||||
proxy_url: { type: 'text' },
|
||||
proxy_use_local_resolver: { value: false, type: 'bool' },
|
||||
tags: { type: 'yaml' },
|
||||
'check.send': { type: 'text' },
|
||||
'check.receive': { type: 'text' },
|
||||
'ssl.certificate_authorities': { type: 'yaml' },
|
||||
'ssl.certificate': { type: 'yaml' },
|
||||
'ssl.key': { type: 'yaml' },
|
||||
'ssl.key_passphrase': { type: 'text' },
|
||||
'ssl.verification_mode': { type: 'text' },
|
||||
'ssl.supported_protocols': { type: 'yaml' },
|
||||
location_name: { value: 'Fleet managed', type: 'text' },
|
||||
...commonVars,
|
||||
id: { type: 'text' },
|
||||
origin: { type: 'text' },
|
||||
ipv4: { type: 'bool', value: true },
|
||||
ipv6: { type: 'bool', value: true },
|
||||
mode: { type: 'text' },
|
||||
},
|
||||
id: `synthetics/tcp-tcp-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'synthetics/icmp',
|
||||
policy_template: 'synthetics',
|
||||
enabled: false,
|
||||
streams: [
|
||||
{
|
||||
enabled: false,
|
||||
data_stream: {
|
||||
type: 'synthetics',
|
||||
dataset: 'icmp',
|
||||
},
|
||||
vars: {
|
||||
__ui: { type: 'yaml' },
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'icmp', type: 'text' },
|
||||
name: { type: 'text' },
|
||||
schedule: { value: '"@every 3m"', type: 'text' },
|
||||
wait: { value: '1s', type: 'text' },
|
||||
hosts: { type: 'text' },
|
||||
'service.name': { type: 'text' },
|
||||
timeout: { type: 'text' },
|
||||
tags: { type: 'yaml' },
|
||||
location_name: { value: 'Fleet managed', type: 'text' },
|
||||
max_attempts: {
|
||||
type: 'integer',
|
||||
value: 2,
|
||||
},
|
||||
id: { type: 'text' },
|
||||
origin: { type: 'text' },
|
||||
ipv4: { type: 'bool', value: true },
|
||||
ipv6: { type: 'bool', value: true },
|
||||
mode: { type: 'text' },
|
||||
},
|
||||
id: `synthetics/icmp-icmp-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'synthetics/browser',
|
||||
policy_template: 'synthetics',
|
||||
enabled: true,
|
||||
streams: [
|
||||
{
|
||||
enabled: true,
|
||||
data_stream: getDataStream('browser'),
|
||||
vars: {
|
||||
__ui: {
|
||||
value: '{"script_source":{"is_generated_script":false,"file_name":""}}',
|
||||
type: 'yaml',
|
||||
},
|
||||
enabled: { value: true, type: 'bool' },
|
||||
type: { value: 'browser', type: 'text' },
|
||||
name: { value: '"check if title is present"', type: 'text' },
|
||||
schedule: { value: '"@every 10m"', type: 'text' },
|
||||
'service.name': { value: null, type: 'text' },
|
||||
timeout: { value: null, type: 'text' },
|
||||
tags: { value: null, type: 'yaml' },
|
||||
'source.zip_url.url': { type: 'text' },
|
||||
'source.zip_url.username': { type: 'text' },
|
||||
'source.zip_url.folder': { type: 'text' },
|
||||
'source.zip_url.password': { type: 'password' },
|
||||
'source.inline.script': { value: null, type: 'yaml' },
|
||||
'source.project.content': {
|
||||
value:
|
||||
'UEsDBBQACAAIAON5qVQAAAAAAAAAAAAAAAAfAAAAZXhhbXBsZXMvdG9kb3MvYmFzaWMuam91cm5leS50c22Q0WrDMAxF3/sVF7MHB0LMXlc6RvcN+wDPVWNviW0sdUsp/fe5SSiD7UFCWFfHujIGlpnkybwxFTZfoY/E3hsaLEtwhs9RPNWKDU12zAOxkXRIbN4tB9d9pFOJdO6EN2HMqQguWN9asFBuQVMmJ7jiWNII9fIXrbabdUYr58l9IhwhQQZCYORCTFFUC31Btj21NRc7Mq4Nds+4bDD/pNVgT9F52Jyr2Fa+g75LAPttg8yErk+S9ELpTmVotlVwnfNCuh2lepl3+JflUmSBJ3uggt1v9INW/lHNLKze9dJe1J3QJK8pSvWkm6aTtCet5puq+x63+AFQSwcIAPQ3VfcAAACcAQAAUEsBAi0DFAAIAAgA43mpVAD0N1X3AAAAnAEAAB8AAAAAAAAAAAAgAKSBAAAAAGV4YW1wbGVzL3RvZG9zL2Jhc2ljLmpvdXJuZXkudHNQSwUGAAAAAAEAAQBNAAAARAEAAAAA',
|
||||
type: 'text',
|
||||
},
|
||||
params: {
|
||||
value:
|
||||
'{"testGlobalParam2":"testGlobalParamValue2","testGlobalParam":"testGlobalParamValue"}',
|
||||
type: 'yaml',
|
||||
},
|
||||
playwright_options: {
|
||||
value: '{"headless":true,"chromiumSandbox":false}',
|
||||
type: 'yaml',
|
||||
},
|
||||
screenshots: { value: 'on', type: 'text' },
|
||||
synthetics_args: { value: null, type: 'text' },
|
||||
ignore_https_errors: { value: false, type: 'bool' },
|
||||
'throttling.config': {
|
||||
value: JSON.stringify({ download: 5, upload: 3, latency: 20 }),
|
||||
type: 'text',
|
||||
},
|
||||
'filter_journeys.tags': { value: null, type: 'yaml' },
|
||||
'filter_journeys.match': { value: '"check if title is present"', 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: 'Test private location 0', type: 'text' },
|
||||
...commonVars,
|
||||
location_id: { value: 'fleet_managed', type: 'text' },
|
||||
id: { value: id, type: 'text' },
|
||||
origin: { value: 'project', type: 'text' },
|
||||
...inputs,
|
||||
},
|
||||
id: `synthetics/browser-browser-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
compiled_stream: {
|
||||
__ui: {
|
||||
script_source: { is_generated_script: false, file_name: '' },
|
||||
},
|
||||
type: 'browser',
|
||||
name: 'check if title is present',
|
||||
id,
|
||||
origin: 'project',
|
||||
enabled: true,
|
||||
schedule: '@every 10m',
|
||||
'run_from.geo.name': locationName,
|
||||
'run_from.id': locationId,
|
||||
timeout: null,
|
||||
throttling: { download: 5, upload: 3, latency: 20 },
|
||||
'source.project.content':
|
||||
'UEsDBBQACAAIAON5qVQAAAAAAAAAAAAAAAAfAAAAZXhhbXBsZXMvdG9kb3MvYmFzaWMuam91cm5leS50c22Q0WrDMAxF3/sVF7MHB0LMXlc6RvcN+wDPVWNviW0sdUsp/fe5SSiD7UFCWFfHujIGlpnkybwxFTZfoY/E3hsaLEtwhs9RPNWKDU12zAOxkXRIbN4tB9d9pFOJdO6EN2HMqQguWN9asFBuQVMmJ7jiWNII9fIXrbabdUYr58l9IhwhQQZCYORCTFFUC31Btj21NRc7Mq4Nds+4bDD/pNVgT9F52Jyr2Fa+g75LAPttg8yErk+S9ELpTmVotlVwnfNCuh2lepl3+JflUmSBJ3uggt1v9INW/lHNLKze9dJe1J3QJK8pSvWkm6aTtCet5puq+x63+AFQSwcIAPQ3VfcAAACcAQAAUEsBAi0DFAAIAAgA43mpVAD0N1X3AAAAnAEAAB8AAAAAAAAAAAAgAKSBAAAAAGV4YW1wbGVzL3RvZG9zL2Jhc2ljLmpvdXJuZXkudHNQSwUGAAAAAAEAAQBNAAAARAEAAAAA',
|
||||
playwright_options: { headless: true, chromiumSandbox: false },
|
||||
screenshots: 'on',
|
||||
'filter_journeys.match': 'check if title is present',
|
||||
params: {
|
||||
testGlobalParam: 'testGlobalParamValue',
|
||||
testGlobalParam2: 'testGlobalParamValue2',
|
||||
},
|
||||
...Object.keys(inputs).reduce((acc: Record<string, unknown>, key) => {
|
||||
acc[key] = inputs[key].value;
|
||||
return acc;
|
||||
}, {}),
|
||||
},
|
||||
},
|
||||
{
|
||||
enabled: true,
|
||||
data_stream: getDataStream('browser.network'),
|
||||
id: `synthetics/browser-browser.network-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
compiled_stream: {
|
||||
processors: [{ add_fields: { target: '', fields: { 'monitor.fleet_managed': true } } }],
|
||||
},
|
||||
},
|
||||
{
|
||||
enabled: true,
|
||||
data_stream: getDataStream('browser.screenshot'),
|
||||
id: `synthetics/browser-browser.screenshot-4b6abc6c-118b-4d93-a489-1135500d09f1-${projectId}-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3`,
|
||||
compiled_stream: {
|
||||
processors: [{ add_fields: { target: '', fields: { 'monitor.fleet_managed': true } } }],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
is_managed: true,
|
||||
revision: 1,
|
||||
created_at: '2022-08-23T13:52:42.531Z',
|
||||
created_by: 'system',
|
||||
updated_at: '2022-08-23T13:52:42.531Z',
|
||||
updated_by: 'system',
|
||||
});
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* 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 { v4 as uuidv4 } from 'uuid';
|
||||
import expect from 'expect';
|
||||
import { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import {
|
||||
MonitorFields,
|
||||
EncryptedSyntheticsSavedMonitor,
|
||||
ProjectMonitorsRequest,
|
||||
PrivateLocation,
|
||||
} from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('SyntheticsSuggestions', function () {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const samlAuth = getService('samlAuth');
|
||||
const privateLocationsTestService = new PrivateLocationTestService(getService);
|
||||
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
|
||||
let projectMonitors: ProjectMonitorsRequest;
|
||||
let _monitors: MonitorFields[];
|
||||
let monitors: MonitorFields[];
|
||||
let editorUser: RoleCredentials;
|
||||
let privateLocation: PrivateLocation;
|
||||
|
||||
const setUniqueIds = (request: ProjectMonitorsRequest) => {
|
||||
return {
|
||||
...request,
|
||||
monitors: request.monitors.map((monitor) => ({
|
||||
...monitor,
|
||||
id: uuidv4(),
|
||||
locations: [],
|
||||
privateLocations: [privateLocation.label],
|
||||
})),
|
||||
};
|
||||
};
|
||||
|
||||
const saveMonitor = async (monitor: MonitorFields) => {
|
||||
const res = await supertest
|
||||
.post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(monitor);
|
||||
|
||||
return res.body as EncryptedSyntheticsSavedMonitor;
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.clean({
|
||||
types: [
|
||||
syntheticsMonitorType,
|
||||
'ingest-agent-policies',
|
||||
'ingest-package-policies',
|
||||
'synthetics-private-location',
|
||||
],
|
||||
});
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
privateLocation = await privateLocationsTestService.addTestPrivateLocation(SPACE_ID);
|
||||
_monitors = [getFixtureJson('http_monitor')].map((monitor) => ({
|
||||
...monitor,
|
||||
locations: [privateLocation],
|
||||
}));
|
||||
projectMonitors = setUniqueIds({
|
||||
monitors: getFixtureJson('project_icmp_monitor')
|
||||
.monitors.slice(0, 2)
|
||||
.map((monitor: any) => ({
|
||||
...monitor,
|
||||
privateLocations: [privateLocation.label],
|
||||
locations: [],
|
||||
})),
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await kibanaServer.savedObjects.clean({
|
||||
types: [syntheticsMonitorType, 'ingest-package-policies'],
|
||||
});
|
||||
|
||||
monitors = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
monitors.push({
|
||||
..._monitors[0],
|
||||
locations: [privateLocation],
|
||||
name: `${_monitors[0].name} ${i}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await kibanaServer.spaces.delete(SPACE_ID);
|
||||
});
|
||||
|
||||
it('returns the suggestions', async () => {
|
||||
const project = `test-project-${uuidv4()}`;
|
||||
await supertest
|
||||
.put(
|
||||
`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace(
|
||||
'{projectName}',
|
||||
project
|
||||
)}`
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(projectMonitors)
|
||||
.expect(200);
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
await saveMonitor(monitors[i]);
|
||||
}
|
||||
const apiResponse = await supertest
|
||||
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SUGGESTIONS}`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
expect(apiResponse.body).toEqual({
|
||||
locations: [
|
||||
{
|
||||
count: 22,
|
||||
label: privateLocation.label,
|
||||
value: privateLocation.id,
|
||||
},
|
||||
],
|
||||
monitorIds: expect.arrayContaining([
|
||||
...monitors.map((monitor) => ({
|
||||
count: 1,
|
||||
label: monitor.name,
|
||||
value: expect.any(String),
|
||||
})),
|
||||
...projectMonitors.monitors.slice(0, 2).map((monitor) => ({
|
||||
count: 1,
|
||||
label: monitor.name,
|
||||
value: expect.any(String),
|
||||
})),
|
||||
]),
|
||||
monitorTypes: [
|
||||
{
|
||||
count: 20,
|
||||
label: 'http',
|
||||
value: 'http',
|
||||
},
|
||||
{
|
||||
count: 2,
|
||||
label: 'icmp',
|
||||
value: 'icmp',
|
||||
},
|
||||
],
|
||||
projects: [
|
||||
{
|
||||
count: 2,
|
||||
label: project,
|
||||
value: project,
|
||||
},
|
||||
],
|
||||
tags: expect.arrayContaining([
|
||||
{
|
||||
count: 21,
|
||||
label: 'tag1',
|
||||
value: 'tag1',
|
||||
},
|
||||
{
|
||||
count: 21,
|
||||
label: 'tag2',
|
||||
value: 'tag2',
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
label: 'org:google',
|
||||
value: 'org:google',
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
label: 'service:smtp',
|
||||
value: 'service:smtp',
|
||||
},
|
||||
]),
|
||||
});
|
||||
});
|
||||
|
||||
it('handles query params for projects', async () => {
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
await saveMonitor(monitors[i]);
|
||||
}
|
||||
const project = `test-project-${uuidv4()}`;
|
||||
await supertest
|
||||
.put(
|
||||
`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace(
|
||||
'{projectName}',
|
||||
project
|
||||
)}`
|
||||
)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(projectMonitors)
|
||||
.expect(200);
|
||||
|
||||
const apiResponse = await supertest
|
||||
.get(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SUGGESTIONS}`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.query({
|
||||
projects: [project],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body).toEqual({
|
||||
locations: [
|
||||
{
|
||||
count: 2,
|
||||
label: privateLocation.label,
|
||||
value: privateLocation.id,
|
||||
},
|
||||
],
|
||||
monitorIds: expect.arrayContaining(
|
||||
projectMonitors.monitors.map((monitor) => ({
|
||||
count: 1,
|
||||
label: monitor.name,
|
||||
value: expect.any(String),
|
||||
}))
|
||||
),
|
||||
monitorTypes: [
|
||||
{
|
||||
count: 2,
|
||||
label: 'icmp',
|
||||
value: 'icmp',
|
||||
},
|
||||
],
|
||||
projects: [
|
||||
{
|
||||
count: 2,
|
||||
label: project,
|
||||
value: project,
|
||||
},
|
||||
],
|
||||
tags: expect.arrayContaining([
|
||||
{
|
||||
count: 1,
|
||||
label: 'tag1',
|
||||
value: 'tag1',
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
label: 'tag2',
|
||||
value: 'tag2',
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
label: 'org:google',
|
||||
value: 'org:google',
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
label: 'service:smtp',
|
||||
value: 'service:smtp',
|
||||
},
|
||||
]),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* 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 { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import {
|
||||
ConfigKey,
|
||||
HTTPFields,
|
||||
LocationStatus,
|
||||
PrivateLocation,
|
||||
ServiceLocation,
|
||||
SyntheticsParams,
|
||||
} from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import { PackagePolicy } from '@kbn/fleet-plugin/common';
|
||||
import expect from '@kbn/expect';
|
||||
import { syntheticsParamType } from '@kbn/synthetics-plugin/common/types/saved_objects';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { PrivateLocationTestService } from '../../../services/synthetics_private_location';
|
||||
import { comparePolicies, getTestSyntheticsPolicy } from './sample_data/test_policy';
|
||||
import { addMonitorAPIHelper, omitMonitorKeys } from './create_monitor';
|
||||
|
||||
export const LOCAL_LOCATION = {
|
||||
id: 'dev',
|
||||
label: 'Dev Service',
|
||||
geo: {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
isServiceManaged: true,
|
||||
};
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe.skip('SyncGlobalParams', function () {
|
||||
this.tags('skipCloud');
|
||||
const supertestAPI = getService('supertestWithoutAuth');
|
||||
const supertestWithAuth = getService('supertest');
|
||||
const kServer = getService('kibanaServer');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
let testFleetPolicyID: string;
|
||||
let _browserMonitorJson: HTTPFields;
|
||||
let browserMonitorJson: HTTPFields;
|
||||
|
||||
let _httpMonitorJson: HTTPFields;
|
||||
let httpMonitorJson: HTTPFields;
|
||||
|
||||
let newMonitorId: string;
|
||||
let newHttpMonitorId: string;
|
||||
let privateLocations: PrivateLocation[] = [];
|
||||
|
||||
let editorUser: RoleCredentials;
|
||||
|
||||
const testPrivateLocations = new PrivateLocationTestService(getService);
|
||||
const params: Record<string, string> = {};
|
||||
|
||||
const addMonitorAPI = async (monitor: any, statusCode = 200) => {
|
||||
return addMonitorAPIHelper(supertestAPI, monitor, statusCode, editorUser, samlAuth);
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
await kServer.savedObjects.cleanStandardList();
|
||||
await testPrivateLocations.installSyntheticsPackage();
|
||||
|
||||
_browserMonitorJson = getFixtureJson('browser_monitor');
|
||||
_httpMonitorJson = getFixtureJson('http_monitor');
|
||||
await kServer.savedObjects.clean({ types: [syntheticsParamType] });
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
browserMonitorJson = _browserMonitorJson;
|
||||
httpMonitorJson = _httpMonitorJson;
|
||||
});
|
||||
|
||||
const testPolicyName = 'Fleet test server policy' + Date.now();
|
||||
|
||||
it('adds a test fleet policy', async () => {
|
||||
const apiResponse = await testPrivateLocations.addFleetPolicy(testPolicyName);
|
||||
testFleetPolicyID = apiResponse.body.item.id;
|
||||
});
|
||||
|
||||
it('add a test private location', async () => {
|
||||
privateLocations = await testPrivateLocations.setTestLocations([testFleetPolicyID]);
|
||||
|
||||
const apiResponse = await supertestAPI.get(SYNTHETICS_API_URLS.SERVICE_LOCATIONS);
|
||||
|
||||
const testLocations: Array<PrivateLocation | ServiceLocation> = [
|
||||
{
|
||||
id: 'dev',
|
||||
label: 'Dev Service',
|
||||
geo: { lat: 0, lon: 0 },
|
||||
url: 'mockDevUrl',
|
||||
isServiceManaged: true,
|
||||
status: LocationStatus.EXPERIMENTAL,
|
||||
isInvalid: false,
|
||||
},
|
||||
{
|
||||
id: 'dev2',
|
||||
label: 'Dev Service 2',
|
||||
geo: { lat: 0, lon: 0 },
|
||||
url: 'mockDevUrl',
|
||||
isServiceManaged: true,
|
||||
status: LocationStatus.EXPERIMENTAL,
|
||||
isInvalid: false,
|
||||
},
|
||||
{
|
||||
id: testFleetPolicyID,
|
||||
isInvalid: false,
|
||||
isServiceManaged: false,
|
||||
label: privateLocations[0].label,
|
||||
geo: {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
agentPolicyId: testFleetPolicyID,
|
||||
},
|
||||
];
|
||||
|
||||
expect(apiResponse.body.locations).eql(testLocations);
|
||||
});
|
||||
|
||||
it('adds a monitor in private location', async () => {
|
||||
const newMonitor = browserMonitorJson;
|
||||
|
||||
const pvtLoc = {
|
||||
id: testFleetPolicyID,
|
||||
agentPolicyId: testFleetPolicyID,
|
||||
label: privateLocations[0].label,
|
||||
isServiceManaged: false,
|
||||
geo: {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
};
|
||||
|
||||
newMonitor.locations.push(pvtLoc);
|
||||
|
||||
const apiResponse = await addMonitorAPI(newMonitor);
|
||||
|
||||
expect(apiResponse.body).eql(
|
||||
omitMonitorKeys({
|
||||
...newMonitor,
|
||||
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
|
||||
[ConfigKey.CONFIG_ID]: apiResponse.body.id,
|
||||
locations: [LOCAL_LOCATION, pvtLoc],
|
||||
})
|
||||
);
|
||||
newMonitorId = apiResponse.rawBody.id;
|
||||
});
|
||||
|
||||
it('added an integration for previously added monitor', async () => {
|
||||
const apiResponse = await supertestAPI.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy = apiResponse.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default'
|
||||
);
|
||||
|
||||
expect(packagePolicy?.policy_id).eql(
|
||||
testFleetPolicyID,
|
||||
JSON.stringify({ testFleetPolicyID, newMonitorId })
|
||||
);
|
||||
|
||||
comparePolicies(
|
||||
packagePolicy,
|
||||
getTestSyntheticsPolicy({
|
||||
name: browserMonitorJson.name,
|
||||
id: newMonitorId,
|
||||
isBrowser: true,
|
||||
location: { id: testFleetPolicyID },
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('adds a test param', async () => {
|
||||
const apiResponse = await supertestAPI
|
||||
.post(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ key: 'test', value: 'http://proxy.com' });
|
||||
|
||||
expect(apiResponse.status).eql(200);
|
||||
});
|
||||
|
||||
it('get list of params', async () => {
|
||||
const apiResponse = await supertestAPI
|
||||
.get(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ key: 'test', value: 'http://proxy.com' });
|
||||
|
||||
expect(apiResponse.status).eql(200);
|
||||
|
||||
apiResponse.body.forEach(({ key, value }: SyntheticsParams) => {
|
||||
params[key] = value;
|
||||
});
|
||||
});
|
||||
|
||||
it('sync global params', async () => {
|
||||
const apiResponse = await supertestAPI
|
||||
.get(SYNTHETICS_API_URLS.SYNC_GLOBAL_PARAMS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ key: 'test', value: 'test' });
|
||||
|
||||
expect(apiResponse.status).eql(200);
|
||||
});
|
||||
|
||||
it('added params to for previously added integration', async () => {
|
||||
const apiResponse = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy = apiResponse.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default'
|
||||
);
|
||||
|
||||
expect(packagePolicy.policy_id).eql(testFleetPolicyID);
|
||||
|
||||
comparePolicies(
|
||||
packagePolicy,
|
||||
getTestSyntheticsPolicy({
|
||||
name: browserMonitorJson.name,
|
||||
id: newMonitorId,
|
||||
params,
|
||||
isBrowser: true,
|
||||
location: { id: testFleetPolicyID },
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('add a http monitor using param', async () => {
|
||||
const newMonitor = httpMonitorJson;
|
||||
const pvtLoc = {
|
||||
id: testFleetPolicyID,
|
||||
agentPolicyId: testFleetPolicyID,
|
||||
label: privateLocations[0].label,
|
||||
isServiceManaged: false,
|
||||
geo: {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
};
|
||||
newMonitor.locations.push(pvtLoc);
|
||||
|
||||
newMonitor.proxy_url = '${test}';
|
||||
|
||||
const apiResponse = await addMonitorAPI(newMonitor);
|
||||
|
||||
expect(apiResponse.body).eql(
|
||||
omitMonitorKeys({
|
||||
...newMonitor,
|
||||
[ConfigKey.MONITOR_QUERY_ID]: apiResponse.body.id,
|
||||
[ConfigKey.CONFIG_ID]: apiResponse.body.id,
|
||||
locations: [LOCAL_LOCATION, pvtLoc],
|
||||
})
|
||||
);
|
||||
newHttpMonitorId = apiResponse.rawBody.id;
|
||||
});
|
||||
|
||||
it('parsed params for previously added http monitors', async () => {
|
||||
const apiResponse = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy = apiResponse.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === newHttpMonitorId + '-' + testFleetPolicyID + '-default'
|
||||
);
|
||||
|
||||
expect(packagePolicy.policy_id).eql(testFleetPolicyID);
|
||||
|
||||
const pPolicy = getTestSyntheticsPolicy({
|
||||
name: httpMonitorJson.name,
|
||||
id: newHttpMonitorId,
|
||||
isTLSEnabled: false,
|
||||
namespace: 'testnamespace',
|
||||
location: { id: testFleetPolicyID },
|
||||
});
|
||||
|
||||
comparePolicies(packagePolicy, pPolicy);
|
||||
});
|
||||
|
||||
it('delete all params and sync again', async () => {
|
||||
await supertestAPI
|
||||
.post(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ key: 'get', value: 'test' });
|
||||
const getResponse = await supertestAPI
|
||||
.get(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(getResponse.body.length).eql(2);
|
||||
|
||||
const paramsResponse = getResponse.body || [];
|
||||
const ids = paramsResponse.map((param: any) => param.id);
|
||||
|
||||
const deleteResponse = await supertestAPI
|
||||
.delete(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send({ ids })
|
||||
.expect(200);
|
||||
|
||||
expect(deleteResponse.body).to.have.length(2);
|
||||
|
||||
const getResponseAfterDelete = await supertestAPI
|
||||
.get(SYNTHETICS_API_URLS.PARAMS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(getResponseAfterDelete.body.length).eql(0);
|
||||
|
||||
await supertestAPI
|
||||
.get(SYNTHETICS_API_URLS.SYNC_GLOBAL_PARAMS)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const apiResponse = await supertestWithAuth.get(
|
||||
'/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics'
|
||||
);
|
||||
|
||||
const packagePolicy = apiResponse.body.items.find(
|
||||
(pkgPolicy: PackagePolicy) =>
|
||||
pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default'
|
||||
);
|
||||
|
||||
expect(packagePolicy.policy_id).eql(testFleetPolicyID);
|
||||
|
||||
comparePolicies(
|
||||
packagePolicy,
|
||||
getTestSyntheticsPolicy({
|
||||
name: browserMonitorJson.name,
|
||||
id: newMonitorId,
|
||||
isBrowser: true,
|
||||
location: { id: testFleetPolicyID },
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
* 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 { v4 as uuidv4 } from 'uuid';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import expect from '@kbn/expect';
|
||||
import { SupertestWithRoleScopeType } from '../../../services';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
const config = getService('config');
|
||||
const isServerless = config.get('serverless');
|
||||
const correctPrivileges = {
|
||||
applications: [],
|
||||
cluster: ['monitor', 'read_pipeline', ...(!isServerless ? ['read_ilm'] : [])],
|
||||
indices: [
|
||||
{
|
||||
allow_restricted_indices: false,
|
||||
names: ['synthetics-*'],
|
||||
privileges: ['view_index_metadata', 'create_doc', 'auto_configure', 'read'],
|
||||
},
|
||||
],
|
||||
metadata: {},
|
||||
run_as: [],
|
||||
transient_metadata: {
|
||||
enabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
describe('SyntheticsEnablement', function () {
|
||||
/* temporarily skip MKI. Public locations appear to be disabled in QA causing failures
|
||||
* in isServiceAllowed check */
|
||||
this.tags(['skipMKI']);
|
||||
|
||||
const roleScopedSupertest = getService('roleScopedSupertest');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
|
||||
let supertestWithEditorScope: SupertestWithRoleScopeType;
|
||||
let supertestWithAdminScope: SupertestWithRoleScopeType;
|
||||
|
||||
const getApiKeys = async () => {
|
||||
const { body } = await supertestWithAdminScope
|
||||
.post('/internal/security/api_key/_query')
|
||||
.send({
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
term: {
|
||||
name: 'synthetics-api-key (required for Synthetics App)',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
sort: { field: 'creation', direction: 'desc' },
|
||||
from: 0,
|
||||
size: 25,
|
||||
filters: {},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const apiKeys = body.apiKeys || [];
|
||||
return apiKeys.filter(
|
||||
(apiKey: any) => apiKey.name.includes('synthetics-api-key') && apiKey.invalidated === false
|
||||
);
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
supertestWithEditorScope = await roleScopedSupertest.getSupertestWithRoleScope('editor', {
|
||||
withInternalHeaders: true,
|
||||
useCookieHeader: true,
|
||||
});
|
||||
supertestWithAdminScope = await roleScopedSupertest.getSupertestWithRoleScope('admin', {
|
||||
withInternalHeaders: true,
|
||||
useCookieHeader: true,
|
||||
});
|
||||
});
|
||||
|
||||
describe('[PUT] /internal/uptime/service/enablement', () => {
|
||||
before(async () => {
|
||||
supertestWithEditorScope = await roleScopedSupertest.getSupertestWithRoleScope('editor', {
|
||||
withInternalHeaders: true,
|
||||
useCookieHeader: true,
|
||||
});
|
||||
supertestWithAdminScope = await roleScopedSupertest.getSupertestWithRoleScope('admin', {
|
||||
withInternalHeaders: true,
|
||||
useCookieHeader: true,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const apiKeys = await getApiKeys();
|
||||
if (apiKeys.length) {
|
||||
await supertestWithAdminScope
|
||||
.delete(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
// always invalidate API key for the scoped role in the end
|
||||
await supertestWithAdminScope.destroy();
|
||||
await supertestWithEditorScope.destroy();
|
||||
});
|
||||
|
||||
it(`returns response when user cannot manage api keys`, async () => {
|
||||
const apiResponse = await supertestWithEditorScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: false,
|
||||
canEnable: false,
|
||||
isEnabled: false,
|
||||
isValidApiKey: false,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
});
|
||||
|
||||
it(`returns response for an admin with privilege`, async () => {
|
||||
const apiResponse = await supertestWithAdminScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: true,
|
||||
canEnable: true,
|
||||
isEnabled: true,
|
||||
isValidApiKey: true,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
const validApiKeys = await getApiKeys();
|
||||
expect(validApiKeys.length).eql(1);
|
||||
expect(validApiKeys[0].role_descriptors.synthetics_writer).eql(correctPrivileges);
|
||||
});
|
||||
|
||||
it(`does not create excess api keys`, async () => {
|
||||
const apiResponse = await supertestWithAdminScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: true,
|
||||
canEnable: true,
|
||||
isEnabled: true,
|
||||
isValidApiKey: true,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
|
||||
const validApiKeys = await getApiKeys();
|
||||
expect(validApiKeys.length).eql(1);
|
||||
expect(validApiKeys[0].role_descriptors.synthetics_writer).eql(correctPrivileges);
|
||||
|
||||
// call api a second time
|
||||
const apiResponse2 = await supertestWithAdminScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse2.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: true,
|
||||
canEnable: true,
|
||||
isEnabled: true,
|
||||
isValidApiKey: true,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
|
||||
const validApiKeys2 = await getApiKeys();
|
||||
expect(validApiKeys2.length).eql(1);
|
||||
expect(validApiKeys2[0].role_descriptors.synthetics_writer).eql(correctPrivileges);
|
||||
});
|
||||
|
||||
it(`auto re-enables api key when invalidated`, async () => {
|
||||
const apiResponse = await supertestWithAdminScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: true,
|
||||
canEnable: true,
|
||||
isEnabled: true,
|
||||
isValidApiKey: true,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
|
||||
const validApiKeys = await getApiKeys();
|
||||
expect(validApiKeys.length).eql(1);
|
||||
expect(validApiKeys[0].role_descriptors.synthetics_writer).eql(correctPrivileges);
|
||||
|
||||
// delete api key
|
||||
await supertestWithAdminScope
|
||||
.post('/internal/security/api_key/invalidate')
|
||||
.send({
|
||||
apiKeys: validApiKeys.map((apiKey: { id: string; name: string }) => ({
|
||||
id: apiKey.id,
|
||||
name: apiKey.name,
|
||||
})),
|
||||
isAdmin: true,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const validApiKeysAferDeletion = await getApiKeys();
|
||||
expect(validApiKeysAferDeletion.length).eql(0);
|
||||
|
||||
// call api a second time
|
||||
const apiResponse2 = await supertestWithAdminScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse2.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: true,
|
||||
canEnable: true,
|
||||
isEnabled: true,
|
||||
isValidApiKey: true,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
|
||||
const validApiKeys2 = await getApiKeys();
|
||||
expect(validApiKeys2.length).eql(1);
|
||||
expect(validApiKeys2[0].role_descriptors.synthetics_writer).eql(correctPrivileges);
|
||||
});
|
||||
|
||||
it('returns response for an uptime all user without admin privileges', async () => {
|
||||
const apiResponse = await supertestWithEditorScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: false,
|
||||
canEnable: false,
|
||||
isEnabled: false,
|
||||
isValidApiKey: false,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('[DELETE] /internal/uptime/service/enablement', () => {
|
||||
beforeEach(async () => {
|
||||
const apiKeys = await getApiKeys();
|
||||
if (apiKeys.length) {
|
||||
await supertestWithAdminScope
|
||||
.delete(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
}
|
||||
});
|
||||
|
||||
it('with an admin', async () => {
|
||||
await supertestWithAdminScope.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT).expect(200);
|
||||
const delResponse = await supertestWithAdminScope
|
||||
.delete(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
expect(delResponse.body).eql({});
|
||||
const apiResponse = await supertestWithAdminScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: true,
|
||||
canEnable: true,
|
||||
isEnabled: true,
|
||||
isValidApiKey: true,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('with an uptime user', async () => {
|
||||
await supertestWithAdminScope.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT).expect(200);
|
||||
await supertestWithEditorScope
|
||||
.delete(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(403);
|
||||
const apiResponse = await supertestWithEditorScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
expect(apiResponse.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: false,
|
||||
canEnable: false,
|
||||
isEnabled: true,
|
||||
isValidApiKey: true,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('is space agnostic', async () => {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name-${uuidv4()}`;
|
||||
await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
|
||||
// can enable synthetics in default space when enabled in a non default space
|
||||
const apiResponseGet = await supertestWithAdminScope
|
||||
.put(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT}`)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponseGet.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: true,
|
||||
canEnable: true,
|
||||
isEnabled: true,
|
||||
isValidApiKey: true,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
|
||||
await supertestWithAdminScope
|
||||
.put(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT}`)
|
||||
.expect(200);
|
||||
await supertestWithAdminScope.delete(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT).expect(200);
|
||||
const apiResponse = await supertestWithAdminScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: true,
|
||||
canEnable: true,
|
||||
isEnabled: true,
|
||||
isValidApiKey: true,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
|
||||
// can disable synthetics in non default space when enabled in default space
|
||||
await supertestWithAdminScope.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT).expect(200);
|
||||
await supertestWithAdminScope
|
||||
.delete(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT}`)
|
||||
.expect(200);
|
||||
const apiResponse2 = await supertestWithAdminScope
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse2.body).eql({
|
||||
areApiKeysEnabled: true,
|
||||
canManageApiKeys: true,
|
||||
canEnable: true,
|
||||
isEnabled: true,
|
||||
isValidApiKey: true,
|
||||
isServiceAllowed: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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 { RoleCredentials } from '@kbn/ftr-common-functional-services';
|
||||
import { MonitorFields } from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import expect from '@kbn/expect';
|
||||
import { omit } from 'lodash';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helpers/get_fixture_json';
|
||||
import { SyntheticsMonitorTestService } from '../../../services/synthetics_monitor';
|
||||
|
||||
export const LOCAL_LOCATION = {
|
||||
id: 'dev',
|
||||
label: 'Dev Service',
|
||||
geo: {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
isServiceManaged: true,
|
||||
};
|
||||
|
||||
export default function ({ getService }: DeploymentAgnosticFtrProviderContext) {
|
||||
describe('RunTestManually', function () {
|
||||
this.tags(['skipMKI', 'skipCloud']);
|
||||
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const samlAuth = getService('samlAuth');
|
||||
|
||||
const monitorTestService = new SyntheticsMonitorTestService(getService);
|
||||
|
||||
let newMonitor: MonitorFields;
|
||||
let editorUser: RoleCredentials;
|
||||
|
||||
before(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
editorUser = await samlAuth.createM2mApiKeyWithRoleScope('editor');
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
newMonitor = getFixtureJson('http_monitor');
|
||||
});
|
||||
|
||||
it('runs test manually', async () => {
|
||||
const resp = await monitorTestService.addMonitor(newMonitor, editorUser);
|
||||
|
||||
const res = await supertest
|
||||
.post(SYNTHETICS_API_URLS.TRIGGER_MONITOR + `/${resp.id}`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const result = res.body;
|
||||
expect(typeof result.testRunId).to.eql('string');
|
||||
expect(typeof result.configId).to.eql('string');
|
||||
expect(result.schedule).to.eql({ number: '5', unit: 'm' });
|
||||
expect(result.locations).to.eql([LOCAL_LOCATION]);
|
||||
|
||||
expect(omit(result.monitor, ['id', 'config_id'])).to.eql(
|
||||
omit(newMonitor, ['id', 'config_id'])
|
||||
);
|
||||
});
|
||||
|
||||
it('works in non default space', async () => {
|
||||
const { SPACE_ID } = await monitorTestService.addNewSpace();
|
||||
|
||||
const resp = await supertest
|
||||
.post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.send(newMonitor)
|
||||
.expect(200);
|
||||
|
||||
const res = await supertest
|
||||
.post(`/s/${SPACE_ID}${SYNTHETICS_API_URLS.TRIGGER_MONITOR}/${resp.body.id}`)
|
||||
.set(editorUser.apiKeyHeader)
|
||||
.set(samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const result = res.body;
|
||||
expect(typeof result.testRunId).to.eql('string');
|
||||
expect(typeof result.configId).to.eql('string');
|
||||
expect(result.schedule).to.eql({ number: '5', unit: 'm' });
|
||||
expect(result.locations).to.eql([LOCAL_LOCATION]);
|
||||
|
||||
expect(omit(result.monitor, ['id', 'config_id'])).to.eql(
|
||||
omit(newMonitor, ['id', 'config_id'])
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -18,5 +18,6 @@ export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext)
|
|||
loadTestFile(require.resolve('../../apis/painless_lab'));
|
||||
loadTestFile(require.resolve('../../apis/saved_objects_management'));
|
||||
loadTestFile(require.resolve('../../apis/observability/slo'));
|
||||
loadTestFile(require.resolve('../../apis/observability/synthetics'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext)
|
|||
loadTestFile(require.resolve('../../apis/observability/alerting'));
|
||||
loadTestFile(require.resolve('../../apis/observability/dataset_quality'));
|
||||
loadTestFile(require.resolve('../../apis/observability/slo'));
|
||||
loadTestFile(require.resolve('../../apis/observability/synthetics'));
|
||||
loadTestFile(require.resolve('../../apis/observability/infra'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -117,6 +117,11 @@ export function createServerlessTestConfig<T extends DeploymentAgnosticCommonSer
|
|||
...(options.serverlessProject !== 'oblt'
|
||||
? ['--xpack.security.roleManagementEnabled=true']
|
||||
: []),
|
||||
// defined in MKI control plane. Necessary for Synthetics app testing
|
||||
'--xpack.uptime.service.password=test',
|
||||
'--xpack.uptime.service.username=localKibanaIntegrationTestsUser',
|
||||
'--xpack.uptime.service.devUrl=mockDevUrl',
|
||||
'--xpack.uptime.service.manifestUrl=mockDevUrl',
|
||||
],
|
||||
},
|
||||
testFiles: options.testFiles,
|
||||
|
|
|
@ -145,6 +145,10 @@ export function createStatefulTestConfig<T extends DeploymentAgnosticCommonServi
|
|||
basic: { 'cloud-basic': { order: 1 } },
|
||||
})}`,
|
||||
`--server.publicBaseUrl=${servers.kibana.protocol}://${servers.kibana.hostname}:${servers.kibana.port}`,
|
||||
'--xpack.uptime.service.password=test',
|
||||
'--xpack.uptime.service.username=localKibanaIntegrationTestsUser',
|
||||
'--xpack.uptime.service.devUrl=mockDevUrl',
|
||||
'--xpack.uptime.service.manifestUrl=mockDevUrl',
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* 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 { RoleCredentials, SamlAuthProviderType } from '@kbn/ftr-common-functional-services';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import { syntheticsMonitorType } from '@kbn/synthetics-plugin/common/types/saved_objects';
|
||||
import { EncryptedSyntheticsSavedMonitor } from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { MonitorInspectResponse } from '@kbn/synthetics-plugin/public/apps/synthetics/state/monitor_management/api';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import expect from '@kbn/expect';
|
||||
import { ProjectAPIKeyResponse } from '@kbn/synthetics-plugin/server/routes/monitor_cruds/get_api_key';
|
||||
import moment from 'moment/moment';
|
||||
import { omit } from 'lodash';
|
||||
import { KibanaSupertestProvider } from '@kbn/ftr-common-functional-services';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export class SyntheticsMonitorTestService {
|
||||
private supertest: ReturnType<typeof KibanaSupertestProvider>;
|
||||
private getService: DeploymentAgnosticFtrProviderContext['getService'];
|
||||
public apiKey: string | undefined = '';
|
||||
public samlAuth: SamlAuthProviderType;
|
||||
|
||||
constructor(getService: DeploymentAgnosticFtrProviderContext['getService']) {
|
||||
this.supertest = getService('supertestWithoutAuth');
|
||||
this.samlAuth = getService('samlAuth');
|
||||
this.getService = getService;
|
||||
}
|
||||
|
||||
generateProjectAPIKey = async (accessToPublicLocations = true, user: RoleCredentials) => {
|
||||
const res = await this.supertest
|
||||
.get(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_PROJECT_APIKEY +
|
||||
'?accessToElasticManagedLocations=' +
|
||||
accessToPublicLocations
|
||||
)
|
||||
.set(user.apiKeyHeader)
|
||||
.set(this.samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
const result = res.body as ProjectAPIKeyResponse;
|
||||
expect(result).to.have.property('apiKey');
|
||||
const apiKey = result.apiKey?.encoded;
|
||||
expect(apiKey).to.not.be.empty();
|
||||
this.apiKey = apiKey;
|
||||
return apiKey;
|
||||
};
|
||||
|
||||
async getMonitor(
|
||||
monitorId: string,
|
||||
{
|
||||
statusCode = 200,
|
||||
space,
|
||||
internal,
|
||||
user,
|
||||
}: {
|
||||
statusCode?: number;
|
||||
space?: string;
|
||||
internal?: boolean;
|
||||
user: RoleCredentials;
|
||||
}
|
||||
) {
|
||||
let url = SYNTHETICS_API_URLS.GET_SYNTHETICS_MONITOR.replace('{monitorId}', monitorId);
|
||||
if (space) {
|
||||
url = '/s/' + space + url;
|
||||
}
|
||||
if (internal) {
|
||||
url += `?internal=${internal}`;
|
||||
}
|
||||
const apiResponse = await this.supertest
|
||||
.get(url)
|
||||
.set(user.apiKeyHeader)
|
||||
.set(this.samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.status).eql(statusCode, JSON.stringify(apiResponse.body));
|
||||
|
||||
if (statusCode === 200) {
|
||||
const {
|
||||
created_at: createdAt,
|
||||
updated_at: updatedAt,
|
||||
id,
|
||||
config_id: configId,
|
||||
spaceId,
|
||||
} = apiResponse.body;
|
||||
expect(id).not.empty();
|
||||
expect(configId).not.empty();
|
||||
expect(spaceId).not.empty();
|
||||
expect([createdAt, updatedAt].map((d) => moment(d).isValid())).eql([true, true]);
|
||||
return {
|
||||
rawBody: omit(apiResponse.body, ['spaceId']),
|
||||
body: {
|
||||
...omit(apiResponse.body, [
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'id',
|
||||
'config_id',
|
||||
'form_monitor_type',
|
||||
'spaceId',
|
||||
]),
|
||||
},
|
||||
};
|
||||
}
|
||||
return apiResponse.body;
|
||||
}
|
||||
|
||||
async addMonitor(monitor: any, user: RoleCredentials) {
|
||||
const res = await this.supertest
|
||||
.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS)
|
||||
.set(user.apiKeyHeader)
|
||||
.set(this.samlAuth.getInternalRequestHeader())
|
||||
.send(monitor)
|
||||
.expect(200);
|
||||
|
||||
return res.body as EncryptedSyntheticsSavedMonitor;
|
||||
}
|
||||
|
||||
async inspectMonitor(user: RoleCredentials, monitor: any, hideParams: boolean = true) {
|
||||
const res = await this.supertest
|
||||
.post(SYNTHETICS_API_URLS.SYNTHETICS_MONITOR_INSPECT)
|
||||
.set(user.apiKeyHeader)
|
||||
.set(this.samlAuth.getInternalRequestHeader())
|
||||
.send(monitor)
|
||||
.expect(200);
|
||||
|
||||
// remove the id and config_id from the response
|
||||
delete res.body.result?.publicConfigs?.[0].monitors[0].id;
|
||||
delete res.body.result?.publicConfigs?.[0].monitors[0].streams[0].id;
|
||||
delete res.body.result?.publicConfigs?.[0].monitors[0].streams[0].config_id;
|
||||
delete res.body.result?.publicConfigs?.[0].monitors[0].streams[0].fields.config_id;
|
||||
delete res.body.result?.publicConfigs?.[0].output.api_key;
|
||||
delete res.body.result?.publicConfigs?.[0].license_issued_to;
|
||||
delete res.body.result?.publicConfigs?.[0].stack_version;
|
||||
|
||||
return res.body as { result: MonitorInspectResponse; decodedCode: string };
|
||||
}
|
||||
|
||||
async addProjectMonitors(project: string, monitors: any, user: RoleCredentials) {
|
||||
if (this.apiKey) {
|
||||
return this.supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(this.samlAuth.getInternalRequestHeader())
|
||||
.set('authorization', `ApiKey ${this.apiKey}`)
|
||||
.send({ monitors });
|
||||
} else {
|
||||
return this.supertest
|
||||
.put(
|
||||
SYNTHETICS_API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)
|
||||
)
|
||||
.set(user.apiKeyHeader)
|
||||
.set(this.samlAuth.getInternalRequestHeader())
|
||||
.send({ monitors });
|
||||
}
|
||||
}
|
||||
|
||||
async deleteMonitorByJourney(
|
||||
journeyId: string,
|
||||
projectId: string,
|
||||
space: string = 'default',
|
||||
user: RoleCredentials
|
||||
) {
|
||||
try {
|
||||
const response = await this.supertest
|
||||
.get(`/s/${space}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
.query({
|
||||
filter: `${syntheticsMonitorType}.attributes.journey_id: "${journeyId}" AND ${syntheticsMonitorType}.attributes.project_id: "${projectId}"`,
|
||||
})
|
||||
.set(user.apiKeyHeader)
|
||||
.set(this.samlAuth.getInternalRequestHeader())
|
||||
.expect(200);
|
||||
|
||||
const { monitors } = response.body;
|
||||
if (monitors[0]?.id) {
|
||||
await this.supertest
|
||||
.delete(`/s/${space}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`)
|
||||
.set(user.apiKeyHeader)
|
||||
.set(this.samlAuth.getInternalRequestHeader())
|
||||
.send({ ids: monitors.map((monitor: { id: string }) => monitor.id) })
|
||||
.expect(200);
|
||||
}
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
async addNewSpace() {
|
||||
const SPACE_ID = `test-space-${uuidv4()}`;
|
||||
const SPACE_NAME = `test-space-name ${uuidv4()}`;
|
||||
|
||||
const kibanaServer = this.getService('kibanaServer');
|
||||
|
||||
await kibanaServer.spaces.create({ id: SPACE_ID, name: SPACE_NAME });
|
||||
|
||||
return { SPACE_ID };
|
||||
}
|
||||
|
||||
async deleteMonitor(
|
||||
user: RoleCredentials,
|
||||
monitorId?: string | string[],
|
||||
statusCode = 200,
|
||||
spaceId?: string
|
||||
) {
|
||||
const deleteResponse = await this.supertest
|
||||
.delete(
|
||||
spaceId
|
||||
? `/s/${spaceId}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}`
|
||||
: SYNTHETICS_API_URLS.SYNTHETICS_MONITORS
|
||||
)
|
||||
.send({ ids: Array.isArray(monitorId) ? monitorId : [monitorId] })
|
||||
.set(user.apiKeyHeader)
|
||||
.set(this.samlAuth.getInternalRequestHeader())
|
||||
.expect(statusCode);
|
||||
|
||||
return deleteResponse;
|
||||
}
|
||||
|
||||
async deleteMonitorByIdParam(
|
||||
user: RoleCredentials,
|
||||
monitorId?: string,
|
||||
statusCode = 200,
|
||||
spaceId?: string
|
||||
) {
|
||||
const deleteResponse = await this.supertest
|
||||
.delete(
|
||||
spaceId
|
||||
? `/s/${spaceId}${SYNTHETICS_API_URLS.SYNTHETICS_MONITORS}/${monitorId}`
|
||||
: SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + monitorId
|
||||
)
|
||||
.send()
|
||||
.set(user.apiKeyHeader)
|
||||
.set(this.samlAuth.getInternalRequestHeader())
|
||||
.expect(statusCode);
|
||||
|
||||
return deleteResponse;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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 { v4 as uuidv4 } from 'uuid';
|
||||
import { RetryService } from '@kbn/ftr-common-functional-services';
|
||||
import { X_ELASTIC_INTERNAL_ORIGIN_REQUEST } from '@kbn/core-http-common';
|
||||
import { privateLocationSavedObjectName } from '@kbn/synthetics-plugin/common/saved_objects/private_locations';
|
||||
import { SyntheticsPrivateLocations } from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { KibanaSupertestProvider } from '@kbn/ftr-common-functional-services';
|
||||
import { DeploymentAgnosticFtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export const INSTALLED_VERSION = '1.1.1';
|
||||
|
||||
export class PrivateLocationTestService {
|
||||
private supertestWithAuth: ReturnType<typeof KibanaSupertestProvider>;
|
||||
private readonly retry: RetryService;
|
||||
|
||||
constructor(getService: DeploymentAgnosticFtrProviderContext['getService']) {
|
||||
this.supertestWithAuth = getService('supertest');
|
||||
this.retry = getService('retry');
|
||||
}
|
||||
|
||||
async installSyntheticsPackage() {
|
||||
await this.supertestWithAuth
|
||||
.post('/api/fleet/setup')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
const response = await this.supertestWithAuth
|
||||
.get(`/api/fleet/epm/packages/synthetics/${INSTALLED_VERSION}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
if (response.body.item.status !== 'installed') {
|
||||
await this.supertestWithAuth
|
||||
.post(`/api/fleet/epm/packages/synthetics/${INSTALLED_VERSION}`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({ force: true })
|
||||
.expect(200);
|
||||
}
|
||||
}
|
||||
|
||||
async addTestPrivateLocation(spaceId?: string) {
|
||||
const apiResponse = await this.addFleetPolicy(uuidv4());
|
||||
const testPolicyId = apiResponse.body.item.id;
|
||||
return (await this.setTestLocations([testPolicyId], spaceId))[0];
|
||||
}
|
||||
|
||||
async addFleetPolicy(name: string) {
|
||||
return await this.retry.try(async () => {
|
||||
const response = await this.supertestWithAuth
|
||||
.post('/api/fleet/agent_policies?sys_monitoring=true')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({
|
||||
name,
|
||||
description: '',
|
||||
namespace: 'default',
|
||||
monitoring_enabled: [],
|
||||
});
|
||||
return response;
|
||||
});
|
||||
}
|
||||
|
||||
async setTestLocations(testFleetPolicyIds: string[], spaceId?: string) {
|
||||
const locations: SyntheticsPrivateLocations = testFleetPolicyIds.map((id, index) => ({
|
||||
label: `Test private location ${id}`,
|
||||
agentPolicyId: id,
|
||||
id,
|
||||
geo: {
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
},
|
||||
isServiceManaged: false,
|
||||
}));
|
||||
|
||||
await this.supertestWithAuth
|
||||
.post(`/s/${spaceId || 'default'}/api/saved_objects/_bulk_create`)
|
||||
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(
|
||||
locations.map((location) => ({
|
||||
type: privateLocationSavedObjectName,
|
||||
id: location.id,
|
||||
attributes: location,
|
||||
initialNamespaces: [spaceId ? spaceId : 'default'],
|
||||
}))
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
return locations;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue