refactor: variable names updated
This commit is contained in:
@@ -101,7 +101,7 @@ In application controls
|
|||||||
| ```( h )``` | Toggle help menu.|
|
| ```( h )``` | Toggle help menu.|
|
||||||
| ```( m )``` | Toggle mouse capture - if disabled, text on screen can be selected.|
|
| ```( m )``` | Toggle mouse capture - if disabled, text on screen can be selected.|
|
||||||
| ```( q )``` | Quit.|
|
| ```( q )``` | Quit.|
|
||||||
| ```( s )``` | Save logs to `$HOME/[container_name]_[timestamp].log`, or the directory set by `--logs-dir`.|
|
| ```( s )``` | Save logs to `$HOME/oxker_[container_name].log`, or the directory set by `--save-dir`.|
|
||||||
|
|
||||||
|
|
||||||
Available command line arguments
|
Available command line arguments
|
||||||
@@ -114,8 +114,8 @@ Available command line arguments
|
|||||||
|```-s```| If running via Docker, will display the oxker container.|
|
|```-s```| If running via Docker, will display the oxker container.|
|
||||||
|```-g```| No TUI, essentially a debugging mode with limited functionality, for now.|
|
|```-g```| No TUI, essentially a debugging mode with limited functionality, for now.|
|
||||||
|```--host [hostname]```| Connect to Docker with a custom hostname. Defaults to `/var/run/docker.sock`. Will use `$DOCKER_HOST` environment variable if set.|
|
|```--host [hostname]```| Connect to Docker with a custom hostname. Defaults to `/var/run/docker.sock`. Will use `$DOCKER_HOST` environment variable if set.|
|
||||||
|```--use-cli```| When executing into a container, use the external Docker CLI application.|
|
|```--save-dir```| Set a custom location to save exported logs into. Defaults to `$HOME`.|
|
||||||
|```--logs-dir```| Set a custom location to save exportings logs into. Defaults to `$HOME`.|
|
|```--use-cli```| When executing into a container, force use of the external Docker CLI application.|
|
||||||
|
|
||||||
## Build step
|
## Build step
|
||||||
|
|
||||||
|
|||||||
+43
-8
@@ -1,15 +1,16 @@
|
|||||||
use std::{
|
use std::{
|
||||||
io::{Read, Write},
|
io::{Read, Stdout, Write},
|
||||||
sync::{atomic::AtomicBool, Arc},
|
sync::{atomic::AtomicBool, Arc},
|
||||||
};
|
};
|
||||||
|
|
||||||
use bollard::{
|
use bollard::{
|
||||||
exec::{CreateExecOptions, StartExecOptions, StartExecResults},
|
exec::{CreateExecOptions, ResizeExecOptions, StartExecOptions, StartExecResults},
|
||||||
Docker,
|
Docker,
|
||||||
};
|
};
|
||||||
use crossterm::terminal::enable_raw_mode;
|
use crossterm::terminal::enable_raw_mode;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use ratatui::{backend::CrosstermBackend, Terminal};
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -24,7 +25,7 @@ const TTY: &str = "/dev/tty";
|
|||||||
const OCI_ERROR: &str = "OCI runtime exec failed";
|
const OCI_ERROR: &str = "OCI runtime exec failed";
|
||||||
|
|
||||||
/// Set the cursor position on the screen to (0,0)
|
/// Set the cursor position on the screen to (0,0)
|
||||||
pub const CURSOR_POS: &str = "\x1B[J\x1B[H";
|
const CURSOR_POS: &str = "\x1B[J\x1B[H";
|
||||||
|
|
||||||
/// This needs to be written to stdout when exiting the exec mode, else the input handler thread gets confused,
|
/// This needs to be written to stdout when exiting the exec mode, else the input handler thread gets confused,
|
||||||
/// see https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement
|
/// see https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement
|
||||||
@@ -110,6 +111,24 @@ struct AsyncTTY {
|
|||||||
rx: std::sync::mpsc::Receiver<u8>,
|
rx: std::sync::mpsc::Receiver<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is used to set the terminal size when exec via the Internal method
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TerminalSize {
|
||||||
|
width: u16,
|
||||||
|
height: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TerminalSize {
|
||||||
|
pub fn new(terminal: &Terminal<CrosstermBackend<Stdout>>) -> Option<Self> {
|
||||||
|
terminal.size().map_or(None, |i| {
|
||||||
|
Some(Self {
|
||||||
|
width: i.width,
|
||||||
|
height: i.height,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ExecMode {
|
pub enum ExecMode {
|
||||||
// use Bollard Rust library
|
// use Bollard Rust library
|
||||||
@@ -192,7 +211,12 @@ impl ExecMode {
|
|||||||
|
|
||||||
/// Exec into the container via the Bollard library, stdout & stdin on different threads
|
/// Exec into the container via the Bollard library, stdout & stdin on different threads
|
||||||
/// Have to deal with strange output once dropped, hence the use of internal_cleanup() method
|
/// Have to deal with strange output once dropped, hence the use of internal_cleanup() method
|
||||||
async fn exec_internal(&self, id: &ContainerId, docker: &Arc<Docker>) -> Result<(), AppError> {
|
async fn exec_internal(
|
||||||
|
&self,
|
||||||
|
id: &ContainerId,
|
||||||
|
docker: &Arc<Docker>,
|
||||||
|
terminal_size: Option<TerminalSize>,
|
||||||
|
) -> Result<(), AppError> {
|
||||||
let run = Arc::new(AtomicBool::new(true));
|
let run = Arc::new(AtomicBool::new(true));
|
||||||
|
|
||||||
if let Ok(exec_result) = docker
|
if let Ok(exec_result) = docker
|
||||||
@@ -239,6 +263,19 @@ impl ExecMode {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if let Some(terminal_size) = terminal_size {
|
||||||
|
docker
|
||||||
|
.resize_exec(
|
||||||
|
&exec_result.id,
|
||||||
|
ResizeExecOptions {
|
||||||
|
height: terminal_size.height,
|
||||||
|
width: terminal_size.width,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
while let Ok(x) = async_tty.rx.recv() {
|
while let Ok(x) = async_tty.rx.recv() {
|
||||||
input.write(&[x]).await.ok();
|
input.write(&[x]).await.ok();
|
||||||
}
|
}
|
||||||
@@ -263,7 +300,6 @@ impl ExecMode {
|
|||||||
let waiting_thread = Arc::clone(&waiting);
|
let waiting_thread = Arc::clone(&waiting);
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
// At the moment the known max length is 26
|
|
||||||
let mut bytes = Vec::with_capacity(26);
|
let mut bytes = Vec::with_capacity(26);
|
||||||
while waiting_thread.load(std::sync::atomic::Ordering::SeqCst) {
|
while waiting_thread.load(std::sync::atomic::Ordering::SeqCst) {
|
||||||
let mut buf = [0];
|
let mut buf = [0];
|
||||||
@@ -296,15 +332,14 @@ impl ExecMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RESET TERMINAL BEFROEHAND
|
pub async fn run(&self, tty_size: Option<TerminalSize>) -> Result<(), AppError> {
|
||||||
pub async fn run(&self) -> Result<(), AppError> {
|
|
||||||
match self {
|
match self {
|
||||||
Self::External(id) => {
|
Self::External(id) => {
|
||||||
Self::exec_external(id);
|
Self::exec_external(id);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::Internal((id, docker)) => self.exec_internal(id, docker).await,
|
Self::Internal((id, docker)) => self.exec_internal(id, docker, tty_size).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ impl InputHandler {
|
|||||||
let args = app_data.lock().args.clone();
|
let args = app_data.lock().args.clone();
|
||||||
let container = app_data.lock().get_selected_container_id_state_name();
|
let container = app_data.lock().get_selected_container_id_state_name();
|
||||||
if let Some((id, _, name)) = container {
|
if let Some((id, _, name)) = container {
|
||||||
if let Some(log_path) = args.logs_dir {
|
if let Some(log_path) = args.save_dir {
|
||||||
let (sx, rx) = tokio::sync::oneshot::channel::<Arc<Docker>>();
|
let (sx, rx) = tokio::sync::oneshot::channel::<Arc<Docker>>();
|
||||||
docker_tx.send(DockerMessage::Exec(sx)).await?;
|
docker_tx.send(DockerMessage::Exec(sx)).await?;
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -37,13 +37,13 @@ pub struct Args {
|
|||||||
#[clap(long, short = None)]
|
#[clap(long, short = None)]
|
||||||
pub host: Option<String>,
|
pub host: Option<String>,
|
||||||
|
|
||||||
/// Use "docker" cli for execing
|
/// Force use of docker cli when execing into containers
|
||||||
#[clap(long="use-cli", short = None)]
|
#[clap(long="use-cli", short = None)]
|
||||||
pub use_cli: bool,
|
pub use_cli: bool,
|
||||||
|
|
||||||
/// Directory for exporting logs, defaults to `$HOME`
|
/// Directory for saving exported logs, defaults to `$HOME`
|
||||||
#[clap(long="logs-dir", short = None)]
|
#[clap(long="save-dir", short = None)]
|
||||||
pub logs_dir: Option<String>,
|
pub save_dir: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -54,7 +54,7 @@ pub struct CliArgs {
|
|||||||
pub gui: bool,
|
pub gui: bool,
|
||||||
pub host: Option<String>,
|
pub host: Option<String>,
|
||||||
pub in_container: bool,
|
pub in_container: bool,
|
||||||
pub logs_dir: Option<PathBuf>,
|
pub save_dir: Option<PathBuf>,
|
||||||
pub raw: bool,
|
pub raw: bool,
|
||||||
pub show_self: bool,
|
pub show_self: bool,
|
||||||
pub timestamp: bool,
|
pub timestamp: bool,
|
||||||
@@ -77,7 +77,7 @@ impl CliArgs {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
let logs_dir = args.logs_dir.map_or_else(
|
let logs_dir = args.save_dir.map_or_else(
|
||||||
|| directories::BaseDirs::new().map(|base_dirs| base_dirs.home_dir().to_owned()),
|
|| directories::BaseDirs::new().map(|base_dirs| base_dirs.home_dir().to_owned()),
|
||||||
|logs_dir| Some(std::path::Path::new(&logs_dir).to_owned()),
|
|logs_dir| Some(std::path::Path::new(&logs_dir).to_owned()),
|
||||||
);
|
);
|
||||||
@@ -95,7 +95,7 @@ impl CliArgs {
|
|||||||
gui: !args.gui,
|
gui: !args.gui,
|
||||||
host: args.host,
|
host: args.host,
|
||||||
in_container: Self::check_if_in_container(),
|
in_container: Self::check_if_in_container(),
|
||||||
logs_dir,
|
save_dir: logs_dir,
|
||||||
raw: args.raw,
|
raw: args.raw,
|
||||||
show_self: !args.show_self,
|
show_self: !args.show_self,
|
||||||
timestamp: !args.timestamp,
|
timestamp: !args.timestamp,
|
||||||
|
|||||||
+2
-1
@@ -28,6 +28,7 @@ pub use self::gui_state::{DeleteButton, GuiState, SelectablePanel, Status};
|
|||||||
use crate::{
|
use crate::{
|
||||||
app_data::{AppData, Columns, ContainerId, Header, SortedOrder},
|
app_data::{AppData, Columns, ContainerId, Header, SortedOrder},
|
||||||
app_error::AppError,
|
app_error::AppError,
|
||||||
|
exec::TerminalSize,
|
||||||
input_handler::InputMessages,
|
input_handler::InputMessages,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -147,7 +148,7 @@ impl Ui {
|
|||||||
if let Some(mode) = exec_mode {
|
if let Some(mode) = exec_mode {
|
||||||
self.reset_terminal().ok();
|
self.reset_terminal().ok();
|
||||||
self.terminal.clear().ok();
|
self.terminal.clear().ok();
|
||||||
if let Err(e) = mode.run().await {
|
if let Err(e) = mode.run(TerminalSize::new(&self.terminal)).await {
|
||||||
self.app_data
|
self.app_data
|
||||||
.lock()
|
.lock()
|
||||||
.set_error(e, &self.gui_state, Status::Error);
|
.set_error(e, &self.gui_state, Status::Error);
|
||||||
|
|||||||
Reference in New Issue
Block a user