From 3d6159d2ff077be3aabbdeaca831df7835ecab70 Mon Sep 17 00:00:00 2001 From: David Hu Date: Wed, 18 Jan 2023 20:55:37 -0800 Subject: [PATCH 1/2] scale-deployment --- src-tauri/src/main.rs | 1 + src-tauri/src/resources/deployments.rs | 25 +++++++- src-tauri/tauri.conf.json | 4 +- src/deployments/deployments.tsx | 35 ++++++++++-- src/deployments/scale-deployment-modal.tsx | 66 ++++++++++++++++++++++ 5 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 src/deployments/scale-deployment-modal.tsx diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 670353c..b452714 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -13,6 +13,7 @@ fn main() { cron_jobs::get_cron_jobs, deployments::get_deployments, deployments::restart_deployment, + deployments::scale_deployment, jobs::get_jobs, pods::get_pod_logs, pods::get_pods, diff --git a/src-tauri/src/resources/deployments.rs b/src-tauri/src/resources/deployments.rs index 0156df5..4d1915a 100644 --- a/src-tauri/src/resources/deployments.rs +++ b/src-tauri/src/resources/deployments.rs @@ -1,5 +1,9 @@ use k8s_openapi::api::apps::v1::Deployment; -use kube::{api::ListParams, core::ObjectList, Api}; +use kube::{ + api::{ListParams, Patch, PatchParams}, + core::ObjectList, + Api, +}; use super::internal::get_api; @@ -25,3 +29,22 @@ pub async fn restart_deployment(namespace: Option, name: String) -> bool }; return result; } + +#[tauri::command] +pub async fn scale_deployment(namespace: Option, name: String, replicas: u8) -> bool { + let api: Api = get_api(namespace).await; + let spec = serde_json::json!({ "spec": { "replicas": replicas }}); + let pp = PatchParams::default(); + let patch = Patch::Merge(&spec); + let resource = api.patch_scale(&name, &pp, &patch).await; + + let result = match resource { + Ok(_resource) => true, + Err(err) => { + println!("Error scaling deployment: {}", err); + return false; + } + }; + + return result; +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 979ff65..03edc7e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -55,10 +55,10 @@ "windows": [ { "fullscreen": false, - "height": 600, + "height": 900, "resizable": true, "title": "Kube Knots", - "width": 800 + "width": 1200 } ] } diff --git a/src/deployments/deployments.tsx b/src/deployments/deployments.tsx index 973f555..11c40df 100644 --- a/src/deployments/deployments.tsx +++ b/src/deployments/deployments.tsx @@ -1,12 +1,15 @@ -import { ArrowPathIcon, PencilIcon } from "@heroicons/react/20/solid"; +import { Dialog } from "@headlessui/react"; +import { ArrowPathIcon, PencilIcon, ArrowsUpDownIcon } from "@heroicons/react/20/solid"; import type { V1Deployment } from "@kubernetes/client-node"; import { useMutation, useQuery } from "@tanstack/react-query"; import { invoke } from "@tauri-apps/api"; import { lazy, Suspense, useState } from "react"; import { ActionButton, ActionGroup } from "../components/action-group"; +import { Modal } from "../components/modal"; import { Table, TableHeader, TableBody, TableCell } from "../components/table"; import { useCurrentNamespace } from "../namespaces/namespaces"; +import { ScaleDeploymentModal } from "./scale-deployment-modal"; const ResourceEditDrawer = lazy(() => import("../components/resource-edit-drawer").then((module) => ({ @@ -39,13 +42,17 @@ export function Deployments() { }, }); + const [action, setAction] = useState<"edit" | "scale" | null>(null); const [selected, setSelected] = useState(null); - const handleEditOpen = (deployment: V1Deployment) => { + const handleOpen = (deployment: V1Deployment, action: "edit" | "scale") => { setSelected(deployment); + setAction(action); }; - const handleEditClose = () => { + + const handleClose = () => { setSelected(null); + setAction(null); }; return ( @@ -68,11 +75,17 @@ export function Deployments() { position="left" onClick={() => restartMutation.mutate(item)} /> + handleOpen(item, "scale")} + /> handleEditOpen(item)} + onClick={() => handleOpen(item, "edit")} /> @@ -83,11 +96,21 @@ export function Deployments() { Loading Editor}> + + Loading Scale Form}> + {selected && ( + + )} + ); } diff --git a/src/deployments/scale-deployment-modal.tsx b/src/deployments/scale-deployment-modal.tsx new file mode 100644 index 0000000..439b33e --- /dev/null +++ b/src/deployments/scale-deployment-modal.tsx @@ -0,0 +1,66 @@ +import { Dialog } from "@headlessui/react"; +import { type V1Deployment } from "@kubernetes/client-node"; +import { useMutation } from "@tanstack/react-query"; +import { invoke } from "@tauri-apps/api"; +import { useState } from "react"; + +interface ModalProps { + isOpen: boolean; + handleClose: () => void; + deployment: V1Deployment; +} +export function ScaleDeploymentModal({ isOpen, handleClose, deployment }: ModalProps): JSX.Element { + const [replicas, setReplicas] = useState(deployment.spec?.replicas || 0); + + const scaleMutation = useMutation({ + mutationFn: (replicas: number) => { + return invoke("scale_deployment", { + namespace: deployment.metadata?.namespace, + name: deployment.metadata?.name, + replicas, + }); + }, + onSuccess: (_data, variables) => { + handleClose(); + alert(`Scaled deployment ${deployment.metadata?.name} to ${variables} replicas`); + }, + }); + + return ( + +
+ +
+
+ + + Scale {deployment.metadata?.name} + + +
+

+ Current replica count: {deployment.spec?.replicas} +

+
+ + setReplicas(parseInt(e.target.value ?? ""))} + type="number" + value={replicas} + className="mt-4 block w-full rounded-md border-gray-300 focus:ring-indigo-500" + step={1} + min={0} + /> + + +
+
+
+
+ ); +} From 7fa71f937a45de1819e0a377a06cf495c7d49ebf Mon Sep 17 00:00:00 2001 From: David Hu Date: Wed, 18 Jan 2023 20:57:37 -0800 Subject: [PATCH 2/2] fix --- src/deployments/scale-deployment-modal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/deployments/scale-deployment-modal.tsx b/src/deployments/scale-deployment-modal.tsx index 439b33e..ef96cc0 100644 --- a/src/deployments/scale-deployment-modal.tsx +++ b/src/deployments/scale-deployment-modal.tsx @@ -31,7 +31,7 @@ export function ScaleDeploymentModal({ isOpen, handleClose, deployment }: ModalP
-
+
Scale {deployment.metadata?.name} @@ -47,7 +47,7 @@ export function ScaleDeploymentModal({ isOpen, handleClose, deployment }: ModalP onChange={(e) => setReplicas(parseInt(e.target.value ?? ""))} type="number" value={replicas} - className="mt-4 block w-full rounded-md border-gray-300 focus:ring-indigo-500" + className="mt-4 block w-full rounded-md border-gray-300 focus:ring-slate-500" step={1} min={0} />