Skip to content

Commit

Permalink
[Ingest Manager] Allow to force unenroll from the UI (elastic#72386)
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet committed Jul 21, 2020
1 parent 2b3dc7f commit 5e06f69
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 31 deletions.
6 changes: 3 additions & 3 deletions x-pack/plugins/ingest_manager/common/services/agent_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ export function getAgentStatus(agent: Agent, now: number = Date.now()): AgentSta
if (!agent.active) {
return 'inactive';
}
if (!agent.last_checkin) {
return 'enrolling';
}
if (agent.unenrollment_started_at && !agent.unenrolled_at) {
return 'unenrolling';
}
if (!agent.last_checkin) {
return 'enrolling';
}

const msLastCheckIn = new Date(lastCheckIn || 0).getTime();
const msSinceLastCheckIn = new Date().getTime() - msLastCheckIn;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ type Props = {
props: EuiButtonProps;
children: JSX.Element;
};
isOpen?: boolean;
onChange?: (isOpen: boolean) => void;
} & (
| {
items: EuiContextMenuPanelProps['items'];
Expand All @@ -31,10 +33,22 @@ type Props = {
}
);

export const ContextMenuActions = React.memo<Props>(({ button, ...props }) => {
const [isOpen, setIsOpen] = useState(false);
const handleCloseMenu = useCallback(() => setIsOpen(false), [setIsOpen]);
const handleToggleMenu = useCallback(() => setIsOpen(!isOpen), [isOpen]);
export const ContextMenuActions = React.memo<Props>(({ button, onChange, isOpen, ...props }) => {
const [isOpenState, setIsOpenState] = useState(false);
const handleCloseMenu = useCallback(() => {
if (onChange) {
onChange(false);
} else {
setIsOpenState(false);
}
}, [setIsOpenState, onChange]);
const handleToggleMenu = useCallback(() => {
if (onChange) {
onChange(!isOpen);
} else {
setIsOpenState(!isOpenState);
}
}, [isOpenState, onChange, isOpen]);

return (
<EuiPopover
Expand All @@ -55,7 +69,7 @@ export const ContextMenuActions = React.memo<Props>(({ button, ...props }) => {
/>
)
}
isOpen={isOpen}
isOpen={isOpen === undefined ? isOpenState : isOpen}
closePopover={handleCloseMenu}
>
{'items' in props ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const AgentDetailsActionMenu: React.FunctionComponent<{
const hasWriteCapabilites = useCapabilities().write;
const refreshAgent = useAgentRefresh();
const [isReassignFlyoutOpen, setIsReassignFlyoutOpen] = useState(assignFlyoutOpenByDefault);
const isUnenrolling = agent.status === 'unenrolling';

const onClose = useMemo(() => {
if (onCancelReassign) {
Expand Down Expand Up @@ -59,7 +60,7 @@ export const AgentDetailsActionMenu: React.FunctionComponent<{
defaultMessage="Assign new agent config"
/>
</EuiContextMenuItem>,
<AgentUnenrollProvider key="unenrollAgent">
<AgentUnenrollProvider key="unenrollAgent" forceUnenroll={isUnenrolling}>
{(unenrollAgentsPrompt) => (
<EuiContextMenuItem
icon="cross"
Expand All @@ -68,10 +69,17 @@ export const AgentDetailsActionMenu: React.FunctionComponent<{
unenrollAgentsPrompt([agent.id], 1, refreshAgent);
}}
>
<FormattedMessage
id="xpack.ingestManager.agentList.unenrollOneButton"
defaultMessage="Unenroll"
/>
{isUnenrolling ? (
<FormattedMessage
id="xpack.ingestManager.agentList.forceUnenrollOneButton"
defaultMessage="Force unenroll"
/>
) : (
<FormattedMessage
id="xpack.ingestManager.agentList.unenrollOneButton"
defaultMessage="Unenroll"
/>
)}
</EuiContextMenuItem>
)}
</AgentUnenrollProvider>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,12 @@ const RowActions = React.memo<{ agent: Agent; onReassignClick: () => void; refre
const { getHref } = useLink();
const hasWriteCapabilites = useCapabilities().write;

const isUnenrolling = agent.status === 'unenrolling';
const [isMenuOpen, setIsMenuOpen] = useState(false);
return (
<ContextMenuActions
isOpen={isMenuOpen}
onChange={(isOpen) => setIsMenuOpen(isOpen)}
items={[
<EuiContextMenuItem
icon="inspect"
Expand All @@ -100,21 +104,29 @@ const RowActions = React.memo<{ agent: Agent; onReassignClick: () => void; refre
/>
</EuiContextMenuItem>,

<AgentUnenrollProvider>
<AgentUnenrollProvider forceUnenroll={isUnenrolling}>
{(unenrollAgentsPrompt) => (
<EuiContextMenuItem
disabled={!hasWriteCapabilites}
icon="cross"
onClick={() => {
unenrollAgentsPrompt([agent.id], 1, () => {
refresh();
setIsMenuOpen(false);
});
}}
>
<FormattedMessage
id="xpack.ingestManager.agentList.unenrollOneButton"
defaultMessage="Unenroll"
/>
{isUnenrolling ? (
<FormattedMessage
id="xpack.ingestManager.agentList.forceUnenrollOneButton"
defaultMessage="Force unenroll"
/>
) : (
<FormattedMessage
id="xpack.ingestManager.agentList.unenrollOneButton"
defaultMessage="Unenroll"
/>
)}
</EuiContextMenuItem>
)}
</AgentUnenrollProvider>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { agentRouteService } from '../../../services';

interface Props {
children: (unenrollAgents: UnenrollAgents) => React.ReactElement;
forceUnenroll?: boolean;
}

export type UnenrollAgents = (
Expand All @@ -24,7 +25,10 @@ export type UnenrollAgents = (

type OnSuccessCallback = (agentsUnenrolled: string[]) => void;

export const AgentUnenrollProvider: React.FunctionComponent<Props> = ({ children }) => {
export const AgentUnenrollProvider: React.FunctionComponent<Props> = ({
children,
forceUnenroll = false,
}) => {
const core = useCore();
const [agents, setAgents] = useState<string[] | string>([]);
const [agentsCount, setAgentsCount] = useState<number>(0);
Expand Down Expand Up @@ -65,19 +69,24 @@ export const AgentUnenrollProvider: React.FunctionComponent<Props> = ({ children
const { error } = await sendRequest<PostAgentUnenrollResponse>({
path: agentRouteService.getUnenrollPath(agentId),
method: 'post',
body: {
force: forceUnenroll,
},
});

if (error) {
throw new Error(error.message);
}

const successMessage = i18n.translate(
'xpack.ingestManager.unenrollAgents.successSingleNotificationTitle',
{
defaultMessage: "Unenrolling agent '{id}'",
values: { id: agentId },
}
);
const successMessage = forceUnenroll
? i18n.translate('xpack.ingestManager.unenrollAgents.successForceSingleNotificationTitle', {
defaultMessage: "Agent '{id}' unenrolled",
values: { id: agentId },
})
: i18n.translate('xpack.ingestManager.unenrollAgents.successSingleNotificationTitle', {
defaultMessage: "Unenrolling agent '{id}'",
values: { id: agentId },
});
core.notifications.toasts.addSuccess(successMessage);

if (onSuccessCallback.current) {
Expand Down Expand Up @@ -107,11 +116,19 @@ export const AgentUnenrollProvider: React.FunctionComponent<Props> = ({ children
<EuiConfirmModal
title={
isSingle && !unenrollByKuery ? (
<FormattedMessage
id="xpack.ingestManager.unenrollAgents.confirmModal.deleteSingleTitle"
defaultMessage="Unenroll agent '{id}'?"
values={{ id: agents[0] }}
/>
forceUnenroll ? (
<FormattedMessage
id="xpack.ingestManager.unenrollAgents.confirmModal.forceDeleteSingleTitle"
defaultMessage="Force unenroll agent '{id}'?"
values={{ id: agents[0] }}
/>
) : (
<FormattedMessage
id="xpack.ingestManager.unenrollAgents.confirmModal.deleteSingleTitle"
defaultMessage="Unenroll agent '{id}'?"
values={{ id: agents[0] }}
/>
)
) : (
<FormattedMessage
id="xpack.ingestManager.unenrollAgents.confirmModal.deleteMultipleTitle"
Expand Down

0 comments on commit 5e06f69

Please sign in to comment.