[Fleet] Support installing bundled package without providing version (#169027)

This commit is contained in:
Nicolas Chaulet 2023-10-18 07:51:33 -04:00 committed by GitHub
parent 0350f17c54
commit 9a8147d6df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 117 additions and 19 deletions

View file

@ -0,0 +1,89 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import fs from 'fs/promises';
import { loggingSystemMock } from '@kbn/core-logging-server-mocks';
import { appContextService } from '../../app_context';
import { getBundledPackageByPkgKey, getBundledPackages } from './bundled_packages';
jest.mock('fs/promises');
jest.mock('../../app_context');
describe('bundledPackages', () => {
beforeAll(() => {
jest.mocked(appContextService.getConfig).mockReturnValue({
developer: {
bundledPackageLocation: '/tmp/test',
},
} as any);
jest.mocked(appContextService.getLogger).mockReturnValue(loggingSystemMock.createLogger());
});
beforeEach(() => {
jest.mocked(fs.stat).mockResolvedValue({} as any);
jest.mocked(fs.readdir).mockResolvedValue(['apm-8.8.0.zip', 'test-1.0.0.zip'] as any);
jest.mocked(fs.readFile).mockResolvedValue(Buffer.from('TEST'));
});
afterEach(() => {
jest.mocked(fs.stat).mockReset();
});
describe('getBundledPackages', () => {
it('return an empty array if dir do not exists', async () => {
jest.mocked(fs.stat).mockRejectedValue(new Error('NOTEXISTS'));
const packages = await getBundledPackages();
expect(packages).toEqual([]);
});
it('return packages in bundled directory', async () => {
const packages = await getBundledPackages();
expect(packages).toEqual([
{
name: 'apm',
version: '8.8.0',
buffer: Buffer.from('TEST'),
},
{
name: 'test',
version: '1.0.0',
buffer: Buffer.from('TEST'),
},
]);
});
});
describe('getBundledPackageByPkgKey', () => {
it('should return package by name if no version is provided', async () => {
const pkg = await getBundledPackageByPkgKey('apm');
expect(pkg).toBeDefined();
expect(pkg).toEqual({
name: 'apm',
version: '8.8.0',
buffer: Buffer.from('TEST'),
});
});
it('should return package by name and version if version is provided', async () => {
const pkg = await getBundledPackageByPkgKey('apm-8.8.0');
expect(pkg).toBeDefined();
expect(pkg).toEqual({
name: 'apm',
version: '8.8.0',
buffer: Buffer.from('TEST'),
});
});
it('should return package by name and version if version is provided and do not exists', async () => {
const pkg = await getBundledPackageByPkgKey('apm-8.0.0');
expect(pkg).not.toBeDefined();
});
});
});

View file

@ -11,7 +11,7 @@ import path from 'path';
import type { BundledPackage } from '../../../types';
import { FleetError } from '../../../errors';
import { appContextService } from '../../app_context';
import { splitPkgKey } from '../registry';
import { splitPkgKey, pkgToPkgKey } from '../registry';
export async function getBundledPackages(): Promise<BundledPackage[]> {
const config = appContextService.getConfig();
@ -57,6 +57,21 @@ export async function getBundledPackages(): Promise<BundledPackage[]> {
}
}
export async function getBundledPackageByPkgKey(
pkgKey: string
): Promise<BundledPackage | undefined> {
const bundledPackages = await getBundledPackages();
const bundledPackage = bundledPackages.find((pkg) => {
if (pkgKey.includes('-')) {
return pkgToPkgKey(pkg) === pkgKey;
} else {
return pkg.name === pkgKey;
}
});
return bundledPackage;
}
export async function getBundledPackageByName(name: string): Promise<BundledPackage | undefined> {
const bundledPackages = await getBundledPackages();
const bundledPackage = bundledPackages.find((pkg) => pkg.name === name);

View file

@ -22,7 +22,7 @@ import * as Registry from '../registry';
import { createInstallation, handleInstallPackageFailure, installPackage } from './install';
import * as install from './_install_package';
import { getBundledPackages } from './bundled_packages';
import { getBundledPackageByPkgKey } from './bundled_packages';
import * as obj from '.';
@ -80,7 +80,7 @@ jest.mock('../archive', () => {
});
jest.mock('../../audit_logging');
const mockGetBundledPackages = jest.mocked(getBundledPackages);
const mockGetBundledPackageByPkgKey = jest.mocked(getBundledPackageByPkgKey);
const mockedAuditLoggingService = jest.mocked(auditLoggingService);
describe('createInstallation', () => {
@ -143,13 +143,13 @@ describe('install', () => {
} as any)
);
mockGetBundledPackages.mockReset();
mockGetBundledPackageByPkgKey.mockReset();
(install._installPackage as jest.Mock).mockClear();
});
describe('registry', () => {
beforeEach(() => {
mockGetBundledPackages.mockResolvedValue([]);
mockGetBundledPackageByPkgKey.mockResolvedValue(undefined);
});
it('should send telemetry on install failure, out of date', async () => {
@ -265,13 +265,11 @@ describe('install', () => {
it('should install from bundled package if one exists', async () => {
(install._installPackage as jest.Mock).mockResolvedValue({});
mockGetBundledPackages.mockResolvedValue([
{
name: 'test_package',
version: '1.0.0',
buffer: Buffer.from('test_package'),
},
]);
mockGetBundledPackageByPkgKey.mockResolvedValue({
name: 'test_package',
version: '1.0.0',
buffer: Buffer.from('test_package'),
});
const response = await installPackage({
spaceId: DEFAULT_SPACE_ID,
@ -428,7 +426,7 @@ describe('handleInstallPackageFailure', () => {
jest.mocked(install._installPackage).mockClear();
jest.mocked(install._installPackage).mockResolvedValue({} as any);
mockedLogger.error.mockClear();
mockGetBundledPackages.mockResolvedValue([]);
mockGetBundledPackageByPkgKey.mockResolvedValue(undefined);
jest.spyOn(licenseService, 'hasAtLeast').mockReturnValue(true);
jest.spyOn(Registry, 'splitPkgKey').mockImplementation((pkgKey: string) => {
const [pkgName, pkgVersion] = pkgKey.split('-');

View file

@ -95,7 +95,7 @@ import { removeInstallation } from './remove';
import { getPackageSavedObjects } from './get';
import { _installPackage } from './_install_package';
import { removeOldAssets } from './cleanup';
import { getBundledPackages } from './bundled_packages';
import { getBundledPackageByPkgKey } from './bundled_packages';
import { withPackageSpan } from './utils';
import { convertStringToTitle, generateDescription } from './custom_integrations/utils';
import { INITIAL_VERSION } from './custom_integrations/constants';
@ -718,8 +718,6 @@ export async function installPackage(args: InstallPackageParams): Promise<Instal
const authorizationHeader = args.authorizationHeader;
const bundledPackages = await getBundledPackages();
if (args.installSource === 'registry') {
const {
pkgkey,
@ -732,9 +730,7 @@ export async function installPackage(args: InstallPackageParams): Promise<Instal
skipDataStreamRollover,
} = args;
const matchingBundledPackage = bundledPackages.find(
(pkg) => Registry.pkgToPkgKey(pkg) === pkgkey
);
const matchingBundledPackage = await getBundledPackageByPkgKey(pkgkey);
if (matchingBundledPackage) {
logger.debug(