Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Endpoint][EPM] Endpoint depending on ingest manager to initialize #62871

Merged
3 changes: 2 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/endpoint/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -32,6 +33,7 @@ type DataMock = Omit<DataPublicStartMock, 'indexPatterns' | 'query'> & {
*/
export interface DepsStartMock {
data: DataMock;
ingestManager: IngestManagerStart;
}

/**
Expand All @@ -54,5 +56,6 @@ export const depsStartMock: () => DepsStartMock = () => {

return {
data: dataMock,
ingestManager: { success: true },
};
};
Original file line number Diff line number Diff line change
@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❔ Where is the "see the full error" message? The two I see here are:

  • 'Ingest Manager failed during its setup.'
  • 'App failed to initialize'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The full error message is returned by the ingest manager app, it's just below these lines
ingestManager.error.message

if (!ingestManager.success) {
      if (ingestManager.error) {
        displayToastWithModal(ingestManager.error.message);

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;
};
2 changes: 2 additions & 0 deletions x-pack/plugins/endpoint/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -18,6 +19,7 @@ export interface EndpointPluginSetupDependencies {
}
export interface EndpointPluginStartDependencies {
data: DataPublicPluginStart;
ingestManager: IngestManagerStart;
}

/**
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/ingest_manager/common/types/models/epm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ export enum IngestAssetType {
export enum DefaultPackages {
base = 'base',
system = 'system',
endpoint = 'endpoint',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Installing the endpoint package by default

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

export interface IndexTemplate {
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/ingest_manager/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
20 changes: 18 additions & 2 deletions x-pack/plugins/ingest_manager/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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() {}
}
2 changes: 2 additions & 0 deletions x-pack/scripts/functional_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oatkiller @kqualters-elastic @jfsiii Any ideas if this needs to be here when we add new testing directories? @jfsiii I didn't see the epm_api_integration tests in here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonathan-buttner I'm not sure. Perhaps someone from @elastic/kibana-platform or @elastic/kibana-operations can help?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script is currently run with the ciGroup tags to determine which tests will run on CI, as you can see in

checks-reporter-with-killswitch "X-Pack Chrome Functional tests / Group ${CI_GROUP}" \
node scripts/functional_tests \
--debug --bail \
--kibana-install-dir "$KIBANA_INSTALL_DIR" \
--include-tag "ciGroup$CI_GROUP"
, so yes. If you add a new FTR configuration it needs to be added to this list to be executed in CI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah thanks @spalger !

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there was a little confusion here. I think we want the endpoint functional UI tests in these 2 paths;

  require.resolve('../test/functional_endpoint_ingest_failure/config.ts'),
  require.resolve('../test/functional_endpoint/config.ts'),

to be in the alwaysImportedTests list, and not in the onlyNotInCoverageTests list. If they are functional UI tests, we do want to run them in the Code Coverage job.
@wayneseymour is testing a change to move them to the other list...

require.resolve('../test/functional_endpoint/config.ts'),
];

require('@kbn/plugin-helpers').babelRegister();
Expand Down
5 changes: 0 additions & 5 deletions x-pack/test/functional/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
],
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,8 @@
"type": "nested"
},
"file_extension": {
"type": "long"
"ignore_above": 1024,
Copy link
Contributor Author

@jonathan-buttner jonathan-buttner Apr 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was conflicting with the mapping installed by the Endpoint package. The file_extension should be a string, not a long.

"type": "keyword"
},
"project_file": {
"properties": {
Expand Down
4 changes: 0 additions & 4 deletions x-pack/test/functional/page_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -81,6 +79,4 @@ export const pageObjects = {
copySavedObjectsToSpace: CopySavedObjectsToSpacePageProvider,
lens: LensPageProvider,
roleMappings: RoleMappingsPageProvider,
endpoint: EndpointPageProvider,
endpointAlerts: EndpointAlertsPageProvider,
};
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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 changes: 37 additions & 0 deletions x-pack/test/functional_endpoint/config.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions x-pack/test/functional_endpoint/ftr_provider_context.d.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions x-pack/test/functional_endpoint/page_objects/index.ts
Original file line number Diff line number Diff line change
@@ -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,
};
Original file line number Diff line number Diff line change
@@ -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'));
});
}
Original file line number Diff line number Diff line change
@@ -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 changes: 30 additions & 0 deletions x-pack/test/functional_endpoint_ingest_failure/config.ts
Original file line number Diff line number Diff line change
@@ -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',
Copy link
Contributor Author

@jonathan-buttner jonathan-buttner Apr 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding an invalid URL to trigger the toast for the functional test.

],
},
};
}
Loading