Skip to content

Commit

Permalink
fix: pass config file to ssh and handle multiple config files
Browse files Browse the repository at this point in the history
Signed-off-by: Nathanael DEMACON <[email protected]>
  • Loading branch information
quantumsheep committed Mar 29, 2024
1 parent 116cb8d commit 3fc0415
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 6 deletions.
53 changes: 51 additions & 2 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ itertools = "0.12.1"
ratatui = "0.26.1"
regex = { version = "1.10.3", default-features = false, features = ["std"] }
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115"
shellexpand = "3.1.0"
shlex = "1.3.0"
strum = "0.26.1"
strum_macros = "0.26.1"
tempfile = "3.10.1"
tui-input = "0.8.0"
unicode-width = "0.1.11"
6 changes: 5 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ struct Args {
sort: bool,

/// Handlebars template of the command to execute
#[arg(short, long, default_value = "ssh \"{{{name}}}\"")]
#[arg(
short,
long,
default_value = "ssh \"{{{name}}}\" -F \"{{{config_file}}}\""
)]
template: String,

/// Exit after ending the SSH session
Expand Down
43 changes: 41 additions & 2 deletions src/ssh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ use anyhow::anyhow;
use handlebars::Handlebars;
use itertools::Itertools;
use serde::Serialize;
use serde_json::json;
use std::collections::VecDeque;
use std::process::Command;
use tempfile::NamedTempFile;

use crate::ssh_config::{self, parser_error::ParseError, HostVecExt};

Expand All @@ -27,9 +29,29 @@ impl Host {
/// # Panics
///
/// Will panic if the regex cannot be compiled.
pub fn run_command_template(&self, pattern: &str) -> anyhow::Result<()> {
pub fn run_command_template<'a>(
&self,
pattern: &str,
config_paths: &Vec<String>,
) -> anyhow::Result<()> {
let handlebars = Handlebars::new();
let rendered_command = handlebars.render_template(pattern, &self)?;

let mut temp_file = None;

let mut template_data = json!(&self);
template_data["config_file"] = match config_paths.len() {
1 => json!(config_paths[0]),
_ => {
let new_temp_file = single_config_file(config_paths)?;
let temp_file_path = new_temp_file.path().to_str().unwrap().to_string();

temp_file = Some(new_temp_file);

json!(temp_file_path)
}
};

let rendered_command = handlebars.render_template(pattern, &template_data)?;

println!("Running command: {rendered_command}");

Expand All @@ -40,6 +62,8 @@ impl Host {
let command = args.pop_front().ok_or(anyhow!("Failed to get command"))?;

let status = Command::new(command).args(args).spawn()?.wait()?;
drop(temp_file);

if !status.success() {
std::process::exit(status.code().unwrap_or(1));
}
Expand All @@ -48,6 +72,21 @@ impl Host {
}
}

fn single_config_file(config_paths: &Vec<String>) -> anyhow::Result<NamedTempFile> {
let temp_file = NamedTempFile::with_prefix("sshs-")?;

// Include all config files
let includes = config_paths
.iter()
.map(|path| format!("Include {}", path))
.join("\n");

// Write to temporary file
std::fs::write(temp_file.path(), includes)?;

Ok(temp_file)
}

#[derive(Debug)]
pub enum ParseConfigError {
Io(std::io::Error),
Expand Down
5 changes: 4 additions & 1 deletion src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ impl App {

restore_terminal(terminal).expect("Failed to restore terminal");

host.run_command_template(&self.config.command_template)?;
host.run_command_template(
&self.config.command_template,
&self.config.config_paths,
)?;

setup_terminal(terminal).expect("Failed to setup terminal");

Expand Down

0 comments on commit 3fc0415

Please sign in to comment.