From f4f4e51c24e851b994b608557a249c5d8b6e6b74 Mon Sep 17 00:00:00 2001 From: Philip Zingmark Date: Tue, 10 Mar 2026 19:51:17 +0100 Subject: [PATCH 1/4] clarify ssh usage for deployments --- src/components/create/GpuSelector.tsx | 6 +++- src/locales/en.json | 5 +++- src/locales/se.json | 4 ++- src/pages/edit/Specs.tsx | 3 +- src/pages/edit/deployments/SSHString.tsx | 35 ++++++++++++++++++++++++ src/pages/onboarding/Onboarding.tsx | 4 +++ 6 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/components/create/GpuSelector.tsx b/src/components/create/GpuSelector.tsx index 9437a93..7757a48 100644 --- a/src/components/create/GpuSelector.tsx +++ b/src/components/create/GpuSelector.tsx @@ -105,7 +105,11 @@ export default function GPUSelector({ gpus, setGpus, zone }: GPUSelectorProps) { } > - + } diff --git a/src/locales/en.json b/src/locales/en.json index 30811d5..7557ba6 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -298,6 +298,7 @@ "onboarding-resources-3": "If you need more resources, please contact us on Discord!", "onboarding-deployments-1": "Deployments are the most common resource type on kthcloud. They are perfect for running experiments, or hosting websites.", "onboarding-deployments-2": "All you need is a Docker image or a repo with a Dockerfile, and a little bit of configuration. kthcloud will take care of the rest.", + "onboarding-deployments-3": "You can add GPU compute to your deployment to use for machine learning.", "onboarding-vms-1": "Virtual machines are the most flexible resource type on kthcloud. You can install any programs you want and have full control over the machine.", "onboarding-vms-2": "Virtual machines are perfect for running machine learning models, databases and other more complex applications.", "onboarding-vms-3": "You can also request a GPU for your virtual machine. Please note that GPU resources are limited, for extended use you may want to provide your own GPU.", @@ -582,6 +583,8 @@ "delete-all-expired": "Delete all expired", "custom-deployment": "Custom", "custom-deployment-description": "Build and use your own image, use CI/CD through Github actions / Gitlab workflows or build and push your own image. Secrets will be provided after the deployment is created", - "deployment-spec-selector": "Select specs" + "deployment-spec-selector": "Select specs", + "deployment-ssh-info": "SSH into your deployments using a private key linked to a public key in your profile", + "deployment-ssh-view-keys": "View your ssh keys in your profile" } } diff --git a/src/locales/se.json b/src/locales/se.json index f52908a..15232ca 100644 --- a/src/locales/se.json +++ b/src/locales/se.json @@ -583,6 +583,8 @@ "delete-all-expired": "Ta bort alla utgågna", "custom-deployment": "Egen", "custom-deployment-description": "Bygg och använd din egna image, använd CI/CD via Github actions / Gitlab workflows eller bygg och pusha din egna image. Nycklar går att se när din deployment är skapad", - "deployment-spec-selector": "Välj specifikationer" + "deployment-spec-selector": "Välj specifikationer", + "deployment-ssh-info": "SSH:a till dina deployments med en privat nyckel kopplad till en offentlig nyckel i din profil", + "deployment-ssh-view-keys": "Se dina SSH nycklar i din profil" } } diff --git a/src/pages/edit/Specs.tsx b/src/pages/edit/Specs.tsx index 0d62ee0..45e950f 100644 --- a/src/pages/edit/Specs.tsx +++ b/src/pages/edit/Specs.tsx @@ -679,7 +679,8 @@ export const Specs = ({ resource }: { resource: Resource }) => { diff --git a/src/pages/edit/deployments/SSHString.tsx b/src/pages/edit/deployments/SSHString.tsx index cee8de0..769c0ef 100644 --- a/src/pages/edit/deployments/SSHString.tsx +++ b/src/pages/edit/deployments/SSHString.tsx @@ -1,16 +1,22 @@ import { + Button, Card, CardContent, CardHeader, + IconButton, Skeleton, Stack, + Tooltip, Typography, } from "@mui/material"; import { useTranslation } from "react-i18next"; import CopyButton from "../../../components/CopyButton"; import { Deployment } from "../../../types"; +import Iconify from "../../../components/Iconify"; +import { useNavigate } from "react-router-dom"; const SSHString = ({ deployment }: { deployment: Deployment }) => { + const navigate = useNavigate(); const { t } = useTranslation(); const sshBase = import.meta.env.VITE_DEPLOYMENT_SSH_BASE ?? window.location.hostname; @@ -22,6 +28,35 @@ const SSHString = ({ deployment }: { deployment: Deployment }) => { + + navigate("/profile")} + sx={{ fontSize: 20 }} + > + + + + + + {t("deployment-ssh-info")} + + + } + > + + + + } /> {!ssh ? ( diff --git a/src/pages/onboarding/Onboarding.tsx b/src/pages/onboarding/Onboarding.tsx index 50fa729..432c74e 100644 --- a/src/pages/onboarding/Onboarding.tsx +++ b/src/pages/onboarding/Onboarding.tsx @@ -369,6 +369,10 @@ export const Onboarding = () => { {t("onboarding-deployments-2")} + + + {t("onboarding-deployments-3")} + From 30b25382f63846e42b8c01ec18ce791ae9b47c78 Mon Sep 17 00:00:00 2001 From: Philip Zingmark Date: Tue, 10 Mar 2026 20:51:37 +0100 Subject: [PATCH 2/4] fix tsc --- src/pages/edit/deployments/SSHString.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/edit/deployments/SSHString.tsx b/src/pages/edit/deployments/SSHString.tsx index 769c0ef..f9ba9fe 100644 --- a/src/pages/edit/deployments/SSHString.tsx +++ b/src/pages/edit/deployments/SSHString.tsx @@ -1,5 +1,4 @@ import { - Button, Card, CardContent, CardHeader, From 5513b274bcb76e024e0255022a9c57ef428db0b3 Mon Sep 17 00:00:00 2001 From: Philip Zingmark Date: Tue, 10 Mar 2026 21:38:28 +0100 Subject: [PATCH 3/4] added CEL expression selection in DRA creation view and added allowed roles display on Admin panel --- src/components/admin/CELExprBuilder.tsx | 4 +--- src/components/admin/GPUClaimEditor.tsx | 29 ++++++++++--------------- src/components/admin/GPUClaimModal.tsx | 2 +- src/pages/admin/AdminV2.tsx | 18 +++++++++++++++ 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/components/admin/CELExprBuilder.tsx b/src/components/admin/CELExprBuilder.tsx index 3999c7e..c968a32 100644 --- a/src/components/admin/CELExprBuilder.tsx +++ b/src/components/admin/CELExprBuilder.tsx @@ -2,7 +2,7 @@ import { Stack, TextField, IconButton, Chip, Typography } from "@mui/material"; import AddIcon from "@mui/icons-material/Add"; import { useState } from "react"; -// Simple CEL validation function (stub, replace with real parser) +// Simple CEL validation function (stub, TODO: replace with real parser) const validateCel = (expr: string): boolean => { try { if (!expr) return true; // empty allowed @@ -52,7 +52,6 @@ export default function CelExprBuilder({ {label} - {/* Existing expressions as Chips */} {value.map((expr, idx) => { const valid = validateCel(expr); @@ -67,7 +66,6 @@ export default function CelExprBuilder({ })} - {/* Input field for new expression */} - {/*gpu.selectors?.find(((s as any)) => "cel" in s) && ( - "cel" in s) as any).cel - .expression, - ]} // wrap as array - onChange={(newExpressions) => { - const newSelectors = gpu.selectors!.map((s) => - "cel" in s - ? { cel: { expression: newExpressions[0] } } // update CEL - : s - ); - updateRequested(idx, { selectors: newSelectors }); - }} - label="Selectors (CEL expression)" - placeholder="gpu.memory > 4 && gpu.computeCapability >= 7.0" - /> - )*/} + { + updateRequested(idx, { + selectors: [...(gpu.selectors || []), ...newExpressions], + }); + }} + label="Selectors (CEL expression)" + placeholder="memory <= 16 && cudaComputeCapability >= 7.0" + /> {"Driver configuration"} diff --git a/src/components/admin/GPUClaimModal.tsx b/src/components/admin/GPUClaimModal.tsx index dc92f0c..302fc91 100644 --- a/src/components/admin/GPUClaimModal.tsx +++ b/src/components/admin/GPUClaimModal.tsx @@ -36,7 +36,7 @@ type Role = | "admin" | string; -function getChipColor(role: Role) { +export function getChipColor(role: Role) { const metalStyles: Record = { bronze: { background: diff --git a/src/pages/admin/AdminV2.tsx b/src/pages/admin/AdminV2.tsx index 4762237..77a83fc 100644 --- a/src/pages/admin/AdminV2.tsx +++ b/src/pages/admin/AdminV2.tsx @@ -56,6 +56,7 @@ import Label from "../../components/Label"; import TimeAgo from "../../components/admin/TimeAgo"; import CluseterOverviewTab from "../../components/admin/ClusterOverviewTab"; import { deleteGpuClaim } from "../../api/deploy/gpuClaims"; +import { getChipColor } from "../../components/admin/GPUClaimModal"; export default function AdminV2() { const { tab: initialTab } = useParams(); @@ -333,6 +334,23 @@ export default function AdminV2() { { id: "id", label: "ID" }, { id: "name", label: "Name" }, { id: "zone", label: "Zone" }, + { + id: "allowedRoles", + label: "Allowed Roles", + renderFunc: (allowedRoles: string[] | undefined) => { + return ( + + {allowedRoles ? ( + allowedRoles.map((role) => ( + + )) + ) : ( + + )} + + ); + }, + }, { id: "*", label: "Requested", From 921ea69a93fd992e2a4416c20775600d893593c6 Mon Sep 17 00:00:00 2001 From: Philip Zingmark Date: Tue, 10 Mar 2026 21:49:59 +0100 Subject: [PATCH 4/4] fix remove behaviour for CEL expressions --- src/components/admin/GPUClaimEditor.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/admin/GPUClaimEditor.tsx b/src/components/admin/GPUClaimEditor.tsx index f8a437d..a58ab05 100644 --- a/src/components/admin/GPUClaimEditor.tsx +++ b/src/components/admin/GPUClaimEditor.tsx @@ -106,9 +106,9 @@ export default function GpuClaimEditor({ value, onChange }: Props) { { + onChange={(exprs) => { updateRequested(idx, { - selectors: [...(gpu.selectors || []), ...newExpressions], + selectors: exprs, }); }} label="Selectors (CEL expression)"