forked from github-starred/komodo
put container state on list deployment return, including NotCreated and Unknown
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Component } from "solid-js";
|
||||
import s from "./home.module.scss"
|
||||
|
||||
const Home: Component<{}> = (p) => {
|
||||
return (
|
||||
|
||||
59
frontend/src/components/home/Summary.tsx
Normal file
59
frontend/src/components/home/Summary.tsx
Normal 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;
|
||||
}
|
||||
0
frontend/src/components/home/home.module.scss
Normal file
0
frontend/src/components/home/home.module.scss
Normal 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)!;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user