Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion x-pack/plugins/fleet/common/types/models/epm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ export enum InstallStatus {
uninstalling = 'uninstalling',
}

export type InstallType = 'reinstall' | 'reupdate' | 'rollback' | 'update' | 'install';
export interface DefaultPackagesInstallationError {
installType: InstallType;
error: Error;
}

export type InstallType = 'reinstall' | 'reupdate' | 'rollback' | 'update' | 'install' | 'unknown';
export type InstallSource = 'registry' | 'upload';

export type EpmPackageInstallStatus = 'installed' | 'installing';
Expand Down
7 changes: 5 additions & 2 deletions x-pack/plugins/fleet/common/types/rest_spec/epm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
RegistrySearchResult,
PackageInfo,
PackageUsageStats,
InstallType,
} from '../models/epm';

export interface GetCategoriesRequest {
Expand Down Expand Up @@ -83,8 +84,10 @@ export interface IBulkInstallPackageHTTPError {
}

export interface InstallResult {
assets: AssetReference[];
status: 'installed' | 'already_installed';
assets?: AssetReference[];
status?: 'installed' | 'already_installed';
error?: Error;
installType: InstallType;
}

export interface BulkInstallPackageInfo {
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
* 2.0.
*/

import type { DefaultPackagesInstallationError } from '../models/epm';

export interface PostIngestSetupResponse {
isInitialized: boolean;
preconfigurationError?: { name: string; message: string };
nonFatalPackageUpgradeErrors?: DefaultPackagesInstallationError[];
}
7 changes: 7 additions & 0 deletions x-pack/plugins/fleet/public/applications/fleet/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ export const WithPermissionsAndSetup: React.FC = memo(({ children }) => {
}),
});
}
if (setupResponse.data.nonFatalPackageUpgradeErrors) {
notifications.toasts.addError(setupResponse.data.nonFatalPackageUpgradeErrors, {
title: i18n.translate('xpack.fleet.setup.nonFatalPackageErrorsTitle', {
defaultMessage: 'One or more packages could not be successfully upgraded',
}),
});
}
} catch (err) {
setInitializationError(err);
}
Expand Down
46 changes: 24 additions & 22 deletions x-pack/plugins/fleet/server/routes/epm/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,20 +226,21 @@ export const installPackageFromRegistryHandler: RequestHandler<
const savedObjectsClient = context.core.savedObjects.client;
const esClient = context.core.elasticsearch.client.asCurrentUser;
const { pkgkey } = request.params;
try {
const res = await installPackage({
installSource: 'registry',
savedObjectsClient,
pkgkey,
esClient,
force: request.body?.force,
});

const res = await installPackage({
installSource: 'registry',
savedObjectsClient,
pkgkey,
esClient,
force: request.body?.force,
});
if (!res.error) {
const body: InstallPackageResponse = {
response: res.assets,
response: res.assets || [],
};
return response.ok({ body });
} catch (e) {
return await defaultIngestErrorHandler({ error: e, response });
} else {
return await defaultIngestErrorHandler({ error: res.error, response });
}
};

Expand Down Expand Up @@ -292,20 +293,21 @@ export const installPackageByUploadHandler: RequestHandler<
const esClient = context.core.elasticsearch.client.asCurrentUser;
const contentType = request.headers['content-type'] as string; // from types it could also be string[] or undefined but this is checked later
const archiveBuffer = Buffer.from(request.body);
try {
const res = await installPackage({
installSource: 'upload',
savedObjectsClient,
esClient,
archiveBuffer,
contentType,
});

const res = await installPackage({
installSource: 'upload',
savedObjectsClient,
esClient,
archiveBuffer,
contentType,
});
if (!res.error) {
const body: InstallPackageResponse = {
response: res.assets,
response: res.assets || [],
};
return response.ok({ body });
} catch (error) {
return defaultIngestErrorHandler({ error, response });
} else {
return defaultIngestErrorHandler({ error: res.error, response });
}
};

