fix: DOCKER_HOST env priority, config.toml fix
This commit is contained in:
@@ -18,8 +18,8 @@
|
|||||||
"show_timestamp": true,
|
"show_timestamp": true,
|
||||||
// Don't draw gui - for debugging - mostly pointless
|
// Don't draw gui - for debugging - mostly pointless
|
||||||
"gui": true,
|
"gui": true,
|
||||||
// Docker host location
|
// Docker host location. Will take priority over a DOCKER_HOST env.
|
||||||
"host": "/var/run/docker.sock",
|
// "host": "/var/run/docker.sock",
|
||||||
// Display the timestamp in a custom format, if given option is invalid, it will default to %Y-%m-%dT%H:%M:%S.%8f -> 2025-02-18T12:34:56.01234567
|
// Display the timestamp in a custom format, if given option is invalid, it will default to %Y-%m-%dT%H:%M:%S.%8f -> 2025-02-18T12:34:56.01234567
|
||||||
// *Should* accept any valid strftime string up to 32 chars, see https://strftime.org/
|
// *Should* accept any valid strftime string up to 32 chars, see https://strftime.org/
|
||||||
"timestamp_format": "%Y-%m-%dT%H:%M:%S.%8f",
|
"timestamp_format": "%Y-%m-%dT%H:%M:%S.%8f",
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ show_timestamp = true
|
|||||||
# Don't draw gui - for debugging - mostly pointless
|
# Don't draw gui - for debugging - mostly pointless
|
||||||
gui = true
|
gui = true
|
||||||
|
|
||||||
# Docker host location
|
# Docker host location. Will take priority over a DOCKER_HOST env.
|
||||||
host = "/var/run/docker.sock"
|
# host = "/var/run/docker.sock"
|
||||||
|
|
||||||
# Display the container logs timestamp with a given timezone, if timezone is unknown, defaults to UTC
|
# Display the container logs timestamp with a given timezone, if timezone is unknown, defaults to UTC
|
||||||
timezone = "Etc/UTC"
|
timezone = "Etc/UTC"
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ show_timestamp = true
|
|||||||
# Don't draw gui - for debugging - mostly pointless
|
# Don't draw gui - for debugging - mostly pointless
|
||||||
gui = true
|
gui = true
|
||||||
|
|
||||||
# Docker host location
|
# Docker host location. Will take priority over a DOCKER_HOST env.
|
||||||
host = "/var/run/docker.sock"
|
# host = "/var/run/docker.sock"
|
||||||
|
|
||||||
# Display the container logs timestamp with a given timezone, if timezone is unknown, defaults to UTC
|
# Display the container logs timestamp with a given timezone, if timezone is unknown, defaults to UTC
|
||||||
timezone = "Etc/UTC"
|
timezone = "Etc/UTC"
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ pub struct ConfigFile {
|
|||||||
pub use_cli: Option<bool>,
|
pub use_cli: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl ConfigFile {
|
impl ConfigFile {
|
||||||
/// Attempt to create a config.toml file, will attempt to recursively create the directories as well
|
/// Attempt to create a config.toml file, will attempt to recursively create the directories as well
|
||||||
fn crate_config_file(in_container: bool) -> Result<(), AppError> {
|
fn crate_config_file(in_container: bool) -> Result<(), AppError> {
|
||||||
@@ -119,6 +121,8 @@ impl ConfigFile {
|
|||||||
toml::from_str::<Self>(input).map_err(|i| AppError::Parse(i.message().to_owned()))
|
toml::from_str::<Self>(input).map_err(|i| AppError::Parse(i.message().to_owned()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO if on windows, omit the docker_host?
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the config file path to string, then attempt to parse
|
/// Read the config file path to string, then attempt to parse
|
||||||
|
|||||||
+20
-14
@@ -42,12 +42,16 @@ fn setup_tracing() {
|
|||||||
tracing_subscriber::fmt().with_max_level(Level::INFO).init();
|
tracing_subscriber::fmt().with_max_level(Level::INFO).init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the optional docker_host path, the cli args take priority over the DOCKER_HOST env
|
/// Read the optional docker_host path, the DOCKER_HOST env take priority over cli or config
|
||||||
|
/// Bollard will use DOCKER_HOST env, so might be pointless here, although it will fix it's priority over any config setting
|
||||||
fn read_docker_host(config: &Config) -> Option<String> {
|
fn read_docker_host(config: &Config) -> Option<String> {
|
||||||
config
|
if let Ok(env) = std::env::var(DOCKER_HOST)
|
||||||
.host
|
&& !env.trim().is_empty()
|
||||||
.as_ref()
|
{
|
||||||
.map_or_else(|| std::env::var(DOCKER_HOST).ok(), |x| Some(x.clone()))
|
Some(env)
|
||||||
|
} else {
|
||||||
|
config.host.as_ref().cloned()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create docker daemon handler, and only spawn up the docker data handler if a ping returns non-error
|
/// Create docker daemon handler, and only spawn up the docker data handler if a ping returns non-error
|
||||||
@@ -59,11 +63,11 @@ async fn docker_init(
|
|||||||
) {
|
) {
|
||||||
let host = read_docker_host(&app_data.lock().config);
|
let host = read_docker_host(&app_data.lock().config);
|
||||||
|
|
||||||
let connection = host.map_or_else(Docker::connect_with_socket_defaults, |host| {
|
if let Ok(docker) = host
|
||||||
Docker::connect_with_socket(&host, 120, API_DEFAULT_VERSION)
|
.as_ref()
|
||||||
});
|
.map_or_else(Docker::connect_with_defaults, |host| {
|
||||||
|
Docker::connect_with_socket(host, 120, API_DEFAULT_VERSION)
|
||||||
if let Ok(docker) = connection
|
})
|
||||||
&& docker.ping().await.is_ok()
|
&& docker.ping().await.is_ok()
|
||||||
{
|
{
|
||||||
tokio::spawn(DockerData::start(
|
tokio::spawn(DockerData::start(
|
||||||
@@ -73,11 +77,13 @@ async fn docker_init(
|
|||||||
docker_tx,
|
docker_tx,
|
||||||
Arc::clone(gui_state),
|
Arc::clone(gui_state),
|
||||||
));
|
));
|
||||||
return;
|
} else {
|
||||||
|
app_data.lock().set_error(
|
||||||
|
AppError::DockerConnect,
|
||||||
|
gui_state,
|
||||||
|
Status::DockerConnect(host),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
app_data
|
|
||||||
.lock()
|
|
||||||
.set_error(AppError::DockerConnect, gui_state, Status::DockerConnect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create data for, and then spawn a tokio thread, for the input handler
|
/// Create data for, and then spawn a tokio thread, for the input handler
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ pub fn draw(
|
|||||||
colors: AppColors,
|
colors: AppColors,
|
||||||
error: &AppError,
|
error: &AppError,
|
||||||
f: &mut Frame,
|
f: &mut Frame,
|
||||||
|
host: Option<String>,
|
||||||
keymap: &Keymap,
|
keymap: &Keymap,
|
||||||
seconds: Option<u8>,
|
seconds: Option<u8>,
|
||||||
) {
|
) {
|
||||||
@@ -32,11 +33,17 @@ pub fn draw(
|
|||||||
.borders(Borders::ALL);
|
.borders(Borders::ALL);
|
||||||
|
|
||||||
let to_push = if matches!(error, AppError::DockerConnect) {
|
let to_push = if matches!(error, AppError::DockerConnect) {
|
||||||
|
let s = if let Some(host) = host {
|
||||||
|
format!(" @ \"{host}\"")
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
format!(
|
format!(
|
||||||
"\n\n {}::v{} closing in {:02} seconds",
|
"{}\n\n {}::v{} closing in {:02} seconds",
|
||||||
|
s,
|
||||||
NAME,
|
NAME,
|
||||||
VERSION,
|
VERSION,
|
||||||
seconds.unwrap_or(5)
|
seconds.unwrap_or(5),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let clear_text = if keymap.clear == Keymap::new().clear {
|
let clear_text = if keymap.clear == Keymap::new().clear {
|
||||||
@@ -107,6 +114,37 @@ mod tests {
|
|||||||
/// Test that the error popup is centered, red background, white border, white text, and displays the correct text
|
/// Test that the error popup is centered, red background, white border, white text, and displays the correct text
|
||||||
fn test_draw_blocks_error_docker_connect_error() {
|
fn test_draw_blocks_error_docker_connect_error() {
|
||||||
let mut setup = test_setup(46, 9, true, true);
|
let mut setup = test_setup(46, 9, true, true);
|
||||||
|
setup
|
||||||
|
.terminal
|
||||||
|
.draw(|f| {
|
||||||
|
super::draw(
|
||||||
|
AppColors::new(),
|
||||||
|
&AppError::DockerConnect,
|
||||||
|
f,
|
||||||
|
None,
|
||||||
|
&Keymap::new(),
|
||||||
|
Some(4),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
assert_snapshot!(setup.terminal.backend());
|
||||||
|
for (row_index, result_row) in get_result(&setup) {
|
||||||
|
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
||||||
|
if let (0 | 8, _) = (row_index, result_cell_index) {
|
||||||
|
assert_eq!(result_cell.bg, Color::Reset);
|
||||||
|
assert_eq!(result_cell.fg, Color::Reset);
|
||||||
|
} else {
|
||||||
|
assert_eq!(result_cell.bg, Color::Red);
|
||||||
|
assert_eq!(result_cell.fg, Color::White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
/// Test that the error popup is centered, red background, white border, white text, and displays the correct text with the custom docker host address
|
||||||
|
fn test_draw_blocks_error_docker_connect_error_custom_host() {
|
||||||
|
let mut setup = test_setup(46, 9, true, true);
|
||||||
|
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
@@ -115,6 +153,7 @@ mod tests {
|
|||||||
AppColors::new(),
|
AppColors::new(),
|
||||||
&AppError::DockerConnect,
|
&AppError::DockerConnect,
|
||||||
f,
|
f,
|
||||||
|
Some("/test/host.sock".to_owned()),
|
||||||
&Keymap::new(),
|
&Keymap::new(),
|
||||||
Some(4),
|
Some(4),
|
||||||
);
|
);
|
||||||
@@ -146,6 +185,8 @@ mod tests {
|
|||||||
AppColors::new(),
|
AppColors::new(),
|
||||||
&AppError::DockerExec,
|
&AppError::DockerExec,
|
||||||
f,
|
f,
|
||||||
|
// TODO test me
|
||||||
|
None,
|
||||||
&Keymap::new(),
|
&Keymap::new(),
|
||||||
Some(4),
|
Some(4),
|
||||||
);
|
);
|
||||||
@@ -183,7 +224,15 @@ mod tests {
|
|||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::draw(colors, &AppError::DockerExec, f, &Keymap::new(), Some(4));
|
// TODO test me
|
||||||
|
super::draw(
|
||||||
|
colors,
|
||||||
|
&AppError::DockerExec,
|
||||||
|
f,
|
||||||
|
None,
|
||||||
|
&Keymap::new(),
|
||||||
|
Some(4),
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -218,7 +267,15 @@ mod tests {
|
|||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::draw(AppColors::new(), &AppError::DockerExec, f, &keymap, None);
|
// TODO test me
|
||||||
|
super::draw(
|
||||||
|
AppColors::new(),
|
||||||
|
&AppError::DockerExec,
|
||||||
|
f,
|
||||||
|
None,
|
||||||
|
&keymap,
|
||||||
|
None,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_snapshot!(setup.terminal.backend());
|
assert_snapshot!(setup.terminal.backend());
|
||||||
@@ -235,7 +292,15 @@ mod tests {
|
|||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::draw(AppColors::new(), &AppError::DockerExec, f, &keymap, None);
|
// TODO test me
|
||||||
|
super::draw(
|
||||||
|
AppColors::new(),
|
||||||
|
&AppError::DockerExec,
|
||||||
|
f,
|
||||||
|
None,
|
||||||
|
&keymap,
|
||||||
|
None,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_snapshot!(setup.terminal.backend());
|
assert_snapshot!(setup.terminal.backend());
|
||||||
@@ -252,7 +317,15 @@ mod tests {
|
|||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::draw(AppColors::new(), &AppError::DockerExec, f, &keymap, None);
|
// TODO test me
|
||||||
|
super::draw(
|
||||||
|
AppColors::new(),
|
||||||
|
&AppError::DockerExec,
|
||||||
|
f,
|
||||||
|
None,
|
||||||
|
&keymap,
|
||||||
|
None,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_snapshot!(setup.terminal.backend());
|
assert_snapshot!(setup.terminal.backend());
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
source: src/ui/draw_blocks/error.rs
|
||||||
|
expression: setup.terminal.backend()
|
||||||
|
---
|
||||||
|
" "
|
||||||
|
"╭────────────────── Error ───────────────────╮"
|
||||||
|
"│ │"
|
||||||
|
"│Unable to access docker daemon @ "/test/host│"
|
||||||
|
"│ │"
|
||||||
|
"│ oxker::v0.00.000 closing in 04 seconds │"
|
||||||
|
"│ │"
|
||||||
|
"╰────────────────────────────────────────────╯"
|
||||||
|
" "
|
||||||
+2
-2
@@ -160,10 +160,10 @@ const FRAMES_LEN: u8 = 9;
|
|||||||
|
|
||||||
/// The application gui state can be in multiple of these four states at the same time
|
/// The application gui state can be in multiple of these four states at the same time
|
||||||
/// Various functions (e.g input handler), operate differently depending upon current Status
|
/// Various functions (e.g input handler), operate differently depending upon current Status
|
||||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub enum Status {
|
pub enum Status {
|
||||||
DeleteConfirm,
|
DeleteConfirm,
|
||||||
DockerConnect,
|
DockerConnect(Option<String>),
|
||||||
Error,
|
Error,
|
||||||
Exec,
|
Exec,
|
||||||
Filter,
|
Filter,
|
||||||
|
|||||||
+8
-4
@@ -132,7 +132,7 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw the the error message ui, for 5 seconds, with a countdown
|
/// Draw the the error message ui, for 5 seconds, with a countdown
|
||||||
fn err_loop(&mut self) -> Result<(), AppError> {
|
fn err_loop(&mut self, host: Option<String>) -> Result<(), AppError> {
|
||||||
let mut seconds = 5;
|
let mut seconds = 5;
|
||||||
let colors = self.app_data.lock().config.app_colors;
|
let colors = self.app_data.lock().config.app_colors;
|
||||||
let keymap = self.app_data.lock().config.keymap.clone();
|
let keymap = self.app_data.lock().config.keymap.clone();
|
||||||
@@ -155,6 +155,7 @@ impl Ui {
|
|||||||
colors,
|
colors,
|
||||||
&AppError::DockerConnect,
|
&AppError::DockerConnect,
|
||||||
f,
|
f,
|
||||||
|
host.clone(),
|
||||||
&keymap,
|
&keymap,
|
||||||
Some(seconds),
|
Some(seconds),
|
||||||
);
|
);
|
||||||
@@ -273,8 +274,11 @@ impl Ui {
|
|||||||
/// Draw either the Error, or main oxker ui, to the terminal
|
/// Draw either the Error, or main oxker ui, to the terminal
|
||||||
async fn draw_ui(&mut self) -> Result<(), AppError> {
|
async fn draw_ui(&mut self) -> Result<(), AppError> {
|
||||||
let status = self.gui_state.lock().get_status();
|
let status = self.gui_state.lock().get_status();
|
||||||
if status.contains(&Status::DockerConnect) {
|
if let Some(Status::DockerConnect(msg)) = status
|
||||||
self.err_loop()?;
|
.iter()
|
||||||
|
.find(|s| matches!(s, Status::DockerConnect(_)))
|
||||||
|
{
|
||||||
|
self.err_loop(msg.clone())?;
|
||||||
} else {
|
} else {
|
||||||
self.gui_loop().await?;
|
self.gui_loop().await?;
|
||||||
}
|
}
|
||||||
@@ -463,6 +467,6 @@ fn draw_frame(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(error) = fd.has_error.as_ref() {
|
if let Some(error) = fd.has_error.as_ref() {
|
||||||
draw_blocks::error::draw(colors, error, f, keymap, None);
|
draw_blocks::error::draw(colors, error, f, None, keymap, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user