[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:
Jonathan Buttner 2020-04-09 09:41:38 -04:00 committed by GitHub
parent 883af70089
commit 6b5cbd562f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 238 additions and 16 deletions

3
.github/CODEOWNERS vendored
View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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 },
};
};

View file

@ -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;
};

View file

@ -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;
}
/**

View file

@ -252,6 +252,7 @@ export enum IngestAssetType {
export enum DefaultPackages {
base = 'base',
system = 'system',
endpoint = 'endpoint',
}
export interface IndexTemplate {

View file

@ -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);
};

View file

@ -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() {}
}

View file

@ -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();

View file

@ -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

View file

@ -389,7 +389,8 @@
"type": "nested"
},
"file_extension": {
"type": "long"
"ignore_above": 1024,
"type": "keyword"
},
"project_file": {
"properties": {

View file

@ -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,
};

View file

@ -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');
});
});
};

View 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',
],
},
};
}

View 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>;

View 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,
};

View file

@ -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'));
});
}

View file

@ -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');
});
});
};

View 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',
],
},
};
}

View 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>;

View file

@ -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'));