mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Endpoint][EPM] Endpoint depending on ingest manager to initialize (#62871)
* Endpoint successfully depending on ingest manager to initialize * Moving the endpoint functional tests to their own directory to avoid enabling ingest in the base tests * Removing page objects and other endpoint fields from base functional * Updating code owners with new functional location * Pointing resolver tests at endpoint functional tests * Pointing space tests at the endpoint functional directory * Adding jest test names
This commit is contained in:
parent
883af70089
commit
6b5cbd562f
31 changed files with 238 additions and 16 deletions
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
|
@ -202,7 +202,8 @@
|
|||
# Endpoint
|
||||
/x-pack/plugins/endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/api_integration/apis/endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional/apps/endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional_endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional_endpoint_ingest_failure/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional/es_archives/endpoint/ @elastic/endpoint-app-team
|
||||
|
||||
# SIEM
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.0.0",
|
||||
"kibanaVersion": "kibana",
|
||||
"configPath": ["xpack", "endpoint"],
|
||||
"requiredPlugins": ["features", "embeddable", "data", "dataEnhanced"],
|
||||
"requiredPlugins": ["features", "embeddable", "data", "dataEnhanced", "ingestManager"],
|
||||
"server": true,
|
||||
"ui": true
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import { PolicyList } from './view/policy';
|
|||
import { PolicyDetails } from './view/policy';
|
||||
import { HeaderNavigation } from './components/header_nav';
|
||||
import { AppRootProvider } from './view/app_root_provider';
|
||||
import { Setup } from './view/setup';
|
||||
|
||||
/**
|
||||
* This module will be loaded asynchronously to reduce the bundle size of your plugin's main bundle.
|
||||
|
@ -48,6 +49,7 @@ const AppRoot: React.FunctionComponent<RouterProps> = React.memo(
|
|||
({ history, store, coreStart, depsStart }) => {
|
||||
return (
|
||||
<AppRootProvider store={store} history={history} coreStart={coreStart} depsStart={depsStart}>
|
||||
<Setup ingestManager={depsStart.ingestManager} notifications={coreStart.notifications} />
|
||||
<HeaderNavigation />
|
||||
<Switch>
|
||||
<Route
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { IngestManagerStart } from '../../../../../ingest_manager/public';
|
||||
import {
|
||||
dataPluginMock,
|
||||
Start as DataPublicStartMock,
|
||||
|
@ -32,6 +33,7 @@ type DataMock = Omit<DataPublicStartMock, 'indexPatterns' | 'query'> & {
|
|||
*/
|
||||
export interface DepsStartMock {
|
||||
data: DataMock;
|
||||
ingestManager: IngestManagerStart;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,5 +56,6 @@ export const depsStartMock: () => DepsStartMock = () => {
|
|||
|
||||
return {
|
||||
data: dataMock,
|
||||
ingestManager: { success: true },
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import * as React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { NotificationsStart } from 'kibana/public';
|
||||
import { IngestManagerStart } from '../../../../../ingest_manager/public';
|
||||
|
||||
export const Setup: React.FunctionComponent<{
|
||||
ingestManager: IngestManagerStart;
|
||||
notifications: NotificationsStart;
|
||||
}> = ({ ingestManager, notifications }) => {
|
||||
React.useEffect(() => {
|
||||
const defaultText = i18n.translate('xpack.endpoint.ingestToastMessage', {
|
||||
defaultMessage: 'Ingest Manager failed during its setup.',
|
||||
});
|
||||
|
||||
const title = i18n.translate('xpack.endpoint.ingestToastTitle', {
|
||||
defaultMessage: 'App failed to initialize',
|
||||
});
|
||||
|
||||
const displayToastWithModal = (text: string) => {
|
||||
const errorText = new Error(defaultText);
|
||||
// we're leveraging the notification's error toast which is usually used for displaying stack traces of an
|
||||
// actually Error. Instead of displaying a stack trace we'll display the more detailed error text when the
|
||||
// user clicks `See the full error` button to see the modal
|
||||
errorText.stack = text;
|
||||
notifications.toasts.addError(errorText, {
|
||||
title,
|
||||
});
|
||||
};
|
||||
|
||||
const displayToast = () => {
|
||||
notifications.toasts.addDanger({
|
||||
title,
|
||||
text: defaultText,
|
||||
});
|
||||
};
|
||||
|
||||
if (!ingestManager.success) {
|
||||
if (ingestManager.error) {
|
||||
displayToastWithModal(ingestManager.error.message);
|
||||
} else {
|
||||
displayToast();
|
||||
}
|
||||
}
|
||||
}, [ingestManager, notifications.toasts]);
|
||||
|
||||
return null;
|
||||
};
|
|
@ -8,6 +8,7 @@ import { Plugin, CoreSetup, AppMountParameters, CoreStart } from 'kibana/public'
|
|||
import { EmbeddableSetup } from 'src/plugins/embeddable/public';
|
||||
import { DataPublicPluginStart } from 'src/plugins/data/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { IngestManagerStart } from '../../ingest_manager/public';
|
||||
import { ResolverEmbeddableFactory } from './embeddables/resolver';
|
||||
|
||||
export type EndpointPluginStart = void;
|
||||
|
@ -18,6 +19,7 @@ export interface EndpointPluginSetupDependencies {
|
|||
}
|
||||
export interface EndpointPluginStartDependencies {
|
||||
data: DataPublicPluginStart;
|
||||
ingestManager: IngestManagerStart;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -252,6 +252,7 @@ export enum IngestAssetType {
|
|||
export enum DefaultPackages {
|
||||
base = 'base',
|
||||
system = 'system',
|
||||
endpoint = 'endpoint',
|
||||
}
|
||||
|
||||
export interface IndexTemplate {
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
import { PluginInitializerContext } from 'src/core/public';
|
||||
import { IngestManagerPlugin } from './plugin';
|
||||
|
||||
export { IngestManagerStart } from './plugin';
|
||||
|
||||
export const plugin = (initializerContext: PluginInitializerContext) => {
|
||||
return new IngestManagerPlugin(initializerContext);
|
||||
};
|
||||
|
|
|
@ -17,11 +17,20 @@ import { LicensingPluginSetup } from '../../licensing/public';
|
|||
import { PLUGIN_ID } from '../common/constants';
|
||||
|
||||
import { IngestManagerConfigType } from '../common/types';
|
||||
import { setupRouteService } from '../common';
|
||||
|
||||
export { IngestManagerConfigType } from '../common/types';
|
||||
|
||||
export type IngestManagerSetup = void;
|
||||
export type IngestManagerStart = void;
|
||||
/**
|
||||
* Describes public IngestManager plugin contract returned at the `start` stage.
|
||||
*/
|
||||
export interface IngestManagerStart {
|
||||
success: boolean;
|
||||
error?: {
|
||||
message: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IngestManagerSetupDeps {
|
||||
licensing: LicensingPluginSetup;
|
||||
|
@ -61,7 +70,14 @@ export class IngestManagerPlugin
|
|||
});
|
||||
}
|
||||
|
||||
public start(core: CoreStart) {}
|
||||
public async start(core: CoreStart): Promise<IngestManagerStart> {
|
||||
try {
|
||||
const { isInitialized: success } = await core.http.post(setupRouteService.getSetupPath());
|
||||
return { success };
|
||||
} catch (error) {
|
||||
return { success: false, error: { message: error.body?.message || 'Unknown error' } };
|
||||
}
|
||||
}
|
||||
|
||||
public stop() {}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ const onlyNotInCoverageTests = [
|
|||
require.resolve('../test/licensing_plugin/config.ts'),
|
||||
require.resolve('../test/licensing_plugin/config.public.ts'),
|
||||
require.resolve('../test/licensing_plugin/config.legacy.ts'),
|
||||
require.resolve('../test/functional_endpoint_ingest_failure/config.ts'),
|
||||
require.resolve('../test/functional_endpoint/config.ts'),
|
||||
];
|
||||
|
||||
require('@kbn/plugin-helpers').babelRegister();
|
||||
|
|
|
@ -57,7 +57,6 @@ export default async function({ readConfigFile }) {
|
|||
resolve(__dirname, './apps/cross_cluster_replication'),
|
||||
resolve(__dirname, './apps/remote_clusters'),
|
||||
resolve(__dirname, './apps/transform'),
|
||||
resolve(__dirname, './apps/endpoint'),
|
||||
// This license_management file must be last because it is destructive.
|
||||
resolve(__dirname, './apps/license_management'),
|
||||
],
|
||||
|
@ -88,7 +87,6 @@ export default async function({ readConfigFile }) {
|
|||
'--xpack.encryptedSavedObjects.encryptionKey="DkdXazszSCYexXqz4YktBGHCRkV6hyNK"',
|
||||
'--telemetry.banner=false',
|
||||
'--timelion.ui.enabled=true',
|
||||
'--xpack.endpoint.enabled=true',
|
||||
],
|
||||
},
|
||||
uiSettings: {
|
||||
|
@ -199,9 +197,6 @@ export default async function({ readConfigFile }) {
|
|||
pathname: '/app/kibana/',
|
||||
hash: '/management/elasticsearch/transform',
|
||||
},
|
||||
endpoint: {
|
||||
pathname: '/app/endpoint',
|
||||
},
|
||||
},
|
||||
|
||||
// choose where esArchiver should load archives from
|
||||
|
|
|
@ -389,7 +389,8 @@
|
|||
"type": "nested"
|
||||
},
|
||||
"file_extension": {
|
||||
"type": "long"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"project_file": {
|
||||
"properties": {
|
||||
|
|
|
@ -46,8 +46,6 @@ import { LensPageProvider } from './lens_page';
|
|||
import { InfraMetricExplorerProvider } from './infra_metric_explorer';
|
||||
import { RoleMappingsPageProvider } from './role_mappings_page';
|
||||
import { SpaceSelectorPageProvider } from './space_selector_page';
|
||||
import { EndpointPageProvider } from './endpoint_page';
|
||||
import { EndpointAlertsPageProvider } from './endpoint_alerts_page';
|
||||
|
||||
// just like services, PageObjects are defined as a map of
|
||||
// names to Providers. Merge in Kibana's or pick specific ones
|
||||
|
@ -81,6 +79,4 @@ export const pageObjects = {
|
|||
copySavedObjectsToSpace: CopySavedObjectsToSpacePageProvider,
|
||||
lens: LensPageProvider,
|
||||
roleMappings: RoleMappingsPageProvider,
|
||||
endpoint: EndpointPageProvider,
|
||||
endpointAlerts: EndpointAlertsPageProvider,
|
||||
};
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default ({ getPageObjects }: FtrProviderContext) => {
|
||||
export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
||||
const pageObjects = getPageObjects(['common', 'endpoint']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
describe('Endpoint landing page', function() {
|
||||
this.tags('ciGroup7');
|
||||
|
@ -20,5 +21,9 @@ export default ({ getPageObjects }: FtrProviderContext) => {
|
|||
const welcomeEndpointMessage = await pageObjects.endpoint.welcomeEndpointTitle();
|
||||
expect(welcomeEndpointMessage).to.be('Hello World');
|
||||
});
|
||||
|
||||
it('Does not display a toast indicating that the ingest manager failed to initialize', async () => {
|
||||
await testSubjects.missingOrFail('euiToastHeader');
|
||||
});
|
||||
});
|
||||
};
|
37
x-pack/test/functional_endpoint/config.ts
Normal file
37
x-pack/test/functional_endpoint/config.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { resolve } from 'path';
|
||||
import { FtrConfigProviderContext } from '@kbn/test/types/ftr';
|
||||
import { pageObjects } from './page_objects';
|
||||
|
||||
export default async function({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js'));
|
||||
|
||||
return {
|
||||
...xpackFunctionalConfig.getAll(),
|
||||
pageObjects,
|
||||
testFiles: [resolve(__dirname, './apps/endpoint')],
|
||||
junit: {
|
||||
reportName: 'X-Pack Endpoint Functional Tests',
|
||||
},
|
||||
apps: {
|
||||
...xpackFunctionalConfig.get('apps'),
|
||||
endpoint: {
|
||||
pathname: '/app/endpoint',
|
||||
},
|
||||
},
|
||||
kbnTestServer: {
|
||||
...xpackFunctionalConfig.get('kbnTestServer'),
|
||||
serverArgs: [
|
||||
...xpackFunctionalConfig.get('kbnTestServer.serverArgs'),
|
||||
'--xpack.endpoint.enabled=true',
|
||||
'--xpack.ingestManager.enabled=true',
|
||||
'--xpack.ingestManager.fleet.enabled=true',
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
12
x-pack/test/functional_endpoint/ftr_provider_context.d.ts
vendored
Normal file
12
x-pack/test/functional_endpoint/ftr_provider_context.d.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { GenericFtrProviderContext } from '@kbn/test/types/ftr';
|
||||
|
||||
import { pageObjects } from './page_objects';
|
||||
import { services } from '../functional/services';
|
||||
|
||||
export type FtrProviderContext = GenericFtrProviderContext<typeof services, typeof pageObjects>;
|
15
x-pack/test/functional_endpoint/page_objects/index.ts
Normal file
15
x-pack/test/functional_endpoint/page_objects/index.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { pageObjects as xpackFunctionalPageObjects } from '../../functional/page_objects';
|
||||
import { EndpointPageProvider } from './endpoint_page';
|
||||
import { EndpointAlertsPageProvider } from './endpoint_alerts_page';
|
||||
|
||||
export const pageObjects = {
|
||||
...xpackFunctionalPageObjects,
|
||||
endpoint: EndpointPageProvider,
|
||||
endpointAlerts: EndpointAlertsPageProvider,
|
||||
};
|
|
@ -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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function({ loadTestFile }: FtrProviderContext) {
|
||||
describe('endpoint when the ingest manager fails to setup correctly', function() {
|
||||
this.tags('ciGroup7');
|
||||
|
||||
loadTestFile(require.resolve('./landing_page'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
||||
describe('home page', function() {
|
||||
const pageObjects = getPageObjects(['common']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
before(async () => {
|
||||
await pageObjects.common.navigateToApp('endpoint');
|
||||
});
|
||||
|
||||
it('displays an error toast', async () => {
|
||||
await testSubjects.existOrFail('euiToastHeader');
|
||||
});
|
||||
});
|
||||
};
|
30
x-pack/test/functional_endpoint_ingest_failure/config.ts
Normal file
30
x-pack/test/functional_endpoint_ingest_failure/config.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { resolve } from 'path';
|
||||
import { FtrConfigProviderContext } from '@kbn/test/types/ftr';
|
||||
|
||||
export default async function({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const xpackFunctionalConfig = await readConfigFile(
|
||||
require.resolve('../functional_endpoint/config.ts')
|
||||
);
|
||||
|
||||
return {
|
||||
...xpackFunctionalConfig.getAll(),
|
||||
testFiles: [resolve(__dirname, './apps/endpoint')],
|
||||
junit: {
|
||||
reportName: 'X-Pack Endpoint Without Ingest Functional Tests',
|
||||
},
|
||||
kbnTestServer: {
|
||||
...xpackFunctionalConfig.get('kbnTestServer'),
|
||||
serverArgs: [
|
||||
...xpackFunctionalConfig.get('kbnTestServer.serverArgs'),
|
||||
// use a bogus port so the ingest manager setup will fail
|
||||
'--xpack.ingestManager.epm.registryUrl=http://127.0.0.1:12345',
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
12
x-pack/test/functional_endpoint_ingest_failure/ftr_provider_context.d.ts
vendored
Normal file
12
x-pack/test/functional_endpoint_ingest_failure/ftr_provider_context.d.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { GenericFtrProviderContext } from '@kbn/test/types/ftr';
|
||||
|
||||
import { pageObjects } from '../functional_endpoint/page_objects';
|
||||
import { services } from '../functional/services';
|
||||
|
||||
export type FtrProviderContext = GenericFtrProviderContext<typeof services, typeof pageObjects>;
|
|
@ -14,7 +14,9 @@ import { pageObjects } from './page_objects';
|
|||
|
||||
/* eslint-disable import/no-default-export */
|
||||
export default async function({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js'));
|
||||
const xpackFunctionalConfig = await readConfigFile(
|
||||
require.resolve('../functional_endpoint/config.ts')
|
||||
);
|
||||
|
||||
// Find all folders in ./plugins since we treat all them as plugin folder
|
||||
const allFiles = fs.readdirSync(resolve(__dirname, 'plugins'));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue