[Fleet] Fix error occurring when multiple package policies are upgraded (#141625)

* [Fleet] Fix error occurring  when multiple package policies are upgraded

* Add integration test

* Fix test

* Improve testing

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Cristina Amico 2022-09-27 15:43:09 +02:00 committed by GitHub
parent fb136431c5
commit ab00a75937
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 172 additions and 15 deletions

View file

@ -666,6 +666,158 @@ describe('Package policy service', () => {
).rejects.toThrow('Saved object [abc/123] conflict');
});
it('should fail to update if the name already exists on another policy', async () => {
const savedObjectsClient = savedObjectsClientMock.create();
savedObjectsClient.find.mockResolvedValue({
total: 1,
per_page: 1,
page: 1,
saved_objects: [
{
id: 'existing-package-policy',
type: 'ingest-package-policies',
score: 1,
references: [],
version: '1.0.0',
attributes: {
name: 'endpoint-1',
description: '',
namespace: 'default',
enabled: true,
policy_id: 'policy-id-1',
package: {
name: 'endpoint',
title: 'Elastic Endpoint',
version: '0.9.0',
},
inputs: [],
},
},
],
});
savedObjectsClient.get.mockResolvedValue({
id: 'the-package-policy-id',
type: 'abcd',
references: [],
version: 'test',
attributes: {},
});
savedObjectsClient.update.mockImplementation(
async (
type: string,
id: string,
attrs: any
): Promise<SavedObjectsUpdateResponse<PackagePolicySOAttributes>> => {
savedObjectsClient.get.mockResolvedValue({
id: 'the-package-policy-id',
type,
references: [],
version: 'test',
attributes: attrs,
});
return attrs;
}
);
const elasticsearchClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
await expect(
packagePolicyService.update(
savedObjectsClient,
elasticsearchClient,
'the-package-policy-id',
{
name: 'endpoint-1',
description: '',
namespace: 'default',
enabled: true,
policy_id: '93c46720-c217-11ea-9906-b5b8a21b268e',
package: {
name: 'endpoint',
title: 'Elastic Endpoint',
version: '0.9.0',
},
inputs: [],
}
)
).rejects.toThrow(
'An integration policy with the name endpoint-1 already exists. Please rename it or choose a different name.'
);
});
it('should not fail to update if skipUniqueNameVerification when the name already exists on another policy', async () => {
const savedObjectsClient = savedObjectsClientMock.create();
savedObjectsClient.find.mockResolvedValue({
total: 1,
per_page: 1,
page: 1,
saved_objects: [
{
id: 'existing-package-policy',
type: 'ingest-package-policies',
score: 1,
references: [],
version: '1.0.0',
attributes: {
name: 'endpoint-1',
description: '',
namespace: 'default',
enabled: true,
policy_id: 'policy-id-1',
package: {
name: 'endpoint',
title: 'Elastic Endpoint',
version: '0.9.0',
},
inputs: [],
},
},
],
});
savedObjectsClient.get.mockResolvedValue({
id: 'the-package-policy-id',
type: 'abcd',
references: [],
version: 'test',
attributes: {},
});
savedObjectsClient.update.mockImplementation(
async (
type: string,
id: string,
attrs: any
): Promise<SavedObjectsUpdateResponse<PackagePolicySOAttributes>> => {
savedObjectsClient.get.mockResolvedValue({
id: 'the-package-policy-id',
type,
references: [],
version: 'test',
attributes: attrs,
});
return attrs;
}
);
const elasticsearchClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
const result = await packagePolicyService.update(
savedObjectsClient,
elasticsearchClient,
'the-package-policy-id',
{
name: 'endpoint-1',
description: '',
namespace: 'default',
enabled: true,
policy_id: '93c46720-c217-11ea-9906-b5b8a21b268e',
package: {
name: 'endpoint',
title: 'Elastic Endpoint',
version: '0.9.0',
},
inputs: [],
},
{ skipUniqueNameVerification: true }
);
expect(result.name).toEqual('endpoint-1');
});
it('should throw if the user try to update input vars that are frozen', async () => {
const savedObjectsClient = savedObjectsClientMock.create();
const mockPackagePolicy = createPackagePolicyMock();

View file

@ -469,7 +469,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient {
esClient: ElasticsearchClient,
id: string,
packagePolicyUpdate: UpdatePackagePolicy,
options?: { user?: AuthenticatedUser; force?: boolean },
options?: { user?: AuthenticatedUser; force?: boolean; skipUniqueNameVerification?: boolean },
currentVersion?: string
): Promise<PackagePolicy> {
const packagePolicy = { ...packagePolicyUpdate, name: packagePolicyUpdate.name.trim() };
@ -479,22 +479,22 @@ class PackagePolicyClientImpl implements PackagePolicyClient {
if (packagePolicyUpdate.is_managed && !options?.force) {
throw new PackagePolicyRestrictionRelatedError(`Cannot update package policy ${id}`);
}
if (!oldPackagePolicy) {
throw new Error('Package policy not found');
}
// Check that the name does not exist already but exclude the current package policy
const existingPoliciesWithName = await this.list(soClient, {
perPage: SO_SEARCH_LIMIT,
kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name:"${packagePolicy.name}"`,
});
const filtered = (existingPoliciesWithName?.items || []).filter((p) => p.id !== id);
if (filtered.length > 0) {
throw new FleetError(
`An integration policy with the name ${packagePolicy.name} already exists. Please rename it or choose a different name.`
);
if (!options?.skipUniqueNameVerification) {
// Check that the name does not exist already but exclude the current package policy
const existingPoliciesWithName = await this.list(soClient, {
perPage: SO_SEARCH_LIMIT,
kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name:"${packagePolicy.name}"`,
});
const filtered = (existingPoliciesWithName?.items || []).filter((p) => p.id !== id);
if (filtered.length > 0) {
throw new FleetError(
`An integration policy with the name ${packagePolicy.name} already exists. Please rename it or choose a different name.`
);
}
}
let inputs = restOfPackagePolicy.inputs.map((input) =>
@ -929,12 +929,17 @@ class PackagePolicyClientImpl implements PackagePolicyClient {
);
updatePackagePolicy.elasticsearch = packageInfo.elasticsearch;
const updateOptions = {
skipUniqueNameVerification: true,
...options,
};
await this.update(
soClient,
esClient,
id,
updatePackagePolicy,
options,
updateOptions,
packagePolicy.package!.version
);

View file

@ -97,7 +97,7 @@ export interface PackagePolicyClient {
esClient: ElasticsearchClient,
id: string,
packagePolicyUpdate: UpdatePackagePolicy,
options?: { user?: AuthenticatedUser; force?: boolean },
options?: { user?: AuthenticatedUser; force?: boolean; skipUniqueNameVerification?: boolean },
currentVersion?: string
): Promise<PackagePolicy>;