selected state deployment and server / deployment status

This commit is contained in:
mbecker20
2022-03-23 02:20:02 -07:00
parent e54b7633bc
commit d059d7fb30
13 changed files with 93 additions and 56 deletions

View File

@@ -1,10 +1,11 @@
import {
getContainerStatus,
intoCollection,
} from "@monitor/util";
import { FastifyInstance } from "fastify";
import fp from "fastify-plugin";
import { deploymentStatusLocal } from "../util/deploymentStatus";
import { getPeripheryContainers } from "../util/periphery/container";
import { getPeripheryContainer, getPeripheryContainers } from "../util/periphery/container";
const deployments = fp((app: FastifyInstance, _: {}, done: () => void) => {
app.get("/deployments", { onRequest: [app.auth] }, async (req, res) => {
@@ -21,12 +22,12 @@ const deployments = fp((app: FastifyInstance, _: {}, done: () => void) => {
{ serverID: server._id },
"name containerName serverID"
);
const status = server.isCore ? await deploymentStatusLocal(app, deployments) : await getPeripheryContainers(server);
const status = server.isCore ? await deploymentStatusLocal(app) : await getPeripheryContainers(server);
res.send(
intoCollection(
deployments.map((dep) => ({
...dep,
status: status[dep.containerName!],
deployments.map((deployment) => ({
...deployment,
status: status[deployment.containerName!],
}))
)
);
@@ -35,6 +36,21 @@ const deployments = fp((app: FastifyInstance, _: {}, done: () => void) => {
app.get("/deployment/:id", { onRequest: [app.auth] }, async (req, res) => {
const { id } = req.params as { id: string };
const deployment = await app.deployments.findById(id);
if (!deployment) {
res.status(400);
res.send("could not find deployment");
return;
}
const onCore = deployment.serverID === app.core._id;
const server = onCore ? app.core : await app.servers.findById(deployment.serverID!);
if (!server) {
res.status(400);
res.send("could not find deployment's server");
return;
}
deployment.status = onCore
? await getContainerStatus(app.dockerode, deployment.containerName!)
: await getPeripheryContainer(server, deployment.containerName!);
res.send(deployment);
});
done();

View File

@@ -5,7 +5,7 @@ import { serverStatusPeriphery } from "../util/periphery/status";
const servers = fp((app: FastifyInstance, _: {}, done: () => void) => {
app.get("/servers", { onRequest: [app.auth] }, async (req, res) => {
const servers = await app.servers.find({}, "name enabled");
const servers = await app.servers.find({});
await Promise.all(
servers.map(async (server) => {
server.status = (await serverStatusPeriphery(server))

View File

@@ -1,10 +1,8 @@
import { ContainerStatus, Deployment } from "@monitor/types";
import { objFrom2Arrays } from "@monitor/util";
import { FastifyInstance } from "fastify";
export async function deploymentStatusLocal(
app: FastifyInstance,
deploymentsAr: Deployment[]
) {
const statusAr = await app.dockerode.listContainers({ all: true });
const statusNames = statusAr.map((stat) =>
@@ -20,27 +18,12 @@ export async function deploymentStatusLocal(
);
return objFrom2Arrays(
statusNames,
statusNames.map((name) => {
const tryDeployment = getDeployment(status[name]!, deploymentsAr);
const _id = tryDeployment ? tryDeployment._id : "none";
return {
...status[name],
deploymentID: _id,
};
})
statusAr.map((stat, i) => ({
name: statusNames[i],
Status: stat.Status,
State: stat.State as "running" | "exited",
}))
);
}
function getDeployment(
status: ContainerStatus,
deploymentsAr: Deployment[]
) {
for (let i = 0; i < deploymentsAr.length; i++) {
if (deploymentsAr[i].containerName === status.name) {
return deploymentsAr[i];
}
}
return undefined;
}

View File

@@ -2,8 +2,9 @@ import { Component } from "solid-js";
import { useAppState } from "../../state/StateProvider";
import s from "./deployment.module.css";
const Deployment: Component<{}> = (p) => {
const Deployment: Component<{ id: string }> = (p) => {
const { servers, deployments } = useAppState();
return (
<div class={s.Deployment} >

View File

@@ -1,6 +1,7 @@
.Sidebar {
grid-area: sidebar;
background-color: blue;
overflow-y: scroll;
}
.Server {
@@ -10,4 +11,9 @@
.Deployments {
background-color: rgb(85, 85, 85);
}
.Deployment {
padding: 0.5rem 1rem;
justify-content: space-between;
}

View File

@@ -1,18 +1,26 @@
import { ContainerStatus } from "@monitor/types";
import { Component, Show } from "solid-js";
import { useAppState } from "../../../state/StateProvider";
import s from "../sidebar.module.css";
const Deployment: Component<{ id: string }> = (p) => {
const { deployments } = useAppState();
const deployment = () => deployments.get(p.id);
return (
const { deployments } = useAppState();
const deployment = () => deployments.get(p.id);
const status = () => {
if (!deployment() || deployment()!.status === "not created") {
return "not created";
} else {
return (deployment()!.status as ContainerStatus).State;
}
};
return (
<Show when={deployment()}>
<div class={s.Deployment}>
<div>{deployment()!.name}</div>
</div>
<button class={s.Deployment}>
<div>{deployment()!.name}</div>
<div>{status()}</div>
</button>
</Show>
);
}
};
export default Deployment;
export default Deployment;

View File

@@ -6,7 +6,8 @@ body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: lightskyblue;
scrollbar-color: rgba(252, 234, 222, 0.3) transparent;
scrollbar-width: thin;
color: #fceade;
}

View File

@@ -1,11 +1,7 @@
import { Accessor, Component, createContext, useContext } from "solid-js";
import { createStore, SetStoreFunction } from "solid-js/store";
import { useLocalStorageToggle } from "../util/hooks";
import {
useBuilds,
useDeployments,
useServers,
useUpdates,
} from "./hooks";
import { useBuilds, useDeployments, useSelected, useServers, useUpdates } from "./hooks";
import socket from "./socket";
export type State = {
@@ -13,8 +9,9 @@ export type State = {
builds: ReturnType<typeof useBuilds>;
deployments: ReturnType<typeof useDeployments>;
updates: ReturnType<typeof useUpdates>;
selected: ReturnType<typeof useSelected>;
sidebar: {
open: Accessor<boolean>,
open: Accessor<boolean>;
toggle: () => void;
};
};
@@ -22,16 +19,20 @@ export type State = {
const context = createContext<State & { ws: ReturnType<typeof socket> }>();
export const AppStateProvider: Component<{}> = (p) => {
const [sidebarOpen, toggleSidebarOpen] = useLocalStorageToggle("sidebar-open");
const [sidebarOpen, toggleSidebarOpen] = useLocalStorageToggle(
"sidebar-open",
true
);
const state: State = {
servers: useServers(),
builds: useBuilds(),
deployments: useDeployments(),
updates: useUpdates(),
selected: useSelected(),
sidebar: {
open: sidebarOpen,
toggle: toggleSidebarOpen,
}
},
};
// created state before attaching ws, to pass state easily
@@ -44,4 +45,4 @@ export const AppStateProvider: Component<{}> = (p) => {
export function useAppState() {
return useContext(context) as State & { ws: ReturnType<typeof socket> };
}
}

View File

@@ -1,6 +1,7 @@
import { Collection, Update } from "@monitor/types";
import { createEffect, createResource } from "solid-js";
import { filterOutFromObj } from "../util/helpers";
import { useLocalStorage } from "../util/hooks";
import {
getBuilds,
getDeployments,
@@ -8,6 +9,21 @@ import {
getUpdates,
} from "../util/query";
export function useSelected() {
const [selected, setSelected] = useLocalStorage<{
id: string;
type: "server" | "deployment" | "build";
}>({ id: "", type: "deployment" }, "selected-item");
const set = (id: string, type: "server" | "deployment" | "build") => {
setSelected({ id, type });
};
return {
id: () => selected().id,
type: () => selected().type,
set,
};
}
export function useServers() {
return useCollection(getServers);
}
@@ -29,11 +45,11 @@ export function useArray<T>(query: () => Promise<T[]>) {
const push = (update: Update) => {
mutate((updates: any) => [update, ...updates]);
};
const loaded = () => collection() ? true : false;
const loaded = () => (collection() ? true : false);
return {
collection,
push,
loaded
loaded,
};
}
@@ -58,9 +74,9 @@ export function useCollection<T>(query: () => Promise<Collection<T>>) {
return collection() && collection()![id];
};
const ids = () => collection() && Object.keys(collection()!);
const loaded = () => collection() ? true : false;
const loaded = () => (collection() ? true : false);
createEffect(() => console.log(collection()))
createEffect(() => console.log(collection()));
return {
collection,

View File

@@ -1,4 +1,5 @@
import { Accessor, createSignal, onCleanup, onMount } from "solid-js";
import { createStore, DeepReadonly, SetStoreFunction } from "solid-js/store";
export function useToggle(initial = false): [Accessor<boolean>, () => void] {
const [s, set] = createSignal(initial);

View File

@@ -20,6 +20,7 @@
"build-core": "cd core && yarn build",
"restart-core": "cd core && yarn build && cd ../cli && yarn restart-default",
"push-core": "cd core && yarn push",
"build-periphery": "cd periphery && yarn build",
"push-periphery": "cd periphery && yarn push"
},
"devDependencies": {

4
types/types.d.ts vendored
View File

@@ -90,6 +90,9 @@ export interface Deployment extends DockerRunArgs {
branch?: string;
accessToken?: string;
containerMount?: string; // the file path to mount repo on inside the container
// running status
status?: "not created" | ContainerStatus;
}
export type Conversion = {
@@ -120,7 +123,6 @@ export type DeployActionState = {
export type ContainerStatus = {
name: string;
deploymentID?: string;
Status: string;
State: "running" | "exited";
};

View File

@@ -1,4 +1,5 @@
import {
ContainerStatus,
Conversion,
DockerBuildArgs,
DockerRunArgs,
@@ -30,13 +31,13 @@ export async function allContainerStatus(dockerode: Dockerode) {
);
}
export async function getContainerStatus(dockerode: Dockerode, name: string) {
export async function getContainerStatus(dockerode: Dockerode, name: string): Promise<ContainerStatus | "not created"> {
const status = (await dockerode.listContainers({ all: true })).filter(
({ Names }) => Names[0] === "/" + name
);
return status[0]
? {
State: status[0].State,
State: status[0].State as "running" | "exited",
Status: status[0].Status,
name,
}