mirror of
https://github.com/house-of-vanity/rexec.git
synced 2025-07-08 01:04:07 +00:00
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
c699bf1849 | |||
502d206dc7 | |||
e661349034 |
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -1043,17 +1043,17 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rexec"
|
name = "rexec"
|
||||||
version = "1.0.1"
|
version = "1.0.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"brace-expand",
|
"brace-expand",
|
||||||
"clap 4.3.4",
|
"clap 4.3.4",
|
||||||
"colored",
|
"colored",
|
||||||
"dialoguer",
|
"dialoguer",
|
||||||
"dns-lookup",
|
"dns-lookup",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"itertools",
|
"itertools",
|
||||||
"lazy-st",
|
"lazy-st",
|
||||||
"log",
|
"log",
|
||||||
"massh",
|
"massh",
|
||||||
"regex",
|
"regex",
|
||||||
"whoami",
|
"whoami",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rexec"
|
name = "rexec"
|
||||||
version = "1.0.1"
|
version = "1.0.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Parallel SSH executor"
|
description = "Parallel SSH executor"
|
||||||
repository = "https://github.com/house-of-vanity/rexec"
|
repository = "https://github.com/house-of-vanity/rexec"
|
||||||
|
82
src/main.rs
82
src/main.rs
@ -1,4 +1,13 @@
|
|||||||
use brace_expand::brace_expand;
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs::read_to_string;
|
||||||
|
use std::hash::Hash;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
use std::process;
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
use colored::*;
|
use colored::*;
|
||||||
use dialoguer::Confirm;
|
use dialoguer::Confirm;
|
||||||
use dns_lookup::lookup_host;
|
use dns_lookup::lookup_host;
|
||||||
@ -7,17 +16,6 @@ use itertools::Itertools;
|
|||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use massh::{MasshClient, MasshConfig, MasshHostConfig, SshAuth};
|
use massh::{MasshClient, MasshConfig, MasshHostConfig, SshAuth};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fs::read_to_string;
|
|
||||||
use std::hash::Hash;
|
|
||||||
use std::net::IpAddr;
|
|
||||||
|
|
||||||
use std::process;
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
|
||||||
|
|
||||||
use clap::Parser;
|
|
||||||
|
|
||||||
// Define args
|
// Define args
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@ -29,7 +27,11 @@ struct Args {
|
|||||||
#[arg(short, long, help = "Use known_hosts to build servers list")]
|
#[arg(short, long, help = "Use known_hosts to build servers list")]
|
||||||
known_hosts: bool,
|
known_hosts: bool,
|
||||||
|
|
||||||
#[arg(short, long, help = "Expression to build server list")]
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
help = "Expression to build server list. List and range expansion available. Example: 'web-[1:12]-io-{prod,dev}'"
|
||||||
|
)]
|
||||||
expression: String,
|
expression: String,
|
||||||
|
|
||||||
#[arg(short, long, help = "Command to execute on servers")]
|
#[arg(short, long, help = "Command to execute on servers")]
|
||||||
@ -75,16 +77,58 @@ fn read_known_hosts() -> Vec<Host> {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_expression(expr: &str) -> Vec<Host> {
|
fn expand_string(string: String) -> Vec<Host> {
|
||||||
let mut result: Vec<Host> = Vec::new();
|
let mut result: Vec<String> = Vec::new();
|
||||||
|
let mut _result: Vec<String> = Vec::new();
|
||||||
|
let mut hosts: Vec<Host> = Vec::new();
|
||||||
|
|
||||||
for hostname in brace_expand(expr) {
|
if let Some(open_bracket_index) = string.find('[') {
|
||||||
result.push(Host {
|
if let Some(close_bracket_index) = string.find(']') {
|
||||||
|
let prefix = &string[..open_bracket_index];
|
||||||
|
let range = &string[open_bracket_index + 1..close_bracket_index];
|
||||||
|
let postfix = &string[close_bracket_index + 1..];
|
||||||
|
|
||||||
|
let parts: Vec<&str> = range.split(':').collect();
|
||||||
|
|
||||||
|
if parts.len() == 2 {
|
||||||
|
if let Ok(start) = parts[0].parse::<u32>() {
|
||||||
|
if let Ok(end) = parts[1].parse::<u32>() {
|
||||||
|
for num in start..=end {
|
||||||
|
_result.push(format!("{}{}{}", prefix, num, postfix));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_result.push(String::from(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
for string in _result {
|
||||||
|
if let Some(open_brace_index) = string.find('{') {
|
||||||
|
if let Some(close_brace_index) = string.find('}') {
|
||||||
|
let prefix = &string[..open_brace_index];
|
||||||
|
let list = &string[open_brace_index + 1..close_brace_index];
|
||||||
|
let postfix = &string[close_brace_index + 1..];
|
||||||
|
|
||||||
|
let items: Vec<&str> = list.split(',').collect();
|
||||||
|
|
||||||
|
for item in items {
|
||||||
|
result.push(format!("{}{}{}", prefix, item, postfix));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.push(String::from(string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for hostname in result {
|
||||||
|
hosts.push(Host {
|
||||||
name: hostname.to_string(),
|
name: hostname.to_string(),
|
||||||
ip: None,
|
ip: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
result
|
hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -112,7 +156,7 @@ fn main() {
|
|||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
info!("Using string expansion to build server list.");
|
info!("Using string expansion to build server list.");
|
||||||
expand_expression(&args.expression)
|
expand_string(args.expression)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dedup hosts from known_hosts file
|
// Dedup hosts from known_hosts file
|
||||||
|
Reference in New Issue
Block a user