Add config and improve variable handling

Signed-off-by: trivernis <trivernis@protonmail.com>
integration-not-installation
trivernis 2 years ago
parent 662d3f749c
commit bf2f0a5b83
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -0,0 +1,15 @@
use serde::Serialize;
use crate::tasks::{
BootloaderConfig, DesktopConfig, LocaleConfig, NetworkConfig, PartitionsConfig, UsersConfig,
};
#[derive(Clone, Debug, Serialize)]
pub struct Config {
pub local: LocaleConfig,
pub network: NetworkConfig,
pub partitions: PartitionsConfig,
pub bootloader: BootloaderConfig,
pub desktop: DesktopConfig,
pub users: UsersConfig,
}

@ -2,6 +2,7 @@ use error::AppResult;
use scripting::{loader::ScriptLoader, script::Script}; use scripting::{loader::ScriptLoader, script::Script};
use tasks::*; use tasks::*;
pub mod config;
pub mod error; pub mod error;
pub(crate) mod scripting; pub(crate) mod scripting;
pub mod tasks; pub mod tasks;
@ -15,7 +16,7 @@ macro_rules! tasks {
($($function:ident => $script:ident),+) => { ($($function:ident => $script:ident),+) => {
$( $(
#[tracing::instrument(level = "trace", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
pub async fn $function(&self, cfg: <$script as crate::scripting::script::Script>::Args) -> AppResult<()> { pub async fn $function(&self, cfg: &<$script as crate::scripting::script::Script>::Args) -> AppResult<()> {
self.execute::<$script>(cfg).await self.execute::<$script>(cfg).await
} }
)+ )+
@ -34,8 +35,8 @@ impl TaskExecutor {
); );
#[inline] #[inline]
async fn execute<S: Script>(&self, args: S::Args) -> AppResult<()> { async fn execute<S: Script>(&self, args: &S::Args) -> AppResult<()> {
self.loader.load::<S>()?.execute(args).await self.loader.load::<S>()?.execute(&args).await
} }
} }

@ -24,7 +24,7 @@ async fn main() -> miette::Result<()> {
}, },
], ],
}; };
executor.setup_users(user_cfg).await?; executor.setup_users(&user_cfg).await?;
Ok(()) Ok(())
} }

