Skip to content

Commit

Permalink
[Fleet] Fix incorrect count of agents in bulk actions (elastic#175318)
Browse files Browse the repository at this point in the history
Fixes elastic#171914

## Summary
Fix a small issue occurring when there are inactive agents, both regular
and managed.

Another PR with some refactoring for this component will follow.

### Repro steps

- Enroll fleet server on fleet-server-policy - make sure to have two
inactive fleet server agents on this policy as well
- Enroll ~20 agents with horde and make them inactive
- Make fleet server policy "managed"
- Select "inactive" in the status filter
- Click on "Select agents on all pages"
- The bulk actions shouldn't report negative actions. If the count is 0,
the actions will appear disabled

#### Before
![Screenshot 2024-01-22 at 15 59
42](https://github.com/elastic/kibana/assets/16084106/cb8c6c80-b23f-4415-af2a-b4de8ae387f6)

#### After
![Screenshot 2024-01-24 at 15 53
53](https://github.com/elastic/kibana/assets/16084106/6b020016-6171-43d7-bc12-685bf01b7989)


### Checklist

- [ ] [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
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed

---------

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
2 people authored and CoenWarmer committed Feb 15, 2024
1 parent b866c28 commit 01ba067
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const defaultProps = {
shownAgents: 10,
inactiveShownAgents: 0,
totalManagedAgentIds: [],
inactiveManagedAgentIds: [],
selectionMode: 'manual',
currentQuery: '',
selectedAgents: [],
Expand Down Expand Up @@ -126,6 +127,10 @@ describe('AgentBulkActions', () => {
});

describe('When in query mode', () => {
mockedExperimentalFeaturesService.get.mockReturnValue({
diagnosticFileUploadEnabled: true,
} as any);

it('should show correct actions for active agents when no managed policies exist', async () => {
const results = render({
...defaultProps,
Expand Down Expand Up @@ -162,15 +167,57 @@ describe('AgentBulkActions', () => {

expect(results.getByText('Add / remove tags').closest('button')!).toBeEnabled();
expect(results.getByText('Assign to new policy').closest('button')!).toBeEnabled();
expect(results.getByText('Unenroll 8 agents').closest('button')!).toBeEnabled();
expect(results.getByText('Upgrade 8 agents').closest('button')!).toBeEnabled();
expect(results.getByText('Schedule upgrade for 8 agents').closest('button')!).toBeDisabled();
expect(
results.getByText('Request diagnostics for 8 agents').closest('button')!
).toBeEnabled();
expect(results.getByText('Unenroll 8 agents').closest('button')!).toBeEnabled();
expect(results.getByText('Upgrade 8 agents').closest('button')!).toBeEnabled();
expect(results.getByText('Schedule upgrade for 8 agents').closest('button')!).toBeDisabled();
expect(results.getByText('Restart upgrade 8 agents').closest('button')!).toBeEnabled();
});

it('should show correct actions also when there are inactive managed agents', async () => {
const results = render({
...defaultProps,
inactiveManagedAgentIds: ['agentId1', 'agentId2'],
totalManagedAgentIds: ['agentId1', 'agentId2', 'agentId3'],
selectionMode: 'query',
});

const bulkActionsButton = results.getByTestId('agentBulkActionsButton');
await act(async () => {
fireEvent.click(bulkActionsButton);
});

expect(results.getByText('Add / remove tags').closest('button')!).toBeEnabled();
expect(results.getByText('Assign to new policy').closest('button')!).toBeEnabled();
expect(results.getByText('Unenroll 9 agents').closest('button')!).toBeEnabled();
expect(results.getByText('Upgrade 9 agents').closest('button')!).toBeEnabled();
expect(results.getByText('Schedule upgrade for 9 agents').closest('button')!).toBeDisabled();
expect(results.getByText('Restart upgrade 9 agents').closest('button')!).toBeEnabled();
});

it('should show disabled actions when only inactive agents are selected', async () => {
const results = render({
...defaultProps,
inactiveShownAgents: 10,
selectedAgents: [{ id: 'agent1' }, { id: 'agent2' }] as Agent[],
selectionMode: 'query',
});

const bulkActionsButton = results.getByTestId('agentBulkActionsButton');
await act(async () => {
fireEvent.click(bulkActionsButton);
});

expect(results.getByText('Add / remove tags').closest('button')!).toBeDisabled();
expect(results.getByText('Assign to new policy').closest('button')!).toBeDisabled();
expect(results.getByText('Unenroll 0 agents').closest('button')!).toBeDisabled();
expect(results.getByText('Upgrade 0 agents').closest('button')!).toBeDisabled();
expect(results.getByText('Schedule upgrade for 0 agents').closest('button')!).toBeDisabled();
expect(results.getByText('Restart upgrade 0 agents').closest('button')!).toBeDisabled();
});

it('should generate a correct kuery to select agents', async () => {
const results = render({
...defaultProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface Props {
shownAgents: number;
inactiveShownAgents: number;
totalManagedAgentIds: string[];
inactiveManagedAgentIds: string[];
selectionMode: SelectionMode;
currentQuery: string;
selectedAgents: Agent[];
Expand All @@ -51,6 +52,7 @@ export const AgentBulkActions: React.FunctionComponent<Props> = ({
shownAgents,
inactiveShownAgents,
totalManagedAgentIds,
inactiveManagedAgentIds,
selectionMode,
currentQuery,
selectedAgents,
Expand Down Expand Up @@ -91,18 +93,19 @@ export const AgentBulkActions: React.FunctionComponent<Props> = ({
}
}, [currentQuery, totalManagedAgentIds]);

// Check if user is working with only inactive agents
const atLeastOneActiveAgentSelected =
selectionMode === 'manual'
? !!selectedAgents.find((agent) => agent.active)
: shownAgents > inactiveShownAgents;
const totalActiveAgents = shownAgents - inactiveShownAgents;

// exclude inactive agents from the count
const agentCount =
selectionMode === 'manual'
? selectedAgents.length
: totalActiveAgents - totalManagedAgentIds?.length;
: totalActiveAgents - (totalManagedAgentIds?.length - inactiveManagedAgentIds?.length);

// Check if user is working with only inactive agents
const atLeastOneActiveAgentSelected =
selectionMode === 'manual'
? !!selectedAgents.find((agent) => agent.active)
: agentCount > 0 && shownAgents > inactiveShownAgents;
const agents = selectionMode === 'manual' ? selectedAgents : selectionQuery;

const [tagsPopoverButton, setTagsPopoverButton] = useState<HTMLElement>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export interface SearchAndFilterBarProps {
inactiveShownAgents: number;
totalInactiveAgents: number;
totalManagedAgentIds: string[];
inactiveManagedAgentIds: string[];
selectionMode: SelectionMode;
currentQuery: string;
selectedAgents: Agent[];
Expand Down Expand Up @@ -78,6 +79,7 @@ export const SearchAndFilterBar: React.FunctionComponent<SearchAndFilterBarProps
inactiveShownAgents,
totalInactiveAgents,
totalManagedAgentIds,
inactiveManagedAgentIds,
selectionMode,
currentQuery,
selectedAgents,
Expand Down Expand Up @@ -202,6 +204,7 @@ export const SearchAndFilterBar: React.FunctionComponent<SearchAndFilterBarProps
shownAgents={shownAgents}
inactiveShownAgents={inactiveShownAgents}
totalManagedAgentIds={totalManagedAgentIds}
inactiveManagedAgentIds={inactiveManagedAgentIds}
selectionMode={selectionMode}
currentQuery={currentQuery}
selectedAgents={selectedAgents}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
const [inactiveShownAgents, setInactiveShownAgents] = useState(0);
const [totalInactiveAgents, setTotalInactiveAgents] = useState(0);
const [totalManagedAgentIds, setTotalManagedAgentIds] = useState<string[]>([]);
const [inactiveManagedAgentIds, setInactiveManagedAgentIds] = useState<string[]>([]);
const [managedAgentsOnCurrentPage, setManagedAgentsOnCurrentPage] = useState(0);
const [showAgentActivityTour, setShowAgentActivityTour] = useState({ isOpen: false });
const getSortFieldForAPI = (field: keyof Agent): string => {
Expand Down Expand Up @@ -335,7 +336,11 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
}
const allManagedAgents = response.data?.items ?? [];
const allManagedAgentIds = allManagedAgents?.map((agent) => agent.id);
const inactiveManagedIds = allManagedAgents
?.filter((agent) => agent.status === 'inactive')
.map((agent) => agent.id);
setTotalManagedAgentIds(allManagedAgentIds);
setInactiveManagedAgentIds(inactiveManagedIds);

setManagedAgentsOnCurrentPage(
agentsResponse.data.items
Expand Down Expand Up @@ -606,6 +611,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {
inactiveShownAgents={inactiveShownAgents}
totalInactiveAgents={totalInactiveAgents}
totalManagedAgentIds={totalManagedAgentIds}
inactiveManagedAgentIds={inactiveManagedAgentIds}
selectionMode={selectionMode}
currentQuery={kuery}
selectedAgents={selectedAgents}
Expand Down

0 comments on commit 01ba067

Please sign in to comment.