[Fleet] Add force option to DELETE package endpoint. (#95051)

* Add force option to DELETE package endpoint.

* Add integration test.

* Adjust openapi spec.

* Run EPM tests before fleet setup tests.

* Run package delete tests first in EPM tests
This commit is contained in:
Sonja Krause-Harder 2021-03-24 17:04:49 +01:00 committed by GitHub
parent 0551472cd9
commit 2e5b5debb5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 106 additions and 8 deletions

View file

@ -1633,7 +1633,21 @@
{
"$ref": "#/paths/~1setup/post/parameters/0"
}
]
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"force": {
"type": "boolean"
}
}
}
}
}
}
}
},
"/agents/{agentId}": {

View file

@ -1038,6 +1038,14 @@ paths:
operationId: post-epm-delete-pkgkey
parameters:
- $ref: '#/paths/~1setup/post/parameters/0'
requestBody:
content:
application/json:
schema:
type: object
properties:
force:
type: boolean
'/agents/{agentId}':
parameters:
- schema:

View file

@ -89,3 +89,11 @@ delete:
operationId: post-epm-delete-pkgkey
parameters:
- $ref: ../components/headers/kbn_xsrf.yaml
requestBody:
content:
application/json:
schema:
type: object
properties:
force:
type: boolean

View file

@ -310,13 +310,20 @@ export const installPackageByUploadHandler: RequestHandler<
};
export const deletePackageHandler: RequestHandler<
TypeOf<typeof DeletePackageRequestSchema.params>
TypeOf<typeof DeletePackageRequestSchema.params>,
undefined,
TypeOf<typeof DeletePackageRequestSchema.body>
> = async (context, request, response) => {
try {
const { pkgkey } = request.params;
const savedObjectsClient = context.core.savedObjects.client;
const esClient = context.core.elasticsearch.client.asCurrentUser;
const res = await removeInstallation({ savedObjectsClient, pkgkey, esClient });
const res = await removeInstallation({
savedObjectsClient,
pkgkey,
esClient,
force: request.body?.force,
});
const body: DeletePackageResponse = {
response: res,
};

View file

@ -32,13 +32,14 @@ export async function removeInstallation(options: {
savedObjectsClient: SavedObjectsClientContract;
pkgkey: string;
esClient: ElasticsearchClient;
force?: boolean;
}): Promise<AssetReference[]> {
const { savedObjectsClient, pkgkey, esClient } = options;
const { savedObjectsClient, pkgkey, esClient, force } = options;
// TODO: the epm api should change to /name/version so we don't need to do this
const { pkgName, pkgVersion } = splitPkgKey(pkgkey);
const installation = await getInstallation({ savedObjectsClient, pkgName });
if (!installation) throw Boom.badRequest(`${pkgName} is not installed`);
if (installation.removable === false)
if (installation.removable === false && !force)
throw Boom.badRequest(`${pkgName} is installed by default and cannot be removed`);
const { total } = await packagePolicyService.list(savedObjectsClient, {

View file

@ -65,4 +65,9 @@ export const DeletePackageRequestSchema = {
params: schema.object({
pkgkey: schema.string(),
}),
body: schema.nullable(
schema.object({
force: schema.boolean(),
})
),
};

View file

@ -0,0 +1,54 @@
/*
* 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 { FtrProviderContext } from '../../../api_integration/ftr_provider_context';
import { skipIfNoDockerRegistry } from '../../helpers';
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const supertest = getService('supertest');
const requiredPackage = 'system-0.11.0';
const installPackage = async (pkgkey: string) => {
await supertest
.post(`/api/fleet/epm/packages/${pkgkey}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true });
};
const deletePackage = async (pkgkey: string) => {
await supertest
.delete(`/api/fleet/epm/packages/${pkgkey}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true });
};
describe('delete and force delete scenarios', async () => {
skipIfNoDockerRegistry(providerContext);
before(async () => {
await installPackage(requiredPackage);
});
after(async () => {
await deletePackage(requiredPackage);
});
it('should return 400 if trying to uninstall a required package', async function () {
await supertest
.delete(`/api/fleet/epm/packages/${requiredPackage}`)
.set('kbn-xsrf', 'xxxx')
.expect(400);
});
it('should return 200 if trying to force uninstall a required package', async function () {
await supertest
.delete(`/api/fleet/epm/packages/${requiredPackage}`)
.set('kbn-xsrf', 'xxxx')
.send({ force: true })
.expect(200);
});
});
}

View file

@ -7,6 +7,7 @@
export default function loadTests({ loadTestFile }) {
describe('EPM Endpoints', () => {
loadTestFile(require.resolve('./delete'));
loadTestFile(require.resolve('./list'));
loadTestFile(require.resolve('./setup'));
loadTestFile(require.resolve('./get'));

View file

@ -8,6 +8,9 @@
export default function ({ loadTestFile }) {
describe('Fleet Endpoints', function () {
this.tags('ciGroup10');
// EPM
loadTestFile(require.resolve('./epm/index'));
// Fleet setup
loadTestFile(require.resolve('./fleet_setup'));
@ -30,9 +33,6 @@ export default function ({ loadTestFile }) {
// Enrollment API keys
loadTestFile(require.resolve('./enrollment_api_keys/crud'));
// EPM
loadTestFile(require.resolve('./epm/index'));
// Package policies
loadTestFile(require.resolve('./package_policy/create'));
loadTestFile(require.resolve('./package_policy/update'));