mirror of
https://codeberg.org/icewind/haze.git
synced 2026-10-01 08:44:09 +02:00
feat(pin): Store pinned state in a file within the container
Signed-off-by: Louis Chmn <louis@chmn.me>
This commit is contained in:
parent
8f7c4e1078
commit
8841570e0a
2 changed files with 39 additions and 43 deletions
62
src/cloud.rs
62
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> {
|
|||
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<String>,
|
||||
|
|
@ -226,7 +228,6 @@ pub struct Cloud {
|
|||
pub ip: Option<IpAddr>,
|
||||
pub workdir: Utf8PathBuf,
|
||||
pub options: CloudOptions,
|
||||
pub pinned: bool,
|
||||
pub address: String,
|
||||
pub preset_config: HashMap<String, Value>,
|
||||
}
|
||||
|
|
@ -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<String, (Option<_>, Option<_>, Vec<_>)> = HashMap::new();
|
||||
let mut containers_by_id: HashMap<String, (Option<_>, 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()
|
||||
},
|
||||
pub async fn is_pinned(&self, docker: &Docker) -> Result<bool> {
|
||||
let mut content = Vec::new();
|
||||
self.exec_with_output(
|
||||
docker,
|
||||
vec!["cat", PINNED_FILE],
|
||||
Some(&mut content),
|
||||
Vec::<String>::new(),
|
||||
)
|
||||
.await
|
||||
.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<Item = &Service> {
|
||||
|
|
|
|||
18
src/main.rs
18
src/main.rs
|
|
@ -68,9 +68,15 @@ async fn main() -> Result<ExitCode> {
|
|||
match args {
|
||||
HazeArgs::Clean => {
|
||||
let list = Cloud::list(&docker, None, &config).await?;
|
||||
let (retain, remove) = list
|
||||
.into_iter()
|
||||
.partition::<Vec<_>, _>(|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 {
|
||||
|
|
@ -102,7 +108,11 @@ async fn main() -> Result<ExitCode> {
|
|||
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(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue