mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[Fleet] Support package capabilities filtering (#162435)
This commit is contained in:
parent
1dbd736b15
commit
9b8950254e
11 changed files with 100 additions and 16 deletions
|
@ -26,3 +26,6 @@ telemetry.labels.serverless: search
|
|||
|
||||
# Alerts config
|
||||
xpack.actions.enabledActionTypes: ['.email', '.index', '.slack', '.jira', '.webhook', '.teams']
|
||||
|
||||
# Fleet specific configuration
|
||||
xpack.fleet.internal.capabilities: ['serverless_search']
|
||||
|
|
|
@ -24,6 +24,9 @@ xpack.fleet.agentIdVerificationEnabled: false
|
|||
## APM Serverless Onboarding flow
|
||||
xpack.apm.serverlessOnboarding: true
|
||||
|
||||
# Fleet specific configuration
|
||||
xpack.fleet.internal.capabilities: ['apm', 'uptime', 'observability']
|
||||
|
||||
## Required for force installation of APM Package
|
||||
xpack.fleet.packages:
|
||||
- name: apm
|
||||
|
|
|
@ -23,7 +23,9 @@ xpack.serverless.plugin.developer.projectSwitcher.currentType: 'security'
|
|||
# Specify in telemetry the project type
|
||||
telemetry.labels.serverless: security
|
||||
|
||||
# Fleet specific configuration
|
||||
xpack.fleet.internal.capabilities: ['security']
|
||||
|
||||
# Serverless security specific options
|
||||
xpack.securitySolution.enableExperimental:
|
||||
- discoverInTimeline
|
||||
|
||||
- discoverInTimeline
|
||||
|
|
|
@ -50,6 +50,7 @@ export interface FleetConfigType {
|
|||
disableProxies: boolean;
|
||||
fleetServerStandalone: boolean;
|
||||
activeAgentsSoftLimit?: number;
|
||||
capabilities: string[];
|
||||
};
|
||||
createArtifactsBulkBatchSize?: number;
|
||||
}
|
||||
|
|
|
@ -182,6 +182,18 @@ export const config: PluginConfigDescriptor = {
|
|||
min: 0,
|
||||
})
|
||||
),
|
||||
capabilities: schema.arrayOf(
|
||||
schema.oneOf([
|
||||
// See package-spec for the list of available capiblities https://github.com/elastic/package-spec/blob/dcc37b652690f8a2bca9cf8a12fc28fd015730a0/spec/integration/manifest.spec.yml#L113
|
||||
schema.literal('apm'),
|
||||
schema.literal('enterprise_search'),
|
||||
schema.literal('observability'),
|
||||
schema.literal('security'),
|
||||
schema.literal('serverless_search'),
|
||||
schema.literal('uptime'),
|
||||
]),
|
||||
{ defaultValue: [] }
|
||||
),
|
||||
})
|
||||
),
|
||||
enabled: schema.boolean({ defaultValue: true }),
|
||||
|
|
|
@ -124,6 +124,7 @@ describe('_installPackage', () => {
|
|||
disableILMPolicies: true,
|
||||
disableProxies: false,
|
||||
fleetServerStandalone: false,
|
||||
capabilities: [],
|
||||
},
|
||||
})
|
||||
);
|
||||
|
@ -176,6 +177,7 @@ describe('_installPackage', () => {
|
|||
disableProxies: false,
|
||||
disableILMPolicies: false,
|
||||
fleetServerStandalone: false,
|
||||
capabilities: [],
|
||||
},
|
||||
})
|
||||
);
|
||||
|
|
|
@ -40,6 +40,7 @@ import type {
|
|||
RegistryPackage,
|
||||
EpmPackageAdditions,
|
||||
GetCategoriesRequest,
|
||||
GetPackagesRequest,
|
||||
} from '../../../../common/types';
|
||||
import type { Installation, PackageInfo, PackagePolicySOAttributes } from '../../../types';
|
||||
import {
|
||||
|
@ -61,7 +62,6 @@ import { getFilteredSearchPackages } from '../filtered_packages';
|
|||
|
||||
import { createInstallableFrom } from '.';
|
||||
|
||||
export type { SearchParams } from '../registry';
|
||||
export { getFile } from '../registry';
|
||||
|
||||
function nameAsTitle(name: string) {
|
||||
|
@ -76,7 +76,7 @@ export async function getPackages(
|
|||
options: {
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
excludeInstallStatus?: boolean;
|
||||
} & Registry.SearchParams
|
||||
} & GetPackagesRequest['query']
|
||||
) {
|
||||
const {
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -13,7 +13,6 @@ import { KibanaAssetType } from '../../../types';
|
|||
import type { AssetType, Installable, Installation } from '../../../types';
|
||||
|
||||
export { bulkInstallPackages, isBulkInstallError } from './bulk_install_packages';
|
||||
export type { SearchParams } from './get';
|
||||
export {
|
||||
getCategories,
|
||||
getFile,
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import { loggingSystemMock } from '@kbn/core-logging-server-mocks';
|
||||
|
||||
import { PackageNotFoundError, RegistryResponseError } from '../../../errors';
|
||||
|
||||
import * as Archive from '../archive';
|
||||
|
||||
import {
|
||||
|
@ -17,10 +16,13 @@ import {
|
|||
fetchFindLatestPackageOrThrow,
|
||||
fetchInfo,
|
||||
getLicensePath,
|
||||
fetchCategories,
|
||||
fetchList,
|
||||
} from '.';
|
||||
|
||||
const mockLoggerFactory = loggingSystemMock.create();
|
||||
const mockLogger = mockLoggerFactory.get('mock logger');
|
||||
const mockGetConfig = jest.fn();
|
||||
|
||||
const mockGetBundledPackageByName = jest.fn();
|
||||
const mockFetchUrl = jest.fn();
|
||||
|
@ -34,7 +36,7 @@ jest.mock('../..', () => ({
|
|||
getLogger: () => mockLogger,
|
||||
getKibanaBranch: () => 'main',
|
||||
getKibanaVersion: () => '99.0.0',
|
||||
getConfig: () => ({}),
|
||||
getConfig: () => mockGetConfig(),
|
||||
getIsProductionMode: () => false,
|
||||
},
|
||||
}));
|
||||
|
@ -219,3 +221,57 @@ describe('fetchInfo', () => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchCategories', () => {
|
||||
beforeEach(() => {
|
||||
mockFetchUrl.mockReset();
|
||||
mockGetConfig.mockReset();
|
||||
});
|
||||
it('call registry with capabilities if configured', async () => {
|
||||
mockGetConfig.mockReturnValue({
|
||||
internal: {
|
||||
capabilities: ['apm', 'security'],
|
||||
},
|
||||
});
|
||||
mockFetchUrl.mockResolvedValue(JSON.stringify([]));
|
||||
await fetchCategories();
|
||||
expect(mockFetchUrl).toBeCalledTimes(1);
|
||||
const callUrl = new URL(mockFetchUrl.mock.calls[0][0]);
|
||||
expect(callUrl.searchParams.get('capabilities')).toBe('apm,security');
|
||||
});
|
||||
it('does not call registry with capabilities if none are configured', async () => {
|
||||
mockGetConfig.mockReturnValue({});
|
||||
mockFetchUrl.mockResolvedValue(JSON.stringify([]));
|
||||
await fetchCategories();
|
||||
expect(mockFetchUrl).toBeCalledTimes(1);
|
||||
const callUrl = new URL(mockFetchUrl.mock.calls[0][0]);
|
||||
expect(callUrl.searchParams.get('capabilities')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchList', () => {
|
||||
beforeEach(() => {
|
||||
mockFetchUrl.mockReset();
|
||||
mockGetConfig.mockReset();
|
||||
});
|
||||
it('call registry with capabilities if configured', async () => {
|
||||
mockGetConfig.mockReturnValue({
|
||||
internal: {
|
||||
capabilities: ['apm', 'security'],
|
||||
},
|
||||
});
|
||||
mockFetchUrl.mockResolvedValue(JSON.stringify([]));
|
||||
await fetchList();
|
||||
expect(mockFetchUrl).toBeCalledTimes(1);
|
||||
const callUrl = new URL(mockFetchUrl.mock.calls[0][0]);
|
||||
expect(callUrl.searchParams.get('capabilities')).toBe('apm,security');
|
||||
});
|
||||
it('does not call registry with capabilities if none are configured', async () => {
|
||||
mockGetConfig.mockReturnValue({});
|
||||
mockFetchUrl.mockResolvedValue(JSON.stringify([]));
|
||||
await fetchList();
|
||||
expect(mockFetchUrl).toBeCalledTimes(1);
|
||||
const callUrl = new URL(mockFetchUrl.mock.calls[0][0]);
|
||||
expect(callUrl.searchParams.get('capabilities')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,11 +18,11 @@ import { splitPkgKey as split } from '../../../../common/services';
|
|||
import { KibanaAssetType } from '../../../types';
|
||||
import type {
|
||||
AssetsGroupedByServiceByType,
|
||||
CategoryId,
|
||||
CategorySummaryList,
|
||||
RegistryPackage,
|
||||
RegistrySearchResults,
|
||||
GetCategoriesRequest,
|
||||
GetPackagesRequest,
|
||||
PackageVerificationResult,
|
||||
ArchivePackage,
|
||||
BundledPackage,
|
||||
|
@ -54,19 +54,14 @@ import { verifyPackageArchiveSignature } from '../packages/package_verification'
|
|||
import { fetchUrl, getResponse, getResponseStream } from './requests';
|
||||
import { getRegistryUrl } from './registry_url';
|
||||
|
||||
export interface SearchParams {
|
||||
category?: CategoryId;
|
||||
prerelease?: boolean;
|
||||
// deprecated
|
||||
experimental?: boolean;
|
||||
}
|
||||
|
||||
export const splitPkgKey = split;
|
||||
|
||||
export const pkgToPkgKey = ({ name, version }: { name: string; version: string }) =>
|
||||
`${name}-${version}`;
|
||||
|
||||
export async function fetchList(params?: SearchParams): Promise<RegistrySearchResults> {
|
||||
export async function fetchList(
|
||||
params?: GetPackagesRequest['query']
|
||||
): Promise<RegistrySearchResults> {
|
||||
const registryUrl = getRegistryUrl();
|
||||
const url = new URL(`${registryUrl}/search`);
|
||||
if (params) {
|
||||
|
@ -79,6 +74,7 @@ export async function fetchList(params?: SearchParams): Promise<RegistrySearchRe
|
|||
}
|
||||
|
||||
setKibanaVersion(url);
|
||||
setCapabilities(url);
|
||||
|
||||
return fetchUrl(url.toString()).then(JSON.parse);
|
||||
}
|
||||
|
@ -111,6 +107,7 @@ async function _fetchFindLatestPackage(
|
|||
|
||||
if (!ignoreConstraints) {
|
||||
setKibanaVersion(url);
|
||||
setCapabilities(url);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -239,6 +236,13 @@ function setKibanaVersion(url: URL) {
|
|||
}
|
||||
}
|
||||
|
||||
function setCapabilities(url: URL) {
|
||||
const capabilities = appContextService.getConfig()?.internal?.capabilities;
|
||||
if (capabilities && capabilities.length > 0) {
|
||||
url.searchParams.set('capabilities', capabilities.join(','));
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchCategories(
|
||||
params?: GetCategoriesRequest['query']
|
||||
): Promise<CategorySummaryList> {
|
||||
|
@ -254,6 +258,7 @@ export async function fetchCategories(
|
|||
}
|
||||
|
||||
setKibanaVersion(url);
|
||||
setCapabilities(url);
|
||||
|
||||
return fetchUrl(url.toString()).then(JSON.parse);
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ export type {
|
|||
InstallSource,
|
||||
InstallResult,
|
||||
GetCategoriesRequest,
|
||||
GetPackagesRequest,
|
||||
DataType,
|
||||
FleetServerEnrollmentAPIKey,
|
||||
FleetServerAgent,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue