diff --git a/README.md b/README.md index 879a3b6..58a46f8 100644 --- a/README.md +++ b/README.md @@ -120,11 +120,12 @@ Ducker is configured via a yaml file found in the relevant config directory for The following table summarises the available config values: -| Key | Default | Description | -| ------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------- | -| prompt | 🦆 | The default prompt to display in the command pane | -| default_exec | `/bin/bash` | The default prompt to display in the command pane. NB - currently uses this for all exec's; it is planned to offer a choice | -| theme | [See below] | The colour theme configuration | +| Key | Default | Description | +| ------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| prompt | 🦆 | The default prompt to display in the command pane | +| default_exec | `/bin/bash` | The default prompt to display in the command pane. NB - currently uses this for all exec's; it is planned to offer a choice | +| docker_path | `unix:///var/run/docker.sock` | The location of the socket on which the docker daemon is exposed (defaults to `npipe:////./pipe/docker_engine` on windows) | +| theme | [See below] | The colour theme configuration | If a value is unset or if the config file is unfound, Ducker will use the default values. If a value is malformed, Ducker will fail to run. diff --git a/src/config.rs b/src/config.rs index 686a74f..63e9eb0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,25 +16,33 @@ pub struct Config { #[serde(default = "default_exec")] pub default_exec: String, + #[serde(default = "default_docker_path")] + pub docker_path: String, + #[serde(default)] pub theme: Theme, } impl Config { - pub fn new(write: &bool) -> Result { + pub fn new(write: &bool, docker_path: Option) -> Result { let config_path = get_app_config_path()?.join("config.yaml"); if *write { write_default_config(&config_path).context("failed to write default config")?; } - if let Ok(f) = File::open(config_path) { - let config: Config = - serde_yml::from_reader(BufReader::new(f)).context("unable to parse config")?; + let mut config: Config; - Ok(config) + if let Ok(f) = File::open(config_path) { + config = serde_yml::from_reader(BufReader::new(f)).context("unable to parse config")?; } else { - Ok(Config::default()) + config = Config::default() + } + + if let Some(p) = docker_path { + config.docker_path = p; } + + Ok(config) } } @@ -46,6 +54,14 @@ fn default_exec() -> String { "/bin/bash".into() } +fn default_docker_path() -> String { + #[cfg(unix)] + return "unix:///var/run/docker.sock".into(); + + #[cfg(windows)] + return "npipe:////./pipe/docker_engine".into(); +} + fn default_use_theme() -> bool { false } @@ -55,7 +71,7 @@ impl Default for Config { Self { prompt: default_prompt(), default_exec: default_exec(), - + docker_path: default_docker_path(), theme: Theme::default(), } } diff --git a/src/docker/mod.rs b/src/docker/mod.rs index 1ea1e70..ec4eb29 100644 --- a/src/docker/mod.rs +++ b/src/docker/mod.rs @@ -1,3 +1,4 @@ pub mod container; pub mod image; pub mod logs; +pub mod util; diff --git a/src/docker/util.rs b/src/docker/util.rs new file mode 100644 index 0000000..7606a4c --- /dev/null +++ b/src/docker/util.rs @@ -0,0 +1,14 @@ +use bollard::{Docker, API_DEFAULT_VERSION}; +use color_eyre::eyre::{Context, Result}; + +use super::container::DockerContainer; + +pub async fn new_local_docker_connection(socket_path: &str) -> Result { + let docker = bollard::Docker::connect_with_socket(socket_path, 120, API_DEFAULT_VERSION) + .with_context(|| "unable to connect to local docker socket")?; + + DockerContainer::list(&docker) + .await + .context("unable to connect to local docker socket")?; + Ok(docker) +} diff --git a/src/main.rs b/src/main.rs index 4872ae0..bcfeaf1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use clap::Parser; use color_eyre::eyre::Context; use config::Config; +use docker::util::new_local_docker_connection; use events::{EventLoop, Key, Message}; use ui::App; @@ -18,6 +19,8 @@ mod traits; mod ui; mod widgets; +const CONFIGURATION_DOC_PATH: &str = "https://github.com/robertpsoane/ducker#configuration"; + #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Args { @@ -25,19 +28,29 @@ struct Args { /// (usually ~/.config/ducker/config.yaml) #[clap(long, short, action)] export_default_config: bool, + + /// Path at which to find the socket to communicate with + /// docker + #[clap(long, short)] + docker_path: Option, } #[tokio::main] async fn main() -> color_eyre::Result<()> { let args = Args::parse(); - let config = Config::new(&args.export_default_config)?; + let config = Config::new(&args.export_default_config, args.docker_path)?; + + let docker = new_local_docker_connection(&config.docker_path) + .await + .context(format!("failed to create docker connection, potentially due to misconfiguration (see {CONFIGURATION_DOC_PATH})"))?; terminal::init_panic_hook(); + let mut terminal = terminal::init().context("failed to initialise terminal")?; let mut events = EventLoop::new(); let events_tx = events.get_tx(); - let mut app = App::new(events_tx, config) + let mut app = App::new(events_tx, docker, config) .await .context("failed to create app")?; diff --git a/src/ui/app.rs b/src/ui/app.rs index f19c0d1..de1c97c 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -1,3 +1,4 @@ +use bollard::Docker; use color_eyre::eyre::{Context, Result}; use ratatui::{ layout::{Constraint, Layout, Rect}, @@ -42,12 +43,16 @@ pub struct App { } impl App { - pub async fn new(tx: Sender>, config: Config) -> Result { + pub async fn new( + tx: Sender>, + docker: Docker, + config: Config, + ) -> Result { let config = Box::new(config); let page = state::CurrentPage::default(); - let body = PageManager::new(page.clone(), tx.clone(), config.clone()) + let body = PageManager::new(page.clone(), tx.clone(), docker, config.clone()) .await .context("unable to create new body component")?; diff --git a/src/ui/page_manager.rs b/src/ui/page_manager.rs index f55488c..b376cd7 100644 --- a/src/ui/page_manager.rs +++ b/src/ui/page_manager.rs @@ -29,11 +29,9 @@ impl PageManager { pub async fn new( page: state::CurrentPage, tx: Sender>, + docker: Docker, config: Box, ) -> Result { - let docker = bollard::Docker::connect_with_socket_defaults() - .context("unable to connect to local docker daemon")?; - let containers = Box::new(Containers::new(docker.clone(), tx.clone(), config.clone())); let mut page_manager = Self {