From 15b6ba02d09254fd9ae692b3bafad15282ebd957 Mon Sep 17 00:00:00 2001 From: Sonja Krause-Harder Date: Tue, 19 May 2020 09:40:03 +0200 Subject: [PATCH] [Ingest Manager] Better handling of package installation problems (#66541) (#66917) * Better handle non-available package registry * Log errors in route handler only * Await installation of prebuilt component templates * Remove leftover import * Remove useless use of await. --- .../server/routes/setup/handlers.ts | 10 ++++++ .../epm/elasticsearch/template/install.ts | 36 +++++++++++-------- .../server/services/epm/packages/install.ts | 18 ++++------ .../server/services/epm/registry/requests.ts | 2 +- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts index 12781f2f77d17..8bc80c69ce9b2 100644 --- a/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts @@ -74,12 +74,22 @@ export const createFleetSetupHandler: RequestHandler< export const ingestManagerSetupHandler: RequestHandler = async (context, request, response) => { const soClient = context.core.savedObjects.client; const callCluster = context.core.elasticsearch.adminClient.callAsCurrentUser; + const logger = appContextService.getLogger(); try { await setupIngestManager(soClient, callCluster); return response.ok({ body: { isInitialized: true }, }); } catch (e) { + if (e.isBoom) { + logger.error(e.output.payload.message); + return response.customError({ + statusCode: e.output.statusCode, + body: { message: e.output.payload.message }, + }); + } + logger.error(e.message); + logger.error(e.stack); return response.customError({ statusCode: 500, body: { message: e.message }, diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts index 6ef6f863753b5..2c452f16cc104 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import Boom from 'boom'; import { Dataset, RegistryPackage, ElasticsearchAssetType, TemplateRef } from '../../../../types'; import { CallESAsCurrentUser } from '../../../../types'; import { Field, loadFieldsFromYaml, processFields } from '../../fields/field'; @@ -20,8 +21,8 @@ export const installTemplates = async ( // install any pre-built index template assets, // atm, this is only the base package's global index templates // Install component templates first, as they are used by the index templates - installPreBuiltComponentTemplates(pkgName, pkgVersion, callCluster); - installPreBuiltTemplates(pkgName, pkgVersion, callCluster); + await installPreBuiltComponentTemplates(pkgName, pkgVersion, callCluster); + await installPreBuiltTemplates(pkgName, pkgVersion, callCluster); // build templates per dataset from yml files const datasets = registryPackage.datasets; @@ -53,16 +54,7 @@ const installPreBuiltTemplates = async ( pkgVersion, (entry: Registry.ArchiveEntry) => isTemplate(entry) ); - // templatePaths.forEach(async path => { - // const { file } = Registry.pathParts(path); - // const templateName = file.substr(0, file.lastIndexOf('.')); - // const content = JSON.parse(Registry.getAsset(path).toString('utf8')); - // await callCluster('indices.putTemplate', { - // name: templateName, - // body: content, - // }); - // }); - templatePaths.forEach(async path => { + const templateInstallPromises = templatePaths.map(async path => { const { file } = Registry.pathParts(path); const templateName = file.substr(0, file.lastIndexOf('.')); const content = JSON.parse(Registry.getAsset(path).toString('utf8')); @@ -91,8 +83,15 @@ const installPreBuiltTemplates = async ( // The existing convenience endpoint `indices.putTemplate` only sends to _template, // which does not support v2 templates. // See src/core/server/elasticsearch/api_types.ts for available endpoints. - await callCluster('transport.request', callClusterParams); + return callCluster('transport.request', callClusterParams); }); + try { + return await Promise.all(templateInstallPromises); + } catch (e) { + throw new Boom(`Error installing prebuilt index templates ${e.message}`, { + statusCode: 400, + }); + } }; const installPreBuiltComponentTemplates = async ( @@ -105,7 +104,7 @@ const installPreBuiltComponentTemplates = async ( pkgVersion, (entry: Registry.ArchiveEntry) => isComponentTemplate(entry) ); - templatePaths.forEach(async path => { + const templateInstallPromises = templatePaths.map(async path => { const { file } = Registry.pathParts(path); const templateName = file.substr(0, file.lastIndexOf('.')); const content = JSON.parse(Registry.getAsset(path).toString('utf8')); @@ -124,8 +123,15 @@ const installPreBuiltComponentTemplates = async ( // This uses the catch-all endpoint 'transport.request' because there is no // convenience endpoint for component templates yet. // See src/core/server/elasticsearch/api_types.ts for available endpoints. - await callCluster('transport.request', callClusterParams); + return callCluster('transport.request', callClusterParams); }); + try { + return await Promise.all(templateInstallPromises); + } catch (e) { + throw new Boom(`Error installing prebuilt component templates ${e.message}`, { + statusCode: 400, + }); + } }; const isTemplate = ({ path }: Registry.ArchiveEntry) => { diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts index 632bc3ac9b69f..79a5e98b9507d 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts @@ -73,17 +73,13 @@ export async function ensureInstalledPackage(options: { if (installedPackage) { return installedPackage; } - // if the requested packaged was not found to be installed, try installing - try { - await installLatestPackage({ - savedObjectsClient, - pkgName, - callCluster, - }); - return await getInstallation({ savedObjectsClient, pkgName }); - } catch (err) { - throw new Error(err.message); - } + // if the requested packaged was not found to be installed, install + await installLatestPackage({ + savedObjectsClient, + pkgName, + callCluster, + }); + return await getInstallation({ savedObjectsClient, pkgName }); } export async function installPackage(options: { diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/requests.ts b/x-pack/plugins/ingest_manager/server/services/epm/registry/requests.ts index 654aa8aae1355..93e475cbc5956 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/registry/requests.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/registry/requests.ts @@ -17,7 +17,7 @@ export async function getResponse(url: string): Promise { throw new Boom(response.statusText, { statusCode: response.status }); } } catch (e) { - throw Boom.boomify(e); + throw new Boom(`Error connecting to package registry: ${e.message}`, { statusCode: 502 }); } }