-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #535 from devtron-labs/feat/extend-node-bulk-actions
feat: extend node bulk actions (cordon, un-cordon & drain) & other fixes
- Loading branch information
Showing
16 changed files
with
262 additions
and
53 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { Checkbox } from '@Common/Checkbox' | ||
import { Tooltip } from '@Common/Tooltip' | ||
import { CHECKBOX_VALUE } from '@Common/Types' | ||
import { ReactComponent as ICTimer } from '@Icons/ic-timer.svg' | ||
import { ChangeEvent, FocusEvent } from 'react' | ||
import { DRAIN_NODE_MODAL_MESSAGING, NODE_DRAIN_OPTIONS_CHECKBOX_CONFIG } from './constants' | ||
import { AdditionalConfirmationModalOptionsProps, NodeDrainRequest } from './types' | ||
|
||
const NodeDrainOptions = ({ | ||
optionsData, | ||
setOptionsData: setNodeDrainOptions, | ||
children, | ||
}: AdditionalConfirmationModalOptionsProps<NodeDrainRequest['nodeDrainOptions']>) => { | ||
const nodeDrainOptions: NodeDrainRequest['nodeDrainOptions'] = optionsData ?? { | ||
gracePeriodSeconds: -1, | ||
deleteEmptyDirData: false, | ||
disableEviction: false, | ||
force: false, | ||
ignoreAllDaemonSets: false, | ||
} | ||
|
||
const handleGracePeriodOnChange = (e: ChangeEvent<HTMLInputElement>) => { | ||
setNodeDrainOptions({ | ||
...nodeDrainOptions, | ||
gracePeriodSeconds: e.target.value ? Number(e.target.value) : -1, | ||
}) | ||
} | ||
|
||
const handleGracePeriodOnBlur = (e: FocusEvent<HTMLInputElement>) => { | ||
if (!e.target.value || Number(e.target.value) < -1) { | ||
e.target.value = '-1' | ||
} | ||
} | ||
|
||
const getCheckboxOnChangeHandler = | ||
(key: keyof NodeDrainRequest['nodeDrainOptions']) => (e: ChangeEvent<HTMLInputElement>) => { | ||
setNodeDrainOptions({ | ||
...nodeDrainOptions, | ||
[key]: e.target.checked, | ||
}) | ||
} | ||
|
||
return ( | ||
<div className="flexbox-col dc__gap-12 w-100"> | ||
<div> | ||
<div className="flexbox dc__gap-8 dc__align-items-center px-8 py-2"> | ||
<ICTimer className="icon-dim-20 dc__no-shrink scn-7" /> | ||
<Tooltip content={DRAIN_NODE_MODAL_MESSAGING.GracePeriod.infoText} alwaysShowTippyOnHover> | ||
<span className="fs-13 cn-9 lh-20 dc__underline-dotted">Grace period</span> | ||
</Tooltip> | ||
<span className="flex left dc__border br-4 cn-9 fw-4 fs-13 lh-20 dc__overflow-hidden"> | ||
<input | ||
name="grace-period" | ||
type="number" | ||
autoComplete="off" | ||
min={-1} | ||
defaultValue={nodeDrainOptions.gracePeriodSeconds} | ||
className="px-8 py-4 lh-20 w-60 dc__no-border" | ||
onChange={handleGracePeriodOnChange} | ||
onBlur={handleGracePeriodOnBlur} | ||
/> | ||
<span className="flex px-8 py-4 dc__border--left">sec</span> | ||
</span> | ||
</div> | ||
|
||
{NODE_DRAIN_OPTIONS_CHECKBOX_CONFIG.map(({ key, infoText, label }) => ( | ||
<Checkbox | ||
key={key} | ||
value={CHECKBOX_VALUE.CHECKED} | ||
isChecked={nodeDrainOptions[key]} | ||
dataTestId="disable-eviction" | ||
rootClassName="mt-0 mb-0 ml-8 mr-8 cn-9 fs-13 py-6 px-8 form__checkbox__root--gap-8" | ||
onChange={getCheckboxOnChangeHandler(key)} | ||
> | ||
<Tooltip content={infoText} alwaysShowTippyOnHover> | ||
<span className="dc__underline-dotted">{label}</span> | ||
</Tooltip> | ||
</Checkbox> | ||
))} | ||
</div> | ||
|
||
{children} | ||
</div> | ||
) | ||
} | ||
|
||
export default NodeDrainOptions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,84 @@ | ||
import { SelectPickerOptionType } from '@Shared/Components' | ||
import { ReactComponent as ICMediumPlay } from '@Icons/ic-medium-play.svg' | ||
import { ReactComponent as ICMediumPause } from '@Icons/ic-medium-pause.svg' | ||
import { ReactComponent as ICCleanBrush } from '@Icons/ic-medium-clean-brush.svg' | ||
import { NodeDrainRequest } from './types' | ||
|
||
export const ALL_NAMESPACE_OPTION: Readonly<Pick<SelectPickerOptionType<string>, 'value' | 'label'>> = { | ||
value: 'all', | ||
label: 'All namespaces', | ||
} | ||
|
||
export const DRAIN_NODE_MODAL_MESSAGING = { | ||
DrainIcon: ICCleanBrush, | ||
GracePeriod: { | ||
heading: 'Grace period', | ||
infoText: | ||
'Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used.', | ||
}, | ||
DeleteEmptyDirectoryData: { | ||
heading: 'Delete empty directory data', | ||
infoText: 'Enabling this field will delete the pods using empty directory data when the node is drained.', | ||
}, | ||
DisableEviction: { | ||
heading: 'Disable eviction (use with caution)', | ||
infoText: `Enabling this field will force drain to use delete, even if eviction is supported. This will bypass checking PodDisruptionBudgets. | ||
Note: Make sure to use with caution.`, | ||
}, | ||
ForceDrain: { | ||
heading: 'Force drain', | ||
infoText: | ||
'Enabling this field will force drain a node even if there are pods that do not declare a controller.', | ||
}, | ||
IgnoreDaemonSets: { | ||
heading: 'Ignore DaemonSets', | ||
infoText: 'Enabling this field will ignore DaemonSet-managed pods.', | ||
}, | ||
Actions: { | ||
infoText: 'Drain will cordon off the node and evict all pods of the node.', | ||
drain: 'Drain', | ||
draining: 'Draining node', | ||
cancel: 'Cancel', | ||
}, | ||
} | ||
|
||
export const CORDON_NODE_MODAL_MESSAGING = { | ||
UncordonIcon: ICMediumPlay, | ||
CordonIcon: ICMediumPause, | ||
cordonInfoText: | ||
'Cordoning a node will mark it as unschedulable. By cordoning a node, you can be sure that no new pods will be scheduled on the node.', | ||
uncordonInfoText: | ||
'Uncordoning this node will mark this node as schedulable. By uncordoning a node, you will allow pods to be scheduled on this node.', | ||
cordon: 'Cordon', | ||
uncordon: 'Uncordon', | ||
cordoning: 'Cordoning node', | ||
uncordoning: 'Uncordoning node', | ||
cancel: 'Cancel', | ||
} | ||
|
||
export const NODE_DRAIN_OPTIONS_CHECKBOX_CONFIG: { | ||
key: Exclude<keyof NodeDrainRequest['nodeDrainOptions'], 'gracePeriodSeconds'> | ||
infoText: string | ||
label: string | ||
}[] = [ | ||
{ | ||
key: 'deleteEmptyDirData', | ||
infoText: DRAIN_NODE_MODAL_MESSAGING.DeleteEmptyDirectoryData.infoText, | ||
label: DRAIN_NODE_MODAL_MESSAGING.DeleteEmptyDirectoryData.heading, | ||
}, | ||
{ | ||
key: 'disableEviction', | ||
infoText: DRAIN_NODE_MODAL_MESSAGING.DisableEviction.infoText, | ||
label: DRAIN_NODE_MODAL_MESSAGING.DisableEviction.heading, | ||
}, | ||
{ | ||
key: 'force', | ||
infoText: DRAIN_NODE_MODAL_MESSAGING.ForceDrain.infoText, | ||
label: DRAIN_NODE_MODAL_MESSAGING.ForceDrain.heading, | ||
}, | ||
{ | ||
key: 'ignoreAllDaemonSets', | ||
infoText: DRAIN_NODE_MODAL_MESSAGING.IgnoreDaemonSets.infoText, | ||
label: DRAIN_NODE_MODAL_MESSAGING.IgnoreDaemonSets.heading, | ||
}, | ||
] as const |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.