put container state on list deployment return, including NotCreated and Unknown

This commit is contained in:
mbecker20
2022-12-26 23:18:17 +00:00
parent 4d3feb52c7
commit 99ce35ce1d
10 changed files with 116 additions and 32 deletions

View File

@@ -10,8 +10,8 @@ use futures_util::future::join_all;
use helpers::handle_anyhow_error;
use mungos::{Deserialize, Document, Serialize};
use types::{
traits::Permissioned, Deployment, DeploymentActionState, DeploymentWithContainer,
PermissionLevel, Server,
traits::Permissioned, Deployment, DeploymentActionState, DeploymentWithContainerState,
PermissionLevel, Server, DockerContainerState,
};
use typeshare::typeshare;
@@ -49,7 +49,7 @@ pub fn router() -> Router {
Extension(user): RequestUserExtension,
Path(deployment_id): Path<DeploymentId>| async move {
let res = state
.get_deployment_with_container(&user, &deployment_id.id)
.get_deployment_with_container_state(&user, &deployment_id.id)
.await
.map_err(handle_anyhow_error)?;
response!(Json(res))
@@ -63,7 +63,7 @@ pub fn router() -> Router {
Extension(user): RequestUserExtension,
Query(query): Query<Document>| async move {
let deployments = state
.list_deployments_with_container_info(&user, query)
.list_deployments_with_container_state(&user, query)
.await
.map_err(handle_anyhow_error)?;
response!(Json(deployments))
@@ -242,31 +242,37 @@ pub fn router() -> Router {
}
impl State {
async fn get_deployment_with_container(
async fn get_deployment_with_container_state(
&self,
user: &RequestUser,
id: &str,
) -> anyhow::Result<DeploymentWithContainer> {
) -> anyhow::Result<DeploymentWithContainerState> {
let deployment = self
.get_deployment_check_permissions(id, user, PermissionLevel::Read)
.await?;
let server = self.db.get_server(&deployment.server_id).await?;
let container = match self.periphery.container_list(&server).await {
Ok(containers) => containers.into_iter().find(|c| c.name == deployment.name),
Err(_) => None,
let (state, container) = match self.periphery.container_list(&server).await {
Ok(containers) => {
match containers.into_iter().find(|c| c.name == deployment.name) {
Some(container) => (container.state, Some(container)),
None => (DockerContainerState::NotDeployed, None)
}
},
Err(_) => (DockerContainerState::Unknown, None),
};
Ok(DeploymentWithContainer {
Ok(DeploymentWithContainerState {
deployment,
state,
container,
})
}
async fn list_deployments_with_container_info(
async fn list_deployments_with_container_state(
&self,
user: &RequestUser,
query: impl Into<Option<Document>>,
) -> anyhow::Result<Vec<DeploymentWithContainer>> {
let mut deployments: Vec<Deployment> = self
) -> anyhow::Result<Vec<DeploymentWithContainerState>> {
let deployments: Vec<Deployment> = self
.db
.deployments
.get_some(query, None)
@@ -297,23 +303,29 @@ impl State {
.into_iter()
.map(|(container, server_id)| (server_id, container.ok()))
.collect::<HashMap<_, _>>();
deployments.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
let res = deployments
let mut res = deployments
.into_iter()
.map(|deployment| {
let container = match containers.get(&deployment.server_id).unwrap() {
Some(container) => container
let (state, container) = match containers.get(&deployment.server_id).unwrap() {
Some(container) => {
match container
.iter()
.find(|c| c.name == deployment.name)
.map(|c| c.to_owned()),
None => None,
.map(|c| c.to_owned()) {
Some(container) => (container.state, Some(container)),
None => (DockerContainerState::NotDeployed, None),
}
},
None => (DockerContainerState::Unknown, None),
};
DeploymentWithContainer {
DeploymentWithContainerState {
container,
deployment,
state,
}
})
.collect();
.collect::<Vec<DeploymentWithContainerState>>();
res.sort_by(|a, b| a.deployment.name.to_lowercase().cmp(&b.deployment.name.to_lowercase()));
Ok(res)
}

View File

@@ -1,4 +1,5 @@
import { Component } from "solid-js";
import s from "./home.module.scss"
const Home: Component<{}> = (p) => {
return (

View File

@@ -0,0 +1,59 @@
import { Component, createMemo } from "solid-js";
import { useAppState } from "../../state/StateProvider";
import { DockerContainerState, ServerStatus } from "../../types";
const Summary: Component<{}> = (p) => {
return <div></div>;
};
export default Summary;
function useDeploymentCount() {
const { deployments } = useAppState();
const count = createMemo(() => {
const ids = deployments.ids();
if (!ids)
return { total: 0, running: 0, stopped: 0, notDeployed: 0, unknown: 0 };
let running = 0;
let stopped = 0;
let notDeployed = 0;
let unknown = 0;
for (const id of ids) {
const state = deployments.get(id)!.state;
if (state === DockerContainerState.NotDeployed) {
notDeployed++
} else if (state === DockerContainerState.Running) {
running++
} else if (state === DockerContainerState.Exited) {
stopped++
} else if (state === DockerContainerState.Unknown) {
unknown++
}
}
return { total: ids.length, running, stopped, notDeployed, unknown };
});
return count;
}
function useServerCount() {
const { servers } = useAppState();
const count = createMemo(() => {
const ids = servers.ids();
if (!ids) return { total: 0, healthy: 0, unhealthy: 0, disabled: 0 };
let healthy = 0;
let unhealthy = 0;
let disabled = 0;
for (const id of ids) {
const server = servers.get(id)!;
if (server.status === ServerStatus.Disabled) {
disabled++;
} else if (server.status === ServerStatus.Ok) {
healthy++;
} else if (server.status === ServerStatus.NotOk) {
unhealthy++;
}
}
return { total: ids.length, healthy, unhealthy, disabled };
});
return count;
}

View File

@@ -54,7 +54,7 @@ export function useDeployments() {
);
const state = (id: string) => {
const deployment = deployments.get(id)!;
return deployment.container?.state;
return deployment.state;
};
const status = (id: string) => {
const deployment = deployments.get(id)!;

View File

@@ -55,8 +55,9 @@ export interface Deployment {
updated_at?: string;
}
export interface DeploymentWithContainer {
export interface DeploymentWithContainerState {
deployment: Deployment;
state: DockerContainerState;
container?: BasicContainerInfo;
}
@@ -249,6 +250,8 @@ export interface ApiSecret {
}
export enum DockerContainerState {
Unknown = "unknown",
NotDeployed = "not_deployed",
Created = "created",
Restarting = "restarting",
Running = "running",

View File

@@ -5,7 +5,7 @@ import {
BuildActionState,
Deployment,
DeploymentActionState,
DeploymentWithContainer,
DeploymentWithContainerState,
Group,
Log,
Procedure,
@@ -69,11 +69,11 @@ export class Client {
// deployment
list_deployments(query?: QueryObject): Promise<DeploymentWithContainer[]> {
list_deployments(query?: QueryObject): Promise<DeploymentWithContainerState[]> {
return this.get("/api/deployment/list" + generateQuery(query));
}
get_deployment(id: string): Promise<DeploymentWithContainer> {
get_deployment(id: string): Promise<DeploymentWithContainerState> {
return this.get(`/api/deployment/${id}`);
}

View File

@@ -1,5 +1,5 @@
use anyhow::Context;
use monitor_types::{Deployment, DeploymentActionState, DeploymentWithContainer, Update};
use monitor_types::{Deployment, DeploymentActionState, DeploymentWithContainerState, Update};
use serde_json::{json, Value};
use crate::MonitorClient;
@@ -8,7 +8,7 @@ impl MonitorClient {
pub async fn list_deployments(
&self,
query: impl Into<Option<Value>>,
) -> anyhow::Result<Vec<DeploymentWithContainer>> {
) -> anyhow::Result<Vec<DeploymentWithContainerState>> {
self.get("/api/deployment/list", query.into())
.await
.context("failed at list deployments")
@@ -17,7 +17,7 @@ impl MonitorClient {
pub async fn get_deployment(
&self,
deployment_id: &str,
) -> anyhow::Result<DeploymentWithContainer> {
) -> anyhow::Result<DeploymentWithContainerState> {
self.get(
&format!("/api/deployment/{deployment_id}"),
Option::<()>::None,

View File

@@ -72,8 +72,9 @@ pub struct Deployment {
#[typeshare]
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct DeploymentWithContainer {
pub struct DeploymentWithContainerState {
pub deployment: Deployment,
pub state: DockerContainerState,
pub container: Option<BasicContainerInfo>,
}
@@ -162,6 +163,8 @@ pub struct DockerContainerStats {
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum DockerContainerState {
Unknown,
NotDeployed,
Created,
Restarting,
Running,
@@ -171,6 +174,12 @@ pub enum DockerContainerState {
Dead,
}
impl Default for DockerContainerState {
fn default() -> Self {
Self::Unknown
}
}
#[typeshare]
#[derive(
Serialize, Deserialize, Debug, Display, EnumString, PartialEq, Hash, Eq, Clone, Copy, Diff,

View File

@@ -1,7 +1,7 @@
use anyhow::{anyhow, Context};
use monitor_client::{
types::{
Build, Command, Conversion, Deployment, DeploymentWithContainer, DockerBuildArgs, Server,
Build, Command, Conversion, Deployment, DeploymentWithContainerState, DockerBuildArgs, Server,
SystemStats, Update,
},
MonitorClient,
@@ -56,7 +56,7 @@ pub async fn get_server_stats(monitor: &MonitorClient) -> anyhow::Result<SystemS
pub async fn deploy_mongo(
monitor: &MonitorClient,
) -> anyhow::Result<(Update, DeploymentWithContainer)> {
) -> anyhow::Result<(Update, DeploymentWithContainerState)> {
let servers = monitor
.list_servers(None)
.await