mod assert;
mod block;
mod command;
mod copy;
mod dconf;
mod debug;
mod file;
pub mod find;
mod get_url;
mod group;
mod include;
mod lineinfile;
mod pacman;
mod set_vars;
mod setup;
mod systemd;
mod template;
mod uri;
mod user;
use crate::context::GlobalParams;
use crate::error::{Error, ErrorKind, Result};
use crate::modules::assert::Assert;
use crate::modules::block::Block;
use crate::modules::command::Command;
use crate::modules::copy::Copy;
use crate::modules::dconf::Dconf;
use crate::modules::debug::Debug;
use crate::modules::file::File;
use crate::modules::find::Find;
use crate::modules::get_url::GetUrl;
use crate::modules::group::Group;
use crate::modules::include::Include;
use crate::modules::lineinfile::Lineinfile;
use crate::modules::pacman::Pacman;
use crate::modules::set_vars::SetVars;
use crate::modules::setup::Setup;
use crate::modules::systemd::Systemd;
use crate::modules::template::Template;
use crate::modules::uri::Uri;
use crate::modules::user::User;
use std::collections::HashMap;
use std::sync::LazyLock;
use minijinja::Value;
#[cfg(feature = "docs")]
use schemars::Schema;
use serde::{Deserialize, Serialize};
use serde_norway::Value as YamlValue;
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct ModuleResult {
changed: bool,
output: Option<String>,
extra: Option<YamlValue>,
}
impl ModuleResult {
pub fn new(changed: bool, extra: Option<YamlValue>, output: Option<String>) -> Self {
Self {
changed,
extra,
output,
}
}
pub fn get_changed(&self) -> bool {
self.changed
}
pub fn get_extra(&self) -> Option<YamlValue> {
self.extra.clone()
}
pub fn get_output(&self) -> Option<String> {
self.output.clone()
}
}
pub trait Module: Send + Sync + std::fmt::Debug {
fn get_name(&self) -> &str;
fn exec(
&self,
global_params: &GlobalParams,
params: YamlValue,
vars: &Value,
check_mode: bool,
) -> Result<(ModuleResult, Option<Value>)>;
fn force_string_on_params(&self) -> bool {
true
}
#[cfg(feature = "docs")]
fn get_json_schema(&self) -> Option<Schema>;
}
pub static MODULES: LazyLock<HashMap<&'static str, Box<dyn Module>>> = LazyLock::new(|| {
vec![
(Assert.get_name(), Box::new(Assert) as Box<dyn Module>),
(Block.get_name(), Box::new(Block) as Box<dyn Module>),
(Command.get_name(), Box::new(Command) as Box<dyn Module>),
(Copy.get_name(), Box::new(Copy) as Box<dyn Module>),
(Dconf.get_name(), Box::new(Dconf) as Box<dyn Module>),
(Debug.get_name(), Box::new(Debug) as Box<dyn Module>),
(File.get_name(), Box::new(File) as Box<dyn Module>),
(Find.get_name(), Box::new(Find) as Box<dyn Module>),
(GetUrl.get_name(), Box::new(GetUrl) as Box<dyn Module>),
(Group.get_name(), Box::new(Group) as Box<dyn Module>),
(Include.get_name(), Box::new(Include) as Box<dyn Module>),
(
Lineinfile.get_name(),
Box::new(Lineinfile) as Box<dyn Module>,
),
(Pacman.get_name(), Box::new(Pacman) as Box<dyn Module>),
(SetVars.get_name(), Box::new(SetVars) as Box<dyn Module>),
(Setup.get_name(), Box::new(Setup) as Box<dyn Module>),
(Systemd.get_name(), Box::new(Systemd) as Box<dyn Module>),
(Template.get_name(), Box::new(Template) as Box<dyn Module>),
(Uri.get_name(), Box::new(Uri) as Box<dyn Module>),
(User.get_name(), Box::new(User) as Box<dyn Module>),
]
.into_iter()
.collect()
});
#[inline(always)]
pub fn is_module(module: &str) -> bool {
MODULES.get(module).is_some()
}
#[inline(always)]
pub fn parse_params<P>(yaml: YamlValue) -> Result<P>
where
for<'a> P: Deserialize<'a>,
{
trace!("parse params: {yaml:?}");
serde_norway::from_value(yaml).map_err(|e| Error::new(ErrorKind::InvalidData, e))
}
#[inline(always)]
pub fn parse_if_json(v: Vec<String>) -> Vec<String> {
v.into_iter()
.flat_map(|s| serde_json::from_str(&s).unwrap_or_else(|_| vec![s]))
.collect::<Vec<String>>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_if_json() {
let vec_string = parse_if_json(vec![
r#"["yea", "foo", "boo"]"#.to_owned(),
r#"["fuu", "buu"]"#.to_owned(),
"yuu".to_owned(),
]);
assert_eq!(
vec_string,
vec![
"yea".to_owned(),
"foo".to_owned(),
"boo".to_owned(),
"fuu".to_owned(),
"buu".to_owned(),
"yuu".to_owned()
]
)
}
}