Skip to content

Commit

Permalink
[Fleet] Allow to skipDatastreamRollover from preconfiguration (#173766)
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet authored Dec 21, 2023
1 parent 85df7c9 commit e51a3f9
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export interface PreconfiguredAgentPolicy extends Omit<NewAgentPolicy, 'namespac

export interface PreconfiguredPackage extends Omit<PackagePolicyPackage, 'title'> {
prerelease?: boolean;
skipDataStreamRollover?: boolean;
}

export interface PreconfiguredOutput extends Omit<Output, 'config_yaml'> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import type { BulkInstallResponse, IBulkInstallPackageError } from './install';

interface BulkInstallPackagesParams {
savedObjectsClient: SavedObjectsClientContract;
packagesToInstall: Array<string | { name: string; version?: string; prerelease?: boolean }>;
packagesToInstall: Array<
| string
| { name: string; version?: string; prerelease?: boolean; skipDataStreamRollover?: boolean }
>;
esClient: ElasticsearchClient;
force?: boolean;
spaceId: string;
Expand Down Expand Up @@ -48,10 +51,18 @@ export async function bulkInstallPackages({
name: pkgRes.name,
version: pkgRes.version,
prerelease: undefined,
skipDataStreamRollover: undefined,
}));
}
if (pkg.version !== undefined) {
return Promise.resolve(pkg as { name: string; version: string; prerelease?: boolean });
return Promise.resolve(
pkg as {
name: string;
version: string;
prerelease?: boolean;
skipDataStreamRollover?: boolean;
}
);
}

return Registry.fetchFindLatestPackageOrThrow(pkg.name, {
Expand All @@ -60,6 +71,7 @@ export async function bulkInstallPackages({
name: pkgRes.name,
version: pkgRes.version,
prerelease: pkg.prerelease,
skipDataStreamRollover: pkg.skipDataStreamRollover,
}));
})
);
Expand Down Expand Up @@ -114,6 +126,7 @@ export async function bulkInstallPackages({
force,
prerelease: prerelease || ('prerelease' in pkgKeyProps && pkgKeyProps.prerelease),
authorizationHeader,
skipDataStreamRollover: pkgKeyProps.skipDataStreamRollover,
});

if (installResult.error) {
Expand Down
88 changes: 57 additions & 31 deletions x-pack/plugins/fleet/server/services/preconfiguration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
} from './preconfiguration';
import { packagePolicyService } from './package_policy';
import { getBundledPackages } from './epm/packages/bundled_packages';
import type { InstallPackageParams } from './epm/packages/install';
import { installPackage, type InstallPackageParams } from './epm/packages/install';

jest.mock('./agent_policy_update');
jest.mock('./output');
Expand Down Expand Up @@ -144,44 +144,46 @@ jest.mock('./epm/registry', () => ({
}));

jest.mock('./epm/packages/install', () => ({
async installPackage(args: InstallPackageParams): Promise<InstallResult | undefined> {
if (args.installSource === 'registry') {
const [pkgName, pkgVersion] = args.pkgkey.split('-');
const installError = mockInstallPackageErrors.get(pkgName);
if (installError) {
installPackage: jest.fn(
async (args: InstallPackageParams): Promise<InstallResult | undefined> => {
if (args.installSource === 'registry') {
const [pkgName, pkgVersion] = args.pkgkey.split('-');
const installError = mockInstallPackageErrors.get(pkgName);
if (installError) {
return {
error: new Error(installError),
installType: 'install',
installSource: 'registry',
};
}

const installedPackage = mockInstalledPackages.get(pkgName);
if (installedPackage) {
if (installedPackage.version === pkgVersion) return installedPackage;
}

const packageInstallation = { name: pkgName, version: pkgVersion, title: pkgName };
mockInstalledPackages.set(pkgName, packageInstallation);

return {
error: new Error(installError),
status: 'installed',
installType: 'install',
installSource: 'registry',
};
}

const installedPackage = mockInstalledPackages.get(pkgName);
if (installedPackage) {
if (installedPackage.version === pkgVersion) return installedPackage;
}
} else if (args.installSource === 'upload') {
const { archiveBuffer } = args;

const packageInstallation = { name: pkgName, version: pkgVersion, title: pkgName };
mockInstalledPackages.set(pkgName, packageInstallation);
// Treat the buffer value passed in tests as the package's name for simplicity
const pkgName = archiveBuffer.toString('utf8');

return {
status: 'installed',
installType: 'install',
installSource: 'registry',
};
} else if (args.installSource === 'upload') {
const { archiveBuffer } = args;

// Treat the buffer value passed in tests as the package's name for simplicity
const pkgName = archiveBuffer.toString('utf8');

// Just install every bundled package at version '1.0.0'
const packageInstallation = { name: pkgName, version: '1.0.0', title: pkgName };
mockInstalledPackages.set(pkgName, packageInstallation);
// Just install every bundled package at version '1.0.0'
const packageInstallation = { name: pkgName, version: '1.0.0', title: pkgName };
mockInstalledPackages.set(pkgName, packageInstallation);

return { status: 'installed', installType: 'install', installSource: 'upload' };
return { status: 'installed', installType: 'install', installSource: 'upload' };
}
}
},
),
ensurePackagesCompletedInstall() {
return [];
},
Expand Down Expand Up @@ -395,6 +397,30 @@ describe('policy preconfiguration', () => {
expect(nonFatalErrors.length).toBe(0);
});

it('should pass skipDatastreamRollover flag if configured', async () => {
const soClient = getPutPreconfiguredPackagesMock();
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;

const { policies, packages, nonFatalErrors } = await ensurePreconfiguredPackagesAndPolicies(
soClient,
esClient,
[] as PreconfiguredAgentPolicy[],
[{ name: 'test_package', version: 'latest', skipDataStreamRollover: true }],
mockDefaultOutput,
mockDefaultDownloadService,
DEFAULT_SPACE_ID
);

expect(policies.length).toEqual(0);
expect(packages).toEqual(expect.arrayContaining(['test_package-1.0.0']));
expect(nonFatalErrors.length).toBe(0);
expect(jest.mocked(installPackage)).toBeCalledWith(
expect.objectContaining({
skipDataStreamRollover: true,
})
);
});

it('should not add new package policy to existing non managed policies', async () => {
const soClient = getPutPreconfiguredPackagesMock();
const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser;
Expand Down
6 changes: 5 additions & 1 deletion x-pack/plugins/fleet/server/services/preconfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ export async function ensurePreconfiguredPackagesAndPolicies(

const packagesToInstall = packages.map((pkg) =>
pkg.version === PRECONFIGURATION_LATEST_KEYWORD
? { name: pkg.name, prerelease: pkg.prerelease }
? {
name: pkg.name,
prerelease: pkg.prerelease,
skipDataStreamRollover: pkg.skipDataStreamRollover,
}
: pkg
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const PreconfiguredPackagesSchema = schema.arrayOf(
},
}),
prerelease: schema.maybe(schema.boolean()),
skipDataStreamRollover: schema.maybe(schema.boolean()),
}),
{
defaultValue: [],
Expand Down

0 comments on commit e51a3f9

Please sign in to comment.