use std::sync::{Arc,RwLock};
use std::path::Path;
use crate::connection::command::cmd_info;
use crate::tasks::{TaskRequest,TaskRequestType,TaskResponse};
use crate::inventory::hosts::Host;
use crate::playbooks::traversal::RunState;
use crate::tasks::cmd_library::screen_general_input_loose;
use crate::handle::handle::CheckRc;
use crate::handle::response::Response;
use crate::connection::command::Forward;
pub struct Local {
run_state: Arc<RunState>,
_host: Arc<RwLock<Host>>,
response: Arc<Response>,
}
impl Local {
pub fn new(run_state_handle: Arc<RunState>, host_handle: Arc<RwLock<Host>>, response:Arc<Response>) -> Self {
Self {
run_state: run_state_handle,
_host: host_handle,
response: response
}
}
pub fn get_localhost(&self) -> Arc<RwLock<Host>> {
let inventory = self.run_state.inventory.read().unwrap();
return inventory.get_host(&String::from("localhost"));
}
fn unwrap_string_result(&self, request: &Arc<TaskRequest>, str_result: &Result<String,String>) -> Result<String, Arc<TaskResponse>> {
return match str_result {
Ok(x) => Ok(x.clone()),
Err(y) => Err(self.response.is_failed(request, &y.clone()))
};
}
fn run(&self, request: &Arc<TaskRequest>, cmd: &String, check_rc: CheckRc) -> Result<Arc<TaskResponse>,Arc<TaskResponse>> {
assert!(request.request_type == TaskRequestType::Query, "local commands can only be run in query stage (was: {:?})", request.request_type);
match screen_general_input_loose(&cmd) {
Ok(_x) => {},
Err(y) => return Err(self.response.is_failed(request, &y.clone()))
}
let ctx = &self.run_state.context;
let local_result = self.run_state.connection_factory.read().unwrap().get_local_connection(&ctx);
let local_conn = match local_result {
Ok(x) => x,
Err(y) => { return Err(self.response.is_failed(request, &y.clone())) }
};
let result = local_conn.lock().unwrap().run_command(&self.response, request, cmd, Forward::No);
if check_rc == CheckRc::Checked {
if result.is_ok() {
let ok_result = result.as_ref().unwrap();
let cmd_result = ok_result.command_result.as_ref().as_ref().unwrap();
if cmd_result.rc != 0 {
return Err(self.response.command_failed(request, &Arc::new(Some(cmd_result.clone()))));
}
}
}
return result;
}
pub fn read_file(&self, request: &Arc<TaskRequest>, path: &Path) -> Result<String, Arc<TaskResponse>> {
return match crate::util::io::read_local_file(path) {
Ok(s) => Ok(s),
Err(x) => Err(self.response.is_failed(request, &x.clone()))
};
}
fn internal_sha512(&self, request: &Arc<TaskRequest>, path: &String) -> Result<String,Arc<TaskResponse>> {
let localhost = self.get_localhost();
let os_type = localhost.read().unwrap().os_type.expect("unable to detect host OS type");
let get_cmd_result = crate::tasks::cmd_library::get_sha512_command(os_type, path);
let cmd = self.unwrap_string_result(&request, &get_cmd_result)?;
let result = self.run(request, &cmd, CheckRc::Unchecked)?;
let (rc, out) = cmd_info(&result);
match rc {
0 => {
let value = out.split_whitespace().nth(0).unwrap().to_string();
return Ok(value);
},
127 => {
return Ok(String::from(""))
},
_ => {
return Err(self.response.is_failed(request, &format!("checksum failed: {}. {}", path, out)));
}
};
}
pub fn get_sha512(&self, request: &Arc<TaskRequest>, path: &Path, use_cache: bool) -> Result<String,Arc<TaskResponse>> {
let path2 = format!("{}", path.display());
let localhost = self.get_localhost();
if use_cache {
let ctx = self.run_state.context.read().unwrap();
let task_id = ctx.get_task_count();
let mut localhost2 = localhost.write().unwrap();
let cached = localhost2.get_checksum_cache(task_id, &path2);
if cached.is_some() {
return Ok(cached.unwrap());
}
}
let value = self.internal_sha512(request, &path2)?;
if use_cache {
let mut localhost2 = localhost.write().unwrap();
localhost2.set_checksum_cache(&path2, &value);
}
return Ok(value);
}
}