kibana/x-pack/test/fleet_api_integration/helpers.ts
Julia Bardi afad46b89a
[Fleet] Auto upgrade fixes: filter out inactive agents in status API, fix agent fetcher (#217024)
## Summary

Filter out inactive agents in auto upgrade status API - this fixes
uninstalled agents incorrectly included in the % calculation.

For example with 10 active and 5 uninstalled agents, the percentages are
lower than expected.
<img width="1787" alt="image"
src="https://github.com/user-attachments/assets/bd0ebcea-88c5-40d0-b982-f605e83b4eb8"
/>

After the change, the 5 uninstalled agents are not included:
<img width="1778" alt="image"
src="https://github.com/user-attachments/assets/72349902-bbb8-4adb-a69e-8dbfc92ad89e"
/>

The other fix is related to the auto upgrade logic:
https://github.com/elastic/kibana/pull/215069#discussion_r2026552722

### 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
2025-04-07 10:55:16 +02:00

231 lines
6.7 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import * as uuid from 'uuid';
import { ToolingLog } from '@kbn/tooling-log';
import { agentPolicyRouteService } from '@kbn/fleet-plugin/common/services';
import { GLOBAL_SETTINGS_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common/constants';
import {
AgentPolicy,
CreateAgentPolicyRequest,
CreateAgentPolicyResponse,
} from '@kbn/fleet-plugin/common';
import { KbnClient } from '@kbn/test';
import { UNINSTALL_TOKENS_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common';
import { Agent as SuperTestAgent } from 'supertest';
import { FtrProviderContext } from '../api_integration/ftr_provider_context';
export function warnAndSkipTest(mochaContext: Mocha.Context, log: ToolingLog) {
log.warning(
'disabling tests because DockerServers service is not enabled, set FLEET_PACKAGE_REGISTRY_PORT to run them'
);
mochaContext.skip();
}
export function isDockerRegistryEnabledOrSkipped(providerContext: FtrProviderContext) {
if (process.env.FLEET_SKIP_RUNNING_PACKAGE_REGISTRY === 'true') {
return true;
}
const { getService } = providerContext;
const dockerServers = getService('dockerServers');
const server = dockerServers.get('registry');
return server.enabled;
}
export function skipIfNoDockerRegistry(providerContext: FtrProviderContext) {
const { getService } = providerContext;
const dockerServers = getService('dockerServers');
if (process.env.FLEET_SKIP_RUNNING_PACKAGE_REGISTRY === 'true') {
return;
}
const server = dockerServers.get('registry');
const log = getService('log');
beforeEach(function beforeSetupWithDockerRegistry() {
if (!server.enabled) {
warnAndSkipTest(this, log);
}
});
}
export const makeSnapshotVersion = (version: string) => {
return version.endsWith('-SNAPSHOT') ? version : `${version}-SNAPSHOT`;
};
export async function generateAgent(
providerContext: FtrProviderContext,
status: string,
id: string,
policyId: string,
version?: string,
upgradeDetails?: any
) {
let data: any = {};
const { getService } = providerContext;
const es = getService('es');
switch (status) {
case 'error':
data = { policy_revision_idx: 1, last_checkin_status: 'error' };
break;
case 'degraded':
data = { policy_revision_idx: 1, last_checkin_status: 'degraded' };
break;
case 'offline':
// default inactivity timeout is 2 weeks
// anything less + above offline timeout will be offline
const oneWeekAgoTimestamp = new Date().getTime() - 7 * 24 * 60 * 60 * 1000;
data = { policy_revision_idx: 1, last_checkin: new Date(oneWeekAgoTimestamp).toISOString() };
break;
case 'inactive':
const threeWeeksAgoTimestamp = new Date().getTime() - 21 * 24 * 60 * 60 * 1000;
data = {
policy_revision_idx: 1,
last_checkin: new Date(threeWeeksAgoTimestamp).toISOString(),
};
break;
// Agent with last checkin status as error and currently unenrolling => should displayd updating status
case 'error-unenrolling':
data = {
policy_revision_idx: 1,
last_checkin_status: 'error',
unenrollment_started_at: '2017-06-07T18:59:04.498Z',
};
break;
case 'uninstalled':
data = {
audit_unenrolled_reason: 'uninstall',
policy_revision_idx: 1,
last_checkin: new Date().toISOString(),
};
break;
default:
data = { policy_revision_idx: 1, last_checkin: new Date().toISOString() };
}
await es.index({
index: '.fleet-agents',
id,
document: {
id,
type: 'PERMANENT',
active: true,
enrolled_at: new Date().toISOString(),
last_checkin: new Date().toISOString(),
policy_id: policyId,
policy_revision: 1,
agent: {
id,
version,
},
local_metadata: {
elastic: {
agent: {
version,
upgradeable: true,
},
},
},
...data,
...(upgradeDetails ? { upgrade_details: upgradeDetails } : {}),
},
refresh: 'wait_for',
});
}
export function setPrereleaseSetting(supertest: SuperTestAgent) {
before(async () => {
await supertest
.put('/api/fleet/settings')
.set('kbn-xsrf', 'xxxx')
.send({ prerelease_integrations_enabled: true });
});
after(async () => {
await supertest
.put('/api/fleet/settings')
.set('kbn-xsrf', 'xxxx')
.send({ prerelease_integrations_enabled: false });
});
}
export async function enableSecrets(providerContext: FtrProviderContext) {
const settingsSO = await providerContext
.getService('kibanaServer')
.savedObjects.get({ type: GLOBAL_SETTINGS_SAVED_OBJECT_TYPE, id: 'fleet-default-settings' })
.catch((err) => {});
if (settingsSO) {
await providerContext.getService('kibanaServer').savedObjects.update({
type: GLOBAL_SETTINGS_SAVED_OBJECT_TYPE,
id: 'fleet-default-settings',
attributes: {
secret_storage_requirements_met: true,
},
overwrite: false,
});
} else {
await providerContext.getService('kibanaServer').savedObjects.create({
type: GLOBAL_SETTINGS_SAVED_OBJECT_TYPE,
id: 'fleet-default-settings',
attributes: {
secret_storage_requirements_met: true,
},
overwrite: true,
});
}
}
export const generateNAgentPolicies = async (
supertest: SuperTestAgent,
number: number,
overwrite?: Partial<CreateAgentPolicyRequest['body']>
): Promise<AgentPolicy[]> => {
const agentPolicyPromises: Array<Promise<AgentPolicy>> = [];
for (let i = 0; i < number; i++) {
agentPolicyPromises.push(generateAgentPolicy(supertest, overwrite));
}
const agentPolicies = await Promise.all(agentPolicyPromises);
return agentPolicies;
};
export const generateAgentPolicy = async (
supertest: SuperTestAgent,
overwrite?: Partial<CreateAgentPolicyRequest['body']>
): Promise<AgentPolicy> => {
const response = await supertest
.post(agentPolicyRouteService.getCreatePath())
.set('kbn-xsrf', 'xxxx')
.send({ name: `Agent Policy ${uuid.v4()}`, namespace: 'default', ...overwrite })
.expect(200);
return (response.body as CreateAgentPolicyResponse).item;
};
export const addUninstallTokenToPolicy = async (
kibanaServer: KbnClient,
policyId: string,
token: string
) => {
const savedObject = await kibanaServer.savedObjects.create({
type: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE,
attributes: {
policy_id: policyId,
token,
},
overwrite: false,
});
return savedObject.id;
};