diff --git a/ofborg/src/bin/builder.rs b/ofborg/src/bin/builder.rs index b61bb16..f6a0e4d 100644 --- a/ofborg/src/bin/builder.rs +++ b/ofborg/src/bin/builder.rs @@ -29,21 +29,15 @@ fn main() -> Result<(), Box> { }; let conn = easylapin::from_config(&cfg.rabbitmq)?; - let handle = self::create_handle(&conn, &cfg, None)?; + let mut handles = Vec::new(); - if let Some(ref additional_build_systems) = cfg.nix.additional_build_systems { - let mut handles = vec![handle]; - - for system in additional_build_systems { - let handle_ext = self::create_handle(&conn, &cfg, Some(system.to_string()))?; - handles.push(handle_ext); - } - - task::block_on(future::join_all(handles)); - } else { - task::block_on(handle); + for system in &cfg.nix.system { + let handle_ext = self::create_handle(&conn, &cfg, system.to_string())?; + handles.push(handle_ext); } + task::block_on(future::join_all(handles)); + drop(conn); // Close connection. info!("Closed the session... EOF"); Ok(()) @@ -52,17 +46,12 @@ fn main() -> Result<(), Box> { fn create_handle( conn: &lapin::Connection, cfg: &config::Config, - system_override: Option, + system: String, ) -> Result, Box> { let mut chan = task::block_on(conn.create_channel())?; let cloner = checkout::cached_cloner(Path::new(&cfg.checkout.root)); - let nix = if let Some(system) = system_override { - cfg.nix().with_system(String::from(system)) - } else { - cfg.nix() - }; - let system = nix.system.clone(); + let nix = cfg.nix().with_system(system.clone()); chan.declare_exchange(easyamqp::ExchangeConfig { exchange: "build-jobs".to_owned(), diff --git a/ofborg/src/config.rs b/ofborg/src/config.rs index 7e93ef2..8fd791e 100644 --- a/ofborg/src/config.rs +++ b/ofborg/src/config.rs @@ -2,14 +2,17 @@ use crate::acl; use crate::nix::Nix; use std::collections::HashMap; +use std::fmt; use std::fs::File; use std::io::Read; +use std::marker::PhantomData; use std::path::{Path, PathBuf}; use hubcaps::{Credentials, Github, InstallationTokenGenerator, JWTCredentials}; use hyper::net::HttpsConnector; use hyper::Client; use hyper_native_tls::NativeTlsClient; +use serde::de::{self, Deserialize, Deserializer}; use tracing::{debug, error, info, warn}; #[derive(Serialize, Deserialize, Debug)] @@ -40,8 +43,8 @@ pub struct RabbitMqConfig { #[derive(Serialize, Deserialize, Debug)] pub struct NixConfig { - pub system: String, - pub additional_build_systems: Option>, + #[serde(deserialize_with = "deserialize_one_or_many")] + pub system: Vec, pub remote: String, pub build_timeout_seconds: u16, pub initial_heap_size: Option, @@ -88,7 +91,7 @@ pub struct CheckoutConfig { impl Config { pub fn whoami(&self) -> String { - format!("{}-{}", self.runner.identity, self.nix.system) + format!("{}-{}", self.runner.identity, self.nix.system.join(",")) } pub fn acl(&self) -> acl::Acl { @@ -136,7 +139,11 @@ impl Config { } Nix::new( - self.nix.system.clone(), + self.nix + .system + .first() + .expect("expected at least one system") + .clone(), self.nix.remote.clone(), self.nix.build_timeout_seconds, self.nix.initial_heap_size.clone(), @@ -224,3 +231,35 @@ impl GithubAppVendingMachine { })) } } + +// Copied from https://stackoverflow.com/a/43627388 +fn deserialize_one_or_many<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + struct StringOrVec(PhantomData>); + + impl<'de> de::Visitor<'de> for StringOrVec { + type Value = Vec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("string or list of strings") + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + Ok(vec![value.to_owned()]) + } + + fn visit_seq(self, visitor: S) -> Result + where + S: de::SeqAccess<'de>, + { + Deserialize::deserialize(de::value::SeqAccessDeserializer::new(visitor)) + } + } + + deserializer.deserialize_any(StringOrVec(PhantomData)) +}