Include failure reason when packages cannot be installed during setup (#116612)
This commit is contained in:
parent
b102846c82
commit
d5963884b6
|
@ -9,7 +9,11 @@ import { elasticsearchServiceMock, savedObjectsClientMock } from 'src/core/serve
|
|||
|
||||
import { SavedObjectsErrorHelpers } from '../../../../../src/core/server';
|
||||
|
||||
import type { PreconfiguredAgentPolicy, PreconfiguredOutput } from '../../common/types';
|
||||
import type {
|
||||
InstallResult,
|
||||
PreconfiguredAgentPolicy,
|
||||
PreconfiguredOutput,
|
||||
} from '../../common/types';
|
||||
import type { AgentPolicy, NewPackagePolicy, Output } from '../types';
|
||||
|
||||
import { AGENT_POLICY_SAVED_OBJECT_TYPE } from '../constants';
|
||||
|
@ -30,6 +34,7 @@ jest.mock('./output');
|
|||
const mockedOutputService = outputService as jest.Mocked<typeof outputService>;
|
||||
|
||||
const mockInstalledPackages = new Map();
|
||||
const mockInstallPackageErrors = new Map<string, string>();
|
||||
const mockConfiguredPolicies = new Map();
|
||||
|
||||
const mockDefaultOutput: Output = {
|
||||
|
@ -99,8 +104,22 @@ function getPutPreconfiguredPackagesMock() {
|
|||
}
|
||||
|
||||
jest.mock('./epm/packages/install', () => ({
|
||||
installPackage({ pkgkey, force }: { pkgkey: string; force?: boolean }) {
|
||||
async installPackage({
|
||||
pkgkey,
|
||||
force,
|
||||
}: {
|
||||
pkgkey: string;
|
||||
force?: boolean;
|
||||
}): Promise<InstallResult> {
|
||||
const [pkgName, pkgVersion] = pkgkey.split('-');
|
||||
const installError = mockInstallPackageErrors.get(pkgName);
|
||||
if (installError) {
|
||||
return {
|
||||
error: new Error(installError),
|
||||
installType: 'install',
|
||||
};
|
||||
}
|
||||
|
||||
const installedPackage = mockInstalledPackages.get(pkgName);
|
||||
if (installedPackage) {
|
||||
if (installedPackage.version === pkgVersion) return installedPackage;
|
||||
|
@ -109,7 +128,10 @@ jest.mock('./epm/packages/install', () => ({
|
|||
const packageInstallation = { name: pkgName, version: pkgVersion, title: pkgName };
|
||||
mockInstalledPackages.set(pkgName, packageInstallation);
|
||||
|
||||
return packageInstallation;
|
||||
return {
|
||||
status: 'installed',
|
||||
installType: 'install',
|
||||
};
|
||||
},
|
||||
ensurePackagesCompletedInstall() {
|
||||
return [];
|
||||
|
@ -133,6 +155,8 @@ jest.mock('./epm/packages/get', () => ({
|
|||
},
|
||||
}));
|
||||
|
||||
jest.mock('./epm/kibana/index_pattern/install');
|
||||
|
||||
jest.mock('./package_policy', () => ({
|
||||
...jest.requireActual('./package_policy'),
|
||||
packagePolicyService: {
|
||||
|
@ -177,6 +201,7 @@ const spyAgentPolicyServicBumpAllAgentPoliciesForOutput = jest.spyOn(
|
|||
describe('policy preconfiguration', () => {
|
||||
beforeEach(() => {
|
||||
mockInstalledPackages.clear();
|
||||
mockInstallPackageErrors.clear();
|
||||
mockConfiguredPolicies.clear();
|
||||
spyAgentPolicyServiceUpdate.mockClear();
|
||||
spyAgentPolicyServicBumpAllAgentPoliciesForOutput.mockClear();
|
||||
|
@ -266,7 +291,38 @@ describe('policy preconfiguration', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('should not create a policy if we are not able to add packages ', async () => {
|
||||
it('should not create a policy and throw an error if install fails for required package', async () => {
|
||||
const soClient = getPutPreconfiguredPackagesMock();
|
||||
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
|
||||
const policies: PreconfiguredAgentPolicy[] = [
|
||||
{
|
||||
name: 'Test policy',
|
||||
namespace: 'default',
|
||||
id: 'test-id',
|
||||
package_policies: [
|
||||
{
|
||||
package: { name: 'test_package' },
|
||||
name: 'Test package',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
mockInstallPackageErrors.set('test_package', 'REGISTRY ERROR');
|
||||
|
||||
await expect(
|
||||
ensurePreconfiguredPackagesAndPolicies(
|
||||
soClient,
|
||||
esClient,
|
||||
policies,
|
||||
[{ name: 'test_package', version: '3.0.0' }],
|
||||
mockDefaultOutput
|
||||
)
|
||||
).rejects.toThrow(
|
||||
'[Test policy] could not be added. [test_package] could not be installed due to error: [Error: REGISTRY ERROR]'
|
||||
);
|
||||
});
|
||||
|
||||
it('should not create a policy and throw an error if package is not installed for an unknown reason', async () => {
|
||||
const soClient = getPutPreconfiguredPackagesMock();
|
||||
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
|
||||
const policies: PreconfiguredAgentPolicy[] = [
|
||||
|
@ -283,22 +339,16 @@ describe('policy preconfiguration', () => {
|
|||
},
|
||||
];
|
||||
|
||||
let error;
|
||||
try {
|
||||
await ensurePreconfiguredPackagesAndPolicies(
|
||||
await expect(
|
||||
ensurePreconfiguredPackagesAndPolicies(
|
||||
soClient,
|
||||
esClient,
|
||||
policies,
|
||||
[{ name: 'CANNOT_MATCH', version: 'x.y.z' }],
|
||||
mockDefaultOutput
|
||||
);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.message).toEqual(
|
||||
'Test policy could not be added. test_package is not installed, add test_package to `xpack.fleet.packages` or remove it from Test package.'
|
||||
)
|
||||
).rejects.toThrow(
|
||||
'[Test policy] could not be added. [test_package] is not installed, add [test_package] to [xpack.fleet.packages] or remove it from [Test package].'
|
||||
);
|
||||
});
|
||||
it('should not attempt to recreate or modify an agent policy if its ID is unchanged', async () => {
|
||||
|
|
|
@ -147,6 +147,8 @@ export async function ensurePreconfiguredPackagesAndPolicies(
|
|||
packages: PreconfiguredPackage[] = [],
|
||||
defaultOutput: Output
|
||||
): Promise<PreconfigurationResult> {
|
||||
const logger = appContextService.getLogger();
|
||||
|
||||
// Validate configured packages to ensure there are no version conflicts
|
||||
const packageNames = groupBy(packages, (pkg) => pkg.name);
|
||||
const duplicatePackages = Object.entries(packageNames).filter(
|
||||
|
@ -181,15 +183,20 @@ export async function ensurePreconfiguredPackagesAndPolicies(
|
|||
});
|
||||
|
||||
const fulfilledPackages = [];
|
||||
const rejectedPackages = [];
|
||||
const rejectedPackages: PreconfigurationError[] = [];
|
||||
for (let i = 0; i < preconfiguredPackages.length; i++) {
|
||||
const packageResult = preconfiguredPackages[i];
|
||||
if ('error' in packageResult)
|
||||
if ('error' in packageResult) {
|
||||
logger.warn(
|
||||
`Failed installing package [${packages[i].name}] due to error: [${packageResult.error}]`
|
||||
);
|
||||
rejectedPackages.push({
|
||||
package: { name: packages[i].name, version: packages[i].version },
|
||||
error: packageResult.error,
|
||||
} as PreconfigurationError);
|
||||
else fulfilledPackages.push(packageResult);
|
||||
});
|
||||
} else {
|
||||
fulfilledPackages.push(packageResult);
|
||||
}
|
||||
}
|
||||
|
||||
// Keeping this outside of the Promise.all because it introduces a race condition.
|
||||
|
@ -264,14 +271,14 @@ export async function ensurePreconfiguredPackagesAndPolicies(
|
|||
);
|
||||
|
||||
const fulfilledPolicies = [];
|
||||
const rejectedPolicies = [];
|
||||
const rejectedPolicies: PreconfigurationError[] = [];
|
||||
for (let i = 0; i < preconfiguredPolicies.length; i++) {
|
||||
const policyResult = preconfiguredPolicies[i];
|
||||
if (policyResult.status === 'rejected') {
|
||||
rejectedPolicies.push({
|
||||
error: policyResult.reason as Error,
|
||||
agentPolicy: { name: policies[i].name },
|
||||
} as PreconfigurationError);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
fulfilledPolicies.push(policyResult.value);
|
||||
|
@ -288,10 +295,25 @@ export async function ensurePreconfiguredPackagesAndPolicies(
|
|||
pkgName: pkg.name,
|
||||
});
|
||||
if (!installedPackage) {
|
||||
const rejectedPackage = rejectedPackages.find((rp) => rp.package?.name === pkg.name);
|
||||
|
||||
if (rejectedPackage) {
|
||||
throw new Error(
|
||||
i18n.translate('xpack.fleet.preconfiguration.packageRejectedError', {
|
||||
defaultMessage: `[{agentPolicyName}] could not be added. [{pkgName}] could not be installed due to error: [{errorMessage}]`,
|
||||
values: {
|
||||
agentPolicyName: preconfiguredAgentPolicy.name,
|
||||
pkgName: pkg.name,
|
||||
errorMessage: rejectedPackage.error.toString(),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
i18n.translate('xpack.fleet.preconfiguration.packageMissingError', {
|
||||
defaultMessage:
|
||||
'{agentPolicyName} could not be added. {pkgName} is not installed, add {pkgName} to `{packagesConfigValue}` or remove it from {packagePolicyName}.',
|
||||
'[{agentPolicyName}] could not be added. [{pkgName}] is not installed, add [{pkgName}] to [{packagesConfigValue}] or remove it from [{packagePolicyName}].',
|
||||
values: {
|
||||
agentPolicyName: preconfiguredAgentPolicy.name,
|
||||
packagePolicyName: name,
|
||||
|
|
Loading…
Reference in a new issue