Expand Down
6 changes: 5 additions & 1 deletion x-pack/plugins/fleet/server/routes/setup/handlers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ describe('FleetSetupHandler', () => {

it('POST /setup succeeds w/200 and body of resolved value', async () => {
mockSetupIngestManager.mockImplementation(() =>
Promise.resolve({ isInitialized: true, preconfigurationError: undefined })
Promise.resolve({
isInitialized: true,
preconfigurationError: undefined,
nonFatalPackageUpgradeErrors: [],
})
);
await fleetSetupHandler(context, request, response);

Expand Down
10 changes: 8 additions & 2 deletions x-pack/plugins/fleet/server/routes/setup/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ export const fleetSetupHandler: RequestHandler = async (context, request, respon
try {
const soClient = context.core.savedObjects.client;
const esClient = context.core.elasticsearch.client.asCurrentUser;
const body: PostIngestSetupResponse = { isInitialized: true };
await setupIngestManager(soClient, esClient);
const setupStatus = await setupIngestManager(soClient, esClient);
const body: PostIngestSetupResponse = {
isInitialized: true,
};

if (setupStatus.nonFatalPackageUpgradeErrors.length > 0) {
body.nonFatalPackageUpgradeErrors = setupStatus.nonFatalPackageUpgradeErrors;
}

return response.ok({
body,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,31 @@ export async function bulkInstallPackages({
);

logger.debug(`kicking off bulk install of ${packagesToInstall.join(', ')} from registry`);
const installResults = await Promise.allSettled(
const bulkInstallResults = await Promise.allSettled(
latestPackagesResults.map(async (result, index) => {
const packageName = packagesToInstall[index];
if (result.status === 'fulfilled') {
const latestPackage = result.value;
return {
name: packageName,
version: latestPackage.version,
result: await installPackage({
savedObjectsClient,
esClient,
pkgkey: Registry.pkgToPkgKey(latestPackage),
installSource,
skipPostInstall: true,
}),
};
const installResult = await installPackage({
savedObjectsClient,
esClient,
pkgkey: Registry.pkgToPkgKey(latestPackage),
installSource,
skipPostInstall: true,
});
if (installResult.error) {
return {
name: packageName,
error: installResult.error,
installType: installResult.installType,
};
} else {
return {
name: packageName,
version: latestPackage.version,
result: installResult,
};
}
}
return { name: packageName, error: result.reason };
})
Expand All @@ -56,18 +65,31 @@ export async function bulkInstallPackages({
// only install index patterns if we completed install for any package-version for the
// first time, aka fresh installs or upgrades
if (
installResults.find(
(result) => result.status === 'fulfilled' && result.value.result?.status === 'installed'
bulkInstallResults.find(
(result) =>
result.status === 'fulfilled' &&
!result.value.result?.error &&
result.value.result?.status === 'installed'
)
) {
await installIndexPatterns({ savedObjectsClient, esClient, installSource });
}

return installResults.map((result, index) => {
return bulkInstallResults.map((result, index) => {
const packageName = packagesToInstall[index];
return result.status === 'fulfilled'
? result.value
: { name: packageName, error: result.reason };
if (result.status === 'fulfilled') {
if (result.value && result.value.error) {
return {
name: packageName,
error: result.value.error,
installType: result.value.installType,
};
} else {
return result.value;
}
} else {
return { name: packageName, error: result.reason };
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ describe('ensureInstalledDefaultPackages', () => {
return [
{
name: mockInstallation.attributes.name,
result: { assets: [], status: 'installed' },
result: { assets: [], status: 'installed', installType: 'install' },
version: '',
statusCode: 200,
},
Expand All @@ -95,13 +95,13 @@ describe('ensureInstalledDefaultPackages', () => {
return [
{
name: 'success one',
result: { assets: [], status: 'installed' },
result: { assets: [], status: 'installed', installType: 'install' },
version: '',
statusCode: 200,
},
{
name: 'success two',
result: { assets: [], status: 'installed' },
result: { assets: [], status: 'installed', installType: 'install' },
version: '',
statusCode: 200,
},
Expand All @@ -111,7 +111,7 @@ describe('ensureInstalledDefaultPackages', () => {
},
{
name: 'success three',
result: { assets: [], status: 'installed' },
result: { assets: [], status: 'installed', installType: 'install' },
version: '',
statusCode: 200,
},
Expand All @@ -134,7 +134,7 @@ describe('ensureInstalledDefaultPackages', () => {
return [
{
name: 'undefined package',
result: { assets: [], status: 'installed' },
result: { assets: [], status: 'installed', installType: 'install' },
version: '',
statusCode: 200,
},
Expand Down
Loading