deploy 2.0.0-dev-82

This commit is contained in:
mbecker20
2025-10-27 02:28:48 -07:00
parent 61ce2ee3db
commit 5139622aad
4 changed files with 301 additions and 339 deletions

40
Cargo.lock generated
View File

@@ -902,7 +902,7 @@ dependencies = [
[[package]]
name = "cache"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"tokio",
@@ -1094,7 +1094,7 @@ dependencies = [
[[package]]
name = "command"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"komodo_client",
"nix 0.30.1",
@@ -1123,7 +1123,7 @@ checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb"
[[package]]
name = "config"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"colored",
"indexmap 2.12.0",
@@ -1445,7 +1445,7 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
[[package]]
name = "database"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"async-compression",
@@ -1744,7 +1744,7 @@ dependencies = [
[[package]]
name = "encoding"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"bytes",
@@ -1786,7 +1786,7 @@ dependencies = [
[[package]]
name = "environment"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"formatting",
@@ -1796,7 +1796,7 @@ dependencies = [
[[package]]
name = "environment_file"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"thiserror 2.0.17",
]
@@ -1892,7 +1892,7 @@ dependencies = [
[[package]]
name = "formatting"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"serror",
]
@@ -2058,7 +2058,7 @@ dependencies = [
[[package]]
name = "git"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"cache",
@@ -2690,7 +2690,7 @@ dependencies = [
[[package]]
name = "interpolate"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"komodo_client",
@@ -2812,7 +2812,7 @@ dependencies = [
[[package]]
name = "komodo_cli"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"bytes",
@@ -2842,7 +2842,7 @@ dependencies = [
[[package]]
name = "komodo_client"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"async_timing_util",
@@ -2877,7 +2877,7 @@ dependencies = [
[[package]]
name = "komodo_core"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"arc-swap",
@@ -2951,7 +2951,7 @@ dependencies = [
[[package]]
name = "komodo_periphery"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"arc-swap",
@@ -3071,7 +3071,7 @@ checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
[[package]]
name = "logger"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"komodo_client",
@@ -3375,7 +3375,7 @@ dependencies = [
[[package]]
name = "noise"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"arc-swap",
@@ -3790,7 +3790,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "periphery_client"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"derive_variants",
@@ -4271,7 +4271,7 @@ dependencies = [
[[package]]
name = "response"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"axum",
@@ -4541,7 +4541,7 @@ dependencies = [
[[package]]
name = "secret_file"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"tokio",
]
@@ -5574,7 +5574,7 @@ dependencies = [
[[package]]
name = "transport"
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
dependencies = [
"anyhow",
"axum",

View File

@@ -8,7 +8,7 @@ members = [
]
[workspace.package]
version = "2.0.0-dev-81"
version = "2.0.0-dev-82"
edition = "2024"
authors = ["mbecker20 <becker.maxh@gmail.com>"]
license = "GPL-3.0-or-later"

View File

@@ -90,7 +90,8 @@ pub async fn create_terminal(
if matches!(recreate, Never | DifferentCommand)
&& let Some(terminal) = terminals
.find(|terminal| {
terminal.name == name && terminal.target == target
terminal.target.matches_on_server(&target)
&& terminal.name == name
})
.await
{
@@ -110,7 +111,10 @@ pub async fn create_terminal(
);
if let Some(prev) = terminals
.insert(
|terminal| terminal.name == name && terminal.target == target,
|terminal| {
terminal.target.matches_on_server(&target)
&& terminal.name == name
},
terminal.clone(),
)
.await
@@ -124,7 +128,7 @@ pub async fn create_terminal(
pub async fn delete_terminal(target: &TerminalTarget, name: &str) {
if let Some(terminal) = terminals()
.remove(|terminal| {
target.matches_on_server(&terminal.target)
terminal.target.matches_on_server(target)
&& name == terminal.name.as_str()
})
.await
@@ -195,7 +199,8 @@ pub async fn get_terminal(
) -> anyhow::Result<Arc<PeripheryTerminal>> {
terminals()
.find(|terminal| {
terminal.name.as_str() == name && &terminal.target == target
terminal.target.matches_on_server(target)
&& terminal.name.as_str() == name
})
.await
.with_context(|| format!("No terminal for {target:?} at {name}"))

View File

@@ -20,16 +20,8 @@ import {
import { filterBySplit } from "@lib/utils";
import { Button } from "@ui/button";
import { DataTable, SortableHeader } from "@ui/data-table";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@ui/dialog";
import { Input } from "@ui/input";
import { Popover, PopoverContent, PopoverTrigger } from "@ui/popover";
import {
Select,
SelectContent,
@@ -188,7 +180,6 @@ const TerminalTargetResourceLink = ({
}: {
target: Types.TerminalTarget;
}) => {
console.log(target);
switch (target.type) {
case "Server":
return <ResourceLink type="Server" id={target.params.server!} />;
@@ -228,13 +219,17 @@ const CreateTerminal = () => {
const Selector = <CreateTerminalTypeSelector type={type} setType={setType} />;
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button className="items-center gap-2" variant="secondary">
New Terminal <PlusCircle className="w-4 h-4" />
</Button>
</DialogTrigger>
<DialogContent>
</PopoverTrigger>
<PopoverContent
align="start"
sideOffset={14}
className="w-[90vw] max-w-[500px]"
>
{type === "Server" ? (
<CreateServerTerminal
open={open}
@@ -254,8 +249,8 @@ const CreateTerminal = () => {
) : (
<></>
)}
</DialogContent>
</Dialog>
</PopoverContent>
</Popover>
);
};
@@ -285,6 +280,28 @@ const CreateTerminalTypeSelector = ({
);
};
const CreateTerminalLayout = ({
children,
onConfirm,
isPending,
}: {
children: ReactNode;
onConfirm: () => void;
isPending: boolean;
}) => {
return (
<div className="flex flex-col gap-6 items-end">
<div className="w-full grid md:grid-cols-[2fr_3fr] gap-6 items-center">
{children}
</div>
<Button variant="secondary" onClick={onConfirm}>
{isPending ? <Loader2 className="w-4 h-4 animate-spin" /> : "Create"}
</Button>
</div>
);
};
const default_create_server_terminal = (
first_server: string
): Types.CreateTerminal => {
@@ -328,68 +345,53 @@ const CreateServerTerminal = ({
mutate(request);
};
return (
<>
<DialogHeader>
<DialogTitle>New Server Terminal</DialogTitle>
<DialogDescription>
Choose the Server and Command for the new Terminal.
</DialogDescription>
</DialogHeader>
<div className="grid md:grid-cols-2 gap-6 items-center">
{Selector}
Server
<ResourceSelector
targetClassName="w-full justify-between"
type="Server"
state={Types.ServerState.Ok}
selected={server}
onSelect={(server) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, server } as any,
},
}))
<CreateTerminalLayout onConfirm={onConfirm} isPending={isPending}>
{Selector}
Server
<ResourceSelector
targetClassName="w-full justify-between"
type="Server"
state={Types.ServerState.Ok}
selected={server}
onSelect={(server) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, server } as any,
},
}))
}
align="end"
/>
Terminal Name
<Input
autoFocus
placeholder="terminal-name"
value={request.name}
onChange={(e) =>
setRequest((req) => ({ ...req, name: e.target.value }))
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
align="end"
/>
Terminal Name
<Input
autoFocus
placeholder="terminal-name"
value={request.name}
onChange={(e) =>
setRequest((req) => ({ ...req, name: e.target.value }))
}}
/>
Command
<Input
placeholder="bash (Optional)"
value={request.command}
onChange={(e) =>
setRequest((req) => ({ ...req, command: e.target.value }))
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
}}
/>
Command
<Input
placeholder="bash (Optional)"
value={request.command}
onChange={(e) =>
setRequest((req) => ({ ...req, command: e.target.value }))
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
}}
/>
</div>
<DialogFooter>
<Button variant="secondary" onClick={onConfirm}>
{isPending ? <Loader2 className="w-4 h-4 animate-spin" /> : "Create"}
</Button>
</DialogFooter>
</>
}}
/>
</CreateTerminalLayout>
);
};
@@ -453,94 +455,79 @@ const CreateContainerTerminal = ({
mutate(request);
};
return (
<>
<DialogHeader>
<DialogTitle>New Container Terminal</DialogTitle>
<DialogDescription>
Choose the Server and Container for the new Terminal.
</DialogDescription>
</DialogHeader>
<div className="grid md:grid-cols-2 gap-6 items-center">
{Selector}
Server
<ResourceSelector
targetClassName="w-full justify-between"
type="Server"
state={Types.ServerState.Ok}
selected={server}
onSelect={(server) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, server } as any,
},
}))
<CreateTerminalLayout onConfirm={onConfirm} isPending={isPending}>
{Selector}
Server
<ResourceSelector
targetClassName="w-full justify-between"
type="Server"
state={Types.ServerState.Ok}
selected={server}
onSelect={(server) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, server } as any,
},
}))
}
align="end"
/>
Container
<ServerContainerSelector
targetClassName="w-full justify-between"
server_id={server}
state={Types.ContainerStateStatusEnum.Running}
selected={container}
onSelect={(container) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, container } as any,
},
}))
}
align="end"
/>
Terminal Name
<Input
autoFocus
placeholder="terminal-name"
value={request.name}
onChange={(e) =>
setRequest((req) => ({ ...req, name: e.target.value }))
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
align="end"
/>
Container
<ServerContainerSelector
targetClassName="w-full justify-between"
server_id={server}
state={Types.ContainerStateStatusEnum.Running}
selected={container}
onSelect={(container) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, container } as any,
},
}))
}
align="end"
/>
Terminal Name
<Input
autoFocus
placeholder="terminal-name"
value={request.name}
onChange={(e) =>
setRequest((req) => ({ ...req, name: e.target.value }))
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}}
/>
Mode
<ContainerTerminalModeSelector
mode={request.mode!}
setMode={(mode) => setRequest({ ...request, mode })}
/>
{request.mode !== Types.ContainerTerminalMode.Attach && (
<>
Command
<Input
placeholder="sh (Optional)"
value={request.command}
onChange={(e) =>
setRequest((req) => ({ ...req, command: e.target.value }))
}
}}
/>
Mode
<ContainerTerminalModeSelector
mode={request.mode!}
setMode={(mode) => setRequest({ ...request, mode })}
/>
{request.mode !== Types.ContainerTerminalMode.Attach && (
<>
Command
<Input
placeholder="sh (Optional)"
value={request.command}
onChange={(e) =>
setRequest((req) => ({ ...req, command: e.target.value }))
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
}}
/>
</>
)}
</div>
<DialogFooter>
<Button variant="secondary" onClick={onConfirm}>
{isPending ? <Loader2 className="w-4 h-4 animate-spin" /> : "Create"}
</Button>
</DialogFooter>
</>
}}
/>
</>
)}
</CreateTerminalLayout>
);
};
@@ -606,94 +593,79 @@ const CreateStackServiceTerminal = ({
mutate(request);
};
return (
<>
<DialogHeader>
<DialogTitle>New Stack Terminal</DialogTitle>
<DialogDescription>
Choose the Stack and Service for the new Terminal.
</DialogDescription>
</DialogHeader>
<div className="grid md:grid-cols-2 gap-6 items-center">
{Selector}
Stack
<ResourceSelector
targetClassName="w-full justify-between"
type="Stack"
state={Types.StackState.Running || Types.StackState.Unhealthy}
selected={stack}
onSelect={(stack) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, stack } as any,
},
}))
<CreateTerminalLayout onConfirm={onConfirm} isPending={isPending}>
{Selector}
Stack
<ResourceSelector
targetClassName="w-full justify-between"
type="Stack"
state={Types.StackState.Running || Types.StackState.Unhealthy}
selected={stack}
onSelect={(stack) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, stack } as any,
},
}))
}
align="end"
/>
Service
<StackServiceSelector
targetClassName="w-full justify-between"
stack_id={stack}
state={Types.ContainerStateStatusEnum.Running}
selected={service}
onSelect={(service) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, service } as any,
},
}))
}
align="end"
/>
Terminal Name
<Input
autoFocus
placeholder="terminal-name"
value={request.name}
onChange={(e) =>
setRequest((req) => ({ ...req, name: e.target.value }))
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
align="end"
/>
Service
<StackServiceSelector
targetClassName="w-full justify-between"
stack_id={stack}
state={Types.ContainerStateStatusEnum.Running}
selected={service}
onSelect={(service) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, service } as any,
},
}))
}
align="end"
/>
Terminal Name
<Input
autoFocus
placeholder="terminal-name"
value={request.name}
onChange={(e) =>
setRequest((req) => ({ ...req, name: e.target.value }))
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}}
/>
Mode
<ContainerTerminalModeSelector
mode={request.mode!}
setMode={(mode) => setRequest({ ...request, mode })}
/>
{request.mode !== Types.ContainerTerminalMode.Attach && (
<>
Command
<Input
placeholder="sh (Optional)"
value={request.command}
onChange={(e) =>
setRequest((req) => ({ ...req, command: e.target.value }))
}
}}
/>
Mode
<ContainerTerminalModeSelector
mode={request.mode!}
setMode={(mode) => setRequest({ ...request, mode })}
/>
{request.mode !== Types.ContainerTerminalMode.Attach && (
<>
Command
<Input
placeholder="sh (Optional)"
value={request.command}
onChange={(e) =>
setRequest((req) => ({ ...req, command: e.target.value }))
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
}}
/>
</>
)}
</div>
<DialogFooter>
<Button variant="secondary" onClick={onConfirm}>
{isPending ? <Loader2 className="w-4 h-4 animate-spin" /> : "Create"}
</Button>
</DialogFooter>
</>
}}
/>
</>
)}
</CreateTerminalLayout>
);
};
@@ -756,77 +728,62 @@ const CreateDeploymentTerminal = ({
mutate(request);
};
return (
<>
<DialogHeader>
<DialogTitle>New Deployment Terminal</DialogTitle>
<DialogDescription>
Choose the Deployment for the new Terminal.
</DialogDescription>
</DialogHeader>
<div className="grid md:grid-cols-2 gap-6 items-center">
{Selector}
Deployment
<ResourceSelector
targetClassName="w-full justify-between"
type="Deployment"
state={Types.DeploymentState.Running}
selected={deployment}
onSelect={(deployment) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, deployment } as any,
},
}))
<CreateTerminalLayout onConfirm={onConfirm} isPending={isPending}>
{Selector}
Deployment
<ResourceSelector
targetClassName="w-full justify-between"
type="Deployment"
state={Types.DeploymentState.Running}
selected={deployment}
onSelect={(deployment) =>
setRequest((req) => ({
...req,
target: {
...req.target,
params: { ...req.target.params, deployment } as any,
},
}))
}
align="end"
/>
Terminal Name
<Input
autoFocus
placeholder="terminal-name"
value={request.name}
onChange={(e) =>
setRequest((req) => ({ ...req, name: e.target.value }))
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
align="end"
/>
Terminal Name
<Input
autoFocus
placeholder="terminal-name"
value={request.name}
onChange={(e) =>
setRequest((req) => ({ ...req, name: e.target.value }))
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}}
/>
Mode
<ContainerTerminalModeSelector
mode={request.mode!}
setMode={(mode) => setRequest({ ...request, mode })}
/>
{request.mode !== Types.ContainerTerminalMode.Attach && (
<>
Command
<Input
placeholder="sh (Optional)"
value={request.command}
onChange={(e) =>
setRequest((req) => ({ ...req, command: e.target.value }))
}
}}
/>
Mode
<ContainerTerminalModeSelector
mode={request.mode!}
setMode={(mode) => setRequest({ ...request, mode })}
/>
{request.mode !== Types.ContainerTerminalMode.Attach && (
<>
Command
<Input
placeholder="sh (Optional)"
value={request.command}
onChange={(e) =>
setRequest((req) => ({ ...req, command: e.target.value }))
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
onKeyDown={(e) => {
if (e.key === "Enter") {
onConfirm();
}
}}
/>
</>
)}
</div>
<DialogFooter>
<Button variant="secondary" onClick={onConfirm}>
{isPending ? <Loader2 className="w-4 h-4 animate-spin" /> : "Create"}
</Button>
</DialogFooter>
</>
}}
/>
</>
)}
</CreateTerminalLayout>
);
};