Skip to content

Commit 9838d5f

Browse files
authored
Add Action to Evict Pods (#44)
This commit adds a new action to evict pods.
1 parent 4116905 commit 9838d5f

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

src/datasource/components/Kubernetes/Actions.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { CronJobSuspendAction } from './CronJobSuspendAction';
1616
import { CronJobResumeAction } from './CronJobResumeAction';
1717
import { CSRApproveAction } from './CSRApproveAction';
1818
import { CSRDenyAction } from './CSRDenyAction';
19+
import { EvictPodAction } from './EvictPodAction';
1920

2021
interface Props {
2122
query: Query;
@@ -111,6 +112,9 @@ export function Actions(props: Props) {
111112
) && (
112113
<Menu.Item label="Deny" onClick={() => setOpen('csrdeny')} />
113114
)}
115+
{resource && ['pods'].includes(resource) && (
116+
<Menu.Item label="Evict" onClick={() => setOpen('evict')} />
117+
)}
114118
{resource &&
115119
[
116120
'daemonsets.apps',
@@ -212,6 +216,15 @@ export function Actions(props: Props) {
212216
onClose={() => setOpen('')}
213217
/>
214218

219+
<EvictPodAction
220+
datasource={datasource}
221+
resource={resource}
222+
namespace={namespace}
223+
name={name}
224+
isOpen={open === 'evict'}
225+
onClose={() => setOpen('')}
226+
/>
227+
215228
{open === 'ai' && (
216229
<AIAction
217230
datasource={datasource}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import React, { useState } from 'react';
2+
import {
3+
ConfirmModal,
4+
LoadingPlaceholder,
5+
Stack,
6+
useStyles2,
7+
} from '@grafana/ui';
8+
import { AppEvents, GrafanaTheme2 } from '@grafana/data';
9+
import { getAppEvents } from '@grafana/runtime';
10+
import { css } from '@emotion/css';
11+
12+
import { getResource } from '../../../utils/utils.resource';
13+
14+
interface Props {
15+
datasource?: string;
16+
resource?: string;
17+
namespace?: string;
18+
name?: string;
19+
isOpen: boolean;
20+
onClose: () => void;
21+
}
22+
23+
export function EvictPodAction(props: Props) {
24+
const styles = useStyles2(getStyles);
25+
const [isLoading, setIsLoading] = useState(false);
26+
27+
const onConfirm = async () => {
28+
try {
29+
setIsLoading(true);
30+
31+
const resource = await getResource(props.datasource, props.resource);
32+
33+
const response = await fetch(
34+
`/api/datasources/uid/${props.datasource}/resources/kubernetes/proxy${resource.path}/namespaces/${props.namespace}/${resource.resource}/${props.name}/eviction?fieldManager=grafana-kubernetes-plugin`,
35+
{
36+
method: 'post',
37+
headers: {
38+
Accept: 'application/json, */*',
39+
'Content-Type': 'application/json',
40+
},
41+
body: JSON.stringify({
42+
apiVersion: 'policy/v1',
43+
kind: 'Eviction',
44+
metadata: {
45+
name: props.name,
46+
namespace: props.namespace,
47+
},
48+
}),
49+
},
50+
);
51+
if (!response.ok) {
52+
throw new Error();
53+
}
54+
55+
const appEvents = getAppEvents();
56+
appEvents.publish({
57+
type: AppEvents.alertSuccess.name,
58+
payload: [`${props.namespace}/${props.name} was evicted`],
59+
});
60+
} catch (_) {
61+
const appEvents = getAppEvents();
62+
appEvents.publish({
63+
type: AppEvents.alertError.name,
64+
payload: [`Failed to evict ${props.namespace}/${props.name}`],
65+
});
66+
} finally {
67+
setIsLoading(false);
68+
props.onClose();
69+
}
70+
};
71+
72+
return (
73+
<ConfirmModal
74+
isOpen={props.isOpen}
75+
title="Evict pod"
76+
body={`Are you sure you want to evict ${props.namespace}/${props.name}?`}
77+
description={
78+
<div className={styles.body}>
79+
<Stack direction="column">
80+
{isLoading && <LoadingPlaceholder text="Evicting pod..." />}
81+
</Stack>
82+
</div>
83+
}
84+
confirmText="Evict"
85+
confirmButtonVariant="destructive"
86+
dismissText="Cancel"
87+
onConfirm={onConfirm}
88+
onDismiss={() => props.onClose()}
89+
disabled={isLoading}
90+
/>
91+
);
92+
}
93+
94+
const getStyles = (theme: GrafanaTheme2) => {
95+
return {
96+
body: css({
97+
marginTop: theme.spacing(2),
98+
}),
99+
};
100+
};

0 commit comments

Comments
 (0)