use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use std::collections::{BTreeMap, HashMap};
pub type ModuleArgs = HashMap<String, ArgumentValue>;
#[derive(Clone, Serialize, Deserialize)]
struct ExitJson {
changed: bool,
failed: bool,
#[serde(flatten)]
result: BTreeMap<String, Value>,
}
#[derive(Clone, Serialize, Deserialize)]
struct FailJson {
msg: String,
changed: bool,
failed: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct InternalArgs {
#[serde(default)]
#[serde(rename(deserialize = "_ansible_no_log"))]
pub no_log: bool,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_debug"))]
pub debug: bool,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_check_mode"))]
pub check_mode: bool,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_diff"))]
pub diff: bool,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_verbosity"))]
pub verbosity: u8,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_socket"))]
pub socket: Option<String>,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_target_log_info"))]
pub target_log_info: Option<String>,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_ignore_unknown_opts"))]
pub ignore_unknown_opts: bool,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_keep_remote_files"))]
pub keep_remote_files: bool,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_string_conversion_action"))]
pub string_conversion_action: Option<String>,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_version"))]
pub version: Option<String>,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_module_name"))]
pub module_name: Option<String>,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_syslog_facility"))]
pub syslog_facility: Option<String>,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_selinux_special_fs"))]
pub selinux_special_fs: Vec<String>,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_shell_executable"))]
pub shell_executable: Option<String>,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_tmpdir"))]
pub tmpdir: Option<String>,
#[serde(default)]
#[serde(rename(deserialize = "_ansible_remote_tmp"))]
pub remote_tmp: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArgumentValue {
pub value: Value,
pub(crate) no_log: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AnsibleModule {
pub params: ModuleArgs,
pub internal_params: InternalArgs,
}
impl AnsibleModule {
pub fn exit_json(self, result: &BTreeMap<String, Value>, changed: bool) -> ! {
let result: BTreeMap<String, Value> = result
.iter()
.map(|(k, v)| {
let val: Value = if let Some(arg_val) = self.params.get(k) {
if arg_val.no_log {
json!("VALUE_SPECIFIED_IN_NO_LOG_PARAMETER")
} else {
v.clone()
}
} else {
v.clone()
};
(k.clone(), val)
})
.collect();
let result: String = serde_json::to_string(&ExitJson {
result,
changed,
failed: false,
})
.unwrap();
println!("{result}");
#[cfg(test)]
panic!("{result}");
#[cfg(not(test))]
std::process::exit(0);
}
pub fn fail_json(msg: String) -> ! {
let result: String = serde_json::to_string(&FailJson {
msg,
changed: false,
failed: true,
})
.unwrap();
println!("{result}");
#[cfg(test)]
panic!("{result}");
#[cfg(not(test))]
std::process::exit(0);
}
}