Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Josh Dover <1813008+joshdover@users.noreply.github.com>
This commit is contained in:
parent
f01ad6c371
commit
8e9c74b5d4
|
@ -53,5 +53,7 @@ export const monitoringTypes = Object.values(dataTypes);
|
|||
|
||||
export const installationStatuses = {
|
||||
Installed: 'installed',
|
||||
Installing: 'installing',
|
||||
InstallFailed: 'install_failed',
|
||||
NotInstalled: 'not_installed',
|
||||
} as const;
|
||||
|
|
|
@ -181,6 +181,8 @@
|
|||
"type": "string",
|
||||
"enum": [
|
||||
"installed",
|
||||
"installing",
|
||||
"install_failed",
|
||||
"not_installed"
|
||||
]
|
||||
},
|
||||
|
|
|
@ -119,6 +119,8 @@ paths:
|
|||
type: string
|
||||
enum:
|
||||
- installed
|
||||
- installing
|
||||
- install_failed
|
||||
- not_installed
|
||||
savedObject:
|
||||
type: string
|
||||
|
|
|
@ -17,6 +17,8 @@ get:
|
|||
type: string
|
||||
enum:
|
||||
- installed
|
||||
- installing
|
||||
- install_failed
|
||||
- not_installed
|
||||
savedObject:
|
||||
type: string
|
||||
|
|
|
@ -45,7 +45,7 @@ export interface DefaultPackagesInstallationError {
|
|||
export type InstallType = 'reinstall' | 'reupdate' | 'rollback' | 'update' | 'install' | 'unknown';
|
||||
export type InstallSource = 'registry' | 'upload';
|
||||
|
||||
export type EpmPackageInstallStatus = 'installed' | 'installing';
|
||||
export type EpmPackageInstallStatus = 'installed' | 'installing' | 'install_failed';
|
||||
|
||||
export type DetailViewPanelName = 'overview' | 'policies' | 'assets' | 'settings' | 'custom';
|
||||
export type ServiceName = 'kibana' | 'elasticsearch';
|
||||
|
@ -399,17 +399,26 @@ export interface PackageUsageStats {
|
|||
agent_policy_count: number;
|
||||
}
|
||||
|
||||
export type Installable<T> = Installed<T> | NotInstalled<T>;
|
||||
export type Installable<T> = Installed<T> | Installing<T> | NotInstalled<T> | InstallFailed<T>;
|
||||
|
||||
export type Installed<T = {}> = T & {
|
||||
status: InstallationStatus['Installed'];
|
||||
savedObject: SavedObject<Installation>;
|
||||
};
|
||||
|
||||
export type Installing<T = {}> = T & {
|
||||
status: InstallationStatus['Installing'];
|
||||
savedObject: SavedObject<Installation>;
|
||||
};
|
||||
|
||||
export type NotInstalled<T = {}> = T & {
|
||||
status: InstallationStatus['NotInstalled'];
|
||||
};
|
||||
|
||||
export type InstallFailed<T = {}> = T & {
|
||||
status: InstallationStatus['InstallFailed'];
|
||||
};
|
||||
|
||||
export type AssetReference = KibanaAssetReference | EsAssetReference;
|
||||
|
||||
export type KibanaAssetReference = Pick<SavedObjectReference, 'id'> & {
|
||||
|
|
|
@ -5,23 +5,30 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
jest.mock('../registry');
|
||||
|
||||
import type { SavedObjectsClientContract, SavedObjectsFindResult } from 'kibana/server';
|
||||
|
||||
import { SavedObjectsErrorHelpers } from '../../../../../../../src/core/server';
|
||||
import { savedObjectsClientMock } from '../../../../../../../src/core/server/mocks';
|
||||
import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../common';
|
||||
import type { PackagePolicySOAttributes } from '../../../../common';
|
||||
import { PACKAGES_SAVED_OBJECT_TYPE, PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../common';
|
||||
import type { PackagePolicySOAttributes, RegistryPackage } from '../../../../common';
|
||||
|
||||
import { getPackageUsageStats } from './get';
|
||||
import * as Registry from '../registry';
|
||||
|
||||
import { createAppContextStartContractMock } from '../../../mocks';
|
||||
import { appContextService } from '../../app_context';
|
||||
|
||||
import { getPackageInfo, getPackageUsageStats } from './get';
|
||||
|
||||
const MockRegistry = Registry as jest.Mocked<typeof Registry>;
|
||||
|
||||
describe('When using EPM `get` services', () => {
|
||||
let soClient: jest.Mocked<SavedObjectsClientContract>;
|
||||
|
||||
beforeEach(() => {
|
||||
soClient = savedObjectsClientMock.create();
|
||||
});
|
||||
|
||||
describe('and invoking getPackageUsageStats()', () => {
|
||||
let soClient: jest.Mocked<SavedObjectsClientContract>;
|
||||
|
||||
beforeEach(() => {
|
||||
soClient = savedObjectsClientMock.create();
|
||||
const savedObjects: Array<SavedObjectsFindResult<PackagePolicySOAttributes>> = [
|
||||
{
|
||||
type: 'ingest-package-policies',
|
||||
|
@ -172,4 +179,105 @@ describe('When using EPM `get` services', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPackageInfo', () => {
|
||||
beforeEach(() => {
|
||||
const mockContract = createAppContextStartContractMock();
|
||||
appContextService.start(mockContract);
|
||||
MockRegistry.fetchFindLatestPackage.mockResolvedValue({
|
||||
name: 'my-package',
|
||||
version: '1.0.0',
|
||||
} as RegistryPackage);
|
||||
MockRegistry.getRegistryPackage.mockResolvedValue({
|
||||
paths: [],
|
||||
packageInfo: {
|
||||
name: 'my-package',
|
||||
version: '1.0.0',
|
||||
} as RegistryPackage,
|
||||
});
|
||||
});
|
||||
|
||||
describe('installation status', () => {
|
||||
it('should be not_installed when no package SO exists', async () => {
|
||||
const soClient = savedObjectsClientMock.create();
|
||||
soClient.get.mockRejectedValue(SavedObjectsErrorHelpers.createGenericNotFoundError());
|
||||
|
||||
expect(
|
||||
await getPackageInfo({
|
||||
savedObjectsClient: soClient,
|
||||
pkgName: 'my-package',
|
||||
pkgVersion: '1.0.0',
|
||||
})
|
||||
).toMatchObject({
|
||||
status: 'not_installed',
|
||||
});
|
||||
});
|
||||
|
||||
it('should be installing when package SO install_status is installing', async () => {
|
||||
const soClient = savedObjectsClientMock.create();
|
||||
soClient.get.mockResolvedValue({
|
||||
id: 'my-package',
|
||||
type: PACKAGES_SAVED_OBJECT_TYPE,
|
||||
references: [],
|
||||
attributes: {
|
||||
install_status: 'installing',
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
await getPackageInfo({
|
||||
savedObjectsClient: soClient,
|
||||
pkgName: 'my-package',
|
||||
pkgVersion: '1.0.0',
|
||||
})
|
||||
).toMatchObject({
|
||||
status: 'installing',
|
||||
});
|
||||
});
|
||||
|
||||
it('should be installed when package SO install_status is installed', async () => {
|
||||
const soClient = savedObjectsClientMock.create();
|
||||
soClient.get.mockResolvedValue({
|
||||
id: 'my-package',
|
||||
type: PACKAGES_SAVED_OBJECT_TYPE,
|
||||
references: [],
|
||||
attributes: {
|
||||
install_status: 'installed',
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
await getPackageInfo({
|
||||
savedObjectsClient: soClient,
|
||||
pkgName: 'my-package',
|
||||
pkgVersion: '1.0.0',
|
||||
})
|
||||
).toMatchObject({
|
||||
status: 'installed',
|
||||
});
|
||||
});
|
||||
|
||||
it('should be install_failed when package SO install_status is install_failed', async () => {
|
||||
const soClient = savedObjectsClientMock.create();
|
||||
soClient.get.mockResolvedValue({
|
||||
id: 'my-package',
|
||||
type: PACKAGES_SAVED_OBJECT_TYPE,
|
||||
references: [],
|
||||
attributes: {
|
||||
install_status: 'install_failed',
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
await getPackageInfo({
|
||||
savedObjectsClient: soClient,
|
||||
pkgName: 'my-package',
|
||||
pkgVersion: '1.0.0',
|
||||
})
|
||||
).toMatchObject({
|
||||
status: 'install_failed',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -53,7 +53,7 @@ export function createInstallableFrom<T>(
|
|||
return savedObject
|
||||
? {
|
||||
...from,
|
||||
status: installationStatuses.Installed,
|
||||
status: savedObject.attributes.install_status,
|
||||
savedObject,
|
||||
}
|
||||
: {
|
||||
|
|
|
@ -12,7 +12,12 @@ import type { ElasticsearchClient, SavedObject, SavedObjectsClientContract } fro
|
|||
|
||||
import { generateESIndexPatterns } from '../elasticsearch/template/template';
|
||||
|
||||
import type { BulkInstallPackageInfo, InstallablePackage, InstallSource } from '../../../../common';
|
||||
import type {
|
||||
BulkInstallPackageInfo,
|
||||
EpmPackageInstallStatus,
|
||||
InstallablePackage,
|
||||
InstallSource,
|
||||
} from '../../../../common';
|
||||
import {
|
||||
IngestManagerError,
|
||||
PackageOperationNotSupportedError,
|
||||
|
@ -158,6 +163,8 @@ export async function handleInstallPackageFailure({
|
|||
await removeInstallation({ savedObjectsClient, pkgkey, esClient });
|
||||
}
|
||||
|
||||
await updateInstallStatus({ savedObjectsClient, pkgName, status: 'install_failed' });
|
||||
|
||||
if (installType === 'update') {
|
||||
if (!installedPkg) {
|
||||
logger.error(
|
||||
|
@ -432,6 +439,21 @@ export const updateVersion = async (
|
|||
version: pkgVersion,
|
||||
});
|
||||
};
|
||||
|
||||
export const updateInstallStatus = async ({
|
||||
savedObjectsClient,
|
||||
pkgName,
|
||||
status,
|
||||
}: {
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
pkgName: string;
|
||||
status: EpmPackageInstallStatus;
|
||||
}) => {
|
||||
return savedObjectsClient.update(PACKAGES_SAVED_OBJECT_TYPE, pkgName, {
|
||||
install_status: status,
|
||||
});
|
||||
};
|
||||
|
||||
export async function createInstallation(options: {
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
packageInfo: InstallablePackage;
|
||||
|
|
Loading…
Reference in a new issue