@ -19,25 +19,11 @@ use crate::error::{AppError, AppResult};
use super::record::RecordValue; use super::record::RecordValue;
#[derive(Clone, Debug)]
pub enum VarValue {
String(String),
Integer(i64),
Float(f64),
Boolean(bool),
}
impl VarValue {
pub fn string<S: ToString>(s: S) -> Self {
Self::String(s.to_string())
}
}
/// An executor for nu scripts /// An executor for nu scripts
pub struct NuExecutor { pub struct NuExecutor {
script_path: PathBuf, script_path: PathBuf,
args: Vec<RecordValue>, args: Vec<RecordValue>,
global_vars: HashMap<String, VarValue>, global_vars: HashMap<String, RecordValue>,
} }
impl NuExecutor { impl NuExecutor {
@ -67,7 +53,7 @@ impl NuExecutor {
/// Adds a global variable to the executor which can /// Adds a global variable to the executor which can
/// be accessed from within the script /// be accessed from within the script
pub fn add_global_var<S: ToString>(&mut self, name: S, value: VarValue) -> &mut Self { pub fn add_global_var<S: ToString>(&mut self, name: S, value: RecordValue) -> &mut Self {
self.global_vars.insert(name.to_string(), value); self.global_vars.insert(name.to_string(), value);
self self
@ -85,7 +71,7 @@ impl NuExecutor {
let vars = mem::take(&mut self.global_vars); let vars = mem::take(&mut self.global_vars);
let vars = vars let vars = vars
.into_iter() .into_iter()
.map(|(k, v)| (k, map_var_to_value(v))) .map(|(k, v)| (k, v.into_protocol_value()))
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
add_variables_to_state(vars, &mut engine_state, &mut stack); add_variables_to_state(vars, &mut engine_state, &mut stack);
@ -226,14 +212,3 @@ fn create_call(decl_id: DeclId, args: Vec<RecordValue>) -> Block {
fn empty_pipeline() -> PipelineData { fn empty_pipeline() -> PipelineData {
PipelineData::new(Span::new(0, 0)) PipelineData::new(Span::new(0, 0))
} }
fn map_var_to_value(var: VarValue) -> Value {
let span = Span::new(0, 0);
match var {
VarValue::String(val) => Value::String { val, span },
VarValue::Integer(val) => Value::Int { val, span },
VarValue::Float(val) => Value::Float { val, span },
VarValue::Boolean(val) => Value::Bool { val, span },
}
}

@ -2,7 +2,7 @@ use std::{borrow::Cow, collections::HashMap};
use nu_protocol::{ use nu_protocol::{
ast::{Expr, Expression}, ast::{Expr, Expression},
Span, Type, Span, Type, Value,
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -18,6 +18,7 @@ pub enum RecordValue {
} }
impl RecordValue { impl RecordValue {
/// Creates an expresion for this value
pub fn into_expr(self) -> Expr { pub fn into_expr(self) -> Expr {
match self { match self {
RecordValue::Int(i) => Expr::Int(i), RecordValue::Int(i) => Expr::Int(i),
@ -37,6 +38,7 @@ impl RecordValue {
} }
} }
/// Creates a new wrapped expression for this value
pub fn into_expression(self) -> Expression { pub fn into_expression(self) -> Expression {
let nu_type = self.get_type(); let nu_type = self.get_type();
let expr = self.into_expr(); let expr = self.into_expr();
@ -49,6 +51,37 @@ impl RecordValue {
} }
} }
/// Creates a nu protocol value from this value
pub fn into_protocol_value(self) -> Value {
let span = Span::new(0, 0);
match self {
RecordValue::Int(val) => Value::Int { val, span },
RecordValue::Float(val) => Value::Float { val, span },
RecordValue::String(val) => Value::String { val, span },
RecordValue::Bytes(val) => Value::Binary { val, span },
RecordValue::Boolean(val) => Value::Bool { val, span },
RecordValue::Null => Value::Nothing { span },
RecordValue::Map(m) => {
let mut cols = Vec::new();
let mut vals = Vec::new();
for (key, val) in m {
cols.push(key.to_string());
vals.push(val.into_protocol_value());
}
Value::Record { cols, vals, span }
}
RecordValue::List(l) => Value::List {
vals: l
.into_iter()
.map(RecordValue::into_protocol_value)
.collect(),
span,
},
}
}
/// Returns the type of this value
fn get_type(&self) -> Type { fn get_type(&self) -> Type {
match &self { match &self {
RecordValue::Int(_) => Type::Int, RecordValue::Int(_) => Type::Int,

@ -5,11 +5,7 @@ use serde::Serialize;
use crate::error::AppResult; use crate::error::AppResult;
use super::{ use super::{executor::NuExecutor, record::RecordValue, record_serializer::RecordSerializer};
executor::{NuExecutor, VarValue},
record::RecordValue,
record_serializer::RecordSerializer,
};
/// A trait implemented for a given nu script type to /// A trait implemented for a given nu script type to
/// associate arguments /// associate arguments
@ -20,16 +16,24 @@ pub trait Script {
/// This function is used by the loader to load the associated file /// This function is used by the loader to load the associated file
/// The name needs to include the file extension /// The name needs to include the file extension
fn get_name() -> &'static str; fn get_name() -> &'static str;
/// Returns the name of the script file that get's executed before
/// the actual script. This has to be the full file name including the extension.
fn get_pre_hook() -> &'static str;
/// Returns the name of the script file that get's executed after
/// the actual script. This has to be the full file name including the extension.
fn get_post_hook() -> &'static str;
} }
/// Script arguments that can be collected in a Vec to /// Script arguments that can be collected in a Vec to
/// be passed to the script /// be passed to the script
pub trait ScriptArgs { pub trait ScriptArgs {
fn get_args(self) -> Vec<RecordValue>; fn get_args(&self) -> Vec<RecordValue>;
} }
impl<T: Serialize> ScriptArgs for T { impl<T: Serialize> ScriptArgs for T {
fn get_args(self) -> Vec<RecordValue> { fn get_args(&self) -> Vec<RecordValue> {
let mut serializer = RecordSerializer::default(); let mut serializer = RecordSerializer::default();
let val = self.serialize(&mut serializer).unwrap(); let val = self.serialize(&mut serializer).unwrap();
match val { match val {
@ -55,19 +59,17 @@ impl<S: Script> NuScript<S> {
/// Executes the script with the given args /// Executes the script with the given args
#[tracing::instrument(level = "trace", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
pub async fn execute(&self, args: S::Args) -> AppResult<()> { pub async fn execute(&self, args: &S::Args) -> AppResult<()> {
NuExecutor::new(&self.path) NuExecutor::new(&self.path)
.add_args(args.get_args()) .add_args(args.get_args())
.add_global_var("BY_TOURMALINE", VarValue::string("Hello from Tourmaline!"))
.add_global_var(
"ANOTHER_ONE",
VarValue::string("This variable was provided by tourmaline"),
)
.execute() .execute()
.await .await
} }
} }
/// Defines a script
/// This macro doesn't accept a file extension for the script name
/// as it is reused for the hook name
#[macro_export] #[macro_export]
macro_rules! script { macro_rules! script {
($script:ident { ($script:ident {
@ -80,7 +82,15 @@ macro_rules! script {
type Args = $argtype; type Args = $argtype;
fn get_name() -> &'static str { fn get_name() -> &'static str {
$name concat!($name, ".nu")
}
fn get_pre_hook() -> &'static str {
concat!("name", ".pre.nu")
}
fn get_post_hook() -> &'static str {
concat!("name", ".post.nu")
} }
} }
}; };

@ -3,7 +3,7 @@ use serde::Serialize;
use crate::script; use crate::script;
script!(ConfigureLocaleScript { script!(ConfigureLocaleScript {
file = "configure-locale.nu" file = "configure-locale"
args = LocaleConfig args = LocaleConfig
}); });

@ -3,7 +3,7 @@ use serde::Serialize;
use crate::script; use crate::script;
script!(ConfigureNetworkScript { script!(ConfigureNetworkScript {
file = "configure-network.nu" file = "configure-network"
args = NetworkConfig args = NetworkConfig
}); });

@ -5,7 +5,7 @@ use serde::Serialize;
use crate::script; use crate::script;
script!(CreatePartitionsScript { script!(CreatePartitionsScript {
file = "create-partitions.nu" file = "create-partitions"
args = PartitionsConfig args = PartitionsConfig
}); });

@ -1,7 +1,7 @@
use crate::script; use crate::script;
script!(InstallBaseScript { script!(InstallBaseScript {
file = "install-base.nu" file = "install-base"
args = InstallBaseArgs args = InstallBaseArgs
}); });

@ -5,12 +5,12 @@ use serde::Serialize;
use crate::script; use crate::script;
script!(InstallBootloaderScript { script!(InstallBootloaderScript {
file = "install-bootloader.nu" file = "install-bootloader"
args = BooloaderConfig args = BootloaderConfig
}); });
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize)]
pub struct BooloaderConfig { pub struct BootloaderConfig {
preset: BootloaderPreset, preset: BootloaderPreset,
location: PathBuf, location: PathBuf,
} }

@ -3,7 +3,7 @@ use serde::Serialize;
use crate::script; use crate::script;
script!(InstallDesktopScript { script!(InstallDesktopScript {
file = "install-desktop.nu" file = "install-desktop"
args = DesktopConfig args = DesktopConfig
}); });

@ -3,7 +3,7 @@ use serde::Serialize;
use crate::script; use crate::script;
script!(SetupUsersScript { script!(SetupUsersScript {
file = "setup-users.nu" file = "setup-users"
args = UsersConfig args = UsersConfig
}); });

@ -5,4 +5,5 @@ const DEFAULT_CONFIG_DIR: &str = "/etc";
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref CFG_PATH: PathBuf = env::var("TRM_CFG_PATH").map(PathBuf::from).unwrap_or_else(|_| PathBuf::from(DEFAULT_CONFIG_DIR).join("tourmaline")); pub static ref CFG_PATH: PathBuf = env::var("TRM_CFG_PATH").map(PathBuf::from).unwrap_or_else(|_| PathBuf::from(DEFAULT_CONFIG_DIR).join("tourmaline"));
pub static ref SCRIPT_PATH: PathBuf = CFG_PATH.join("scripts"); pub static ref SCRIPT_PATH: PathBuf = CFG_PATH.join("scripts");
pub static ref HOOK_PATH: PathBuf = CFG_PATH.join("hooks");
} }

Loading…
Cancel
Save