|
|
@@ -5,16 +5,20 @@ import { useQuery } from "@tanstack/react-query";
|
|
|
import { z } from "zod";
|
|
|
import api from "shared/api";
|
|
|
|
|
|
-const clusterDataValidator = z.object({
|
|
|
+const DEFAULT_INSTANCE_CLASS = "t3";
|
|
|
+const DEFAULT_INSTANCE_SIZE = "medium";
|
|
|
+
|
|
|
+const clusterNodesValidator = z.object({
|
|
|
labels: z.object({
|
|
|
"beta.kubernetes.io/instance-type": z.string().nullish(),
|
|
|
"porter.run/workload-kind": z.string().nullish(),
|
|
|
}).optional(),
|
|
|
}).transform((data) => {
|
|
|
const defaultResources = {
|
|
|
- maxCPU: AWS_INSTANCE_LIMITS["t3"]["medium"]["vCPU"],
|
|
|
- maxRAM: AWS_INSTANCE_LIMITS["t3"]["medium"]["RAM"],
|
|
|
- instanceType: "t3.medium",
|
|
|
+ maxCPU: AWS_INSTANCE_LIMITS[DEFAULT_INSTANCE_CLASS][DEFAULT_INSTANCE_SIZE]["vCPU"],
|
|
|
+ maxRAM: AWS_INSTANCE_LIMITS[DEFAULT_INSTANCE_CLASS][DEFAULT_INSTANCE_SIZE]["RAM"],
|
|
|
+ instanceClass: DEFAULT_INSTANCE_CLASS,
|
|
|
+ instanceSize: DEFAULT_INSTANCE_SIZE,
|
|
|
};
|
|
|
if (!data.labels) {
|
|
|
return defaultResources;
|
|
|
@@ -34,7 +38,8 @@ const clusterDataValidator = z.object({
|
|
|
return {
|
|
|
maxCPU: vCPU,
|
|
|
maxRAM: RAM,
|
|
|
- instanceType: instanceType,
|
|
|
+ instanceClass,
|
|
|
+ instanceSize,
|
|
|
};
|
|
|
}
|
|
|
return defaultResources;
|
|
|
@@ -55,33 +60,35 @@ export const useClusterResourceLimits = (
|
|
|
defaultCPU: number,
|
|
|
defaultRAM: number,
|
|
|
clusterContainsGPUNodes: boolean,
|
|
|
+ clusterIngressIp: string,
|
|
|
} => {
|
|
|
const SMALL_INSTANCE_UPPER_BOUND = 0.75;
|
|
|
const LARGE_INSTANCE_UPPER_BOUND = 0.9;
|
|
|
const DEFAULT_MULTIPLIER = 0.125;
|
|
|
- const [clusterContainsGPUNodes, setGpuNodes] = useState(false);
|
|
|
+ const [clusterContainsGPUNodes, setClusterContainsGPUNodes] = useState(false);
|
|
|
const [maxCPU, setMaxCPU] = useState(
|
|
|
- AWS_INSTANCE_LIMITS["t3"]["medium"]["vCPU"] * SMALL_INSTANCE_UPPER_BOUND
|
|
|
- ); //default is set to a t3 medium
|
|
|
+ AWS_INSTANCE_LIMITS[DEFAULT_INSTANCE_CLASS][DEFAULT_INSTANCE_SIZE]["vCPU"] * SMALL_INSTANCE_UPPER_BOUND
|
|
|
+ );
|
|
|
const [maxRAM, setMaxRAM] = useState(
|
|
|
// round to nearest 100
|
|
|
Math.round(
|
|
|
- convert(AWS_INSTANCE_LIMITS["t3"]["medium"]["RAM"], "GiB").to("MB") *
|
|
|
+ convert(AWS_INSTANCE_LIMITS[DEFAULT_INSTANCE_CLASS][DEFAULT_INSTANCE_SIZE]["RAM"], "GiB").to("MB") *
|
|
|
SMALL_INSTANCE_UPPER_BOUND / 100
|
|
|
) * 100
|
|
|
- ); //default is set to a t3 medium
|
|
|
+ );
|
|
|
const [defaultCPU, setDefaultCPU] = useState(
|
|
|
- AWS_INSTANCE_LIMITS["t3"]["medium"]["vCPU"] * DEFAULT_MULTIPLIER
|
|
|
- ); //default is set to a t3 medium
|
|
|
+ AWS_INSTANCE_LIMITS[DEFAULT_INSTANCE_CLASS][DEFAULT_INSTANCE_SIZE]["vCPU"] * DEFAULT_MULTIPLIER
|
|
|
+ );
|
|
|
const [defaultRAM, setDefaultRAM] = useState(
|
|
|
// round to nearest 100
|
|
|
Math.round(
|
|
|
- convert(AWS_INSTANCE_LIMITS["t3"]["medium"]["RAM"], "GiB").to("MB") *
|
|
|
+ convert(AWS_INSTANCE_LIMITS[DEFAULT_INSTANCE_CLASS][DEFAULT_INSTANCE_SIZE]["RAM"], "GiB").to("MB") *
|
|
|
DEFAULT_MULTIPLIER / 100
|
|
|
) * 100
|
|
|
- ); //default is set to a t3 medium
|
|
|
+ );
|
|
|
+ const [clusterIngressIp, setClusterIngressIp] = useState<string>("");
|
|
|
|
|
|
- const { data } = useQuery(
|
|
|
+ const getClusterNodes = useQuery(
|
|
|
["getClusterNodes", projectId, clusterId],
|
|
|
async () => {
|
|
|
if (!projectId || !clusterId || clusterId === -1) {
|
|
|
@@ -97,7 +104,7 @@ export const useClusterResourceLimits = (
|
|
|
}
|
|
|
)
|
|
|
|
|
|
- return await z.array(clusterDataValidator).parseAsync(res.data);
|
|
|
+ return await z.array(clusterNodesValidator).parseAsync(res.data);
|
|
|
},
|
|
|
{
|
|
|
enabled: !!projectId && !!clusterId,
|
|
|
@@ -105,9 +112,9 @@ export const useClusterResourceLimits = (
|
|
|
retry: false,
|
|
|
}
|
|
|
);
|
|
|
-
|
|
|
useEffect(() => {
|
|
|
- if (data) {
|
|
|
+ if (getClusterNodes.isSuccess) {
|
|
|
+ const data = getClusterNodes.data;
|
|
|
// this logic handles CPU and RAM independently - we might want to change this later
|
|
|
const maxCPU = data.reduce((acc, curr) => {
|
|
|
return Math.max(acc, curr.maxCPU);
|
|
|
@@ -131,13 +138,39 @@ export const useClusterResourceLimits = (
|
|
|
setMaxRAM(newMaxRAM);
|
|
|
setDefaultCPU(Number((newMaxCPU * DEFAULT_MULTIPLIER).toFixed(2)));
|
|
|
setDefaultRAM(Number((newMaxRAM * DEFAULT_MULTIPLIER).toFixed(0)));
|
|
|
+ setClusterContainsGPUNodes(data.some(item => item.instanceClass === "g4dn"));
|
|
|
+ }
|
|
|
+ }, [getClusterNodes])
|
|
|
|
|
|
- // Check if any instance type has "gd4n" and update clusterContainsGPUNodes accordingly
|
|
|
- setGpuNodes(data.some(item =>
|
|
|
- item.instanceType.includes("g4dn")
|
|
|
- ));
|
|
|
+ const getCluster = useQuery(
|
|
|
+ ["getCluster", projectId, clusterId],
|
|
|
+ async () => {
|
|
|
+ if (!projectId || !clusterId || clusterId === -1) {
|
|
|
+ return Promise.resolve({ ingress_ip: "" });
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await api.getCluster(
|
|
|
+ "<token>",
|
|
|
+ {},
|
|
|
+ {
|
|
|
+ project_id: projectId,
|
|
|
+ cluster_id: clusterId,
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ return await z.object({ ingress_ip: z.string() }).parseAsync(res.data);
|
|
|
+ },
|
|
|
+ {
|
|
|
+ enabled: !!projectId && !!clusterId,
|
|
|
+ refetchOnWindowFocus: false,
|
|
|
+ retry: false,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ useEffect(() => {
|
|
|
+ if (getCluster.isSuccess) {
|
|
|
+ setClusterIngressIp(getCluster.data.ingress_ip);
|
|
|
}
|
|
|
- }, [data])
|
|
|
+ }, [getCluster])
|
|
|
|
|
|
|
|
|
return {
|
|
|
@@ -146,6 +179,7 @@ export const useClusterResourceLimits = (
|
|
|
defaultCPU,
|
|
|
defaultRAM,
|
|
|
clusterContainsGPUNodes,
|
|
|
+ clusterIngressIp,
|
|
|
}
|
|
|
}
|
|
|
|