1
0
Fork 0
mirror of https://codeberg.org/icewind/haze.git synced 2026-06-03 17:14:08 +02:00

presets wip

This commit is contained in:
Robin Appelman 2023-07-16 16:39:29 +02:00
commit fdcb8de4f2
17 changed files with 192 additions and 120 deletions

View file

@ -20,6 +20,7 @@ with lib; let
read_only = volume.readOnly; read_only = volume.readOnly;
}) })
cfg.volumes; cfg.volumes;
preset = cfg.presets;
} }
// ( // (
if (cfg.blackfire == null) if (cfg.blackfire == null)
@ -121,6 +122,23 @@ in {
}); });
}; };
presets = mkOption {
default = [];
type = types.listOf (types.submodule {
options = {
name = mkOption {
type = types.str;
description = "Name of the preset";
};
commands = mkOption {
type = types.listOf types.str;
description = "Commands to run post setup when the preset is enabled";
default = [];
};
};
});
};
proxy = mkOption { proxy = mkOption {
default = null; default = null;
type = types.nullOr (types.submodule { type = types.nullOr (types.submodule {

View file

@ -1,4 +1,5 @@
use crate::cloud::CloudOptions; use crate::cloud::CloudOptions;
use crate::config::Preset;
use crate::service::{Service, ServiceTrait}; use crate::service::{Service, ServiceTrait};
use miette::{IntoDiagnostic, Report, Result}; use miette::{IntoDiagnostic, Report, Result};
use parse_display::Display; use parse_display::Display;
@ -78,20 +79,18 @@ pub enum LogService {
} }
impl LogService { impl LogService {
pub fn from_type(ty: &str) -> Option<Self> { pub fn from_type(presets: &[Preset], ty: &str) -> Option<Self> {
if ty == "db" { if ty == "db" {
return Some(LogService::Database); return Some(LogService::Database);
} }
Some(LogService::Service( Some(LogService::Service(
Service::from_type(ty)?.first()?.clone(), Service::from_type(presets, ty)?.into_iter().next()?,
)) ))
} }
pub fn container_name(&self, cloud_id: &str) -> String { pub fn container_name(&self, cloud_id: &str) -> Option<String> {
match self { match self {
LogService::Database => { LogService::Database => Some(format!("{}-db", cloud_id)),
format!("{}-db", cloud_id)
}
LogService::Service(service) => service.container_name(cloud_id), LogService::Service(service) => service.container_name(cloud_id),
} }
} }
@ -103,7 +102,7 @@ pub enum ExecService {
} }
impl HazeArgs { impl HazeArgs {
pub fn parse<I, S>(mut args: I) -> Result<HazeArgs> pub fn parse<I, S>(presets: &[Preset], mut args: I) -> Result<HazeArgs>
where where
S: AsRef<str> + Into<String> + Display, S: AsRef<str> + Into<String> + Display,
I: Iterator<Item = S>, I: Iterator<Item = S>,
@ -140,7 +139,7 @@ impl HazeArgs {
}), }),
HazeCommand::Start => { HazeCommand::Start => {
let mut args = args.peekable(); let mut args = args.peekable();
let options = CloudOptions::parse(&mut args)?; let options = CloudOptions::parse(presets, &mut args)?;
if let Some(leftover) = args.next() { if let Some(leftover) = args.next() {
return Err(Report::msg(format!("unrecognized option {}", leftover))); return Err(Report::msg(format!("unrecognized option {}", leftover)));
} }
@ -149,13 +148,13 @@ impl HazeArgs {
HazeCommand::Stop => Ok(HazeArgs::Stop { filter }), HazeCommand::Stop => Ok(HazeArgs::Stop { filter }),
HazeCommand::Test => { HazeCommand::Test => {
let mut args = args.peekable(); let mut args = args.peekable();
let options = CloudOptions::parse(&mut args)?; let options = CloudOptions::parse(presets, &mut args)?;
let args = args.map(S::into).collect(); let args = args.map(S::into).collect();
Ok(HazeArgs::Test { options, args }) Ok(HazeArgs::Test { options, args })
} }
HazeCommand::Integration => { HazeCommand::Integration => {
let mut args = args.peekable(); let mut args = args.peekable();
let options = CloudOptions::parse(&mut args)?; let options = CloudOptions::parse(presets, &mut args)?;
let args = args.map(S::into).collect(); let args = args.map(S::into).collect();
Ok(HazeArgs::Integration { options, args }) Ok(HazeArgs::Integration { options, args })
} }
@ -190,8 +189,8 @@ impl HazeArgs {
let mut args = args.peekable(); let mut args = args.peekable();
let follow = args.next_if(|arg| arg.as_ref() == "-f").is_some(); let follow = args.next_if(|arg| arg.as_ref() == "-f").is_some();
let service = args let service = args
.next_if(|arg| LogService::from_type(arg.as_ref()).is_some()) .next_if(|arg| LogService::from_type(presets, arg.as_ref()).is_some())
.and_then(|arg| LogService::from_type(arg.as_ref())); .and_then(|arg| LogService::from_type(presets, arg.as_ref()));
Ok(HazeArgs::Logs { Ok(HazeArgs::Logs {
filter, filter,
follow, follow,
@ -213,7 +212,7 @@ impl HazeArgs {
} }
HazeCommand::Shell => { HazeCommand::Shell => {
let mut args = args.peekable(); let mut args = args.peekable();
let options = CloudOptions::parse(&mut args)?; let options = CloudOptions::parse(presets, &mut args)?;
let command = args.map(S::into).collect(); let command = args.map(S::into).collect();
Ok(HazeArgs::Shell { options, command }) Ok(HazeArgs::Shell { options, command })
} }

View file

@ -1,4 +1,4 @@
use crate::config::{HazeConfig, HazeVolumeConfig}; use crate::config::{HazeConfig, HazeVolumeConfig, Preset};
use crate::database::Database; use crate::database::Database;
use crate::exec::{exec, exec_tty, ExitCode}; use crate::exec::{exec, exec_tty, ExitCode};
use crate::mapping::{default_mappings, Mapping}; use crate::mapping::{default_mappings, Mapping};
@ -38,7 +38,7 @@ pub struct CloudOptions {
} }
impl CloudOptions { impl CloudOptions {
pub fn parse<I, S>(args: &mut Peekable<I>) -> Result<CloudOptions> pub fn parse<I, S>(presets: &[Preset], args: &mut Peekable<I>) -> Result<CloudOptions>
where where
S: AsRef<str> + Into<String> + Display, S: AsRef<str> + Into<String> + Display,
I: Iterator<Item = S>, I: Iterator<Item = S>,
@ -56,8 +56,8 @@ impl CloudOptions {
} else if let Ok(php_option) = PhpVersion::from_str(option.as_ref()) { } else if let Ok(php_option) = PhpVersion::from_str(option.as_ref()) {
php = Some(php_option); php = Some(php_option);
let _ = args.next(); let _ = args.next();
} else if let Some(service) = Service::from_type(option.as_ref()) { } else if let Some(service) = Service::from_type(presets, option.as_ref()) {
services.extend_from_slice(service); services.extend_from_slice(&service);
let _ = args.next(); let _ = args.next();
} else if option.as_ref().ends_with(".tar.gz") { } else if option.as_ref().ends_with(".tar.gz") {
app_package.push(option.to_string().into()); app_package.push(option.to_string().into());
@ -282,14 +282,14 @@ impl Cloud {
env.push(format!("BLACKFIRE_CLIENT_TOKEN={}", blackfire.client_token)); env.push(format!("BLACKFIRE_CLIENT_TOKEN={}", blackfire.client_token));
} }
let service_containers = try_join_all( let service_containers: Vec<Option<String>> = try_join_all(
options options
.services .services
.iter() .iter()
.map(|service| service.spawn(docker, &id, &network, config)), .map(|service| service.spawn(docker, &id, &network, config)),
) )
.await?; .await?;
containers.extend_from_slice(&service_containers); containers.extend(service_containers.iter().flatten().cloned());
env.extend( env.extend(
options options
@ -308,10 +308,10 @@ impl Cloud {
{ {
Ok(container) => container, Ok(container) => container,
Err(e) => { Err(e) => {
for container in service_containers { for container in service_containers.iter().flatten() {
docker docker
.remove_container( .remove_container(
&container, container,
Some(RemoveContainerOptions { Some(RemoveContainerOptions {
force: true, force: true,
..RemoveContainerOptions::default() ..RemoveContainerOptions::default()
@ -519,9 +519,8 @@ impl Cloud {
.flat_map(|container| &container.labels) .flat_map(|container| &container.labels)
.flat_map(|labels| labels.get("haze-type")) .flat_map(|labels| labels.get("haze-type"))
.map(String::as_str) .map(String::as_str)
.flat_map(Service::from_type) .flat_map(|ty| Service::from_type(&[], ty))
.flatten() .flatten()
.cloned()
.collect(); .collect();
let mut service_ids: Vec<String> = services let mut service_ids: Vec<String> = services
.iter() .iter()

View file

@ -16,6 +16,7 @@ pub struct HazeConfig {
pub volume: Vec<HazeVolumeConfig>, pub volume: Vec<HazeVolumeConfig>,
pub blackfire: Option<HazeBlackfireConfig>, pub blackfire: Option<HazeBlackfireConfig>,
pub proxy: ProxyConfig, pub proxy: ProxyConfig,
pub preset: Vec<Preset>,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -31,6 +32,8 @@ pub struct RawHazeConfig {
pub blackfire: Option<HazeBlackfireConfig>, pub blackfire: Option<HazeBlackfireConfig>,
#[serde(default)] #[serde(default)]
pub proxy: ProxyConfig, pub proxy: ProxyConfig,
#[serde(default)]
pub preset: Vec<Preset>,
} }
impl From<RawHazeConfig> for HazeConfig { impl From<RawHazeConfig> for HazeConfig {
@ -51,6 +54,7 @@ impl From<RawHazeConfig> for HazeConfig {
volume: raw.volume, volume: raw.volume,
blackfire: raw.blackfire, blackfire: raw.blackfire,
proxy: raw.proxy, proxy: raw.proxy,
preset: raw.preset,
} }
} }
} }
@ -200,3 +204,9 @@ impl HazeConfig {
.wrap_err("Failed to parse config file") .wrap_err("Failed to parse config file")
} }
} }
#[derive(Default, Deserialize, Debug)]
pub struct Preset {
pub name: String,
pub commands: Vec<String>,
}

View file

@ -49,7 +49,7 @@ async fn main() -> Result<()> {
.wrap_err("Failed to connect to docker")?; .wrap_err("Failed to connect to docker")?;
let config = HazeConfig::load().wrap_err("Failed to load config")?; let config = HazeConfig::load().wrap_err("Failed to load config")?;
let args = HazeArgs::parse(std::env::args())?; let args = HazeArgs::parse(&config.preset, std::env::args())?;
match args { match args {
HazeArgs::Clean => { HazeArgs::Clean => {
@ -93,7 +93,9 @@ async fn main() -> Result<()> {
} => { } => {
let cloud = Cloud::get_by_filter(&docker, filter, &config).await?; let cloud = Cloud::get_by_filter(&docker, filter, &config).await?;
let container = if let Some(service) = service { let container = if let Some(service) = service {
service.container_name(&cloud.id) service
.container_name(&cloud.id)
.ok_or_else(|| Report::msg(format!("service has no logs")))?
} else { } else {
cloud.id cloud.id
}; };

View file

@ -58,7 +58,7 @@ impl ActiveInstances {
_ => None, _ => None,
}) })
.next()?; .next()?;
let ip = push.get_ip(&self.docker, &cloud.id).await.ok()?; let ip = push.get_ip(&self.docker, &cloud.id).await.ok()??;
SocketAddr::new(ip, 7867) SocketAddr::new(ip, 7867)
} else if let Some(name) = name.strip_suffix("-office") { } else if let Some(name) = name.strip_suffix("-office") {
let cloud = Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config) let cloud = Cloud::get_by_filter(&self.docker, Some(name.into()), &self.config)
@ -72,7 +72,7 @@ impl ActiveInstances {
_ => None, _ => None,
}) })
.next()?; .next()?;
let ip = office.get_ip(&self.docker, &cloud.id).await.ok()?; let ip = office.get_ip(&self.docker, &cloud.id).await.ok()??;
SocketAddr::new(ip, 9980) SocketAddr::new(ip, 9980)
} else { } else {
SocketAddr::new( SocketAddr::new(

View file

@ -9,7 +9,7 @@ mod push;
mod sftp; mod sftp;
mod smb; mod smb;
use crate::config::HazeConfig; use crate::config::{HazeConfig, Preset};
pub use crate::service::clam::ClamIcap; pub use crate::service::clam::ClamIcap;
use crate::service::dav::Dav; use crate::service::dav::Dav;
use crate::service::kaspersky::{Kaspersky, KasperskyIcap}; use crate::service::kaspersky::{Kaspersky, KasperskyIcap};
@ -39,15 +39,20 @@ pub trait ServiceTrait {
async fn spawn( async fn spawn(
&self, &self,
docker: &Docker, _docker: &Docker,
cloud_id: &str, _cloud_id: &str,
network: &str, _network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String>; ) -> Result<Option<String>> {
Ok(None)
}
async fn is_healthy(&self, docker: &Docker, cloud_id: &str) -> Result<bool> { async fn is_healthy(&self, docker: &Docker, cloud_id: &str) -> Result<bool> {
let Some(container) = self.container_name(cloud_id) else {
return Ok(true)
};
let info = docker let info = docker
.inspect_container(&self.container_name(cloud_id), None) .inspect_container(&container, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(matches!( Ok(matches!(
@ -59,7 +64,9 @@ pub trait ServiceTrait {
)) ))
} }
fn container_name(&self, cloud_id: &str) -> String; fn container_name(&self, _cloud_id: &str) -> Option<String> {
None
}
async fn start_message(&self, _docker: &Docker, _cloud_id: &str) -> Result<Option<String>> { async fn start_message(&self, _docker: &Docker, _cloud_id: &str) -> Result<Option<String>> {
Ok(None) Ok(None)
@ -79,8 +86,11 @@ pub trait ServiceTrait {
} }
async fn is_running(&self, docker: &Docker, cloud_id: &str) -> Result<bool> { async fn is_running(&self, docker: &Docker, cloud_id: &str) -> Result<bool> {
let Some(container) = self.container_name(cloud_id) else {
return Ok(true)
};
let info = docker let info = docker
.inspect_container(&self.container_name(cloud_id), None) .inspect_container(&container, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(matches!( Ok(matches!(
@ -104,9 +114,12 @@ pub trait ServiceTrait {
.wrap_err("Timeout after 30 seconds")? .wrap_err("Timeout after 30 seconds")?
} }
async fn get_ip(&self, docker: &Docker, cloud_id: &str) -> Result<IpAddr> { async fn get_ip(&self, docker: &Docker, cloud_id: &str) -> Result<Option<IpAddr>> {
let Some(container) = self.container_name(cloud_id) else {
return Ok(None);
};
docker docker
.start_container::<String>(&self.container_name(cloud_id), None) .start_container::<String>(&container, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
self.wait_for_running(docker, cloud_id).await?; self.wait_for_running(docker, cloud_id).await?;
@ -114,7 +127,7 @@ pub trait ServiceTrait {
sleep(Duration::from_millis(100)).await; sleep(Duration::from_millis(100)).await;
let info = docker let info = docker
.inspect_container(&self.container_name(cloud_id), None) .inspect_container(&container, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
if matches!( if matches!(
@ -136,6 +149,7 @@ pub trait ServiceTrait {
.unwrap() .unwrap()
.parse() .parse()
.into_diagnostic() .into_diagnostic()
.map(Some)
.wrap_err("Invalid ip address") .wrap_err("Invalid ip address")
} else { } else {
Err(Report::msg("service not started")) Err(Report::msg("service not started"))
@ -158,26 +172,31 @@ pub enum Service {
Kaspersky(Kaspersky), Kaspersky(Kaspersky),
KasperskyIcap(KasperskyIcap), KasperskyIcap(KasperskyIcap),
ClamIcap(ClamIcap), ClamIcap(ClamIcap),
Preset(PresetService),
} }
impl Service { impl Service {
pub fn from_type(ty: &str) -> Option<&'static [Self]> { pub fn from_type(presets: &[Preset], ty: &str) -> Option<Vec<Self>> {
match ty { match ty {
"s3" => Some(&[Service::ObjectStore(ObjectStore::S3)]), "s3" => Some(vec![Service::ObjectStore(ObjectStore::S3)]),
"s3m" => Some(&[Service::ObjectStore(ObjectStore::S3m)]), "s3m" => Some(vec![Service::ObjectStore(ObjectStore::S3m)]),
"s3mb" => Some(&[Service::ObjectStore(ObjectStore::S3mb)]), "s3mb" => Some(vec![Service::ObjectStore(ObjectStore::S3mb)]),
"azure" => Some(&[Service::ObjectStore(ObjectStore::Azure)]), "azure" => Some(vec![Service::ObjectStore(ObjectStore::Azure)]),
"ldap" => Some(&[Service::Ldap(Ldap), Service::LdapAdmin(LdapAdmin)]), "ldap" => Some(vec![Service::Ldap(Ldap), Service::LdapAdmin(LdapAdmin)]),
"onlyoffice" => Some(&[Service::OnlyOffice(OnlyOffice)]), "onlyoffice" => Some(vec![Service::OnlyOffice(OnlyOffice)]),
"office" => Some(&[Service::Office(Office)]), "office" => Some(vec![Service::Office(Office)]),
"push" => Some(&[Service::Push(NotifyPush)]), "push" => Some(vec![Service::Push(NotifyPush)]),
"smb" => Some(&[Service::Smb(Smb)]), "smb" => Some(vec![Service::Smb(Smb)]),
"dav" => Some(&[Service::Dav(Dav)]), "dav" => Some(vec![Service::Dav(Dav)]),
"sftp" => Some(&[Service::Sftp(Sftp)]), "sftp" => Some(vec![Service::Sftp(Sftp)]),
"kaspersky" => Some(&[Service::Kaspersky(Kaspersky)]), "kaspersky" => Some(vec![Service::Kaspersky(Kaspersky)]),
"kaspersky-icap" => Some(&[Service::KasperskyIcap(KasperskyIcap)]), "kaspersky-icap" => Some(vec![Service::KasperskyIcap(KasperskyIcap)]),
"clamav-icap" => Some(&[Service::ClamIcap(ClamIcap)]), "clamav-icap" => Some(vec![Service::ClamIcap(ClamIcap)]),
_ => None, _ => presets
.iter()
.find_map(|preset| (preset.name == ty).then(|| PresetService(preset.name.clone())))
.map(Service::Preset)
.map(|service| vec![service]),
} }
} }
@ -193,3 +212,28 @@ impl Service {
.wrap_err("Timeout after 30 seconds")? .wrap_err("Timeout after 30 seconds")?
} }
} }
fn get_preset<'a>(presets: &'a [Preset], name: &str) -> Option<&'a Preset> {
presets.iter().find(|preset| preset.name == name)
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct PresetService(String);
#[async_trait::async_trait]
impl ServiceTrait for PresetService {
fn name(&self) -> &str {
self.0.as_str()
}
async fn post_setup(
&self,
_docker: &Docker,
_cloud_id: &str,
config: &HazeConfig,
) -> Result<Vec<String>> {
let preset =
get_preset(&config.preset, &self.0).ok_or_else(|| Report::msg("invalid preset"))?;
Ok(preset.commands.clone())
}
}

View file

@ -32,11 +32,11 @@ impl ServiceTrait for ClamIcap {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "deepdiver/icap-clamav-service"; let image = "deepdiver/icap-clamav-service";
pull_image(docker, image).await?; pull_image(docker, image).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id), name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
}); });
let config = Config { let config = Config {
@ -68,11 +68,11 @@ impl ServiceTrait for ClamIcap {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-clamav-icap", cloud_id) Some(format!("{}-clamav-icap", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {

View file

@ -23,11 +23,11 @@ impl ServiceTrait for Dav {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "ugeek/webdav:amd64"; let image = "ugeek/webdav:amd64";
pull_image(docker, image).await?; pull_image(docker, image).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id), name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
}); });
let config = Config { let config = Config {
@ -60,11 +60,11 @@ impl ServiceTrait for Dav {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-dav", cloud_id) Some(format!("{}-dav", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {

View file

@ -29,14 +29,14 @@ impl ServiceTrait for Kaspersky {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "kaspersky"; let image = "kaspersky";
if !image_exists(docker, image).await { if !image_exists(docker, image).await {
bail!("You need to manually create the 'kaspersky' image"); bail!("You need to manually create the 'kaspersky' image");
} }
pull_image(docker, image).await?; pull_image(docker, image).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id), name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
}); });
let config = Config { let config = Config {
@ -68,13 +68,13 @@ impl ServiceTrait for Kaspersky {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
async fn is_healthy(&self, docker: &Docker, cloud_id: &str) -> Result<bool> { async fn is_healthy(&self, docker: &Docker, cloud_id: &str) -> Result<bool> {
let exit = exec( let exit = exec(
docker, docker,
self.container_name(cloud_id), self.container_name(cloud_id).unwrap(),
"root", "root",
vec!["curl", "localhost/licenseinfo"], vec!["curl", "localhost/licenseinfo"],
Vec::<String>::default(), Vec::<String>::default(),
@ -84,8 +84,8 @@ impl ServiceTrait for Kaspersky {
Ok(exit.to_result().is_ok()) Ok(exit.to_result().is_ok())
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-kaspersky", cloud_id) Some(format!("{}-kaspersky", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {
@ -130,14 +130,14 @@ impl ServiceTrait for KasperskyIcap {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "kaspersky-icap"; let image = "kaspersky-icap";
if !image_exists(docker, image).await { if !image_exists(docker, image).await {
bail!("You need to manually create the 'kaspersky-icap' image"); bail!("You need to manually create the 'kaspersky-icap' image");
} }
pull_image(docker, image).await?; pull_image(docker, image).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id), name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
}); });
let config = Config { let config = Config {
@ -169,7 +169,7 @@ impl ServiceTrait for KasperskyIcap {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
// async fn is_healthy(&self, docker: &Docker, cloud_id: &str) -> Result<bool> { // async fn is_healthy(&self, docker: &Docker, cloud_id: &str) -> Result<bool> {
@ -185,8 +185,8 @@ impl ServiceTrait for KasperskyIcap {
// Ok(exit.to_result().is_ok()) // Ok(exit.to_result().is_ok())
// } // }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-kaspersky-icap", cloud_id) Some(format!("{}-kaspersky-icap", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {

View file

@ -27,11 +27,11 @@ impl ServiceTrait for Ldap {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "icewind1991/haze-ldap"; let image = "icewind1991/haze-ldap";
pull_image(docker, image).await?; pull_image(docker, image).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id), name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
}); });
let config = Config { let config = Config {
@ -65,11 +65,11 @@ impl ServiceTrait for Ldap {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-ldap", cloud_id) Some(format!("{}-ldap", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {
@ -96,11 +96,11 @@ impl ServiceTrait for LdapAdmin {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "osixia/phpldapadmin"; let image = "osixia/phpldapadmin";
pull_image(docker, image).await?; pull_image(docker, image).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id), name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
}); });
let config = Config { let config = Config {
@ -134,16 +134,16 @@ impl ServiceTrait for LdapAdmin {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-ldap-admin", cloud_id) Some(format!("{}-ldap-admin", cloud_id))
} }
async fn start_message(&self, docker: &Docker, cloud_id: &str) -> Result<Option<String>> { async fn start_message(&self, docker: &Docker, cloud_id: &str) -> Result<Option<String>> {
let info = docker let info = docker
.inspect_container(&self.container_name(cloud_id), None) .inspect_container(&self.container_name(cloud_id).unwrap(), None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
let ip = if matches!( let ip = if matches!(

View file

@ -77,7 +77,7 @@ impl ServiceTrait for ObjectStore {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
pull_image(docker, self.image()).await?; pull_image(docker, self.image()).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: format!("{}-object", cloud_id), name: format!("{}-object", cloud_id),
@ -114,7 +114,7 @@ impl ServiceTrait for ObjectStore {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
async fn is_healthy(&self, docker: &Docker, cloud_id: &str) -> Result<bool> { async fn is_healthy(&self, docker: &Docker, cloud_id: &str) -> Result<bool> {
@ -134,7 +134,7 @@ impl ServiceTrait for ObjectStore {
} }
_ => { _ => {
let info = docker let info = docker
.inspect_container(&self.container_name(cloud_id), None) .inspect_container(&self.container_name(cloud_id).unwrap(), None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(matches!( Ok(matches!(
@ -148,8 +148,8 @@ impl ServiceTrait for ObjectStore {
} }
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-object", cloud_id) Some(format!("{}-object", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {

View file

@ -27,10 +27,10 @@ impl ServiceTrait for Office {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
config: &HazeConfig, config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "collabora/code"; let image = "collabora/code";
pull_image(docker, image).await?; pull_image(docker, image).await?;
let container_id = self.container_name(cloud_id); let container_id = self.container_name(cloud_id).unwrap();
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: container_id.clone(), name: container_id.clone(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
@ -82,11 +82,11 @@ impl ServiceTrait for Office {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-office", cloud_id) Some(format!("{}-office", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {
@ -99,7 +99,7 @@ impl ServiceTrait for Office {
cloud_id: &str, cloud_id: &str,
config: &HazeConfig, config: &HazeConfig,
) -> Result<Vec<String>> { ) -> Result<Vec<String>> {
let container = &self.container_name(cloud_id); let container = &self.container_name(cloud_id).unwrap();
let info = docker let info = docker
.inspect_container(container, None) .inspect_container(container, None)
.await .await

View file

@ -27,11 +27,11 @@ impl ServiceTrait for OnlyOffice {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "onlyoffice/documentserver"; let image = "onlyoffice/documentserver";
pull_image(docker, image).await?; pull_image(docker, image).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id), name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
}); });
let config = Config { let config = Config {
@ -63,11 +63,11 @@ impl ServiceTrait for OnlyOffice {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-onlyoffice", cloud_id) Some(format!("{}-onlyoffice", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {
@ -81,7 +81,7 @@ impl ServiceTrait for OnlyOffice {
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<Vec<String>> { ) -> Result<Vec<String>> {
let info = docker let info = docker
.inspect_container(&self.container_name(cloud_id), None) .inspect_container(&self.container_name(cloud_id).unwrap(), None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
let ip = if matches!( let ip = if matches!(

View file

@ -26,11 +26,11 @@ impl ServiceTrait for NotifyPush {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
config: &HazeConfig, config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "icewind1991/notify_push"; let image = "icewind1991/notify_push";
pull_image(docker, image).await?; pull_image(docker, image).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id), name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
}); });
let config = Config { let config = Config {
@ -68,11 +68,11 @@ impl ServiceTrait for NotifyPush {
.await .await
.into_diagnostic()? .into_diagnostic()?
.id; .id;
Ok(id) Ok(Some(id))
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-push", cloud_id) Some(format!("{}-push", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {
@ -89,10 +89,10 @@ impl ServiceTrait for NotifyPush {
cloud_id: &str, cloud_id: &str,
config: &HazeConfig, config: &HazeConfig,
) -> Result<Vec<String>> { ) -> Result<Vec<String>> {
let ip = self.get_ip(docker, cloud_id).await?; let ip = self.get_ip(docker, cloud_id).await?.unwrap();
let addr = config let addr = config
.proxy .proxy
.addr_with_port(&self.container_name(cloud_id), ip, 7867); .addr_with_port(&self.container_name(cloud_id).unwrap(), ip, 7867);
Ok(vec![ Ok(vec![
format!("occ config:system:set trusted_proxies 1 --value {}", ip), format!("occ config:system:set trusted_proxies 1 --value {}", ip),
format!("occ notify_push:setup {}", addr), format!("occ notify_push:setup {}", addr),

View file

@ -23,11 +23,11 @@ impl ServiceTrait for Sftp {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "atmoz/sftp:alpine"; let image = "atmoz/sftp:alpine";
pull_image(docker, image).await?; pull_image(docker, image).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id), name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
}); });
let config = Config { let config = Config {
@ -60,11 +60,11 @@ impl ServiceTrait for Sftp {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-sftp", cloud_id) Some(format!("{}-sftp", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {

View file

@ -23,11 +23,11 @@ impl ServiceTrait for Smb {
cloud_id: &str, cloud_id: &str,
network: &str, network: &str,
_config: &HazeConfig, _config: &HazeConfig,
) -> Result<String> { ) -> Result<Option<String>> {
let image = "servercontainers/samba"; let image = "servercontainers/samba";
pull_image(docker, image).await?; pull_image(docker, image).await?;
let options = Some(CreateContainerOptions { let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id), name: self.container_name(cloud_id).unwrap(),
..CreateContainerOptions::default() ..CreateContainerOptions::default()
}); });
let config = Config { let config = Config {
@ -64,11 +64,11 @@ impl ServiceTrait for Smb {
.start_container::<String>(&id, None) .start_container::<String>(&id, None)
.await .await
.into_diagnostic()?; .into_diagnostic()?;
Ok(id) Ok(Some(id))
} }
fn container_name(&self, cloud_id: &str) -> String { fn container_name(&self, cloud_id: &str) -> Option<String> {
format!("{}-smb", cloud_id) Some(format!("{}-smb", cloud_id))
} }
fn apps(&self) -> &'static [&'static str] { fn apps(&self) -> &'static [&'static str] {