pub const CONTAINER_ID_EMPTY: &str = "Container ID must not be empty.";
pub const CONTAINER_RUNTIME_MISSING: &str = "No container runtime found. Install Docker or Podman.";
pub fn container_id_invalid_char(c: char) -> String {
format!("Container ID contains invalid character: '{c}'")
}
pub fn container_unknown_sentinel(s: &str) -> String {
format!("Unknown sentinel: {s}")
}
pub fn container_invalid_id(reason: &str) -> String {
format!("Container exec blocked: {reason}")
}
pub fn scp_copying_one(source: &str) -> String {
format!("Copying {}...", source)
}
pub fn scp_copying_many(count: usize) -> String {
format!("Copying {} files...", count)
}
pub fn scp_failed_exit_code(code: i32) -> String {
format!("Copy failed (exit code {}).", code)
}
pub fn scp_spawn_failed(e: &impl std::fmt::Display) -> String {
format!("scp failed: {}", e)
}
pub fn container_action_complete(action: &str) -> String {
format!("Container {} complete.", action)
}
pub const HOST_KEY_UNKNOWN: &str = "Host key unknown. Connect first (Enter) to trust the host.";
pub const HOST_KEY_CHANGED: &str =
"Host key changed. Possible tampering or server re-install. Clear with ssh-keygen -R.";
pub const CONTAINER_RUNTIME_NOT_FOUND: &str = "Docker or Podman not found on remote host.";
pub const CONTAINER_PERMISSION_DENIED: &str =
"Permission denied. Is your user in the docker group?";
pub const CONTAINER_DAEMON_NOT_RUNNING: &str = "Container daemon is not running.";
pub const CONTAINER_CONNECTION_REFUSED: &str = "Connection refused.";
pub const CONTAINER_HOST_UNREACHABLE: &str = "Host unreachable.";
pub fn container_command_failed(code: i32) -> String {
format!("Command failed with code {}.", code)
}
pub const CONTAINER_INSPECT_EMPTY: &str = "Inspect returned no data.";
pub fn container_inspect_parse_failed(reason: &str) -> String {
format!("Inspect parse failed: {}", reason)
}
pub fn container_not_running(name: &str) -> String {
format!("{} is not running. Cannot exec.", name)
}
pub const DEMO_CONTAINER_EXEC_DISABLED: &str = "Demo mode: container exec disabled.";
pub fn container_exec_opened_in_tmux(name: &str, alias: &str) -> String {
format!("Opened {} on {} in tmux window.", name, alias)
}
pub fn container_exec_ended(name: &str) -> String {
format!("Container shell ended: {}.", name)
}
pub fn container_exec_failed_with_reason(name: &str, reason: &str) -> String {
format!("Container exec failed for {}: {}", name, reason)
}
pub fn container_exec_exited_with_code(name: &str, code: i32) -> String {
format!("Container exec for {} exited with code {}.", name, code)
}
pub fn container_exec_spawn_failed(name: &str) -> String {
format!("Failed to launch ssh for container {}.", name)
}
pub const CONTAINER_EXEC_INVALID_COMMAND: &str =
"Command rejected: control characters not allowed.";
pub const CONTAINER_LOGS_LOADING: &str = "fetching logs…";
pub fn container_logs_fetched(secs_ago: u64) -> String {
format!(
"fetched {} ago",
crate::containers::format_uptime_short(secs_ago)
)
}
pub fn container_logs_failed(reason: &str) -> String {
format!("logs fetch failed: {}", reason)
}
pub fn container_logs_search_position(current: usize, total: usize) -> String {
format!("{} of {}", current, total)
}
pub const CONTAINER_LOGS_SEARCH_NO_MATCHES: &str = "no matches";
pub const CONTAINER_RESTART_BODY: &str =
"Sends SIGTERM, waits 10s, then SIGKILL. Live connections will drop.";
pub const CONTAINER_STOP_BODY: &str = "Sends SIGTERM, waits 10s, then SIGKILL. Container will not restart unless its policy reschedules it.";
pub fn container_stack_unknown(name: &str) -> String {
format!("Stack unknown for {}: open the detail panel first.", name)
}
pub fn container_stack_no_running(project: &str) -> String {
format!("Stack {} has no running members to restart.", project)
}
pub const CONTAINER_STACK_RESTART_BODY: &str = "Restart cycles every running member one by one. Exited members are not touched. Live connections will drop.";
pub const CONTAINER_HOST_RESTART_ALL_BODY: &str = "Restart cycles every running container on the host one by one. Exited containers are not touched. Live connections will drop.";
pub const CONTAINER_HOST_STOP_ALL_BODY: &str = "Stops every running container on the host one by one. Exited containers are not touched. Restart policies may reschedule them.";
pub fn container_action_needs_single(action: &str) -> String {
format!(
"{} need a single container. Place the cursor on a container row.",
action.to_lowercase()
)
}
pub fn container_host_no_running(alias: &str) -> String {
format!("No running containers on {}.", alias)
}
pub fn container_refreshing(alias: &str) -> String {
format!("Refreshing {}…", alias)
}
pub const REFRESH_BATCH_ALREADY_RUNNING: &str = "Refresh already in progress.";
pub const REFRESH_NOTHING_TO_REFRESH: &str = "No cached hosts to refresh. Press 'a' to add a host.";
pub fn container_refresh_progress(done: usize, total: usize) -> String {
format!("Refreshing {}/{} hosts…", done, total)
}
pub fn container_refresh_complete(total: usize) -> String {
format!(
"Refreshed {} host{}.",
total,
if total == 1 { "" } else { "s" }
)
}
pub const CONTAINER_HOST_PICKER_NO_MATCH: &str = "No hosts match.";
pub const CONTAINER_HOST_PICKER_NOTHING_TO_ADD: &str =
"All hosts already cached. Use 'r' or 'R' to refresh.";