Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const _allowedExperimentalValues = {
enabledUpgradeAgentlessDeploymentsTask: true,
enableAgentMigrations: false,
enablePackageRollback: false,
enableAutoInstallContentPackages: false,
enableAutoInstallContentPackages: true,
enableOtelIntegrations: false,
enableAgentStatusAlerting: false,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import * as Registry from '../services/epm/registry';
import { createAppContextStartContractMock, createMockPackageService } from '../mocks';

import type { PackageClient } from '../services';
import { appContextService } from '../services';
import { appContextService, dataStreamService } from '../services';

import { getInstalledPackages } from '../services/epm/packages';

Expand Down Expand Up @@ -122,14 +122,17 @@ describe('AutoInstallContentPackagesTask', () => {
beforeEach(async () => {
const [{ elasticsearch }] = await mockCore.getStartServices();
esClient = elasticsearch.client.asInternalUser as ElasticsearchClientMock;
esClient.esql.query.mockResolvedValue({
took: 100,
values: [
[1, 'system.cpu'],
[2, 'system.memory'],
[3, 'system.test'],
],
} as any);
(dataStreamService.getAllFleetDataStreams as jest.Mock).mockResolvedValue([
{
name: 'logs-system.cpu-default',
} as any,
{
name: 'logs-system.memory-default',
} as any,
{
name: 'logs-system.test-default',
} as any,
]);
jest
.spyOn(appContextService, 'getExperimentalFeatures')
.mockReturnValue({ enableAutoInstallContentPackages: true } as any);
Expand Down Expand Up @@ -172,12 +175,6 @@ describe('AutoInstallContentPackagesTask', () => {
automaticInstall: true,
});
expect(packageClientMock.installPackage).toHaveBeenCalledTimes(2);
expect(esClient.esql.query).toHaveBeenCalledWith({
query: `FROM logs-*,metrics-*,traces-*
| KEEP @timestamp, data_stream.dataset
| WHERE @timestamp > NOW() - 10 minutes
| STATS COUNT(*) BY data_stream.dataset `,
});
});

it('should install content packages and filter out installed datasets', async () => {
Expand All @@ -199,12 +196,6 @@ describe('AutoInstallContentPackagesTask', () => {
automaticInstall: true,
});
expect(packageClientMock.installPackage).toHaveBeenCalledTimes(1);
expect(esClient.esql.query).toHaveBeenCalledWith({
query: `FROM logs-*,metrics-*,traces-*
| KEEP @timestamp, data_stream.dataset
| WHERE @timestamp > NOW() - 10 minutes
| STATS COUNT(*) BY data_stream.dataset | WHERE data_stream.dataset NOT IN ("system.test")`,
});
});

it('should not call registry if cached', async () => {
Expand Down Expand Up @@ -256,7 +247,7 @@ describe('AutoInstallContentPackagesTask', () => {
await runTask();

expect(packageClientMock.installPackage).not.toHaveBeenCalled();
expect(esClient.esql.query).not.toHaveBeenCalled();
expect(dataStreamService.getAllFleetDataStreams).not.toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { errors } from '@elastic/elasticsearch';
import type { DiscoveryDataset } from '../../common/types';

import type { PackageClient } from '../services';
import { appContextService } from '../services';
import { appContextService, dataStreamService } from '../services';
import * as Registry from '../services/epm/registry';

import { MAX_CONCURRENT_EPM_PACKAGES_INSTALLATIONS, SO_SEARCH_LIMIT } from '../constants';
Expand Down Expand Up @@ -293,32 +293,16 @@ export class AutoInstallContentPackagesTask {
esClient: ElasticsearchClient,
datasetsOfInstalledContentPackages: string[]
): Promise<string[]> {
const whereClause =
datasetsOfInstalledContentPackages.length > 0
? `| WHERE data_stream.dataset NOT IN (${datasetsOfInstalledContentPackages
.map((dataset) => `"${dataset}"`)
.join(',')})`
: '';
const query = `FROM logs-*,metrics-*,traces-*
| KEEP @timestamp, data_stream.dataset
| WHERE @timestamp > NOW() - ${this.intervalToEsql(this.taskInterval)}
| STATS COUNT(*) BY data_stream.dataset ${whereClause}`;
const response = await esClient.esql.query({ query });
this.logger.info(`[AutoInstallContentPackagesTask] ESQL query took: ${response.took}ms`);

const datasetsWithData: string[] = response.values.map((value: any[]) => value[1]);
const allFleetDataStreams = await dataStreamService.getAllFleetDataStreams(esClient);
const datasetsWithData: string[] = allFleetDataStreams
.map((dataStream: any) => dataStream.name.split('-')[1])
.filter((dataset) => !datasetsOfInstalledContentPackages.includes(dataset));
this.logger.info(
`[AutoInstallContentPackagesTask] Found datasets with data: ${datasetsWithData.join(', ')}`
);
return datasetsWithData;
}

private intervalToEsql(interval: string): string {
const value = parseInt(interval, 10);
const unit = interval.includes('h') ? 'hours' : interval.includes('m') ? 'minutes' : 'seconds';
return `${value} ${unit}`;
}

private async getContentPackagesDiscoveryMap(prerelease: boolean): Promise<DiscoveryMap> {
const type = 'content';
const discoveryMap: DiscoveryMap = {};
Expand Down
Loading