staxman-old/src/node/container.rs

137 lines
4.0 KiB
Rust

use crate::http::error::Result;
use bollard::{
container::{
InspectContainerOptions, KillContainerOptions, RemoveContainerOptions,
RestartContainerOptions, StartContainerOptions, StopContainerOptions,
},
service::{ContainerInspectResponse, ContainerSummary, MountPoint},
Docker,
};
use serde::Serialize;
use std::{collections::HashMap, path::Path};
use time::OffsetDateTime;
#[derive(Serialize)]
pub struct ContainerInfo {
pub id: String,
pub name: String,
pub state: String,
pub image: String,
pub image_id: String,
pub created_at: String,
pub volumes: Option<Vec<MountPoint>>,
pub env: Option<Vec<String>>,
pub labels: Option<HashMap<String, String>>,
}
impl ContainerInfo {
pub fn stack(&self) -> Option<String> {
self.labels
.clone()
.and_then(|lab| lab.get("com.docker.compose.project").cloned())
}
pub fn stack_folder(&self) -> Option<String> {
self.labels
.clone()
.and_then(|lab| lab.get("com.docker.compose.project.working_dir").cloned())
.and_then(|workdir| {
Path::new(&workdir)
.components()
.last()
.and_then(|part| part.as_os_str().to_str())
.map(|s| s.to_string())
})
}
pub fn running(&self) -> bool {
self.state == "running"
}
}
impl From<ContainerSummary> for ContainerInfo {
fn from(value: ContainerSummary) -> Self {
let created = OffsetDateTime::from_unix_timestamp(value.created.unwrap())
.unwrap_or(OffsetDateTime::UNIX_EPOCH);
ContainerInfo {
id: value.id.unwrap_or_default(),
name: value.names.unwrap_or_default()[0]
.trim_start_matches('/')
.to_string(),
state: value.state.unwrap_or_default(),
image: value.image.unwrap_or_default(),
image_id: value.image_id.unwrap_or_default(),
created_at: created.time().to_string(),
volumes: value.mounts,
labels: value.labels,
env: None,
}
}
}
impl From<ContainerInspectResponse> for ContainerInfo {
fn from(value: ContainerInspectResponse) -> Self {
let config = value.config.unwrap_or_default();
ContainerInfo {
id: value.id.unwrap_or_default(),
name: value.name.unwrap_or_default(),
state: value
.state
.and_then(|s| s.status)
.unwrap_or(bollard::service::ContainerStateStatusEnum::EMPTY)
.to_string(),
image: config.image.unwrap_or_default(),
image_id: value.image.unwrap_or_default(),
created_at: value.created.unwrap_or_default(),
volumes: value.mounts,
labels: config.labels,
env: config.env,
}
}
}
pub async fn get_info(docker: &Docker, name: &str) -> Result<ContainerInfo> {
let info = docker
.inspect_container(name, Some(InspectContainerOptions { size: true }))
.await?;
Ok(info.into())
}
pub async fn start(docker: &Docker, name: &str) -> Result<()> {
Ok(docker
.start_container(name, None::<StartContainerOptions<String>>)
.await?)
}
pub async fn restart(docker: &Docker, name: &str) -> Result<()> {
Ok(docker
.restart_container(name, Some(RestartContainerOptions { t: 30 }))
.await?)
}
pub async fn stop(docker: &Docker, name: &str) -> Result<()> {
Ok(docker
.stop_container(name, Some(StopContainerOptions { t: 30 }))
.await?)
}
pub async fn kill(docker: &Docker, name: &str) -> Result<()> {
Ok(docker
.kill_container(name, None::<KillContainerOptions<String>>)
.await?)
}
pub async fn remove(docker: &Docker, name: &str) -> Result<()> {
Ok(docker
.remove_container(
name,
Some(RemoveContainerOptions {
v: false,
force: true,
link: false,
}),
)
.await?)
}