From 6038c091116043a37489ed422855aa44134500ac Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Tue, 15 Aug 2023 15:45:51 -0700 Subject: [PATCH] Reporting Test Serverless structure: api_integration --- .buildkite/ftr_configs.yml | 2 - .../api_integration/services/index.ts | 5 +- .../api_integration/services/reporting_api.ts | 22 -- .../api_integration/services/svl_reporting.ts | 99 ++++++++ .../test_suites/common/index.ts | 1 + .../test_suites/common/reporting/index.ts | 14 ++ .../common/reporting/management.ts | 66 +++++ .../test_suites/reporting/config.ts | 45 ---- .../test_suites/reporting/index.ts | 25 -- .../test_suites/reporting/management.ts | 49 ---- .../test_suites/reporting/reporting.ts | 38 --- .../reporting/security_role_priviledges.ts | 53 ---- .../test_suites/reporting/services/index.ts | 24 -- .../reporting/services/scenarios.ts | 226 ------------------ .../test_suites/reporting/services/usage.ts | 123 ---------- .../functional/page_objects/index.ts | 2 - .../page_objects/svl_reporting_page.ts | 18 -- .../functional/test_suites/common/index.ts | 3 + .../test_suites/common/reporting/index.ts | 14 ++ .../common/reporting/management.ts | 18 ++ .../test_suites/reporting/config.ts | 17 -- x-pack/test_serverless/tsconfig.json | 3 + 22 files changed, 221 insertions(+), 646 deletions(-) delete mode 100644 x-pack/test_serverless/api_integration/services/reporting_api.ts create mode 100644 x-pack/test_serverless/api_integration/services/svl_reporting.ts create mode 100644 x-pack/test_serverless/api_integration/test_suites/common/reporting/index.ts create mode 100644 x-pack/test_serverless/api_integration/test_suites/common/reporting/management.ts delete mode 100644 x-pack/test_serverless/api_integration/test_suites/reporting/config.ts delete mode 100644 x-pack/test_serverless/api_integration/test_suites/reporting/index.ts delete mode 100644 x-pack/test_serverless/api_integration/test_suites/reporting/management.ts delete mode 100644 x-pack/test_serverless/api_integration/test_suites/reporting/reporting.ts delete mode 100644 x-pack/test_serverless/api_integration/test_suites/reporting/security_role_priviledges.ts delete mode 100644 x-pack/test_serverless/api_integration/test_suites/reporting/services/index.ts delete mode 100644 x-pack/test_serverless/api_integration/test_suites/reporting/services/scenarios.ts delete mode 100644 x-pack/test_serverless/api_integration/test_suites/reporting/services/usage.ts delete mode 100644 x-pack/test_serverless/functional/page_objects/svl_reporting_page.ts create mode 100644 x-pack/test_serverless/functional/test_suites/common/reporting/index.ts create mode 100644 x-pack/test_serverless/functional/test_suites/common/reporting/management.ts delete mode 100644 x-pack/test_serverless/functional/test_suites/reporting/config.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 0df0cf3793a912..70be71f08184ab 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -87,12 +87,10 @@ disabled: - x-pack/test_serverless/api_integration/test_suites/observability/config.ts - x-pack/test_serverless/api_integration/test_suites/search/config.ts - x-pack/test_serverless/api_integration/test_suites/security/config.ts - - x-pack/test_serverless/api_integration/test_suites/reporting/config.ts - x-pack/test_serverless/functional/test_suites/common/config.ts - x-pack/test_serverless/functional/test_suites/observability/config.ts - x-pack/test_serverless/functional/test_suites/search/config.ts - x-pack/test_serverless/functional/test_suites/security/config.ts - - x-pack/test_serverless/functional/test_suites/reporting/config.ts defaultQueue: 'n2-4-spot' enabled: diff --git a/x-pack/test_serverless/api_integration/services/index.ts b/x-pack/test_serverless/api_integration/services/index.ts index 4b5bef7f70fb36..8da2b387ca3777 100644 --- a/x-pack/test_serverless/api_integration/services/index.ts +++ b/x-pack/test_serverless/api_integration/services/index.ts @@ -11,15 +11,16 @@ import { services as xpackApiIntegrationServices } from '../../../test/api_integ import { services as svlSharedServices } from '../../shared/services'; import { SvlCommonApiServiceProvider } from './svl_common_api'; +import { SvlReportingServiceProvider } from './svl_reporting'; import { AlertingApiProvider } from './alerting_api'; -import { ReportingApiProvider } from './reporting_api'; export const services = { ...xpackApiIntegrationServices, ...svlSharedServices, + svlCommonApi: SvlCommonApiServiceProvider, + svlReportingAPI: SvlReportingServiceProvider, alertingApi: AlertingApiProvider, - reportingApi: ReportingApiProvider, }; export type InheritedFtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test_serverless/api_integration/services/reporting_api.ts b/x-pack/test_serverless/api_integration/services/reporting_api.ts deleted file mode 100644 index 29ed0491044473..00000000000000 --- a/x-pack/test_serverless/api_integration/services/reporting_api.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 { createUsageServices } from '../test_suites/reporting/services/usage'; -import { createScenarios } from '../test_suites/reporting/services/scenarios'; -import { FtrProviderContext } from '../ftr_provider_context'; -import { services as apiIntegrationServices } from '.'; - -export function ReportingApiProvider(context: FtrProviderContext) { - return { - ...createScenarios(context), - ...createUsageServices(context), - }; -} - -export const services = { - supertestWithoutAuth: apiIntegrationServices.supertestWithoutAuth, - usageAPI: apiIntegrationServices.usageAPI, -}; diff --git a/x-pack/test_serverless/api_integration/services/svl_reporting.ts b/x-pack/test_serverless/api_integration/services/svl_reporting.ts new file mode 100644 index 00000000000000..f71b9b311b46b2 --- /dev/null +++ b/x-pack/test_serverless/api_integration/services/svl_reporting.ts @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; + +const DATA_ANALYST_PASSWORD = 'data_analyst-password'; +const DATA_ANALYST_ROLE = 'data_analyst_role'; +const DATA_ANALYST_USERNAME = 'data_analyst'; +const REPORTING_ROLE = 'reporting_user_role'; +const REPORTING_USER_PASSWORD = 'reporting_user-password'; +const REPORTING_USER_USERNAME = 'reporting_user'; + +export function SvlReportingServiceProvider({ getService }: FtrProviderContext) { + const security = getService('security'); + + return { + DATA_ANALYST_PASSWORD, + DATA_ANALYST_USERNAME, + REPORTING_USER_PASSWORD, + REPORTING_USER_USERNAME, + + /** + * Define a role that DOES NOT grant privileges to create any type of report. + */ + async createDataAnalystRole() { + await security.role.create(DATA_ANALYST_ROLE, { + metadata: {}, + elasticsearch: { + cluster: [], + indices: [ + { + names: ['ecommerce'], + privileges: ['read', 'view_index_metadata'], + allow_restricted_indices: false, + }, + ], + run_as: [], + }, + kibana: [ + { + base: ['read'], + feature: {}, + spaces: ['*'], + }, + ], + }); + }, + + async createDataAnalystUser() { + await security.user.create(DATA_ANALYST_USERNAME, { + password: DATA_ANALYST_PASSWORD, + roles: [DATA_ANALYST_ROLE], + full_name: 'Data Analyst User', + }); + }, + + /** + * Define a role that DOES grant privileges to create certain types of reports. + */ + async createReportingRole() { + await security.role.create(REPORTING_ROLE, { + metadata: {}, + elasticsearch: { + cluster: [], + indices: [ + { + names: ['ecommerce'], + privileges: ['read', 'view_index_metadata'], + allow_restricted_indices: false, + }, + ], + run_as: [], + }, + kibana: [ + { + base: [], + feature: { discover: ['minimal_read', 'generate_report'] }, + spaces: ['*'], + }, + ], + }); + }, + + async createReportingUser( + username = REPORTING_USER_USERNAME, + password = REPORTING_USER_PASSWORD + ) { + await security.user.create(username, { + password, + roles: [REPORTING_ROLE], + full_name: 'Reporting User', + }); + }, + }; +} diff --git a/x-pack/test_serverless/api_integration/test_suites/common/index.ts b/x-pack/test_serverless/api_integration/test_suites/common/index.ts index 7f5c93b0dbaffb..0f701ee60243ea 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/index.ts @@ -12,5 +12,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./security_users')); loadTestFile(require.resolve('./spaces')); loadTestFile(require.resolve('./security_response_headers')); + loadTestFile(require.resolve('./reporting')); }); } diff --git a/x-pack/test_serverless/api_integration/test_suites/common/reporting/index.ts b/x-pack/test_serverless/api_integration/test_suites/common/reporting/index.ts new file mode 100644 index 00000000000000..461b195d36f0cd --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/common/reporting/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default ({ loadTestFile }: FtrProviderContext) => { + describe('Reporting', function () { + loadTestFile(require.resolve('./management')); + }); +}; diff --git a/x-pack/test_serverless/api_integration/test_suites/common/reporting/management.ts b/x-pack/test_serverless/api_integration/test_suites/common/reporting/management.ts new file mode 100644 index 00000000000000..df128dd1fec48c --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/common/reporting/management.ts @@ -0,0 +1,66 @@ +/* + * 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 { X_ELASTIC_INTERNAL_ORIGIN_REQUEST } from '@kbn/core-http-common/src/constants'; +import { INTERNAL_ROUTES } from '@kbn/reporting-plugin/common/constants'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +// the archived data holds a report created by test_user +const TEST_USERNAME = 'test_user'; +const TEST_USER_PASSWORD = 'changeme'; +const API_HEADER: [string, string] = ['kbn-xsrf', 'reporting']; +const INTERNAL_HEADER: [string, string] = [X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'Kibana']; + +export default ({ getService }: FtrProviderContext) => { + const esArchiver = getService('esArchiver'); + const reportingAPI = getService('svlReportingAPI'); + const supertest = getService('supertestWithoutAuth'); + + describe('Reporting Management', function () { + before(async () => { + // NOTE: unused, since we only need test_user for this suite + await reportingAPI.createReportingRole(); + await reportingAPI.createReportingUser(); + await reportingAPI.createReportingUser(TEST_USERNAME, TEST_USER_PASSWORD); + }); + + beforeEach(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/reporting/archived_reports'); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/reporting/archived_reports'); + }); + + describe('Deletion', () => { + const DELETE_REPORT_ID = 'krazcyw4156m0763b503j7f9'; + + it(`user can delete a report they've created`, async () => { + const response = await supertest + .delete(`${INTERNAL_ROUTES.JOBS.DELETE_PREFIX}/${DELETE_REPORT_ID}`) + .auth(TEST_USERNAME, TEST_USER_PASSWORD) + .set(...API_HEADER) + .set(...INTERNAL_HEADER); + + expect(response.status).to.be(200); + expect(response.body).to.eql({ deleted: true }); + }); + + it(`user can not delete a report they haven't created`, async () => { + const response = await supertest + .delete(`${INTERNAL_ROUTES.JOBS.DELETE_PREFIX}/${DELETE_REPORT_ID}`) + .auth(reportingAPI.REPORTING_USER_USERNAME, reportingAPI.REPORTING_USER_PASSWORD) + .set(...API_HEADER) + .set(...INTERNAL_HEADER); + + expect(response.status).to.be(404); + expect(response.body.message).to.be('Not Found'); + }); + }); + }); +}; diff --git a/x-pack/test_serverless/api_integration/test_suites/reporting/config.ts b/x-pack/test_serverless/api_integration/test_suites/reporting/config.ts deleted file mode 100644 index 237bb94ed1dc6e..00000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/reporting/config.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 { FtrConfigProviderContext } from '@kbn/test'; -import { resolve } from 'path'; -import { ReportingAPIProvider } from './services'; - -export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const apiConfig = await readConfigFile(require.resolve('../api_integration/config')); - - // config for testing network policy - const testPolicyRules = [ - { allow: true, protocol: 'http:' }, - { allow: false, host: 'via.placeholder.com' }, - { allow: true, protocol: 'https:' }, - { allow: true, protocol: 'data:' }, - { allow: false }, - ]; - - return { - ...apiConfig.getAll(), - junit: { reportName: 'X-Pack Reporting API Integration Tests' }, - testFiles: [resolve(__dirname, './reporting_and_security')], - services: { - ...apiConfig.get('services'), - reportingAPI: ReportingAPIProvider, - }, - kbnTestServer: { - ...apiConfig.get('kbnTestServer'), - serverArgs: [ - ...apiConfig.get('kbnTestServer.serverArgs'), - `--xpack.screenshotting.networkPolicy.rules=${JSON.stringify(testPolicyRules)}`, - `--xpack.reporting.capture.maxAttempts=1`, - `--xpack.reporting.csv.maxSizeBytes=6000`, - '--xpack.reporting.roles.enabled=false', // Reporting access control is implemented by sub-feature application privileges - // for testing set buffer duration to 0 to immediately flush counters into saved objects. - '--usageCollection.usageCounters.bufferDuration=0', - ], - }, - }; -} diff --git a/x-pack/test_serverless/api_integration/test_suites/reporting/index.ts b/x-pack/test_serverless/api_integration/test_suites/reporting/index.ts deleted file mode 100644 index 6c1f979e269089..00000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/reporting/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FtrProviderContext } from '../../ftr_provider_context'; - -// eslint-disable-next-line import/no-default-export -export default function ({ getService, loadTestFile }: FtrProviderContext) { - describe('Reporting Functional Tests with Security enabled for Serverless', function () { - before(async () => { - const reportingFunctional = getService('reportingFunctional'); - await reportingFunctional.logTaskManagerHealth(); - await reportingFunctional.createDataAnalystRole(); - await reportingFunctional.createDataAnalyst(); - await reportingFunctional.createTestReportingUserRole(); - await reportingFunctional.createTestReportingUser(); - }); - - loadTestFile(require.resolve('./security_roles_privileges')); - loadTestFile(require.resolve('./management')); - }); -} diff --git a/x-pack/test_serverless/api_integration/test_suites/reporting/management.ts b/x-pack/test_serverless/api_integration/test_suites/reporting/management.ts deleted file mode 100644 index cdd890b906291a..00000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/reporting/management.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 type { FtrProviderContext } from '../../../functional/page_objects/svl_common_navigation'; - -export default ({ getService, getPageObject }: FtrProviderContext) => { - // const svlCommonApi = getService('svlCommonApi'); - const svlCommonNavigation = getPageObject('svlCommonNavigation'); - const testSubjects = getService('testSubjects'); - - /** - * Load sample data from the visualize library - */ - // http://localhost:5601/cue/app/home#/tutorial_directory/sampleData - // Management - // data-test-subj="showSampleDataButton" - // data-test-subj="addSampleDataSetecommerce" - // wait for toast Sample eCommerce orders installed - - const reportingFunctional = getService('reportingFunctional'); - - describe('Access to Management > Reporting', () => { - // before(async () => { - // await reportingFunctional.initEcommerce(); - // svlCommonNavigation.sideNav.clickLink('Management') - - // }); - // after(async () => { - // await reportingFunctional.teardownEcommerce(); - // }); - // this.tags(['skipSvlObt', 'skipSvlSec'], () => {}) - - it('does not allow user that does not have reporting privileges', async () => { - await reportingFunctional.loginDataAnalyst(); - await svlCommonNavigation.navigateToApp('reporting'); - await testSubjects.missingOrFail('reportJobListing'); - }); - - it('does allow user with reporting privileges', async () => { - await reportingFunctional.loginReportingUser(); - await svlCommonNavigation.navigateToApp('reporting'); - await testSubjects.existOrFail('reportJobListing'); - }); - }); -}; diff --git a/x-pack/test_serverless/api_integration/test_suites/reporting/reporting.ts b/x-pack/test_serverless/api_integration/test_suites/reporting/reporting.ts deleted file mode 100644 index 3d7482af0edaec..00000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/reporting/reporting.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 { FtrConfigProviderContext } from '@kbn/test'; -import { resolve } from 'path'; -import { ReportingFunctionalProvider } from '../../../../test/reporting_functional/services'; -import { ReportingAPIProvider } from './services'; - -export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); // Reporting API tests need a fully working UI - const apiConfig = await readConfigFile(require.resolve('../api_integration/config')); - - return { - ...apiConfig.getAll(), - ...functionalConfig.getAll(), - junit: { reportName: 'X-Pack Reporting Functional Tests' }, - testFiles: [resolve(__dirname, './reporting_and_security')], - kbnTestServer: { - ...functionalConfig.get('kbnTestServer'), - serverArgs: [ - ...functionalConfig.get('kbnTestServer.serverArgs'), - `--xpack.reporting.capture.maxAttempts=1`, - `--xpack.reporting.csv.maxSizeBytes=6000`, - '--xpack.reporting.roles.enabled=false', // Reporting access control is implemented by sub-feature application privileges - ], - }, - services: { - ...apiConfig.get('services'), - ...functionalConfig.get('services'), - reportingAPI: ReportingAPIProvider, - reportingFunctional: ReportingFunctionalProvider, - }, - }; -} diff --git a/x-pack/test_serverless/api_integration/test_suites/reporting/security_role_priviledges.ts b/x-pack/test_serverless/api_integration/test_suites/reporting/security_role_priviledges.ts deleted file mode 100644 index 5a64b2934914f7..00000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/reporting/security_role_priviledges.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FtrProviderContext } from '../../ftr_provider_context'; - -const DASHBOARD_TITLE = 'Ecom Dashboard'; -const SAVEDSEARCH_TITLE = 'Ecommerce Data'; - -// eslint-disable-next-line import/no-default-export -export default function ({ getService }: FtrProviderContext) { - const reportingFunctional = getService('reportingFunctional'); - - describe('Security with `reporting_user` built-in role', () => { - before(async () => { - await reportingFunctional.initEcommerce(); - }); - after(async () => { - await reportingFunctional.teardownEcommerce(); - }); - - describe('Dashboard: Download CSV file', () => { - it('does not allow user that does not have reporting privileges', async () => { - await reportingFunctional.loginDataAnalyst(); - await reportingFunctional.openSavedDashboard(DASHBOARD_TITLE); - await reportingFunctional.tryDashboardDownloadCsvNotAvailable('Ecommerce Data'); - }); - - it('does allow user with reporting privileges', async () => { - await reportingFunctional.loginReportingUser(); - await reportingFunctional.openSavedDashboard(DASHBOARD_TITLE); - await reportingFunctional.tryDashboardDownloadCsvSuccess('Ecommerce Data'); - }); - }); - - describe('Discover: Generate CSV', () => { - it('does not allow user that does not have reporting privileges', async () => { - await reportingFunctional.loginDataAnalyst(); - await reportingFunctional.openSavedSearch(SAVEDSEARCH_TITLE); - await reportingFunctional.tryDiscoverCsvNotAvailable(); - }); - - it('does allow user with reporting privileges', async () => { - await reportingFunctional.loginReportingUser(); - await reportingFunctional.openSavedSearch(SAVEDSEARCH_TITLE); - await reportingFunctional.tryDiscoverCsvSuccess(); - }); - }); - }); -} diff --git a/x-pack/test_serverless/api_integration/test_suites/reporting/services/index.ts b/x-pack/test_serverless/api_integration/test_suites/reporting/services/index.ts deleted file mode 100644 index 31c108a6fae834..00000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/reporting/services/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 { services as svlServices } from '../../../services'; -import { createUsageServices } from './usage'; -import { createScenarios } from './scenarios'; -import { FtrProviderContext } from '../../../ftr_provider_context'; - -export function ReportingAPIProvider(context: FtrProviderContext) { - return { - ...createScenarios(context), - ...createUsageServices(context), - }; -} - -export const services = { - ...svlServices, - supertestWithoutAuth: svlServices.supertestWithoutAuth, - usageAPI: svlServices.usageAPI, - reportingAPI: ReportingAPIProvider, -}; diff --git a/x-pack/test_serverless/api_integration/test_suites/reporting/services/scenarios.ts b/x-pack/test_serverless/api_integration/test_suites/reporting/services/scenarios.ts deleted file mode 100644 index 230b246d93f901..00000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/reporting/services/scenarios.ts +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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 { INTERNAL_ROUTES } from '@kbn/reporting-plugin/common/constants/routes'; -import { JobParamsCSV } from '@kbn/reporting-plugin/server/export_types/csv_searchsource/types'; -import { JobParamsDownloadCSV } from '@kbn/reporting-plugin/server/export_types/csv_searchsource_immediate/types'; -import rison from '@kbn/rison'; -import { FtrProviderContext } from '../../../ftr_provider_context'; - -function removeWhitespace(str: string) { - return str.replace(/\s/g, ''); -} - -export function createScenarios({ getService }: Pick) { - const security = getService('security'); - const esArchiver = getService('esArchiver'); - const log = getService('log'); - const supertest = getService('supertest'); - const esSupertest = getService('esSupertest'); - const kibanaServer = getService('kibanaServer'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const retry = getService('retry'); - - const ecommerceSOPath = 'x-pack/test/functional/fixtures/kbn_archiver/reporting/ecommerce.json'; - const logsSOPath = 'x-pack/test/functional/fixtures/kbn_archiver/reporting/logs'; - - const DATA_ANALYST_USERNAME = 'data_analyst'; - const DATA_ANALYST_PASSWORD = 'data_analyst-password'; - const REPORTING_USER_USERNAME = 'reporting_user'; - const REPORTING_USER_PASSWORD = 'reporting_user-password'; - const REPORTING_ROLE = 'test_reporting_user'; - - const logTaskManagerHealth = async () => { - // Check task manager health for analyzing test failures. See https://github.com/elastic/kibana/issues/114946 - const tmHealth = await supertest.get(`/api/task_manager/_health`); - const driftValues = tmHealth.body?.stats?.runtime?.value; - - log.info(`Task Manager status: "${tmHealth.body?.status}"`); - log.info(`Task Manager overall drift rankings: "${JSON.stringify(driftValues?.drift)}"`); - log.info( - `Task Manager drift rankings for "report:execute": "${JSON.stringify( - driftValues?.drift_by_type?.['report:execute'] - )}"` - ); - }; - - const initEcommerce = async () => { - await esArchiver.load('x-pack/test/functional/es_archives/reporting/ecommerce'); - await kibanaServer.importExport.load(ecommerceSOPath); - }; - const teardownEcommerce = async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/reporting/ecommerce'); - await kibanaServer.importExport.unload(ecommerceSOPath); - await deleteAllReports(); - }; - - const initLogs = async () => { - await esArchiver.load('x-pack/test/functional/es_archives/logstash_functional'); - await kibanaServer.importExport.load(logsSOPath); - }; - const teardownLogs = async () => { - await kibanaServer.importExport.unload(logsSOPath); - await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional'); - }; - - const createDataAnalystRole = async () => { - await security.role.create('data_analyst', { - metadata: {}, - elasticsearch: { - cluster: [], - indices: [ - { - names: ['ecommerce'], - privileges: ['read', 'view_index_metadata'], - allow_restricted_indices: false, - }, - ], - run_as: [], - }, - kibana: [{ base: ['read'], feature: {}, spaces: ['*'] }], - }); - }; - - const createTestReportingUserRole = async () => { - await security.role.create(REPORTING_ROLE, { - metadata: {}, - elasticsearch: { - cluster: [], - indices: [ - { - names: ['ecommerce'], - privileges: ['read', 'view_index_metadata'], - allow_restricted_indices: false, - }, - ], - run_as: [], - }, - kibana: [ - { - base: [], - feature: { - dashboard: ['minimal_read', 'download_csv_report', 'generate_report'], - discover: ['minimal_read', 'generate_report'], - canvas: ['minimal_read', 'generate_report'], - visualize: ['minimal_read', 'generate_report'], - }, - spaces: ['*'], - }, - ], - }); - }; - - const createDataAnalyst = async () => { - await security.user.create('data_analyst', { - password: 'data_analyst-password', - roles: ['data_analyst'], - full_name: 'Data Analyst User', - }); - }; - - const createTestReportingUser = async () => { - await security.user.create(REPORTING_USER_USERNAME, { - password: REPORTING_USER_PASSWORD, - roles: [REPORTING_ROLE], - full_name: 'Reporting User', - }); - }; - - const downloadCsv = async (username: string, password: string, job: JobParamsDownloadCSV) => { - return await supertestWithoutAuth - .post(INTERNAL_ROUTES.DOWNLOAD_CSV) - .auth(username, password) - .set('kbn-xsrf', 'xxx') - .send(job); - }; - - const generateCsv = async ( - job: JobParamsCSV, - username = 'elastic', - password = process.env.TEST_KIBANA_PASS || 'changeme' - ) => { - const jobParams = rison.encode(job); - - return await supertestWithoutAuth - .post(`/api/reporting/generate/csv_searchsource`) - .auth(username, password) - .set('kbn-xsrf', 'xxx') - .send({ jobParams }); - }; - - const postJob = async (apiPath: string): Promise => { - log.debug(`ReportingAPI.postJob(${apiPath})`); - const { body } = await supertest - .post(removeWhitespace(apiPath)) - .set('kbn-xsrf', 'xxx') - .expect(200); - return body.path; - }; - - const postJobJSON = async (apiPath: string, jobJSON: object = {}): Promise => { - log.debug(`ReportingAPI.postJobJSON((${apiPath}): ${JSON.stringify(jobJSON)})`); - const { body } = await supertest.post(apiPath).set('kbn-xsrf', 'xxx').send(jobJSON); - return body.path; - }; - - const getCompletedJobOutput = async (downloadReportPath: string) => { - const response = await supertest.get(downloadReportPath); - return response.text as unknown; - }; - - const getJobErrorCode = async ( - id: string, - username = 'elastic', - password = process.env.TEST_KIBANA_PASS || 'changeme' - ): Promise => { - const { - body: [job], - } = await supertestWithoutAuth - .get(`${INTERNAL_ROUTES.JOBS.LIST}?page=0&ids=${id}`) - .auth(username, password) - .set('kbn-xsrf', 'xxx') - .send() - .expect(200); - return job?.output?.error_code; - }; - - const deleteAllReports = async () => { - log.debug('ReportingAPI.deleteAllReports'); - - // ignores 409 errs and keeps retrying - await retry.tryForTime(5000, async () => { - await esSupertest - .post('/.reporting*/_delete_by_query') - .send({ query: { match_all: {} } }) - .expect(200); - }); - }; - - return { - logTaskManagerHealth, - initEcommerce, - teardownEcommerce, - initLogs, - teardownLogs, - DATA_ANALYST_USERNAME, - DATA_ANALYST_PASSWORD, - REPORTING_USER_USERNAME, - REPORTING_USER_PASSWORD, - REPORTING_ROLE, - createDataAnalystRole, - createDataAnalyst, - createTestReportingUserRole, - createTestReportingUser, - downloadCsv, - generateCsv, - postJob, - postJobJSON, - getCompletedJobOutput, - deleteAllReports, - getJobErrorCode, - }; -} diff --git a/x-pack/test_serverless/api_integration/test_suites/reporting/services/usage.ts b/x-pack/test_serverless/api_integration/test_suites/reporting/services/usage.ts deleted file mode 100644 index a74ccd6a9b221d..00000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/reporting/services/usage.ts +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 { INTERNAL_ROUTES, PUBLIC_ROUTES } from '@kbn/reporting-plugin/common/constants/routes'; -import { indexTimestamp } from '@kbn/reporting-plugin/server/lib/store/index_timestamp'; -import { JobTypes, ReportingUsageType } from '@kbn/reporting-plugin/server/usage/types'; -import { Response } from 'supertest'; -import { FtrProviderContext } from '../../../ftr_provider_context'; - -export function createUsageServices({ getService }: FtrProviderContext) { - const log = getService('log'); - const esSupertest = getService('esSupertest'); - const supertest = getService('supertest'); - - return { - async waitForJobToFinish(downloadReportPath: string, ignoreFailure = false) { - log.debug(`Waiting for job to finish: ${downloadReportPath}`); - const JOB_IS_PENDING_CODE = 503; - let response: Response & { statusCode?: number }; - - const statusCode = await new Promise((resolve) => { - const intervalId = setInterval(async () => { - response = await supertest.get(downloadReportPath).responseType('blob'); - if (response.statusCode === 503) { - log.debug(`Report at path ${downloadReportPath} is pending`); - } else if (response.statusCode === 200) { - log.debug(`Report at path ${downloadReportPath} is complete`); - } else { - log.debug(`Report at path ${downloadReportPath} returned code ${response.statusCode}`); - } - if (response.statusCode !== JOB_IS_PENDING_CODE) { - clearInterval(intervalId); - resolve(response.statusCode); - } - }, 1500); - }); - if (!ignoreFailure) { - const jobInfo = await supertest.get( - downloadReportPath.replace( - PUBLIC_ROUTES.JOBS.DOWNLOAD_PREFIX, - INTERNAL_ROUTES.JOBS.INFO_PREFIX - ) - ); - expect(jobInfo.body.output.warnings).to.be(undefined); // expect no failure message to be present in job info - expect(statusCode).to.be(200); - } - }, - - /** - * - * @return {Promise} A function to call to clean up the index alias that was added. - */ - async coerceReportsIntoExistingIndex(indexName: string) { - log.debug(`ReportingAPI.coerceReportsIntoExistingIndex(${indexName})`); - - // Adding an index alias coerces the report to be generated on an existing index which means any new - // index schema won't be applied. This is important if a point release updated the schema. Reports may still - // be inserted into an existing index before the new schema is applied. - const timestampForIndex = indexTimestamp('week', '.'); - await esSupertest - .post('/_aliases') - .send({ - actions: [ - { - add: { index: indexName, alias: `.reporting-${timestampForIndex}` }, - }, - ], - }) - .expect(200); - - return async () => { - await esSupertest - .post('/_aliases') - .send({ - actions: [ - { - remove: { index: indexName, alias: `.reporting-${timestampForIndex}` }, - }, - ], - }) - .expect(200); - }; - }, - - async expectAllJobsToFinishSuccessfully(jobPaths: string[]) { - await Promise.all( - jobPaths.map(async (path) => { - log.debug(`wait for job to finish: ${path}`); - await this.waitForJobToFinish(path); - }) - ); - }, - - expectRecentJobTypeTotalStats(stats: ReportingUsageType, jobType: string, count: number) { - const actual = stats.last7Days[jobType as keyof JobTypes].total; - log.info( - `expecting recent stats to report ${count} ${jobType} job types (actual: ${actual})` - ); - expect(actual).to.be(count); - }, - - expectAllTimeJobTypeTotalStats(stats: ReportingUsageType, jobType: string, count: number) { - const actual = stats[jobType as keyof JobTypes].total; - log.info( - `expecting all time stats to report ${count} ${jobType} job types (actual: ${actual})` - ); - expect(actual).to.be(count); - }, - - getCompletedReportCount(stats: ReportingUsageType) { - return stats.status.completed; - }, - - expectCompletedReportCount(stats: ReportingUsageType, count: number) { - expect(this.getCompletedReportCount(stats)).to.be(count); - }, - }; -} diff --git a/x-pack/test_serverless/functional/page_objects/index.ts b/x-pack/test_serverless/functional/page_objects/index.ts index e667bba0b6c47c..a40eca62f0b52c 100644 --- a/x-pack/test_serverless/functional/page_objects/index.ts +++ b/x-pack/test_serverless/functional/page_objects/index.ts @@ -14,7 +14,6 @@ import { SvlObltOnboardingStreamLogFilePageProvider } from './svl_oblt_onboardin import { SvlObltOverviewPageProvider } from './svl_oblt_overview_page'; import { SvlSearchLandingPageProvider } from './svl_search_landing_page'; import { SvlSecLandingPageProvider } from './svl_sec_landing_page'; -import { SvlReportingProvider } from './svl_reporting_page'; export const pageObjects = { ...xpackFunctionalPageObjects, @@ -26,5 +25,4 @@ export const pageObjects = { svlObltOverviewPage: SvlObltOverviewPageProvider, svlSearchLandingPage: SvlSearchLandingPageProvider, svlSecLandingPage: SvlSecLandingPageProvider, - svlReportingPage: SvlReportingProvider, }; diff --git a/x-pack/test_serverless/functional/page_objects/svl_reporting_page.ts b/x-pack/test_serverless/functional/page_objects/svl_reporting_page.ts deleted file mode 100644 index c9d8c4b0f9b891..00000000000000 --- a/x-pack/test_serverless/functional/page_objects/svl_reporting_page.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FtrProviderContext } from '../ftr_provider_context'; - -export function SvlReportingProvider({ getService }: FtrProviderContext) { - const testSubjects = getService('testSubjects'); - - return { - async assertPageHeaderExists() { - await testSubjects.existOrFail('reportingPageHeader'); - }, - }; -} diff --git a/x-pack/test_serverless/functional/test_suites/common/index.ts b/x-pack/test_serverless/functional/test_suites/common/index.ts index 31497afb8c7d8a..ffad53a2f0000b 100644 --- a/x-pack/test_serverless/functional/test_suites/common/index.ts +++ b/x-pack/test_serverless/functional/test_suites/common/index.ts @@ -12,6 +12,9 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./home_page')); loadTestFile(require.resolve('./management')); + // reporting management app + loadTestFile(require.resolve('./reporting')); + // platform security loadTestFile(require.resolve('./security/navigation/avatar_menu')); }); diff --git a/x-pack/test_serverless/functional/test_suites/common/reporting/index.ts b/x-pack/test_serverless/functional/test_suites/common/reporting/index.ts new file mode 100644 index 00000000000000..461b195d36f0cd --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/common/reporting/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default ({ loadTestFile }: FtrProviderContext) => { + describe('Reporting', function () { + loadTestFile(require.resolve('./management')); + }); +}; diff --git a/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts b/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts new file mode 100644 index 00000000000000..923ddb822c9b32 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + // const esArchiver = getService('esArchiver'); + // const log = getService('log'); + // const pageObjects = getPageObjects(['common', 'security']); + // const retry = getService('retry'); + // const testSubjects = getService('testSubjects'); + + describe('Reporting Management', function () {}); +}; diff --git a/x-pack/test_serverless/functional/test_suites/reporting/config.ts b/x-pack/test_serverless/functional/test_suites/reporting/config.ts deleted file mode 100644 index 3b603fefed4ee9..00000000000000 --- a/x-pack/test_serverless/functional/test_suites/reporting/config.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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 { createTestConfig } from '../../config.base'; - -export default createTestConfig({ - serverlessProject: 'es', - testFiles: [require.resolve('../common'), require.resolve('.')], - junit: { - reportName: 'Serverless Reporting Functional Tests', - }, - suiteTags: { exclude: ['skipSvlOblt', 'skipSvlSecurity'] }, -}); diff --git a/x-pack/test_serverless/tsconfig.json b/x-pack/test_serverless/tsconfig.json index 8044832f4db6d1..9e48f09291a3e8 100644 --- a/x-pack/test_serverless/tsconfig.json +++ b/x-pack/test_serverless/tsconfig.json @@ -46,5 +46,8 @@ "@kbn/test-subj-selector", "@kbn/reporting-plugin", "@kbn/rison", + "@kbn/core-http-common", + "@kbn/data-views-plugin", + "@kbn/core-saved-objects-server", ] }