Add example user creation script and execution logic

init-main
trivernis 2 years ago
parent 9db6b249c3
commit a1b8750a8e
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

1
.gitignore vendored

@ -10,3 +10,4 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
.env

9
Cargo.lock generated

@ -658,6 +658,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]]
name = "dtparse"
version = "1.3.0"
@ -3277,6 +3283,7 @@ version = "0.1.0"
dependencies = [
"clap",
"color-eyre",
"dotenv",
"lazy_static",
"miette 5.3.0",
"nu-cli",
@ -3284,6 +3291,8 @@ dependencies = [
"nu-engine",
"nu-parser",
"nu-protocol",
"serde",
"serde_json",
"thiserror",
"tokio",
"tracing",

@ -15,6 +15,7 @@ path = "src/main.rs"
[dependencies]
clap = "3.2.22"
color-eyre = "0.6.2"
dotenv = "0.15.0"
lazy_static = "1.4.0"
miette = "5.3.0"
nu-cli = "0.68.1"
@ -22,6 +23,8 @@ nu-command = "0.68.1"
nu-engine = "0.68.1"
nu-parser = "0.68.1"
nu-protocol = "0.68.1"
serde = { version = "1.0.144", features = ["derive"] }
serde_json = "1.0.85"
thiserror = "1.0.35"
tokio = { version = "1.21.1", features = ["rt", "io-std", "io-util", "process", "time", "macros", "tracing", "fs"] }
tracing = "0.1.36"

@ -0,0 +1,9 @@
def main [cfg] {
$cfg | get users | each {|$it| create_user $it } | ignore
}
def create_user [user] {
echo "This would create a user with:"
echo $user
echo
}

@ -14,11 +14,15 @@ pub enum AppError {
#[error("Could not find the script file {0}")]
ScriptNotFound(PathBuf),
#[diagnostic()]
#[error("Could not parse the source file {0}")]
ParseError(#[from] nu_parser::ParseError),
#[error("Could not find the main mehod in the script file {0}")]
MissingMain(PathBuf),
#[error("Failed to execute script")]
FailedToExecuteScript,
}
impl From<miette::Error> for AppError {

@ -1,40 +1,29 @@
use error::AppResult;
use scripting::{
loader::ScriptLoader,
script::{Script, ScriptArgs},
};
use scripting::{loader::ScriptLoader, script::JSONArgs};
use tasks::{SetupUsersScript, UsersConfig};
pub mod error;
pub(crate) mod scripting;
pub mod tasks;
pub(crate) mod utils;
pub struct TestScript;
impl Script for TestScript {
type Args = TestScriptArgs;
fn get_name() -> &'static str {
"test.nu"
}
}
pub struct TestScriptArgs {
pub msg: String,
pub struct TaskExecutor {
loader: ScriptLoader,
}
impl ScriptArgs for TestScriptArgs {
fn get_args(self) -> Vec<String> {
vec![self.msg]
impl TaskExecutor {
pub fn new() -> Self {
Self {
loader: ScriptLoader::new(),
}
}
}
pub async fn test_execute() -> AppResult<()> {
let loader = ScriptLoader::new();
let test_script = loader.load::<TestScript>()?;
test_script
.execute(TestScriptArgs {
msg: "'Hello World'".to_string(),
})
.await
/// Sets up user accounts
#[tracing::instrument(level = "debug", skip(self))]
pub async fn setup_users(&self, users_cfg: UsersConfig) -> AppResult<()> {
self.loader
.load::<SetupUsersScript>()?
.execute(JSONArgs(users_cfg))
.await
}
}

@ -1,5 +1,28 @@
use tourmaline::{
tasks::{User, UsersConfig},
TaskExecutor,
};
#[tokio::main(flavor = "current_thread")]
async fn main() {
color_eyre::install().unwrap();
tourmaline::test_execute().await.unwrap();
dotenv::dotenv().unwrap();
let executor = TaskExecutor::new();
let user_cfg = UsersConfig {
users: vec![
User {
name: String::from("test"),
password: String::from("password"),
sudoer: false,
shell: String::from("/bin/zsh"),
},
User {
name: String::from("test2"),
password: String::from("superpassword"),
sudoer: true,
shell: String::from("/bin/nu"),
},
],
};
executor.setup_users(user_cfg).await.unwrap();
}

@ -99,15 +99,20 @@ impl NuExecutor {
tokio::task::spawn_blocking(move || {
// TODO: Create the AST for the call here instead of parsing it from a string
let args = format!("main {}", args.join(" "));
nu_cli::eval_source(
if !nu_cli::eval_source(
&mut engine_state,
&mut stack,
args.as_bytes(),
"<commandline>",
PipelineData::new(Span::new(0, 0)),
);
) {
Err(AppError::FailedToExecuteScript)
} else {
Ok(())
}
})
.await;
.await
.unwrap()?;
Ok(())
}

@ -1,3 +1,4 @@
use serde::Serialize;
use std::{marker::PhantomData, path::PathBuf};
use crate::error::AppResult;
@ -48,3 +49,17 @@ impl<S: Script> NuScript<S> {
.await
}
}
pub struct JSONArgs<T: Serialize>(pub T);
impl<T: Serialize> ScriptArgs for JSONArgs<T> {
fn get_args(self) -> Vec<String> {
// TODO: Make this lesss... weird
// Maybe try providing the value directly in the executor
// instead of parsing and wrapping it
vec![format!(
"('{}' | from json)",
serde_json::to_string(&self.0).unwrap()
)]
}
}

@ -0,0 +1,15 @@
mod configure_locale;
mod configure_network;
mod create_partitions;
mod install_base;
mod install_bootloader;
mod install_desktop;
mod setup_users;
pub use configure_locale::*;
pub use configure_network::*;
pub use create_partitions::*;
pub use install_base::*;
pub use install_bootloader::*;
pub use install_desktop::*;
pub use setup_users::*;

@ -0,0 +1,26 @@
use serde::Serialize;
use crate::scripting::script::{JSONArgs, Script};
pub struct SetupUsersScript;
#[derive(Clone, Debug, Serialize)]
pub struct UsersConfig {
pub users: Vec<User>,
}
#[derive(Clone, Debug, Serialize)]
pub struct User {
pub name: String,
pub password: String,
pub sudoer: bool,
pub shell: String,
}
impl Script for SetupUsersScript {
type Args = JSONArgs<UsersConfig>;
fn get_name() -> &'static str {
"setup-users.nu"
}
}

@ -1,8 +1,8 @@
use std::path::PathBuf;
use std::{env, path::PathBuf};
const CONFIG_DIR: &str = "/etc";
const DEFAULT_CONFIG_DIR: &str = "/etc";
lazy_static::lazy_static! {
pub static ref CFG_PATH: PathBuf = PathBuf::from(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");
}

Loading…
Cancel
Save