Skip to content

Commit

Permalink
Add new function: parse_hosts_json
Browse files Browse the repository at this point in the history
  • Loading branch information
hahnavi committed Dec 17, 2024
1 parent 9aff83d commit db66574
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 3 deletions.
25 changes: 25 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ mlua = { version = "0.10.1", features = ["anyhow", "async", "luajit", "macros",
rand = "0.8.5"
regex = "1.11.1"
rustyline = "15.0.0"
serde_json = "1.0.133"
ssh2 = { version = "0.9.4", features = ["vendored-openssl"] }
tokio = { version = "1.42.0", features = ["io-std", "macros", "rt"] }
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ For detailed explanations, arguments, and examples of each module, please refer
Komandan offers built-in functions to enhance scripting capabilities:

- **`komandan.filter_hosts`**: Filters a list of hosts based on a pattern.
- **`komandan.parse_hosts_json`**: Parses a JSON file containing hosts information.
- **`komandan.set_defaults`**: Sets default values for host connection parameters.

For detailed descriptions and usage examples of these functions, please visit the [Built-in Functions section of the Komandan Documentation Site](https://komandan.vercel.app/docs/functions/).
Expand Down
15 changes: 15 additions & 0 deletions examples/parse_hosts_json.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
local hosts = komandan.parse_hosts_json("/path/to/hosts.json")

komandan.set_defaults({
user = "user1",
private_key_file = os.getenv("HOME") .. "/.ssh/id_ed25519",
})

for _, host in pairs(hosts) do
komandan.komando(host, {
name = "Create a directory",
komandan.modules.cmd({
cmd = "mkdir /tmp/newdir1",
}),
})
end
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod ssh;
mod util;
mod validator;

use util::{dprint, filter_hosts, regex_is_match};
use util::{dprint, filter_hosts, parse_hosts_json, regex_is_match};
use validator::{validate_host, validate_module, validate_task};

#[tokio::main(flavor = "current_thread")]
Expand Down Expand Up @@ -70,6 +70,7 @@ fn setup_komandan_table(lua: &Lua) -> mlua::Result<()> {
// Add utils
komandan.set("regex_is_match", lua.create_function(regex_is_match)?)?;
komandan.set("filter_hosts", lua.create_function(filter_hosts)?)?;
komandan.set("parse_hosts_json", lua.create_function(parse_hosts_json)?)?;
komandan.set("dprint", lua.create_function(dprint)?)?;

// Add core modules
Expand Down Expand Up @@ -443,6 +444,7 @@ mod tests {
assert!(komandan_table.contains_key("komando").unwrap());
assert!(komandan_table.contains_key("regex_is_match").unwrap());
assert!(komandan_table.contains_key("filter_hosts").unwrap());
assert!(komandan_table.contains_key("parse_hosts_json").unwrap());
assert!(komandan_table.contains_key("dprint").unwrap());

let modules_table = komandan_table.get::<Table>("modules").unwrap();
Expand Down
57 changes: 55 additions & 2 deletions src/util.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::args::Args;
use crate::{args::Args, validator::validate_host};
use clap::Parser;
use mlua::{chunk, Lua, Table, Value};
use mlua::{chunk, Error::RuntimeError, Lua, LuaSerdeExt, Table, Value};
use std::{fs::File, io::Read};

pub fn dprint(lua: &Lua, value: Value) -> mlua::Result<()> {
let args = Args::parse();
Expand Down Expand Up @@ -91,6 +92,58 @@ pub fn filter_hosts(lua: &Lua, (hosts, pattern): (Value, Value)) -> mlua::Result
Ok(matched_hosts)
}

pub fn parse_hosts_json(lua: &Lua, src: Value) -> mlua::Result<Table> {
let src = match src.as_string_lossy() {
Some(s) => s,
None => return Err(RuntimeError(String::from("Invalid src path"))),
};

let mut file = match File::open(&src) {
Ok(f) => f,
Err(_) => return Err(RuntimeError(String::from("Failed to open JSON file"))),
};

let mut content = String::new();
match file.read_to_string(&mut content) {
Ok(_) => (),
Err(_) => return Err(RuntimeError(String::from("Failed to read JSON file"))),
};

let json: serde_json::Value = match serde_json::from_str(&content) {
Ok(j) => j,
Err(_) => return Err(RuntimeError(String::from("Failed to parse JSON file"))),
};

let hosts = lua.create_table()?;

let lua_value = match lua.to_value(&json) {
Ok(o) => o,
Err(_) => return Err(RuntimeError(String::from("Failed to convert JSON to Lua"))),
};

let lua_table = match lua_value.as_table() {
Some(t) => t,
None => return Err(RuntimeError(String::from("JSON does not contain a table"))),
};

for pair in lua_table.pairs() {
let (_, value): (Value, Value) = pair?;
match validate_host(&lua, value) {
Ok(host) => {
hosts.set(hosts.len()? + 1, host)?;
}
Err(_) => {}
};
}

dprint(
lua,
lua.to_value(&format!("Loaded {} hosts from '{}'", hosts.len()?, src))?,
)?;

Ok(hosts)
}

pub fn regex_is_match(
_: &Lua,
(text, pattern): (mlua::String, mlua::String),
Expand Down

0 comments on commit db66574

Please sign in to comment.