This commit is contained in:
mbecker20
2022-03-26 06:37:18 -07:00
parent 68cb92a7dc
commit 84b1b4e57b
14 changed files with 225 additions and 74 deletions
+3 -3
View File
@@ -31,9 +31,9 @@ async function deployDeployment(
app.deployActionStates.set(deploymentID, DEPLOYING, true);
app.broadcast(DEPLOY, { complete: false, deploymentID });
try {
const server = deployment.serverID
? await app.servers.findById(deployment.serverID)
: undefined;
const server = deployment.serverID === app.core._id
? undefined
: await app.servers.findById(deployment.serverID!);
if (server) {
// delete the container on periphery
await deletePeripheryContainer(server, deployment.containerName!);
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>download</title>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path fill="#fceade" d="M16.4338096,0 C16.7850725,2.73772263e-15 17.1105793,0.184298834 17.2913025,0.485504245 L20,5 L20,19 C20,19.5522847 19.5522847,20 19,20 L1,20 C0.44771525,20 6.76353751e-17,19.5522847 0,19 L0,5 L2.70869745,0.485504245 C2.8894207,0.184298834 3.21492753,-1.57518666e-16 3.56619038,0 L16.4338096,0 Z M10,8 C9.45,8 9,8.45 9,9 L9,9 L9,13.58 L7.71,12.29 L7.62868805,12.2167055 C7.45795918,12.0781633 7.24,11.99 7,11.99 C6.45,11.99 6,12.44 6,12.99 C6,13.27 6.11,13.52 6.29,13.7 L6.29,13.7 L9.29,16.7 L9.38564815,16.7839815 C9.55416667,16.9136111 9.76666667,16.99 10,16.99 C10.28,16.99 10.53,16.88 10.71,16.7 L10.71,16.7 L13.71,13.7 L13.7939815,13.6043519 C13.9236111,13.4358333 14,13.2233333 14,12.99 C14,12.44 13.55,11.99 13,11.99 C12.72,11.99 12.47,12.1 12.29,12.28 L12.29,12.28 L11,13.58 L11,9 L10.9932398,8.88380102 C10.9352041,8.3880102 10.5107143,8 10,8 Z M16,2 L4,2 L2,5.00162374 L18,5.00162374 L16,2 Z" id="Combined-Shape" fill="#000000"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>upload</title>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path fill="#fceade" d="M16.4338096,0 C16.7850725,2.73772263e-15 17.1105793,0.184298834 17.2913025,0.485504245 L20,5 L20,19 C20,19.5522847 19.5522847,20 19,20 L1,20 C0.44771525,20 6.76353751e-17,19.5522847 0,19 L0,5 L2.70869745,0.485504245 C2.8894207,0.184298834 3.21492753,-1.57518666e-16 3.56619038,0 L16.4338096,0 Z M10,8 C9.72,8 9.47,8.11 9.29,8.29 L9.29,8.29 L6.29,11.29 L6.20601852,11.3856481 C6.07638889,11.5541667 6,11.7666667 6,12 C6,12.55 6.45,13 7,13 C7.28,13 7.53,12.89 7.71,12.71 L7.71,12.71 L9,11.41 L9,15.99 L9.0067602,16.106199 C9.06479592,16.6019898 9.48928571,16.99 10,16.99 C10.55,16.99 11,16.54 11,15.99 L11,15.99 L11,11.41 L12.29,12.7 L12.371312,12.7732945 C12.5420408,12.9118367 12.76,13 13,13 C13.55,13 14,12.55 14,12 C14,11.72 13.89,11.47 13.71,11.29 L13.71,11.29 L10.71,8.29 L10.6143519,8.20601852 C10.4458333,8.07638889 10.2333333,8 10,8 Z M16,2 L4,2 L2,5.00162374 L18,5.00162374 L16,2 Z" id="Combined-Shape" fill="#000000"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+109 -53
View File
@@ -1,68 +1,124 @@
import { ContainerStatus, Deployment } from "@monitor/types";
import { Component, Match, Switch } from "solid-js";
import { Component, Match, Show, Switch } from "solid-js";
import { pushNotification } from "../..";
import {
DELETE_CONTAINER,
DEPLOY,
START_CONTAINER,
STOP_CONTAINER,
} from "../../state/actions";
import { useAppState } from "../../state/StateProvider";
import { combineClasses } from "../../util/helpers";
import ConfirmButton from "../util/ConfirmButton";
import Icon from "../util/icons/Icon";
import Flex from "../util/layout/Flex";
import Grid from "../util/layout/Grid";
import s from "./deployment.module.css";
const Actions: Component<{ deployment: Deployment }> = (p) => {
const { ws } = useAppState();
return (
<Grid class={combineClasses(s.Actions, "shadow")}>
<div class={s.ItemHeader}>actions</div>
<Switch>
<Match
when={(p.deployment.status as ContainerStatus)?.State === "running"}
>
<Flex class={combineClasses(s.Action, "shadow")}>
deploy{" "}
<Flex>
<button class="green">
<Icon type="reset" />
</button>
<button class="red">
<Icon type="trash" />
</button>
<Show when={true}>
<Grid class={combineClasses(s.Actions, "shadow")}>
<div class={s.ItemHeader}>actions</div>
<Switch>
<Match
when={(p.deployment.status as ContainerStatus)?.State === "running"}
>
<Flex class={combineClasses(s.Action, "shadow")}>
deploy{" "}
<Flex>
<ConfirmButton
color="green"
onConfirm={() => {
ws.send(DEPLOY, { deploymentID: p.deployment._id });
pushNotification("ok", `deploying ${p.deployment.name}...`);
}}
>
<Icon type="reset" />
</ConfirmButton>
<ConfirmButton
color="red"
onConfirm={() => {
ws.send(DELETE_CONTAINER, {
deploymentID: p.deployment._id,
});
pushNotification("ok", `removing container...`);
}}
>
<Icon type="trash" />
</ConfirmButton>
</Flex>
</Flex>
</Flex>
<Flex class={combineClasses(s.Action, "shadow")}>
container{" "}
<button class="orange">
<Icon type="pause" />
</button>
</Flex>
</Match>
<Flex class={combineClasses(s.Action, "shadow")}>
container{" "}
<ConfirmButton
color="orange"
onConfirm={() => {
ws.send(STOP_CONTAINER, { deploymentID: p.deployment._id });
pushNotification("ok", `stopping container`);
}}
>
<Icon type="pause" />
</ConfirmButton>
</Flex>
</Match>
<Match
when={(p.deployment.status as ContainerStatus).State === "exited"}
>
<Flex class={combineClasses(s.Action, "shadow")}>
deploy{" "}
<button class="green">
<Icon type="reset" />
</button>
<button class="red">
<Icon type="trash" />
</button>
</Flex>
<Flex class={combineClasses(s.Action, "shadow")}>
container{" "}
<button class="green">
<Icon type="play" />
</button>
</Flex>
</Match>
<Match
when={(p.deployment.status as ContainerStatus).State === "exited"}
>
<Flex class={combineClasses(s.Action, "shadow")}>
deploy{" "}
<ConfirmButton
color="green"
onConfirm={() => {
ws.send(DEPLOY, { deploymentID: p.deployment._id });
pushNotification("ok", `deploying ${p.deployment.name}...`);
}}
>
<Icon type="reset" />
</ConfirmButton>
<ConfirmButton
color="red"
onConfirm={() => {
ws.send(DELETE_CONTAINER, { deploymentID: p.deployment._id });
pushNotification("ok", `removing container...`);
}}
>
<Icon type="trash" />
</ConfirmButton>
</Flex>
<Flex class={combineClasses(s.Action, "shadow")}>
container{" "}
<ConfirmButton
color="green"
onConfirm={() => {
ws.send(START_CONTAINER, { deploymentID: p.deployment._id });
pushNotification("ok", `starting container...`);
}}
>
<Icon type="play" />
</ConfirmButton>
</Flex>
</Match>
<Match when={p.deployment.status === "not created"}>
<Flex class={combineClasses(s.Action, "shadow")}>
deploy{" "}
<button class="green">
<Icon type="play" />
</button>
</Flex>
</Match>
</Switch>
</Grid>
<Match when={p.deployment.status === "not created"}>
<Flex class={combineClasses(s.Action, "shadow")}>
deploy{" "}
<ConfirmButton
color="green"
onConfirm={() => {
ws.send(DEPLOY, { deploymentID: p.deployment._id });
pushNotification("ok", `deploying ${p.deployment.name}...`);
}}
>
<Icon type="play" />
</ConfirmButton>
</Flex>
</Match>
</Switch>
</Grid>
</Show>
);
};
@@ -39,6 +39,11 @@
padding: 0.5rem;
}
.UpdatesContainer {
max-height: 50vh;
overflow: scroll;
}
.Update {
background-color: rgb(69, 34, 96);
}
+22 -4
View File
@@ -1,15 +1,31 @@
import { Component, For, Show } from "solid-js";
import { Component, For, onCleanup, Show } from "solid-js";
import { useArray, useUpdates } from "../../state/hooks";
import { combineClasses } from "../../util/helpers";
import Grid from "../util/layout/Grid";
import s from "./deployment.module.css";
import Update from "../update/Update";
import { getUpdates } from "../../util/query";
import { useAppState } from "../../state/StateProvider";
import { ADD_UPDATE } from "../../state/actions";
const Updates: Component<{ deploymentID: string }> = (p) => {
const { ws } = useAppState();
const selectedUpdates = useArray(() =>
getUpdates({ deploymentID: p.deploymentID })
);
const listener = ({ data }: { data: string }) => {
const message = JSON.parse(data);
if (
message.type === ADD_UPDATE &&
message.update.deploymentID === p.deploymentID
) {
selectedUpdates.add(message.update);
}
};
ws.socket.addEventListener("message", listener);
onCleanup(() => {
ws.socket.removeEventListener("message", listener);
});
return (
<Show
when={
@@ -19,9 +35,11 @@ const Updates: Component<{ deploymentID: string }> = (p) => {
>
<Grid class={combineClasses(s.Updates, "shadow")}>
<div class={s.ItemHeader}>updates</div>
<For each={selectedUpdates.collection()}>
{(update) => <Update update={update} showName={false} />}
</For>
<Grid class={s.UpdatesContainer}>
<For each={selectedUpdates.collection()}>
{(update) => <Update update={update} showName={false} />}
</For>
</Grid>
</Grid>
</Show>
);
+49 -5
View File
@@ -1,10 +1,16 @@
import { Update as UpdateType } from "@monitor/types";
import { Component, Show } from "solid-js";
import { useAppState } from "../../state/StateProvider";
import { combineClasses, readableOperation, readableTimestamp } from "../../util/helpers";
import {
combineClasses,
readableOperation,
readableTimestamp,
} from "../../util/helpers";
import { useToggle } from "../../util/hooks";
import Icon from "../util/icons/Icon";
import Flex from "../util/layout/Flex";
import Grid from "../util/layout/Grid";
import CenterMenu from "../util/menu/CenterMenu";
import s from "./update.module.css";
const Update: Component<{ update: UpdateType; showName: boolean }> = (p) => {
@@ -33,7 +39,20 @@ const Update: Component<{ update: UpdateType; showName: boolean }> = (p) => {
} else {
return op;
}
};
const log = () => {
const outText = p.update.log.stdout
? `stdout:\n\n${p.update.log.stdout}` +
(p.update.log.stderr ? "\n\n" : "")
: "";
const errText = p.update.log.stderr
? `stderr:\n\n${p.update.log.stderr}`
: "";
return outText + errText;
}
const [showCommand, toggleShowCommand] = useToggle();
const [showLog, toggleShowLog] = useToggle();
const [showNote, toggleShowNote] = useToggle();
return (
<Grid gap="0.5rem" class={combineClasses(s.Update, "shadow")}>
<Show when={p.showName}>
@@ -46,7 +65,13 @@ const Update: Component<{ update: UpdateType; showName: boolean }> = (p) => {
"grid-template-rows": "1fr 1fr",
}}
>
<div>{operation()}</div>
<div
style={{
color: p.update.isError ? "rgb(182, 47, 52)" : "inherit",
}}
>
{operation()}
</div>
<div style={{ "place-self": "center end" }}>
{readableTimestamp(p.update.timestamp)}
</div>
@@ -56,12 +81,31 @@ const Update: Component<{ update: UpdateType; showName: boolean }> = (p) => {
</Flex>
<Flex justifyContent="space-between" alignItems="center">
{/* show command */}
<Icon type="arrow-down" />
<CenterMenu
title="command"
show={showCommand}
toggleShow={toggleShowCommand}
target={<Icon type="arrow-down" />}
content={<pre class={s.Log}>{p.update.command}</pre>}
/>
<Show when={p.update.note}>
<Icon type="arrow-down" />
<CenterMenu
title="note"
show={showNote}
toggleShow={toggleShowNote}
target={<Icon type="arrow-down" />}
content={<div></div>}
/>
</Show>
{/* show log */}
<Icon type="arrow-down" />
<CenterMenu
title="log"
show={showLog}
toggleShow={toggleShowLog}
target={<Icon type="arrow-down" />}
content={<pre class={s.Log}>{log()}</pre>}
/>
</Flex>
</Grid>
</Grid>
@@ -1,4 +1,16 @@
.Update {
background-color: rgb(98, 46, 46);
background-color: rgb(83, 37, 37);
padding: 0.75rem;
}
.Log {
white-space: pre-line;
overflow-wrap: anywhere;
word-wrap: break-word;
max-height: 80vh;
overflow: scroll;
tab-size: 2;
-moz-tab-size: 2;
width: 40rem;
max-width: 90vw;
}
@@ -2,7 +2,7 @@ import { Component, createSignal, JSX } from "solid-js";
const ConfirmButton: Component<{
onConfirm: () => void;
color?: "red" | "green" | "blue";
color?: "red" | "green" | "blue" | "orange";
style?: JSX.CSSProperties;
}> = (p) => {
const [confirm, set] = createSignal(false);
@@ -20,7 +20,7 @@ const ConfirmButton: Component<{
set(confirm => !confirm);
}}
>
{confirm() ? "Confirm" : p.children}
{confirm() ? "confirm" : p.children}
</button>
);
};
+3 -1
View File
@@ -24,7 +24,9 @@ export type IconType =
| "reset"
| "plus"
| "minus"
| "floppy-disk";
| "floppy-disk"
| "download"
| "upload";
const Icon: Component<{
type: IconType;
@@ -115,14 +115,14 @@
}
.CenterMenuContainer {
position: absolute;
position: fixed;
z-index: 200;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
place-items: center;
background-color: rgba(0, 0, 0, 0.1);
background-color: rgba(0, 0, 0, 0.2);
}
.CenterMenuTitle {
-1
View File
@@ -85,7 +85,6 @@ export function useUpdates(query?: Parameters<typeof getUpdates>[0]) {
export function useArray<T>(query: () => Promise<T[]>) {
const [collection, set] = createSignal<T[]>();
createEffect(() => {
console.log("running query")
query().then(set);
})
const add = (item: T) => {
+1
View File
@@ -33,6 +33,7 @@ function socket(state: State) {
});
return {
socket: ws,
send: <T>(type: string, message: T) => {
ws.send(JSON.stringify({ ...message, type }));
},
+2 -2
View File
@@ -118,7 +118,7 @@ export async function dockerRun(
repoMount?: { repoFolder: string; containerMount: string }
) {
const command =
`docker pull ${image}${latest && ":latest"} && docker run -d` +
`docker pull ${image}${latest ? ":latest" : ""} && docker run -d` +
name(containerName) +
containerUserString(containerUser) +
portsString(ports) +
@@ -173,7 +173,7 @@ function repoVolume(
function restartString(restart?: string) {
return restart
? ` --restart=${restart}${restart === "on-failure" ? ":10" : ""}`
? ` --restart ${restart}${restart === "on-failure" ? ":10" : ""}`
: "";
}