Skip to content

Commit

Permalink
[Fleet] return uploaded packages that are not in registry (elastic#15…
Browse files Browse the repository at this point in the history
…0332)

## Summary

Related to elastic#148599
Fixes elastic#81995

Changed `GET /epm/packages` API to list uploaded packages as well that
are not in registry.

Testing steps:
- Built a test package that is not in registry from kibana repo:
```
x-pack/test/fleet_api_integration/apis/fixtures/package_verification/packages/src/verified-1.0.0
elastic-package build --zip -v
```
- Uploaded the resulting zip
[verified-1.0.0.zip](https://github.com/elastic/kibana/files/10664094/verified-1.0.0.zip)
```
curl -XPOST -H 'content-type: application/zip' -H 'kbn-xsrf: true' http://localhost:5601/julia/api/fleet/epm/packages -u elastic:changeme --data-binary @verified-1.0.0.zip
```
- Navigate to `Integrations` page, verify that the `Verified` package is
displayed under `Browse` / `Installed` integrations, and the details are
visible when clicking on the package.

<img width="639" alt="image"
src="https://user-images.githubusercontent.com/90178898/217000305-90c28293-bdfa-42d5-b30b-50f7a63aad11.png">
<img width="757" alt="image"
src="https://user-images.githubusercontent.com/90178898/217000420-208d3b90-5341-4f1f-8ab8-554f78821bbf.png">
<img width="1147" alt="image"
src="https://user-images.githubusercontent.com/90178898/217000541-06324345-4204-43cc-8411-6c961ec37d17.png">


### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
  • Loading branch information
juliaElastic authored and darnautov committed Feb 7, 2023
1 parent 3377ea8 commit 2b5df12
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 2 deletions.
61 changes: 60 additions & 1 deletion x-pack/plugins/fleet/server/services/epm/packages/get.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { PackageNotFoundError } from '../../../errors';

import { getSettings } from '../../settings';

import { getPackageInfo, getPackageUsageStats } from './get';
import { getPackageInfo, getPackages, getPackageUsageStats } from './get';

const MockRegistry = Registry as jest.Mocked<typeof Registry>;

Expand Down Expand Up @@ -186,6 +186,65 @@ describe('When using EPM `get` services', () => {
});
});

describe('getPackages', () => {
beforeEach(() => {
const mockContract = createAppContextStartContractMock();
appContextService.start(mockContract);
jest.clearAllMocks();
MockRegistry.fetchList.mockResolvedValue([
{
name: 'nginx',
version: '1.0.0',
title: 'Nginx',
} as any,
]);
});

it('should return installed package that is not in registry', async () => {
const soClient = savedObjectsClientMock.create();
soClient.find.mockResolvedValue({
saved_objects: [
{
id: 'elasticsearch',
attributes: {
name: 'elasticsearch',
version: '0.0.1',
install_status: 'upload',
},
},
],
} as any);

await expect(
getPackages({
savedObjectsClient: soClient,
})
).resolves.toMatchObject([
{
name: 'elasticsearch',
version: '0.0.1',
title: 'Elasticsearch',
status: 'upload',
savedObject: {
id: 'elasticsearch',
attributes: {
name: 'elasticsearch',
version: '0.0.1',
install_status: 'upload',
},
},
},
{
name: 'nginx',
version: '1.0.0',
title: 'Nginx',
id: 'nginx',
status: 'not_installed',
},
]);
});
});

describe('getPackageInfo', () => {
beforeEach(() => {
const mockContract = createAppContextStartContractMock();
Expand Down
12 changes: 11 additions & 1 deletion x-pack/plugins/fleet/server/services/epm/packages/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import {
PACKAGE_POLICY_SAVED_OBJECT_TYPE,
} from '../../../../common/constants';
import { isPackageLimited } from '../../../../common/services';
import type { PackageUsageStats, PackagePolicySOAttributes } from '../../../../common/types';
import type {
PackageUsageStats,
PackagePolicySOAttributes,
Installable,
} from '../../../../common/types';
import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../constants';
import type {
ArchivePackage,
Expand Down Expand Up @@ -68,13 +72,19 @@ export async function getPackages(
});
// get the installed packages
const packageSavedObjects = await getPackageSavedObjects(savedObjectsClient);

const packagesNotInRegistry = packageSavedObjects.saved_objects
.filter((pkg) => !registryItems.some((item) => item.name === pkg.id))
.map((pkg) => createInstallableFrom({ ...pkg.attributes, title: nameAsTitle(pkg.id) }, pkg));

const packageList = registryItems
.map((item) =>
createInstallableFrom(
item,
packageSavedObjects.saved_objects.find(({ id }) => id === item.name)
)
)
.concat(packagesNotInRegistry as Installable<any>)
.sort(sortByName);

if (!excludeInstallStatus) {
Expand Down

0 comments on commit 2b5df12

Please sign in to comment.