Skip to content

Commit

Permalink
[Fleet] fixed tags query, added missing runtime fields (#148236)
Browse files Browse the repository at this point in the history
## Summary

Partial fix for #148233

Added missing runtime fields to tags query.
This fixes Tags filter on Agent List UI when status filters are present.

<img width="1060" alt="image"
src="https://user-images.githubusercontent.com/90178898/210068647-347ed2a9-9339-47f3-b84a-b916afbf17d1.png">

Added a quick fix to remove default status filter from bulk update tags.
This will not work correctly if there are inactive/unenrolled agents.
Update tags with non-default status filters doesn't work either.

EDIT: added back status filters on real fields from history, and using
them in update tags. The missing piece is to tweak the
unenrolled/inactive filters to their latest logic. This should fix
update tags on all status filters, though we have the status logic in
two places. Ideally the status field should become a real field.

<img width="1039" alt="image"
src="https://user-images.githubusercontent.com/90178898/210070213-f466b381-59a8-454c-81be-699989becf02.png">

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
juliaElastic and kibanamachine authored Jan 5, 2023
1 parent dc1ae9e commit 2a54625
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 30 deletions.
3 changes: 2 additions & 1 deletion x-pack/plugins/fleet/server/routes/agent/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,10 @@ export const getAgentTagsHandler: RequestHandler<
> = async (context, request, response) => {
const coreContext = await context.core;
const esClient = coreContext.elasticsearch.client.asInternalUser;
const soClient = coreContext.savedObjects.client;

try {
const tags = await AgentService.getAgentTags(esClient, {
const tags = await AgentService.getAgentTags(soClient, esClient, {
showInactive: request.query.showInactive,
kuery: request.query.kuery,
});
Expand Down
68 changes: 40 additions & 28 deletions x-pack/plugins/fleet/server/services/agents/crud.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,23 @@ describe('Agents CRUD test', () => {
},
});

const result = await getAgentTags(esClientMock, { showInactive: false });
const result = await getAgentTags(soClientMock, esClientMock, { showInactive: false });

expect(result).toEqual(['tag1', 'tag2']);
expect(searchMock).toHaveBeenCalledWith({
aggs: { tags: { terms: { field: 'tags', size: 10000 } } },
body: {
query: expect.any(Object),
},
index: '.fleet-agents',
size: 0,
});
expect(searchMock).toHaveBeenCalledWith(
expect.objectContaining({
aggs: { tags: { terms: { field: 'tags', size: 10000 } } },
body: {
query: expect.any(Object),
},
index: '.fleet-agents',
size: 0,
fields: ['status'],
runtime_mappings: {
status: expect.anything(),
},
})
);
});

it('should return empty list if no agent tags', async () => {
Expand All @@ -74,15 +80,15 @@ describe('Agents CRUD test', () => {
},
});

const result = await getAgentTags(esClientMock, { showInactive: false });
const result = await getAgentTags(soClientMock, esClientMock, { showInactive: false });

expect(result).toEqual([]);
});

it('should return empty list if no agent index', async () => {
searchMock.mockRejectedValueOnce(new errors.ResponseError({ statusCode: 404 } as any));

const result = await getAgentTags(esClientMock, { showInactive: false });
const result = await getAgentTags(soClientMock, esClientMock, { showInactive: false });

expect(result).toEqual([]);
});
Expand All @@ -94,30 +100,36 @@ describe('Agents CRUD test', () => {
},
});

await getAgentTags(esClientMock, {
await getAgentTags(soClientMock, esClientMock, {
showInactive: true,
kuery: 'fleet-agents.policy_id: 123',
});

expect(searchMock).toHaveBeenCalledWith({
aggs: { tags: { terms: { field: 'tags', size: 10000 } } },
body: {
query: {
bool: {
minimum_should_match: 1,
should: [
{
match: {
policy_id: '123',
expect(searchMock).toHaveBeenCalledWith(
expect.objectContaining({
aggs: { tags: { terms: { field: 'tags', size: 10000 } } },
body: {
query: {
bool: {
minimum_should_match: 1,
should: [
{
match: {
policy_id: '123',
},
},
},
],
],
},
},
},
},
index: '.fleet-agents',
size: 0,
});
index: '.fleet-agents',
size: 0,
fields: ['status'],
runtime_mappings: {
status: expect.anything(),
},
})
);
});
});

Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/fleet/server/services/agents/crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export async function closePointInTime(esClient: ElasticsearchClient, pitId: str
}

export async function getAgentTags(
soClient: SavedObjectsClientContract,
esClient: ElasticsearchClient,
options: ListWithKuery & {
showInactive: boolean;
Expand All @@ -137,11 +138,14 @@ export async function getAgentTags(

const kueryNode = _joinFilters(filters);
const body = kueryNode ? { query: toElasticsearchQuery(kueryNode) } : {};
const runtimeFields = await buildAgentStatusRuntimeField(soClient);
try {
const result = await esClient.search<{}, { tags: { buckets: Array<{ key: string }> } }>({
index: AGENTS_INDEX,
size: 0,
body,
fields: Object.keys(runtimeFields),
runtime_mappings: runtimeFields,
aggs: {
tags: {
terms: { field: 'tags', size: SO_SEARCH_LIMIT },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,12 @@ export async function updateTagsBatch(
} else if (options.tagsToRemove.length === 1 && options.tagsToAdd.length === 0) {
extraFilters.push(`tags:${options.tagsToRemove[0]}`);
}
query = getElasticsearchQuery(options.kuery, false, false, hostedIds, extraFilters);
const DEFAULT_STATUS_FILTER =
'status:online or (status:error or status:degraded) or (status:updating or status:unenrolling or status:enrolling) or status:offline';
// removing default staus filters, as it is a runtime field and doesn't work with updateByQuery
// this is a quick fix for bulk update tags with default filters
const kuery = options.kuery === DEFAULT_STATUS_FILTER ? '' : options.kuery;
query = getElasticsearchQuery(kuery, false, false, hostedIds, extraFilters);
} else {
query = {
terms: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ export const fleetUsagesSchema: RootSchema<any> = {
description: 'The total number of enrolled agents currently offline',
},
},
inactive: {
type: 'long',
_meta: {
description: 'The total number of enrolled agents currently inactive',
},
},
unenrolled: {
type: 'long',
_meta: {
description: 'The total number of unenrolled agents',
},
},
total_all_statuses: {
type: 'long',
_meta: {
Expand Down Expand Up @@ -113,6 +125,18 @@ export const fleetUsagesSchema: RootSchema<any> = {
description: 'The number of Fleet Server hosts configured in Fleet settings.',
},
},
inactive: {
type: 'long',
_meta: {
description: 'The total number of enrolled agents currently inactive',
},
},
unenrolled: {
type: 'long',
_meta: {
description: 'The total number of unenrolled agents',
},
},
},
},
packages: {
Expand Down

0 comments on commit 2a54625

Please sign in to comment.