Skip to content

Commit

Permalink
[Fleet] Allow some agent actions for managed policies (elastic#155923)
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet authored Apr 27, 2023
1 parent 98165d2 commit f06e55f
Show file tree
Hide file tree
Showing 5 changed files with 381 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* 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 React from 'react';
import { fireEvent } from '@testing-library/dom';

import { createFleetTestRendererMock } from '../../../../../../mock';
import type { Agent, AgentPolicy } from '../../../../types';
import { ExperimentalFeaturesService } from '../../../../services';
import { useAuthz } from '../../../../../../hooks/use_authz';

import { AgentDetailsActionMenu } from './actions_menu';

jest.mock('../../../../../../hooks/use_fleet_status', () => ({
FleetStatusProvider: (props: any) => {
return props.children;
},
}));

jest.mock('../../../../../../services/experimental_features');
jest.mock('../../../../../../hooks/use_authz');

const mockedExperimentalFeaturesService = jest.mocked(ExperimentalFeaturesService);
const mockedUseAuthz = jest.mocked(useAuthz);

function renderActions({ agent, agentPolicy }: { agent: Agent; agentPolicy?: AgentPolicy }) {
const renderer = createFleetTestRendererMock();

const utils = renderer.render(
<AgentDetailsActionMenu
agent={agent}
agentPolicy={agentPolicy}
assignFlyoutOpenByDefault={false}
onCancelReassign={jest.fn()}
/>
);

fireEvent.click(utils.getByRole('button'));

return { utils };
}

describe('AgentDetailsActionMenu', () => {
beforeEach(() => {
mockedExperimentalFeaturesService.get.mockReturnValue({
diagnosticFileUploadEnabled: true,
} as any);
mockedUseAuthz.mockReturnValue({
fleet: {
all: true,
},
} as any);
});

describe('Request Diagnotics action', () => {
function renderAndGetDiagnosticsButton({
agent,
agentPolicy,
}: {
agent: Agent;
agentPolicy?: AgentPolicy;
}) {
const { utils } = renderActions({
agent,
agentPolicy,
});

return utils.queryByTestId('requestAgentDiagnosticsBtn');
}

it('should not render action if feature is disabled', async () => {
mockedExperimentalFeaturesService.get.mockReturnValue({
diagnosticFileUploadEnabled: false,
} as any);
const res = renderAndGetDiagnosticsButton({
agent: {} as Agent,
agentPolicy: {} as AgentPolicy,
});
expect(res).toBe(null);
});

it('should render an active action button if agent version >= 8.7', async () => {
const res = renderAndGetDiagnosticsButton({
agent: {
status: 'online',
local_metadata: { elastic: { agent: { version: '8.8.0' } } },
} as any,
agentPolicy: {} as AgentPolicy,
});

expect(res).not.toBe(null);
expect(res).toBeEnabled();
});

it('should render an active action button if agent version >= 8.7 and policy is_managed', async () => {
const res = renderAndGetDiagnosticsButton({
agent: {
status: 'online',
local_metadata: { elastic: { agent: { version: '8.8.0' } } },
} as any,
agentPolicy: {
is_managed: true,
} as AgentPolicy,
});

expect(res).not.toBe(null);
expect(res).toBeEnabled();
});

it('should render a disabled action button if agent version < 8.7', async () => {
const res = renderAndGetDiagnosticsButton({
agent: {
status: 'online',
local_metadata: { elastic: { agent: { version: '8.6.0' } } },
} as any,
agentPolicy: {
is_managed: true,
} as AgentPolicy,
});

expect(res).not.toBe(null);
expect(res).not.toBeEnabled();
});
});

describe('View agent JSON action', () => {
function renderAndGetViewJSONButton({
agent,
agentPolicy,
}: {
agent: Agent;
agentPolicy?: AgentPolicy;
}) {
const { utils } = renderActions({
agent,
agentPolicy,
});

return utils.queryByTestId('viewAgentDetailsJsonBtn');
}

it('should render an active button', async () => {
const res = renderAndGetViewJSONButton({
agent: {} as any,
agentPolicy: {} as AgentPolicy,
});

expect(res).not.toBe(null);
expect(res).toBeEnabled();
});

it('should render an active button for managed agent policy', async () => {
const res = renderAndGetViewJSONButton({
agent: {} as any,
agentPolicy: {
is_managed: true,
} as AgentPolicy,
});

expect(res).not.toBe(null);
expect(res).toBeEnabled();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -61,67 +61,75 @@ export const AgentDetailsActionMenu: React.FunctionComponent<{
}
}, [onCancelReassign, setIsReassignFlyoutOpen]);

const menuItems = [
<EuiContextMenuItem
icon="pencil"
onClick={() => {
setIsReassignFlyoutOpen(true);
}}
disabled={!agent.active}
key="reassignPolicy"
>
<FormattedMessage
id="xpack.fleet.agentList.reassignActionText"
defaultMessage="Assign to new policy"
/>
</EuiContextMenuItem>,
<EuiContextMenuItem
icon="trash"
disabled={!hasFleetAllPrivileges || !agent.active}
onClick={() => {
setIsUnenrollModalOpen(true);
}}
key="unenrollAgent"
>
{isUnenrolling ? (
const menuItems = [];

if (!agentPolicy?.is_managed) {
menuItems.push(
<EuiContextMenuItem
icon="pencil"
onClick={() => {
setIsReassignFlyoutOpen(true);
}}
disabled={!agent.active && !agentPolicy}
key="reassignPolicy"
>
<FormattedMessage
id="xpack.fleet.agentList.forceUnenrollOneButton"
defaultMessage="Force unenroll"
id="xpack.fleet.agentList.reassignActionText"
defaultMessage="Assign to new policy"
/>
) : (
</EuiContextMenuItem>,
<EuiContextMenuItem
icon="trash"
disabled={!hasFleetAllPrivileges || !agent.active}
onClick={() => {
setIsUnenrollModalOpen(true);
}}
key="unenrollAgent"
>
{isUnenrolling ? (
<FormattedMessage
id="xpack.fleet.agentList.forceUnenrollOneButton"
defaultMessage="Force unenroll"
/>
) : (
<FormattedMessage
id="xpack.fleet.agentList.unenrollOneButton"
defaultMessage="Unenroll agent"
/>
)}
</EuiContextMenuItem>,
<EuiContextMenuItem
icon="refresh"
disabled={!isAgentUpgradeable(agent, kibanaVersion)}
onClick={() => {
setIsUpgradeModalOpen(true);
}}
key="upgradeAgent"
>
<FormattedMessage
id="xpack.fleet.agentList.unenrollOneButton"
defaultMessage="Unenroll agent"
id="xpack.fleet.agentList.upgradeOneButton"
defaultMessage="Upgrade agent"
/>
)}
</EuiContextMenuItem>,
<EuiContextMenuItem
icon="refresh"
disabled={!isAgentUpgradeable(agent, kibanaVersion)}
onClick={() => {
setIsUpgradeModalOpen(true);
}}
key="upgradeAgent"
>
<FormattedMessage
id="xpack.fleet.agentList.upgradeOneButton"
defaultMessage="Upgrade agent"
/>
</EuiContextMenuItem>,
</EuiContextMenuItem>
);
}

menuItems.push(
<EuiContextMenuItem
icon="inspect"
onClick={() => {
setIsContextMenuOpen(false);
setIsAgentDetailsJsonFlyoutOpen(!isAgentDetailsJsonFlyoutOpen);
}}
key="agentDetailsJson"
data-test-subj="viewAgentDetailsJsonBtn"
>
<FormattedMessage
id="xpack.fleet.agentList.viewAgentDetailsJsonText"
defaultMessage="View agent JSON"
/>
</EuiContextMenuItem>,
];
</EuiContextMenuItem>
);

if (diagnosticFileUploadEnabled) {
menuItems.push(
Expand All @@ -131,6 +139,7 @@ export const AgentDetailsActionMenu: React.FunctionComponent<{
onClick={() => {
setIsRequestDiagnosticsModalOpen(true);
}}
data-test-subj="requestAgentDiagnosticsBtn"
key="requestDiagnostics"
>
<FormattedMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export const AgentDetailsPage: React.FunctionComponent = () => {
<>
<EuiSpacer size="m" />
<EuiFlexGroup justifyContent="flexEnd" alignItems="center" gutterSize="s" direction="row">
{!isAgentPolicyLoading && !agentPolicyData?.item?.is_managed && (
{!isAgentPolicyLoading && (
<EuiFlexItem grow={false}>
<AgentDetailsActionMenu
agent={agentData.item}
Expand Down
Loading

0 comments on commit f06e55f

Please sign in to comment.