mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[APM] Add e2e tests for storage explorer (#141959)
* Refactor APM user creation and add tests for storage explorer
This commit is contained in:
parent
6a0b2fd717
commit
e3bf5539a1
19 changed files with 370 additions and 165 deletions
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* 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 url from 'url';
|
||||
import { synthtrace } from '../../../../synthtrace';
|
||||
import { opbeans } from '../../../fixtures/synthtrace/opbeans';
|
||||
import { checkA11y } from '../../../support/commands';
|
||||
|
||||
const timeRange = {
|
||||
rangeFrom: '2021-10-10T00:00:00.000Z',
|
||||
rangeTo: '2021-10-10T00:15:00.000Z',
|
||||
};
|
||||
|
||||
const storageExplorerHref = url.format({
|
||||
pathname: '/app/apm/storage-explorer',
|
||||
query: timeRange,
|
||||
});
|
||||
|
||||
const mainApiRequestsToIntercept = [
|
||||
{
|
||||
endpoint: '/internal/apm/storage_chart',
|
||||
aliasName: 'storageChartRequest',
|
||||
},
|
||||
{
|
||||
endpoint: '/internal/apm/storage_explorer_summary_stats',
|
||||
aliasName: 'summaryStatsRequest',
|
||||
},
|
||||
{
|
||||
endpoint: '/internal/apm/storage_explorer',
|
||||
aliasName: 'storageExlorerRequest',
|
||||
},
|
||||
];
|
||||
|
||||
const mainAliasNames = mainApiRequestsToIntercept.map(
|
||||
({ aliasName }) => `@${aliasName}`
|
||||
);
|
||||
|
||||
describe('Storage Explorer', () => {
|
||||
before(() => {
|
||||
const { rangeFrom, rangeTo } = timeRange;
|
||||
synthtrace.index(
|
||||
opbeans({
|
||||
from: new Date(rangeFrom).getTime(),
|
||||
to: new Date(rangeTo).getTime(),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
synthtrace.clean();
|
||||
});
|
||||
|
||||
describe('When navigating to storage explorer without the required permissions', () => {
|
||||
beforeEach(() => {
|
||||
cy.loginAsViewerUser();
|
||||
cy.visitKibana(storageExplorerHref);
|
||||
});
|
||||
|
||||
it('displays a prompt for permissions', () => {
|
||||
cy.contains('You need permission');
|
||||
});
|
||||
});
|
||||
|
||||
describe('When navigating to storage explorer with the required permissions', () => {
|
||||
beforeEach(() => {
|
||||
cy.loginAsMonitorUser();
|
||||
cy.visitKibana(storageExplorerHref);
|
||||
});
|
||||
|
||||
it('has no detectable a11y violations on load', () => {
|
||||
cy.contains('h1', 'Storage explorer');
|
||||
// set skipFailures to true to not fail the test when there are accessibility failures
|
||||
checkA11y({ skipFailures: true });
|
||||
});
|
||||
|
||||
it('has a list of summary stats', () => {
|
||||
cy.contains('Total APM size');
|
||||
cy.contains('Daily data generation');
|
||||
cy.contains('Traces per minute');
|
||||
cy.contains('Number of services');
|
||||
});
|
||||
|
||||
it('renders the storage timeseries chart', () => {
|
||||
cy.get('[data-test-subj="storageExplorerTimeseriesChart"]');
|
||||
});
|
||||
|
||||
it('has a list of services and environments', () => {
|
||||
cy.contains('opbeans-node');
|
||||
cy.contains('opbeans-java');
|
||||
cy.contains('opbeans-rum');
|
||||
cy.get('td:contains(production)').should('have.length', 3);
|
||||
});
|
||||
|
||||
it('when clicking on a service it loads the service overview for that service', () => {
|
||||
cy.contains('opbeans-node').click({ force: true });
|
||||
cy.url().should('include', '/apm/services/opbeans-node/overview');
|
||||
cy.contains('h1', 'opbeans-node');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Calls APIs', () => {
|
||||
beforeEach(() => {
|
||||
mainApiRequestsToIntercept.forEach(({ endpoint, aliasName }) => {
|
||||
cy.intercept({ pathname: endpoint }).as(aliasName);
|
||||
});
|
||||
|
||||
cy.loginAsMonitorUser();
|
||||
cy.visitKibana(storageExplorerHref);
|
||||
});
|
||||
|
||||
it('with the correct environment when changing the environment', () => {
|
||||
cy.wait(mainAliasNames);
|
||||
|
||||
cy.get('[data-test-subj="environmentFilter"]').type('production');
|
||||
|
||||
cy.contains('button', 'production').click({ force: true });
|
||||
|
||||
cy.expectAPIsToHaveBeenCalledWith({
|
||||
apisIntercepted: mainAliasNames,
|
||||
value: 'environment=production',
|
||||
});
|
||||
});
|
||||
|
||||
it('when clicking the refresh button', () => {
|
||||
cy.wait(mainAliasNames);
|
||||
cy.contains('Refresh').click();
|
||||
cy.wait(mainAliasNames);
|
||||
});
|
||||
|
||||
it('when selecting a different time range and clicking the update button', () => {
|
||||
cy.wait(mainAliasNames);
|
||||
|
||||
cy.selectAbsoluteTimeRange(
|
||||
moment(timeRange.rangeFrom).subtract(5, 'm').toISOString(),
|
||||
moment(timeRange.rangeTo).subtract(5, 'm').toISOString()
|
||||
);
|
||||
cy.contains('Update').click();
|
||||
cy.wait(mainAliasNames);
|
||||
|
||||
cy.contains('Refresh').click();
|
||||
cy.wait(mainAliasNames);
|
||||
});
|
||||
|
||||
it('with the correct lifecycle phase when changing the lifecycle phase', () => {
|
||||
cy.wait(mainAliasNames);
|
||||
|
||||
cy.get('[data-test-subj="storageExplorerLifecyclePhaseSelect"]').click();
|
||||
cy.contains('button', 'Warm').click();
|
||||
|
||||
cy.expectAPIsToHaveBeenCalledWith({
|
||||
apisIntercepted: mainAliasNames,
|
||||
value: 'indexLifecyclePhase=warm',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Storage details per service', () => {
|
||||
beforeEach(() => {
|
||||
const apiRequestsToIntercept = [
|
||||
...mainApiRequestsToIntercept,
|
||||
{
|
||||
endpoint: '/internal/apm/services/opbeans-node/storage_details',
|
||||
aliasName: 'storageDetailsRequest',
|
||||
},
|
||||
];
|
||||
|
||||
apiRequestsToIntercept.forEach(({ endpoint, aliasName }) => {
|
||||
cy.intercept({ pathname: endpoint }).as(aliasName);
|
||||
});
|
||||
|
||||
cy.loginAsMonitorUser();
|
||||
cy.visitKibana(storageExplorerHref);
|
||||
});
|
||||
|
||||
it('shows storage details', () => {
|
||||
cy.wait(mainAliasNames);
|
||||
cy.contains('opbeans-node');
|
||||
|
||||
cy.get('[data-test-subj="storageDetailsButton_opbeans-node"]').click();
|
||||
cy.get('[data-test-subj="loadingSpinner"]').should('be.visible');
|
||||
cy.wait('@storageDetailsRequest');
|
||||
|
||||
cy.contains('Service storage details');
|
||||
cy.get('[data-test-subj="storageExplorerTimeseriesChart"]');
|
||||
cy.get('[data-test-subj="serviceStorageDetailsTable"]');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -9,13 +9,21 @@ import { Interception } from 'cypress/types/net-stubbing';
|
|||
import 'cypress-axe';
|
||||
import moment from 'moment';
|
||||
import { AXE_CONFIG, AXE_OPTIONS } from '@kbn/axe-config';
|
||||
import { ApmUsername } from '../../../server/test_helpers/create_apm_users/authentication';
|
||||
|
||||
Cypress.Commands.add('loginAsViewerUser', () => {
|
||||
return cy.loginAs({ username: 'viewer', password: 'changeme' });
|
||||
return cy.loginAs({ username: ApmUsername.viewerUser, password: 'changeme' });
|
||||
});
|
||||
|
||||
Cypress.Commands.add('loginAsEditorUser', () => {
|
||||
return cy.loginAs({ username: 'editor', password: 'changeme' });
|
||||
return cy.loginAs({ username: ApmUsername.editorUser, password: 'changeme' });
|
||||
});
|
||||
|
||||
Cypress.Commands.add('loginAsMonitorUser', () => {
|
||||
return cy.loginAs({
|
||||
username: ApmUsername.apmMonitorIndices,
|
||||
password: 'changeme',
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
|
|
|
@ -9,6 +9,7 @@ declare namespace Cypress {
|
|||
interface Chainable {
|
||||
loginAsViewerUser(): Cypress.Chainable<Cypress.Response<any>>;
|
||||
loginAsEditorUser(): Cypress.Chainable<Cypress.Response<any>>;
|
||||
loginAsMonitorUser(): Cypress.Chainable<Cypress.Response<any>>;
|
||||
loginAs(params: {
|
||||
username: string;
|
||||
password: string;
|
||||
|
|
|
@ -11,7 +11,7 @@ import { esTestConfig } from '@kbn/test';
|
|||
import { apm, createLogger, LogLevel } from '@kbn/apm-synthtrace';
|
||||
import path from 'path';
|
||||
import { FtrProviderContext } from './ftr_provider_context';
|
||||
import { createApmUsers } from '../scripts/create_apm_users/create_apm_users';
|
||||
import { createApmUsers } from '../server/test_helpers/create_apm_users/create_apm_users';
|
||||
|
||||
export async function cypressTestRunner({ getService }: FtrProviderContext) {
|
||||
const config = getService('config');
|
||||
|
@ -26,12 +26,6 @@ export async function cypressTestRunner({ getService }: FtrProviderContext) {
|
|||
const username = config.get('servers.elasticsearch.username');
|
||||
const password = config.get('servers.elasticsearch.password');
|
||||
|
||||
// Creates APM users
|
||||
await createApmUsers({
|
||||
elasticsearch: { username, password },
|
||||
kibana: { hostname: kibanaUrl },
|
||||
});
|
||||
|
||||
const esNode = Url.format({
|
||||
protocol: config.get('servers.elasticsearch.protocol'),
|
||||
port: config.get('servers.elasticsearch.port'),
|
||||
|
@ -39,6 +33,12 @@ export async function cypressTestRunner({ getService }: FtrProviderContext) {
|
|||
auth: `${username}:${password}`,
|
||||
});
|
||||
|
||||
// Creates APM users
|
||||
await createApmUsers({
|
||||
elasticsearch: { node: esNode, username, password },
|
||||
kibana: { hostname: kibanaUrl },
|
||||
});
|
||||
|
||||
const esRequestTimeout = config.get('timeouts.esRequestTimeout');
|
||||
const kibanaClient = new apm.ApmSynthtraceKibanaClient(
|
||||
createLogger(LogLevel.info)
|
||||
|
|
|
@ -18,5 +18,6 @@
|
|||
"references": [
|
||||
{ "path": "../../../test/tsconfig.json" },
|
||||
{ "path": "../../../../test/tsconfig.json" },
|
||||
{ "path": "../tsconfig.json" },
|
||||
]
|
||||
}
|
||||
|
|
|
@ -130,6 +130,7 @@ export function IndexLifecyclePhaseSelect() {
|
|||
}}
|
||||
hasDividers
|
||||
style={{ minWidth: 200 }}
|
||||
data-test-subj="storageExplorerLifecyclePhaseSelect"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -186,7 +186,10 @@ export function StorageDetailsPerService({
|
|||
<EuiFlexItem>
|
||||
<EuiFlexGroup justifyContent="spaceBetween" gutterSize="m">
|
||||
<EuiFlexItem>
|
||||
<EuiPanel hasShadow={false}>
|
||||
<EuiPanel
|
||||
hasShadow={false}
|
||||
data-test-subj="serviceStorageDetailsChart"
|
||||
>
|
||||
<Chart>
|
||||
<Settings
|
||||
theme={[
|
||||
|
@ -224,7 +227,11 @@ export function StorageDetailsPerService({
|
|||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiPanel hasShadow={false} paddingSize="l">
|
||||
<EuiPanel
|
||||
hasShadow={false}
|
||||
paddingSize="l"
|
||||
data-test-subj="serviceStorageDetailsTable"
|
||||
>
|
||||
{processorEventStats.map(
|
||||
({ processorEventLabel, docs, size }) => (
|
||||
<>
|
||||
|
|
|
@ -8,13 +8,17 @@
|
|||
/* eslint-disable no-console */
|
||||
|
||||
import { argv } from 'yargs';
|
||||
import { AbortError, isAxiosError } from './helpers/call_kibana';
|
||||
import { createApmUsers } from './create_apm_users';
|
||||
import { getKibanaVersion } from './helpers/get_version';
|
||||
import {
|
||||
AbortError,
|
||||
isAxiosError,
|
||||
} from '../../server/test_helpers/create_apm_users/helpers/call_kibana';
|
||||
import { createApmUsers } from '../../server/test_helpers/create_apm_users/create_apm_users';
|
||||
import { getKibanaVersion } from '../../server/test_helpers/create_apm_users/helpers/get_version';
|
||||
|
||||
async function init() {
|
||||
const esUserName = (argv.username as string) || 'elastic';
|
||||
const esPassword = argv.password as string | undefined;
|
||||
const esUrl = argv.esUrl as string | undefined;
|
||||
const kibanaBaseUrl = argv.kibanaUrl as string | undefined;
|
||||
|
||||
if (!esPassword) {
|
||||
|
@ -24,6 +28,20 @@ async function init() {
|
|||
process.exit();
|
||||
}
|
||||
|
||||
if (!esUrl) {
|
||||
console.error(
|
||||
'Please specify the url for elasticsearch: `--es-url http://localhost:9200` '
|
||||
);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
if (!esUrl.startsWith('https://') && !esUrl.startsWith('http://')) {
|
||||
console.error(
|
||||
'Elasticsearch url must be prefixed with http(s):// `--es-url http://localhost:9200`'
|
||||
);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
if (!kibanaBaseUrl) {
|
||||
console.error(
|
||||
'Please specify the url for Kibana: `--kibana-url http://localhost:5601` '
|
||||
|
@ -42,7 +60,11 @@ async function init() {
|
|||
}
|
||||
|
||||
const kibana = { hostname: kibanaBaseUrl };
|
||||
const elasticsearch = { username: esUserName, password: esPassword };
|
||||
const elasticsearch = {
|
||||
node: esUrl,
|
||||
username: esUserName,
|
||||
password: esPassword,
|
||||
};
|
||||
|
||||
console.log({ kibana, elasticsearch });
|
||||
|
||||
|
@ -50,9 +72,7 @@ async function init() {
|
|||
console.log(`Connected to Kibana ${version}`);
|
||||
|
||||
const users = await createApmUsers({ elasticsearch, kibana });
|
||||
const credentials = users
|
||||
.map((u) => ` - ${u.username} / ${esPassword}`)
|
||||
.join('\n');
|
||||
const credentials = users.map((u) => ` - ${u} / ${esPassword}`).join('\n');
|
||||
|
||||
console.log(
|
||||
`\nYou can now login to ${kibana.hostname} with:\n${credentials}`
|
||||
|
|
|
@ -5,15 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Client } from '@elastic/elasticsearch';
|
||||
import { PrivilegeType } from '@kbn/apm-plugin/common/privilege_type';
|
||||
import { ToolingLog } from '@kbn/tooling-log';
|
||||
import { omit } from 'lodash';
|
||||
import { KbnClientRequesterError } from '@kbn/test';
|
||||
import { AxiosError } from 'axios';
|
||||
import { SecurityServiceProvider } from '../../../../test/common/services/security';
|
||||
|
||||
type SecurityService = Awaited<ReturnType<typeof SecurityServiceProvider>>;
|
||||
import { PrivilegeType } from '../../../common/privilege_type';
|
||||
|
||||
export enum ApmUsername {
|
||||
noAccessUser = 'no_access_user',
|
||||
|
@ -34,7 +26,7 @@ export enum ApmCustomRolename {
|
|||
apmMonitorIndices = 'apm_monitor_indices',
|
||||
}
|
||||
|
||||
const customRoles = {
|
||||
export const customRoles = {
|
||||
[ApmCustomRolename.apmReadUserWithoutMlAccess]: {
|
||||
elasticsearch: {
|
||||
cluster: [],
|
||||
|
@ -97,7 +89,7 @@ const customRoles = {
|
|||
},
|
||||
};
|
||||
|
||||
const users: Record<
|
||||
export const users: Record<
|
||||
ApmUsername,
|
||||
{ builtInRoleNames?: string[]; customRoleNames?: ApmCustomRolename[] }
|
||||
> = {
|
||||
|
@ -132,70 +124,4 @@ const users: Record<
|
|||
},
|
||||
};
|
||||
|
||||
function logErrorResponse(logger: ToolingLog, e: Error) {
|
||||
if (e instanceof KbnClientRequesterError) {
|
||||
logger.error(`KbnClientRequesterError: ${JSON.stringify(e.axiosError?.response?.data)}`);
|
||||
} else if (e instanceof AxiosError) {
|
||||
logger.error(`AxiosError: ${JSON.stringify(e.response?.data)}`);
|
||||
} else {
|
||||
logger.error(`Unknown error: ${e.constructor.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function createApmUser({
|
||||
username,
|
||||
security,
|
||||
es,
|
||||
logger,
|
||||
}: {
|
||||
username: ApmUsername;
|
||||
security: SecurityService;
|
||||
es: Client;
|
||||
logger: ToolingLog;
|
||||
}) {
|
||||
const user = users[username];
|
||||
|
||||
if (!user) {
|
||||
throw new Error(`No configuration found for ${username}`);
|
||||
}
|
||||
|
||||
const { builtInRoleNames = [], customRoleNames = [] } = user;
|
||||
|
||||
try {
|
||||
// create custom roles
|
||||
await Promise.all(
|
||||
customRoleNames.map(async (roleName) => createCustomRole({ roleName, security, es }))
|
||||
);
|
||||
|
||||
// create user
|
||||
await security.user.create(username, {
|
||||
full_name: username,
|
||||
password: APM_TEST_PASSWORD,
|
||||
roles: [...builtInRoleNames, ...customRoleNames],
|
||||
});
|
||||
} catch (e) {
|
||||
logErrorResponse(logger, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async function createCustomRole({
|
||||
roleName,
|
||||
security,
|
||||
es,
|
||||
}: {
|
||||
roleName: ApmCustomRolename;
|
||||
security: SecurityService;
|
||||
es: Client;
|
||||
}) {
|
||||
const role = customRoles[roleName];
|
||||
|
||||
// Add application privileges with es client as they are not supported by
|
||||
// security.user.create. They are preserved when updating the role below
|
||||
if ('applications' in role) {
|
||||
await es.security.putRole({ name: roleName, body: role });
|
||||
}
|
||||
await security.role.create(roleName, omit(role, 'applications'));
|
||||
}
|
||||
|
||||
export const APM_TEST_PASSWORD = 'changeme';
|
|
@ -5,10 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { asyncForEach } from '@kbn/std';
|
||||
import { AbortError, callKibana } from './helpers/call_kibana';
|
||||
import { createOrUpdateUser } from './helpers/create_or_update_user';
|
||||
|
||||
import { ApmUsername, users } from './authentication';
|
||||
import { createCustomRole } from './helpers/create_custom_role';
|
||||
export interface Elasticsearch {
|
||||
node: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
@ -28,6 +31,7 @@ export async function createApmUsers({
|
|||
elasticsearch,
|
||||
kibana,
|
||||
});
|
||||
|
||||
if (!isCredentialsValid) {
|
||||
throw new AbortError('Invalid username/password');
|
||||
}
|
||||
|
@ -36,24 +40,33 @@ export async function createApmUsers({
|
|||
elasticsearch,
|
||||
kibana,
|
||||
});
|
||||
|
||||
if (!isSecurityEnabled) {
|
||||
throw new AbortError('Security must be enabled!');
|
||||
}
|
||||
|
||||
// user definitions
|
||||
const users = [
|
||||
{ username: 'viewer', roles: ['viewer'] },
|
||||
{ username: 'editor', roles: ['editor'] },
|
||||
];
|
||||
const apmUsers = Object.values(ApmUsername);
|
||||
await asyncForEach(apmUsers, async (username) => {
|
||||
const user = users[username];
|
||||
const { builtInRoleNames = [], customRoleNames = [] } = user;
|
||||
|
||||
// create users
|
||||
await Promise.all(
|
||||
users.map(async (user) =>
|
||||
createOrUpdateUser({ elasticsearch, kibana, user })
|
||||
)
|
||||
);
|
||||
// create custom roles
|
||||
await Promise.all(
|
||||
customRoleNames.map(async (roleName) =>
|
||||
createCustomRole({ elasticsearch, kibana, roleName })
|
||||
)
|
||||
);
|
||||
|
||||
return users;
|
||||
// create user
|
||||
const roles = builtInRoleNames.concat(customRoleNames);
|
||||
await createOrUpdateUser({
|
||||
elasticsearch,
|
||||
kibana,
|
||||
user: { username, roles },
|
||||
});
|
||||
});
|
||||
|
||||
return apmUsers;
|
||||
}
|
||||
|
||||
async function getIsSecurityEnabled({
|
|
@ -13,7 +13,7 @@ export async function callKibana<T>({
|
|||
kibana,
|
||||
options,
|
||||
}: {
|
||||
elasticsearch: Elasticsearch;
|
||||
elasticsearch: Omit<Elasticsearch, 'node'>;
|
||||
kibana: Kibana;
|
||||
options: AxiosRequestConfig;
|
||||
}): Promise<T> {
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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 { Client } from '@elastic/elasticsearch';
|
||||
import { omit } from 'lodash';
|
||||
import { Elasticsearch, Kibana } from '../create_apm_users';
|
||||
import { callKibana } from './call_kibana';
|
||||
import { customRoles, ApmCustomRolename } from '../authentication';
|
||||
|
||||
export async function createCustomRole({
|
||||
elasticsearch,
|
||||
kibana,
|
||||
roleName,
|
||||
}: {
|
||||
elasticsearch: Elasticsearch;
|
||||
kibana: Kibana;
|
||||
roleName: ApmCustomRolename;
|
||||
}) {
|
||||
const role = customRoles[roleName];
|
||||
|
||||
// Add application privileges with es client as they are not supported by
|
||||
// the security API. They are preserved when updating the role below
|
||||
if ('applications' in role) {
|
||||
const esClient = getEsClient(elasticsearch);
|
||||
await esClient.security.putRole({ name: roleName, body: role });
|
||||
}
|
||||
|
||||
await callKibana({
|
||||
elasticsearch,
|
||||
kibana,
|
||||
options: {
|
||||
method: 'PUT',
|
||||
url: `/api/security/role/${roleName}`,
|
||||
data: {
|
||||
...omit(role, 'applications'),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function getEsClient(elasticsearch: Elasticsearch) {
|
||||
const { node, username, password } = elasticsearch;
|
||||
const client = new Client({
|
||||
node,
|
||||
tls: {
|
||||
rejectUnauthorized: false,
|
||||
},
|
||||
requestTimeout: 120000,
|
||||
auth: {
|
||||
username,
|
||||
password,
|
||||
},
|
||||
});
|
||||
|
||||
return client;
|
||||
}
|
|
@ -13,7 +13,7 @@ export async function getKibanaVersion({
|
|||
elasticsearch,
|
||||
kibana,
|
||||
}: {
|
||||
elasticsearch: Elasticsearch;
|
||||
elasticsearch: Omit<Elasticsearch, 'node'>;
|
||||
kibana: Kibana;
|
||||
}) {
|
||||
try {
|
|
@ -10,7 +10,7 @@
|
|||
import Url from 'url';
|
||||
import { run as syntheticsRun } from '@elastic/synthetics';
|
||||
import { PromiseType } from 'utility-types';
|
||||
import { createApmUsers } from '@kbn/apm-plugin/scripts/create_apm_users/create_apm_users';
|
||||
import { createApmUsers } from '@kbn/apm-plugin/server/test_helpers/create_apm_users/create_apm_users';
|
||||
|
||||
import { esArchiverUnload } from './tasks/es_archiver';
|
||||
|
||||
|
@ -23,6 +23,7 @@ export interface ArgParams {
|
|||
export class SyntheticsRunner {
|
||||
public getService: any;
|
||||
public kibanaUrl: string;
|
||||
private elasticsearchUrl: string;
|
||||
|
||||
public testFilesLoaded: boolean = false;
|
||||
|
||||
|
@ -31,6 +32,7 @@ export class SyntheticsRunner {
|
|||
constructor(getService: any, params: ArgParams) {
|
||||
this.getService = getService;
|
||||
this.kibanaUrl = this.getKibanaUrl();
|
||||
this.elasticsearchUrl = this.getElasticsearchUrl();
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
|
@ -40,7 +42,7 @@ export class SyntheticsRunner {
|
|||
|
||||
async createTestUsers() {
|
||||
await createApmUsers({
|
||||
elasticsearch: { username: 'elastic', password: 'changeme' },
|
||||
elasticsearch: { node: this.elasticsearchUrl, username: 'elastic', password: 'changeme' },
|
||||
kibana: { hostname: this.kibanaUrl },
|
||||
});
|
||||
}
|
||||
|
@ -79,6 +81,16 @@ export class SyntheticsRunner {
|
|||
});
|
||||
}
|
||||
|
||||
getElasticsearchUrl() {
|
||||
const config = this.getService('config');
|
||||
|
||||
return Url.format({
|
||||
protocol: config.get('servers.elasticsearch.protocol'),
|
||||
hostname: config.get('servers.elasticsearch.hostname'),
|
||||
port: config.get('servers.elasticsearch.port'),
|
||||
});
|
||||
}
|
||||
|
||||
async run() {
|
||||
if (!this.testFilesLoaded) {
|
||||
throw new Error('Test files not loaded');
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { journey, step, expect, before } from '@elastic/synthetics';
|
||||
import { callKibana } from '@kbn/apm-plugin/scripts/create_apm_users/helpers/call_kibana';
|
||||
import { callKibana } from '@kbn/apm-plugin/server/test_helpers/create_apm_users/helpers/call_kibana';
|
||||
import { byTestId, waitForLoadingToFinish } from '@kbn/observability-plugin/e2e/utils';
|
||||
import { loginPageProvider } from '../page_objects/login';
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { apm, createLogger, LogLevel } from '@kbn/apm-synthtrace';
|
||||
import { esTestConfig } from '@kbn/test';
|
||||
import { APM_TEST_PASSWORD } from './authentication';
|
||||
import { APM_TEST_PASSWORD } from '@kbn/apm-plugin/server/test_helpers/create_apm_users/authentication';
|
||||
import { InheritedFtrProviderContext } from './ftr_provider_context';
|
||||
|
||||
export async function bootstrapApmSynthtrace(
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
import { FtrConfigProviderContext } from '@kbn/test';
|
||||
import supertest from 'supertest';
|
||||
import { format, UrlObject } from 'url';
|
||||
import { Client } from '@elastic/elasticsearch';
|
||||
import { ToolingLog } from '@kbn/tooling-log';
|
||||
import { SecurityServiceProvider } from '../../../../test/common/services/security';
|
||||
import {
|
||||
ApmUsername,
|
||||
APM_TEST_PASSWORD,
|
||||
} from '@kbn/apm-plugin/server/test_helpers/create_apm_users/authentication';
|
||||
import { createApmUsers } from '@kbn/apm-plugin/server/test_helpers/create_apm_users/create_apm_users';
|
||||
import { InheritedFtrProviderContext, InheritedServices } from './ftr_provider_context';
|
||||
import { createApmUser, APM_TEST_PASSWORD, ApmUsername } from './authentication';
|
||||
import { APMFtrConfigName } from '../configs';
|
||||
import { createApmApiClient } from './apm_api_supertest';
|
||||
import { RegistryProvider } from './registry';
|
||||
|
@ -25,17 +26,8 @@ export interface ApmFtrConfig {
|
|||
kibanaConfig?: Record<string, string | string[]>;
|
||||
}
|
||||
|
||||
type SecurityService = Awaited<ReturnType<typeof SecurityServiceProvider>>;
|
||||
|
||||
function getLegacySupertestClient(kibanaServer: UrlObject, username: ApmUsername) {
|
||||
return async (context: InheritedFtrProviderContext) => {
|
||||
const security = context.getService('security');
|
||||
const es = context.getService('es');
|
||||
const logger = context.getService('log');
|
||||
await security.init();
|
||||
|
||||
await createApmUser({ security, username, es, logger });
|
||||
|
||||
const url = format({
|
||||
...kibanaServer,
|
||||
auth: `${username}:${APM_TEST_PASSWORD}`,
|
||||
|
@ -47,19 +39,11 @@ function getLegacySupertestClient(kibanaServer: UrlObject, username: ApmUsername
|
|||
|
||||
async function getApmApiClient({
|
||||
kibanaServer,
|
||||
security,
|
||||
username,
|
||||
es,
|
||||
logger,
|
||||
}: {
|
||||
kibanaServer: UrlObject;
|
||||
security: SecurityService;
|
||||
username: ApmUsername;
|
||||
es: Client;
|
||||
logger: ToolingLog;
|
||||
}) {
|
||||
await createApmUser({ security, username, es, logger });
|
||||
|
||||
const url = format({
|
||||
...kibanaServer,
|
||||
auth: `${username}:${APM_TEST_PASSWORD}`,
|
||||
|
@ -81,6 +65,8 @@ export function createTestConfig(config: ApmFtrConfig) {
|
|||
const services = xPackAPITestsConfig.get('services') as InheritedServices;
|
||||
const servers = xPackAPITestsConfig.get('servers');
|
||||
const kibanaServer = servers.kibana as UrlObject;
|
||||
const kibanaServerUrl = format(kibanaServer);
|
||||
const esServer = servers.elasticsearch as UrlObject;
|
||||
|
||||
return {
|
||||
testFiles: [require.resolve('../tests')],
|
||||
|
@ -91,72 +77,50 @@ export function createTestConfig(config: ApmFtrConfig) {
|
|||
apmFtrConfig: () => config,
|
||||
registry: RegistryProvider,
|
||||
synthtraceEsClient: (context: InheritedFtrProviderContext) => {
|
||||
const kibanaServerUrl = format(kibanaServer);
|
||||
return bootstrapApmSynthtrace(context, kibanaServerUrl);
|
||||
},
|
||||
apmApiClient: async (context: InheritedFtrProviderContext) => {
|
||||
const security = context.getService('security');
|
||||
const es = context.getService('es');
|
||||
const logger = context.getService('log');
|
||||
const { username, password } = servers.kibana;
|
||||
const esUrl = format(esServer);
|
||||
|
||||
await security.init();
|
||||
// Creates APM users
|
||||
await createApmUsers({
|
||||
elasticsearch: { node: esUrl, username, password },
|
||||
kibana: { hostname: kibanaServerUrl },
|
||||
});
|
||||
|
||||
return {
|
||||
noAccessUser: await getApmApiClient({
|
||||
kibanaServer,
|
||||
security,
|
||||
username: ApmUsername.noAccessUser,
|
||||
es,
|
||||
logger,
|
||||
}),
|
||||
readUser: await getApmApiClient({
|
||||
kibanaServer,
|
||||
security,
|
||||
username: ApmUsername.viewerUser,
|
||||
es,
|
||||
logger,
|
||||
}),
|
||||
writeUser: await getApmApiClient({
|
||||
kibanaServer,
|
||||
security,
|
||||
username: ApmUsername.editorUser,
|
||||
es,
|
||||
logger,
|
||||
}),
|
||||
annotationWriterUser: await getApmApiClient({
|
||||
kibanaServer,
|
||||
security,
|
||||
username: ApmUsername.apmAnnotationsWriteUser,
|
||||
es,
|
||||
logger,
|
||||
}),
|
||||
noMlAccessUser: await getApmApiClient({
|
||||
kibanaServer,
|
||||
security,
|
||||
username: ApmUsername.apmReadUserWithoutMlAccess,
|
||||
es,
|
||||
logger,
|
||||
}),
|
||||
manageOwnAgentKeysUser: await getApmApiClient({
|
||||
kibanaServer,
|
||||
security,
|
||||
username: ApmUsername.apmManageOwnAgentKeys,
|
||||
es,
|
||||
logger,
|
||||
}),
|
||||
createAndAllAgentKeysUser: await getApmApiClient({
|
||||
kibanaServer,
|
||||
security,
|
||||
username: ApmUsername.apmManageOwnAndCreateAgentKeys,
|
||||
es,
|
||||
logger,
|
||||
}),
|
||||
monitorIndicesUser: await getApmApiClient({
|
||||
kibanaServer,
|
||||
security,
|
||||
username: ApmUsername.apmMonitorIndices,
|
||||
es,
|
||||
logger,
|
||||
}),
|
||||
};
|
||||
},
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
import expect from '@kbn/expect';
|
||||
import { first } from 'lodash';
|
||||
import { PrivilegeType } from '@kbn/apm-plugin/common/privilege_type';
|
||||
import { ApmUsername } from '@kbn/apm-plugin/server/test_helpers/create_apm_users/authentication';
|
||||
import { FtrProviderContext } from '../../../common/ftr_provider_context';
|
||||
import { ApmApiError, ApmApiSupertest } from '../../../common/apm_api_supertest';
|
||||
import { ApmUsername } from '../../../common/authentication';
|
||||
|
||||
export default function ApiTest({ getService }: FtrProviderContext) {
|
||||
const registry = getService('registry');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue