From 5eb8d6067921bf5fe267d8836056db747d1147f5 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 31 May 2024 12:14:05 -0400 Subject: [PATCH] [8.14] [Fleet] Fix bulk install package with force flag when package is already installed (#184580) (#184593) # Backport This will backport the following commits from `main` to `8.14`: - [[Fleet] Fix bulk install package with force flag when package is already installed (#184580)](https://github.com/elastic/kibana/pull/184580) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> --- .../epm/packages/bulk_install_packages.ts | 48 ++++++++++--------- .../fleet/server/services/preconfiguration.ts | 1 + .../apis/epm/bulk_install.ts | 24 +++++++++- .../fleet_api_integration/apis/epm/index.js | 1 + 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts b/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts index 74dc880477ff9..08bc17f193bd7 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/bulk_install_packages.ts @@ -29,6 +29,7 @@ interface BulkInstallPackagesParams { preferredSource?: 'registry' | 'bundled'; prerelease?: boolean; authorizationHeader?: HTTPAuthorizationHeader | null; + skipIfInstalled?: boolean; } export async function bulkInstallPackages({ @@ -39,6 +40,7 @@ export async function bulkInstallPackages({ force, prerelease, authorizationHeader, + skipIfInstalled, }: BulkInstallPackagesParams): Promise { const logger = appContextService.getLogger(); @@ -91,28 +93,30 @@ export async function bulkInstallPackages({ } const pkgKeyProps = result.value; - const installedPackageResult = await isPackageVersionOrLaterInstalled({ - savedObjectsClient, - pkgName: pkgKeyProps.name, - pkgVersion: pkgKeyProps.version, - }); - - if (installedPackageResult) { - const { - name, - version, - installed_es: installedEs, - installed_kibana: installedKibana, - } = installedPackageResult.package; - return { - name, - version, - result: { - assets: [...installedEs, ...installedKibana], - status: 'already_installed', - installType: 'unknown', - } as InstallResult, - }; + if (!force || skipIfInstalled) { + const installedPackageResult = await isPackageVersionOrLaterInstalled({ + savedObjectsClient, + pkgName: pkgKeyProps.name, + pkgVersion: pkgKeyProps.version, + }); + + if (installedPackageResult) { + const { + name, + version, + installed_es: installedEs, + installed_kibana: installedKibana, + } = installedPackageResult.package; + return { + name, + version, + result: { + assets: [...installedEs, ...installedKibana], + status: 'already_installed', + installType: 'unknown', + } as InstallResult, + }; + } } const pkgkey = Registry.pkgToPkgKey(pkgKeyProps); diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.ts b/x-pack/plugins/fleet/server/services/preconfiguration.ts index 877fb343b6507..56a2c17d18409 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.ts @@ -99,6 +99,7 @@ export async function ensurePreconfiguredPackagesAndPolicies( esClient, packagesToInstall, force: true, // Always force outdated packages to be installed if a later version isn't installed + skipIfInstalled: true, // force flag alone would reinstall packages that are already installed spaceId, }); diff --git a/x-pack/test/fleet_api_integration/apis/epm/bulk_install.ts b/x-pack/test/fleet_api_integration/apis/epm/bulk_install.ts index 7b483c06e36b5..790fcd13873ea 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/bulk_install.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/bulk_install.ts @@ -52,6 +52,26 @@ export default function (providerContext: FtrProviderContext) { await uninstallPackage(pkgName, pkgOlderVersion); }); + it('should install an older version if force is true when package is already installed', async () => { + // install latest package + await supertest + .post(`/api/fleet/epm/packages/_bulk?prerelease=true`) + .set('kbn-xsrf', 'xxxx') + .send({ packages: [pkgName] }) + .expect(200); + + const response = await supertest + .post(`/api/fleet/epm/packages/_bulk?prerelease=true`) + .set('kbn-xsrf', 'xxxx') + .send({ packages: [{ name: pkgName, version: pkgOlderVersion }], force: true }) + .expect(200); + + expect(response.body.items.length).equal(1); + expect(response.body.items[0].version).equal(pkgOlderVersion); + + await uninstallPackage(pkgName, pkgOlderVersion); + }); + it('should reject installing an older version if force is false', async () => { const response = await supertest .post(`/api/fleet/epm/packages/_bulk?prerelease=true`) @@ -59,8 +79,8 @@ export default function (providerContext: FtrProviderContext) { .send({ packages: [{ name: pkgName, version: pkgOlderVersion }] }) .expect(200); - expect(response.body.response[0].statusCode).equal(400); - expect(response.body.response[0].error).equal( + expect(response.body.items[0].statusCode).equal(400); + expect(response.body.items[0].error).equal( 'multiple_versions-0.1.0 is out-of-date and cannot be installed or updated' ); }); diff --git a/x-pack/test/fleet_api_integration/apis/epm/index.js b/x-pack/test/fleet_api_integration/apis/epm/index.js index 3c4315eff20cb..3caed7da79f65 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/index.js +++ b/x-pack/test/fleet_api_integration/apis/epm/index.js @@ -32,6 +32,7 @@ export default function loadTests({ loadTestFile, getService }) { loadTestFile(require.resolve('./install_tsds_disable')); loadTestFile(require.resolve('./install_tag_assets')); loadTestFile(require.resolve('./bulk_upgrade')); + loadTestFile(require.resolve('./bulk_install')); loadTestFile(require.resolve('./update_assets')); loadTestFile(require.resolve('./data_stream')); loadTestFile(require.resolve('./package_install_complete'));