diff --git a/src/cloud.rs b/src/cloud.rs index afa01cf..c7faadd 100644 --- a/src/cloud.rs +++ b/src/cloud.rs @@ -2,12 +2,12 @@ use crate::config::{HazeConfig, HazeVolumeConfig}; use crate::database::Database; use crate::exec::{exec, exec_io, exec_tty, ExitCode}; use crate::mapping::{for_config, Mapping}; -use crate::php::{PhpVersion, PHP_MEMORY_LIMIT}; +use crate::php::PhpVersion; use crate::service::Service; use crate::service::ServiceTrait; use crate::sources::download_nc; use bollard::config::NetworkCreateRequest; -use bollard::models::{ContainerState, ContainerUpdateBody}; +use bollard::models::ContainerState; use bollard::query_parameters::{ListContainersOptions, RemoveContainerOptions}; use bollard::Docker; use camino::{Utf8Path, Utf8PathBuf}; @@ -51,6 +51,8 @@ fn get_max_php_version(base_path: &Utf8Path) -> Option { PhpVersion::from_number(major, minor) } +const PINNED_FILE: &str = "/var/www/html/data/.haze-pinned"; + #[derive(Clone, Debug, Eq, PartialEq, Default)] pub struct CloudOptions { pub name: Option, @@ -226,7 +228,6 @@ pub struct Cloud { pub ip: Option, pub workdir: Utf8PathBuf, pub options: CloudOptions, - pub pinned: bool, pub address: String, pub preset_config: HashMap, } @@ -555,7 +556,6 @@ impl Cloud { ip: Some(ip), workdir, options, - pinned: false, address, preset_config, }) @@ -671,7 +671,7 @@ impl Cloud { })) .await .into_diagnostic()?; - let mut containers_by_id: HashMap, Option<_>, Vec<_>)> = HashMap::new(); + let mut containers_by_id: HashMap, Vec<_>)> = HashMap::new(); for container in containers { let labels = container.labels.clone().unwrap_or_default(); if let Some(cloud_id) = labels.get("haze-cloud-id") { @@ -681,11 +681,9 @@ impl Cloud { } { let entry = containers_by_id.entry(cloud_id.to_string()).or_default(); if labels.get("haze-type").map(String::as_str) == Some("cloud") { - let info = docker.inspect_container(cloud_id, None).await.ok(); entry.0 = Some(container); - entry.1 = info; } else { - entry.2.push(container) + entry.1.push(container) } } } @@ -693,7 +691,7 @@ impl Cloud { let mut sortable_containers: Vec<_> = containers_by_id .into_iter() - .filter_map(|(id, (cloud, info, services))| { + .filter_map(|(id, (cloud, services))| { let cloud = cloud?; let network = id.clone(); let networks = cloud.network_settings?.networks?; @@ -719,13 +717,6 @@ impl Cloud { .filter_map(|service| service.names.as_ref()?.first().cloned()) .collect(); - let pinned = (info - .and_then(|info| info.host_config) - .and_then(|host| host.memory) - .unwrap() - % 2) - == 1; - let ip = network_info.ip_address.as_ref()?.parse().ok(); let address = if let Some(ip) = ip { config.proxy.addr(&id, ip) @@ -750,7 +741,6 @@ impl Cloud { app_packages: vec![], version, }, - pinned, address, preset_config: HashMap::default(), }, @@ -814,32 +804,28 @@ impl Cloud { Ok(()) } - pub async fn pin(&self, docker: &Docker) -> Result<()> { - // abuse memory limits as editable label - docker - .update_container( - &self.id, - ContainerUpdateBody { - memory: Some(PHP_MEMORY_LIMIT + 1), - ..ContainerUpdateBody::default() - }, - ) - .await + pub async fn is_pinned(&self, docker: &Docker) -> Result { + let mut content = Vec::new(); + self.exec_with_output( + docker, + vec!["cat", PINNED_FILE], + Some(&mut content), + Vec::::new(), + ) + .await? + .to_result()?; + + String::from_utf8(content) .into_diagnostic() + .map(|content| content.trim() == "1") + } + + pub async fn pin(&self, docker: &Docker) -> Result<()> { + self.write_file(docker, PINNED_FILE, "1").await } pub async fn unpin(&self, docker: &Docker) -> Result<()> { - // abuse memory limits as editable label - docker - .update_container( - &self.id, - ContainerUpdateBody { - memory: Some(PHP_MEMORY_LIMIT), - ..ContainerUpdateBody::default() - }, - ) - .await - .into_diagnostic() + self.write_file(docker, PINNED_FILE, "0").await } pub fn services(&self) -> impl Iterator { diff --git a/src/main.rs b/src/main.rs index 9c14ab1..5b2e945 100644 --- a/src/main.rs +++ b/src/main.rs @@ -68,9 +68,15 @@ async fn main() -> Result { match args { HazeArgs::Clean => { let list = Cloud::list(&docker, None, &config).await?; - let (retain, remove) = list - .into_iter() - .partition::, _>(|cloud| cloud.pinned); + let mut retain = Vec::new(); + let mut remove = Vec::new(); + for cloud in list { + if cloud.is_pinned(&docker).await.unwrap_or(false) { + retain.push(cloud); + } else { + remove.push(cloud); + } + } for cloud in remove { if let Err(e) = cloud.destroy(&docker).await { @@ -98,7 +104,11 @@ async fn main() -> Result { let mut services: Vec<_> = cloud.services().map(Service::name).collect(); services.push(cloud.db().name()); let services = services.join(", "); - let pin = if cloud.pinned { "*" } else { "" }; + let pin = if cloud.is_pinned(&docker).await.unwrap_or(false) { + "*" + } else { + "" + }; let version = match cloud.options.version.as_ref() { Some(version) => format!(", v{version}"), None => String::new(),