Avoid derived UDP host in SSH imports
ci / test (push) Canceled after 0s
ci / fuzz-smoke (push) Canceled after 0s
ci / macos-client (macos-aarch64, macos-14) (push) Canceled after 0s
ci / macos-client (macos-x86_64, macos-13) (push) Canceled after 0s
ci / windows-client (push) Canceled after 0s
ci / package-release (linux-x86_64, ubuntu-latest, , , ) (push) Canceled after 0s
ci / package-release (macos-aarch64, macos-14, , , ) (push) Canceled after 0s
ci / package-release (macos-x86_64, macos-13, , , ) (push) Canceled after 0s
ci / package-release (windows-aarch64, windows-latest, aarch64, windows, aarch64-pc-windows-msvc) (push) Canceled after 0s
ci / package-release (windows-x86_64, windows-latest, , , ) (push) Canceled after 0s
ci / remote-bench (push) Canceled after 0s
ci / publish-gitea-release (push) Canceled after 0s
ci / test (push) Canceled after 0s
ci / fuzz-smoke (push) Canceled after 0s
ci / macos-client (macos-aarch64, macos-14) (push) Canceled after 0s
ci / macos-client (macos-x86_64, macos-13) (push) Canceled after 0s
ci / windows-client (push) Canceled after 0s
ci / package-release (linux-x86_64, ubuntu-latest, , , ) (push) Canceled after 0s
ci / package-release (macos-aarch64, macos-14, , , ) (push) Canceled after 0s
ci / package-release (macos-x86_64, macos-13, , , ) (push) Canceled after 0s
ci / package-release (windows-aarch64, windows-latest, aarch64, windows, aarch64-pc-windows-msvc) (push) Canceled after 0s
ci / package-release (windows-x86_64, windows-latest, , , ) (push) Canceled after 0s
ci / remote-bench (push) Canceled after 0s
ci / publish-gitea-release (push) Canceled after 0s
This commit is contained in:
+88
-37
@@ -752,7 +752,11 @@ async fn run_setup_command(config: &dosh::config::ClientConfig, args: &Args) ->
|
||||
match entry.action {
|
||||
ImportAction::Added => println!(
|
||||
"[ok] host config: [{}] ssh={} ssh_config={} dosh_host={} port={}",
|
||||
entry.alias, entry.ssh, entry.ssh_config, entry.dosh_host, entry.port
|
||||
entry.alias,
|
||||
entry.ssh,
|
||||
entry.ssh_config,
|
||||
imported_dosh_host_display(&entry),
|
||||
entry.port
|
||||
),
|
||||
ImportAction::Skipped => println!("[ok] host config: [{}] already exists", entry.alias),
|
||||
}
|
||||
@@ -4858,7 +4862,7 @@ struct ImportedHost {
|
||||
alias: String,
|
||||
ssh: String,
|
||||
ssh_config: String,
|
||||
dosh_host: String,
|
||||
dosh_host: Option<String>,
|
||||
port: u16,
|
||||
action: ImportAction,
|
||||
}
|
||||
@@ -4870,10 +4874,19 @@ fn run_import_ssh(config: &dosh::config::ClientConfig, aliases: &[String]) -> Re
|
||||
let imported = import_ssh_aliases(config, aliases)?;
|
||||
for entry in imported {
|
||||
match entry.action {
|
||||
ImportAction::Added => eprintln!(
|
||||
"dosh import-ssh: added [{}] ssh={} ssh_config={} dosh_host={}",
|
||||
entry.alias, entry.ssh, entry.ssh_config, entry.dosh_host
|
||||
),
|
||||
ImportAction::Added => {
|
||||
if let Some(dosh_host) = &entry.dosh_host {
|
||||
eprintln!(
|
||||
"dosh import-ssh: added [{}] ssh={} ssh_config={} dosh_host={}",
|
||||
entry.alias, entry.ssh, entry.ssh_config, dosh_host
|
||||
)
|
||||
} else {
|
||||
eprintln!(
|
||||
"dosh import-ssh: added [{}] ssh={} ssh_config={} dosh_host=ssh",
|
||||
entry.alias, entry.ssh, entry.ssh_config
|
||||
)
|
||||
}
|
||||
}
|
||||
ImportAction::Skipped => {
|
||||
eprintln!(
|
||||
"dosh import-ssh: [{}] already exists, skipping",
|
||||
@@ -4904,46 +4917,23 @@ fn import_ssh_aliases(
|
||||
}
|
||||
let mut imported = Vec::new();
|
||||
for alias in aliases {
|
||||
let ssh_config = ssh_config(alias, None)
|
||||
.with_context(|| format!("read SSH config for {alias} with ssh -G"))?;
|
||||
let udp_host = ssh_config
|
||||
.hostname
|
||||
.clone()
|
||||
.unwrap_or_else(|| ssh_destination_host(alias));
|
||||
if raw_contains_host_table(&raw, alias) {
|
||||
imported.push(ImportedHost {
|
||||
alias: alias.clone(),
|
||||
ssh: alias.clone(),
|
||||
ssh_config: alias.clone(),
|
||||
dosh_host: udp_host,
|
||||
dosh_host: None,
|
||||
port: config.dosh_port,
|
||||
action: ImportAction::Skipped,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
let ssh_config = ssh_config(alias, None)
|
||||
.with_context(|| format!("read SSH config for {alias} with ssh -G"))?;
|
||||
let (block, entry) = imported_host_block(config, alias, &ssh_config);
|
||||
raw.push('\n');
|
||||
raw.push_str(&format!("[{}]\n", toml_bare_key_or_quoted(alias)));
|
||||
raw.push_str(&format!("ssh = {}\n", toml_string(alias)));
|
||||
raw.push_str(&format!("ssh_config = {}\n", toml_string(alias)));
|
||||
raw.push_str(&format!("dosh_host = {}\n", toml_string(&udp_host)));
|
||||
raw.push_str(&format!("port = {}\n", config.dosh_port));
|
||||
if let Some(user) = &ssh_config.user {
|
||||
raw.push_str(&format!("user = {}\n", toml_string(user)));
|
||||
}
|
||||
if let Some(port) = ssh_config.port
|
||||
&& port != 22
|
||||
{
|
||||
raw.push_str(&format!("ssh_port = {port}\n"));
|
||||
}
|
||||
raw.push_str("predict = true\n");
|
||||
imported.push(ImportedHost {
|
||||
alias: alias.clone(),
|
||||
ssh: alias.clone(),
|
||||
ssh_config: alias.clone(),
|
||||
dosh_host: udp_host,
|
||||
port: config.dosh_port,
|
||||
action: ImportAction::Added,
|
||||
});
|
||||
raw.push_str(&block);
|
||||
imported.push(entry);
|
||||
}
|
||||
if let Some(parent) = path.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
@@ -4952,6 +4942,43 @@ fn import_ssh_aliases(
|
||||
Ok(imported)
|
||||
}
|
||||
|
||||
fn imported_host_block(
|
||||
config: &dosh::config::ClientConfig,
|
||||
alias: &str,
|
||||
ssh_config: &SshConfig,
|
||||
) -> (String, ImportedHost) {
|
||||
let mut raw = String::new();
|
||||
raw.push_str(&format!("[{}]\n", toml_bare_key_or_quoted(alias)));
|
||||
raw.push_str(&format!("ssh = {}\n", toml_string(alias)));
|
||||
raw.push_str(&format!("ssh_config = {}\n", toml_string(alias)));
|
||||
raw.push_str("# dosh_host = \"server.example.com\"\n");
|
||||
raw.push_str(&format!("port = {}\n", config.dosh_port));
|
||||
if let Some(user) = &ssh_config.user {
|
||||
raw.push_str(&format!("user = {}\n", toml_string(user)));
|
||||
}
|
||||
if let Some(port) = ssh_config.port
|
||||
&& port != 22
|
||||
{
|
||||
raw.push_str(&format!("ssh_port = {port}\n"));
|
||||
}
|
||||
raw.push_str("predict = true\n");
|
||||
(
|
||||
raw,
|
||||
ImportedHost {
|
||||
alias: alias.to_string(),
|
||||
ssh: alias.to_string(),
|
||||
ssh_config: alias.to_string(),
|
||||
dosh_host: None,
|
||||
port: config.dosh_port,
|
||||
action: ImportAction::Added,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn imported_dosh_host_display(entry: &ImportedHost) -> &str {
|
||||
entry.dosh_host.as_deref().unwrap_or("ssh")
|
||||
}
|
||||
|
||||
fn raw_contains_host_table(raw: &str, alias: &str) -> bool {
|
||||
let quoted = toml_string(alias);
|
||||
raw.lines().any(|line| {
|
||||
@@ -10616,8 +10643,8 @@ mod tests {
|
||||
TERMINAL_SNAPSHOT_RESET, UpdateOptions, UpdateRole, auth_allows, cache_key,
|
||||
cache_server_prefix, cleanup_stream_state, clear_cached_credentials,
|
||||
effective_update_artifact_tag, ensure_tui_safe_status_overlay, expand_ssh_path_tokens,
|
||||
first_resolved_addr, input_contains_focus_in, input_matches_escape, is_local_status_target,
|
||||
is_resume_response_for_client, latest_release_download_url,
|
||||
first_resolved_addr, imported_host_block, input_contains_focus_in, input_matches_escape,
|
||||
is_local_status_target, is_resume_response_for_client, latest_release_download_url,
|
||||
load_first_native_identity_with_prompt, local_symlink_target_is_dir,
|
||||
local_username_from_env, native_proxy_udp_warning, newest_client_trace_path_from,
|
||||
parse_dynamic_forward, parse_escape_key, parse_local_forward, parse_remote_forward,
|
||||
@@ -11155,6 +11182,30 @@ mod tests {
|
||||
assert_eq!(toml_bare_key_or_quoted("home box"), "\"home box\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn imported_ssh_host_block_does_not_bake_derived_udp_host() {
|
||||
let config = ClientConfig {
|
||||
dosh_port: 50000,
|
||||
..ClientConfig::default()
|
||||
};
|
||||
let ssh_config = SshConfig {
|
||||
hostname: Some("10.0.0.5".to_string()),
|
||||
user: Some("deploy".to_string()),
|
||||
port: Some(2222),
|
||||
..SshConfig::default()
|
||||
};
|
||||
|
||||
let (block, imported) = imported_host_block(&config, "prod", &ssh_config);
|
||||
|
||||
assert!(block.contains("[prod]\n"));
|
||||
assert!(block.contains("ssh_config = \"prod\"\n"));
|
||||
assert!(block.contains("# dosh_host = \"server.example.com\"\n"));
|
||||
assert!(!block.contains("dosh_host = \"10.0.0.5\""));
|
||||
assert!(block.contains("user = \"deploy\"\n"));
|
||||
assert!(block.contains("ssh_port = 2222\n"));
|
||||
assert_eq!(imported.dosh_host, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn strips_user_from_fallback_udp_host() {
|
||||
assert_eq!(ssh_destination_host("alice@example.com"), "example.com");
|
||||
|
||||
Reference in New Issue
Block a user