Skip to content

Commit 1c375a8

Browse files
author
vishwajeetpal
committed
added node list and selector
1 parent 4ce562f commit 1c375a8

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React, { Fragment, useState } from "react";
2+
import { EuiSuperSelect, EuiText } from "@elastic/eui";
3+
import { useMerlinApi } from "../../../../../hooks/useMerlinApi";
4+
5+
const DEFAULT_VALUE = "__default__";
6+
const HOSTNAME_LABEL = "kubernetes.io/hostname";
7+
8+
const taintSummary = (taints) =>
9+
taints && taints.length > 0
10+
? taints
11+
.map((t) => `${t.key}=${t.value || ""}:${t.effect || ""}`)
12+
.join(", ")
13+
: "no taints";
14+
15+
/**
16+
* NodeSelect - a dropdown to pin a model onto a specific node.
17+
*
18+
* Selecting a node sets the node selector to that node's hostname (pin) and adds
19+
* a toleration for each of the node's taints (permit), so the pod can land there.
20+
*
21+
* Props
22+
* environment – environment name (used to fetch that cluster's nodes)
23+
* onSelect(sel, tols) – called with the new node_selector + tolerations
24+
*/
25+
export const NodeSelect = ({ environment, onSelect }) => {
26+
const [selected, setSelected] = useState(DEFAULT_VALUE);
27+
28+
const [{ data: nodes, isLoaded }] = useMerlinApi(
29+
`/environments/${environment}/nodes`,
30+
{},
31+
[],
32+
!!environment
33+
);
34+
35+
const options = [
36+
{
37+
value: DEFAULT_VALUE,
38+
inputDisplay: "Default — any available node",
39+
},
40+
...(nodes || []).map((node) => ({
41+
value: node.name,
42+
inputDisplay: node.name,
43+
disabled: !node.ready,
44+
dropdownDisplay: (
45+
<Fragment>
46+
<strong>
47+
{node.name}
48+
{!node.ready ? " (not ready)" : ""}
49+
</strong>
50+
<EuiText size="s" color="subdued">
51+
<p>{taintSummary(node.taints)}</p>
52+
</EuiText>
53+
</Fragment>
54+
),
55+
})),
56+
];
57+
58+
const onChange = (value) => {
59+
setSelected(value);
60+
if (value === DEFAULT_VALUE) {
61+
onSelect({}, []);
62+
return;
63+
}
64+
const node = (nodes || []).find((n) => n.name === value);
65+
if (!node) return;
66+
67+
const nodeSelector = { [HOSTNAME_LABEL]: node.name };
68+
const tolerations = (node.taints || []).map((t) => ({
69+
key: t.key,
70+
operator: t.value ? "Equal" : "Exists",
71+
...(t.value ? { value: t.value } : {}),
72+
...(t.effect ? { effect: t.effect } : {}),
73+
}));
74+
onSelect(nodeSelector, tolerations);
75+
};
76+
77+
return (
78+
<EuiSuperSelect
79+
fullWidth
80+
options={options}
81+
valueOfSelected={selected}
82+
onChange={onChange}
83+
isLoading={!!environment && !isLoaded}
84+
hasDividers
85+
/>
86+
);
87+
};

0 commit comments

Comments
 (0)