mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Fleet] Change 'Out-of-date' to 'Outdated policy' in agent list table (#164673)
## Summary Closes #164575. Bonus: also fix the bug where the warning goes under the policy revision I thought that looked a bit weird. Double bonus: Updated the create agent test script to be able to create outdated agents + to use nicer policy names so the table doesnt get messy Before: <img width="1237" alt="Screenshot 2023-08-24 at 10 10 58" src="86a88ad6
-a2c7-4f17-82bb-fe026d05d937"> After: <img width="1244" alt="Screenshot 2023-08-24 at 10 09 53" src="1cf76dd3
-2e6a-4aa9-a004-109797f54c52">
This commit is contained in:
parent
86224d4cf6
commit
1610e32972
2 changed files with 96 additions and 12 deletions
|
@ -180,9 +180,11 @@ export const AgentListTable: React.FC<Props> = (props: Props) => {
|
|||
const showWarning = agent.policy_revision && agentPolicy?.revision > agent.policy_revision;
|
||||
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="none" style={{ minWidth: 0 }} direction="column">
|
||||
<EuiFlexGroup gutterSize="m" style={{ minWidth: 0 }} alignItems="center">
|
||||
{agentPolicy && (
|
||||
<AgentPolicySummaryLine direction="column" policy={agentPolicy} agent={agent} />
|
||||
<EuiFlexItem grow={false}>
|
||||
<AgentPolicySummaryLine direction="column" policy={agentPolicy} agent={agent} />
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{showWarning && (
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -191,7 +193,7 @@ export const AgentListTable: React.FC<Props> = (props: Props) => {
|
|||
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentList.outOfDateLabel"
|
||||
defaultMessage="Out-of-date"
|
||||
defaultMessage="Outdated policy"
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -8,6 +8,7 @@ import fetch from 'node-fetch';
|
|||
import { ToolingLog } from '@kbn/tooling-log';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import yargs from 'yargs';
|
||||
import { omit } from 'lodash';
|
||||
|
||||
import type { AgentStatus } from '../../common';
|
||||
import type { Agent } from '../../common';
|
||||
|
@ -27,6 +28,7 @@ const printUsage = () =>
|
|||
[--password]: password for kibana, defaults to changeme
|
||||
[--batches]: run the script in batches, defaults to 1 e.g if count is 50 and batches is 10, 500 agents will be created and 10 agent policies
|
||||
[--concurrentBatches]: how many batches to run concurrently, defaults to 10
|
||||
[--outdated]: agents will show as outdated (their revision is below the policies), defaults to false
|
||||
`);
|
||||
|
||||
const DEFAULT_KIBANA_URL = 'http://localhost:5601';
|
||||
|
@ -51,7 +53,8 @@ const {
|
|||
agentVersion: agentVersionArg,
|
||||
username: kbnUsername = DEFAULT_KIBANA_USERNAME,
|
||||
password: kbnPassword = DEFAULT_KIBANA_PASSWORD,
|
||||
batches: batchesArg,
|
||||
batches: batchesArg = 1,
|
||||
outdated: outdatedArg = false,
|
||||
concurrentBatches: concurrentBatchesArg = 10,
|
||||
// ignore yargs positional args, we only care about named args
|
||||
_,
|
||||
|
@ -133,10 +136,12 @@ function createAgentWithStatus({
|
|||
policyId,
|
||||
status,
|
||||
version,
|
||||
hostname,
|
||||
}: {
|
||||
policyId: string;
|
||||
status: AgentStatus;
|
||||
version: string;
|
||||
hostname: string;
|
||||
}) {
|
||||
const baseAgent = {
|
||||
access_api_key_id: 'api-key-1',
|
||||
|
@ -153,7 +158,7 @@ function createAgentWithStatus({
|
|||
version,
|
||||
},
|
||||
},
|
||||
host: { hostname: uuidv4() },
|
||||
host: { hostname },
|
||||
},
|
||||
user_provided_metadata: {},
|
||||
enrolled_at: new Date().toISOString(),
|
||||
|
@ -167,7 +172,8 @@ function createAgentWithStatus({
|
|||
function createAgentsWithStatuses(
|
||||
statusMap: Partial<{ [status in AgentStatus]: number }>,
|
||||
policyId: string,
|
||||
version: string
|
||||
version: string,
|
||||
namePrefix?: string
|
||||
) {
|
||||
// loop over statuses and create agents with that status
|
||||
const agents = [];
|
||||
|
@ -176,13 +182,35 @@ function createAgentsWithStatuses(
|
|||
const currentAgentStatus = currentStatus as AgentStatus;
|
||||
const statusCount = statusMap[currentAgentStatus] || 0;
|
||||
for (let i = 0; i < statusCount; i++) {
|
||||
agents.push(createAgentWithStatus({ policyId, status: currentAgentStatus, version }));
|
||||
const hostname = `${namePrefix ? namePrefix + '-' : ''}${currentAgentStatus}-${i}`;
|
||||
agents.push(
|
||||
createAgentWithStatus({ policyId, status: currentAgentStatus, version, hostname })
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return agents;
|
||||
}
|
||||
|
||||
async function getAgentPolicy(id: string) {
|
||||
const res = await fetch(`${kibanaUrl}/api/fleet/agent_policies/${id}`, {
|
||||
method: 'get',
|
||||
headers: {
|
||||
Authorization: kbnAuth,
|
||||
'Content-Type': 'application/json',
|
||||
'kbn-xsrf': 'kibana',
|
||||
'x-elastic-product-origin': 'fleet',
|
||||
},
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
if (!data.item) {
|
||||
logger.error('Agent policy not found, API response: ' + JSON.stringify(data));
|
||||
process.exit(1);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
async function deleteAgents() {
|
||||
const auth = 'Basic ' + Buffer.from(ES_SUPERUSER + ':' + ES_PASSWORD).toString('base64');
|
||||
const res = await fetch(`${ES_URL}/.fleet-agents/_delete_by_query`, {
|
||||
|
@ -256,12 +284,12 @@ async function createSuperUser() {
|
|||
return { role, user };
|
||||
}
|
||||
|
||||
async function createAgentPolicy(id: string) {
|
||||
async function createAgentPolicy(id: string, name: string) {
|
||||
const res = await fetch(`${kibanaUrl}/api/fleet/agent_policies`, {
|
||||
method: 'post',
|
||||
body: JSON.stringify({
|
||||
id,
|
||||
name: id,
|
||||
name,
|
||||
namespace: 'default',
|
||||
description: '',
|
||||
monitoring_enabled: ['logs', 'metrics'],
|
||||
|
@ -277,12 +305,56 @@ async function createAgentPolicy(id: string) {
|
|||
const data = await res.json();
|
||||
|
||||
if (!data.item) {
|
||||
if (data.message.includes('already exists')) {
|
||||
// use regex to get the id from the error message, id is the first string in single quotes
|
||||
const idRegex = /'([^']+)'/;
|
||||
const idMatch = data.message.match(idRegex);
|
||||
if (!idMatch || !idMatch[1]) {
|
||||
logger.error('Cannot extract id from error message, API response: ' + JSON.stringify(data));
|
||||
process.exit(1);
|
||||
}
|
||||
logger.info(`Agent policy ${idMatch[1]} already exists, using existing policy`);
|
||||
return getAgentPolicy(idMatch![1]);
|
||||
}
|
||||
logger.error('Agent policy not created, API response: ' + JSON.stringify(data));
|
||||
process.exit(1);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
async function bumpAgentPolicyRevision(id: string, policy: any) {
|
||||
const res = await fetch(`${kibanaUrl}/api/fleet/agent_policies/${id}`, {
|
||||
method: 'put',
|
||||
body: JSON.stringify({
|
||||
...omit(policy, [
|
||||
'id',
|
||||
'updated_at',
|
||||
'updated_by',
|
||||
'revision',
|
||||
'status',
|
||||
'schema_version',
|
||||
'package_policies',
|
||||
'agents',
|
||||
]),
|
||||
monitoring_enabled: ['logs'], // change monitoring to add a revision
|
||||
}),
|
||||
headers: {
|
||||
Authorization: kbnAuth,
|
||||
'Content-Type': 'application/json',
|
||||
'kbn-xsrf': 'kibana',
|
||||
'x-elastic-product-origin': 'fleet',
|
||||
},
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if (!data.item) {
|
||||
logger.error('Agent policy not updated, API response: ' + JSON.stringify(data));
|
||||
process.exit(1);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function logStatusMap(statusMap: Partial<{ [status in AgentStatus]: number }>) {
|
||||
const statuses = Object.keys(statusMap);
|
||||
logger.info(
|
||||
|
@ -337,14 +409,24 @@ export async function run() {
|
|||
Array(currentBatchSize)
|
||||
.fill(0)
|
||||
.map(async (__, i) => {
|
||||
const agentPolicyId = uuidv4();
|
||||
const agentPolicy = await createAgentPolicy(agentPolicyId);
|
||||
let agentPolicyId = uuidv4();
|
||||
const agentPolicy = await createAgentPolicy(agentPolicyId, `Policy ${i}`);
|
||||
agentPolicyId = agentPolicy.item.id;
|
||||
logger.info(`Created agent policy ${agentPolicy.item.id}`);
|
||||
|
||||
const statusMap = statusesArg.reduce((acc, status) => ({ ...acc, [status]: count }), {});
|
||||
logStatusMap(statusMap);
|
||||
const agents = createAgentsWithStatuses(statusMap, agentPolicyId, agentVersion);
|
||||
const agents = createAgentsWithStatuses(
|
||||
statusMap,
|
||||
agentPolicyId,
|
||||
agentVersion,
|
||||
i > 0 ? `batch-${i}` : undefined
|
||||
);
|
||||
const createRes = await createAgentDocsBulk(agents);
|
||||
if (outdatedArg) {
|
||||
logger.info(`Bumping agent policy revision so that agents will have outdated policies`);
|
||||
bumpAgentPolicyRevision(agentPolicyId, agentPolicy.item);
|
||||
}
|
||||
logger.info(
|
||||
`Batch complete, created ${createRes.items.length} agent docs, took ${createRes.took}, errors: ${createRes.errors}`
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue