Skip to content

Commit

Permalink
WIP: probably the end of the refactor
Browse files Browse the repository at this point in the history
All commands done just testing needed
  • Loading branch information
sandorex committed Oct 31, 2024
1 parent a2e0d3a commit 4fb5c56
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 125 deletions.
12 changes: 6 additions & 6 deletions src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
mod cmd_start;
mod cmd_shell;
// mod cmd_exec;
// mod cmd_exists;
// mod cmd_config;
mod cmd_exec;
mod cmd_exists;
mod cmd_config;
mod cmd_list;
mod cmd_logs;
mod cmd_kill;
mod cmd_init;

pub use cmd_start::start_container;
pub use cmd_shell::open_shell;
// pub use cmd_exec::container_exec;
// pub use cmd_exists::container_exists;
// pub use cmd_config::*;
pub use cmd_exec::container_exec;
pub use cmd_exists::container_exists;
pub use cmd_config::*;
pub use cmd_list::print_containers;
pub use cmd_logs::print_logs;
pub use cmd_kill::kill_container;
Expand Down
25 changes: 11 additions & 14 deletions src/commands/cmd_config/cmd_extract_config.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
use crate::ExitResult;
use crate::util::Engine;
use crate::prelude::*;
use crate::cli::cli_config::CmdConfigExtractArgs;
use crate::util::command_extensions::*;

pub fn extract_config(engine: Engine, dry_run: bool, cli_args: &CmdConfigExtractArgs) -> ExitResult {
pub fn extract_config(ctx: Context, cli_args: CmdConfigExtractArgs) -> Result<()> {
// allow dry run to run always
if !dry_run {
let cmd = Command::new(&engine.path)
if !ctx.dry_run {
let cmd = ctx.engine_command()
.args(["image", "exists", &cli_args.image])
.output()
.expect(crate::ENGINE_ERR_MSG);

if !cmd.status.success() {
eprintln!("Image {} does not exist", cli_args.image);

return Err(2);
return Err(anyhow!("Image {} does not exist", cli_args.image));
}
}

let mut cmd = Command::new(&engine.path);
let mut cmd = ctx.engine_command();
cmd.args([
"run", "--rm", "-it",
// basically just cat the file, should be pretty portable
Expand All @@ -27,8 +24,10 @@ pub fn extract_config(engine: Engine, dry_run: bool, cli_args: &CmdConfigExtract
"/config.toml"
]);

if dry_run {
cmd.print_escaped_cmd()
if ctx.dry_run {
cmd.print_escaped_cmd();

Ok(())
} else {
let output = cmd
.output()
Expand All @@ -40,9 +39,7 @@ pub fn extract_config(engine: Engine, dry_run: bool, cli_args: &CmdConfigExtract

Ok(())
} else {
eprintln!("Failed to extract config from image {}", cli_args.image);

Err(1)
return Err(anyhow!("Failed to extract config from image {}", cli_args.image));
}
}
}
21 changes: 7 additions & 14 deletions src/commands/cmd_config/cmd_inspect_config.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
use std::path::Path;

use crate::config::ConfigFile;
use crate::cli::cli_config::CmdConfigInspectArgs;
use crate::ExitResult;

pub fn inspect_config(cli_args: &CmdConfigInspectArgs) -> ExitResult {
match ConfigFile::load_from_file(&cli_args.path) {
Ok(x) => {
println!("{:#?}", x);
use crate::prelude::*;

Ok(())
},
Err(err) => {
// NOTE err is custom error so the message is already predefined
eprintln!("{}", err);
// TODO also try to find it as config name instead of literal path if prefixed @config
pub fn inspect_config(cli_args: CmdConfigInspectArgs) -> Result<()> {
println!("{:#?}", ConfigFile::load_from_file(Path::new(&cli_args.path))?);

Err(1)
}
}
Ok(())
}
13 changes: 5 additions & 8 deletions src/commands/cmd_config/cmd_options_config.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
use code_docs::DocumentedStruct;
use crate::config::Config;
use crate::util;
use crate::vars;
use crate::prelude::*;

pub fn show_config_options() {
pub fn show_config_options(ctx: Context) {
let docstring = Config::commented_fields()
.unwrap()
// replacing vec with array for people that dont know rust
.replace("Vec<", "Array<");

// TODO generate the example config with the serialize function instead of
// raw text so it is always up to date
println!(r#"ENV {appdir_env}: {appdir:?}
APP DIRECTORY: {appdir:?}
println!(r#"APP DIRECTORY (ENV {appdir_env}): {appdir:?}
CONFIG DIRECTORY: {cfgdir:?}
--- EXAMPLE CONFIG FILE ---
Expand All @@ -38,7 +35,7 @@ ports = [
"#,
appdir_env=crate::ENV_APP_DIR,
appdir=util::app_dir(),
cfgdir=util::config_dir(),
appdir=ctx.app_dir,
cfgdir=ctx.config_dir(),
);
}
43 changes: 16 additions & 27 deletions src/commands/cmd_exec.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,34 @@
use crate::util::{self, Engine};
use crate::cli;
use crate::util::command_extensions::*;
use crate::ExitResult;
use crate::prelude::*;

pub fn container_exec(engine: Engine, dry_run: bool, mut cli_args: cli::CmdExecArgs) -> ExitResult {
pub fn container_exec(ctx: Context, mut cli_args: cli::CmdExecArgs) -> Result<()> {
// try to find container in current directory
if cli_args.name.is_empty() {
if let Some(containers) = util::find_containers_by_cwd(&engine) {
if let Some(containers) = ctx.get_cwd_container() {
if containers.is_empty() {
eprintln!("Could not find a running container in current directory");
return Err(1);
return Err(anyhow!("Could not find a running container in current directory"));
}

cli_args.name = containers.first().unwrap().clone();
}
} else if !dry_run && !util::container_exists(&engine, &cli_args.name) {
eprintln!("Container {:?} does not exist", &cli_args.name);
return Err(1);
} else if !ctx.dry_run && !ctx.engine_container_exists(&cli_args.name) {
return Err(anyhow!("Container {:?} does not exist", &cli_args.name));
}

// check if container is owned
let ws_dir = match util::get_container_ws(&engine, &cli_args.name) {
let ws_dir = match ctx.get_container_label(&cli_args.name, crate::CONTAINER_LABEL_CONTAINER_DIR) {
Some(x) => x,
// allow dry_run to work
None if dry_run => "/ws/dry_run".to_string(),
None => {
eprintln!("Container {:?} is not owned by {}", &cli_args.name, crate::APP_NAME);

return Err(1);
}
None if ctx.dry_run => "/ws/dry_run".to_string(),
None => return Err(anyhow!("Container {:?} is not owned by {}", &cli_args.name, crate::APP_NAME)),
};

let user = std::env::var("USER").expect("Unable to get USER from env var");

let mut cmd = Command::new(&engine.path);
let mut cmd = ctx.engine_command();
cmd.args(["exec", "-it"]);
cmd.args([
format!("--workdir={}", ws_dir),
format!("--user={}", user),
format!("--user={}", ctx.user),
format!("--env=TERM={}", std::env::var("TERM").unwrap_or("xterm".into())),
]);

Expand All @@ -57,13 +48,11 @@ pub fn container_exec(engine: Engine, dry_run: bool, mut cli_args: cli::CmdExecA
cmd.args(&cli_args.command);
}

if dry_run {
cmd.print_escaped_cmd()
if ctx.dry_run {
cmd.print_escaped_cmd();
} else {
cmd
.status()
.expect(crate::ENGINE_ERR_MSG)
.to_exitcode()
cmd.run_interactive()?;
}
}

Ok(())
}
22 changes: 12 additions & 10 deletions src/commands/cmd_exists.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
use crate::cli;
use crate::util::{self, Engine};
use crate::ExitResult;
use crate::prelude::*;

pub fn container_exists(engine: Engine, mut cli_args: cli::CmdExistsArgs) -> ExitResult {
pub fn container_exists(ctx: Context, mut cli_args: cli::CmdExistsArgs) -> Result<()> {
// try to find container in current directory
if cli_args.name.is_empty() {
if let Some(containers) = util::find_containers_by_cwd(&engine) {
// TODO this whole thing could be a function its used at least 3 times!
if let Some(containers) = ctx.get_cwd_container() {
if containers.is_empty() {
eprintln!("Could not find a running container in current directory");
return Err(1);
return Err(anyhow!("Could not find a running container in current directory"));
}

cli_args.name = containers.first().unwrap().clone();
}
}

match util::container_exists(&engine,&cli_args.name) {
use std::process::exit;

// TODO i am not sure if there is any problems with using exit here
match ctx.engine_container_exists(&cli_args.name) {
// give different exit code if the container exists but is not owned
true => match util::get_container_ws(&engine, &cli_args.name) {
true => match ctx.get_container_label(&cli_args.name, crate::CONTAINER_LABEL_CONTAINER_DIR) {
Some(_) => Ok(()),
None => Err(2),
None => exit(2),
},
false => Err(1),
false => exit(1),
}
}
1 change: 0 additions & 1 deletion src/commands/cmd_shell.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::prelude::*;
use crate::cli;
use crate::util::command_extensions::*;
use crate::prelude::*;

/// Extracts default shell for user from /etc/passwd inside a container
fn get_user_shell(ctx: &Context, container: &str) -> Result<String> {
Expand Down
54 changes: 9 additions & 45 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ mod cli;
mod commands;
mod config;
mod context;
mod vars;

use clap::Parser;
use cli::CliCommands;
use cli::cli_config::ConfigCommands;
use util::Engine;
use anyhow::anyhow;

pub use vars::*;
pub use context::Context;

pub mod prelude {
Expand All @@ -19,43 +21,6 @@ pub mod prelude {
pub use crate::context::Context;
}

pub const ENGINE_ERR_MSG: &str = "Failed to execute engine";

pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const FULL_VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), "-", env!("VERGEN_GIT_DESCRIBE"), " (", env!("VERGEN_GIT_BRANCH"), ")");

pub const APP_NAME: &str = env!("CARGO_PKG_NAME");
pub const APP_NAME_UPPERCASE: &str = env!("CARGO_PKG_NAME_UPPERCASE");

/// Container label used to specify the host directory where container was started
pub const CONTAINER_LABEL_HOST_DIR: &str = "host_dir";

/// Container label used to specify the path to main project in the container
pub const CONTAINER_LABEL_CONTAINER_DIR: &str = "container_dir";

/// Prefix env var name with proper prefix
#[macro_export]
macro_rules! ENV_VAR_PREFIX {
($($args:literal),*) => {
concat!(env!("CARGO_PKG_NAME_UPPERCASE"), "_", $($args),*)
};
}

/// Wayland socket to pass through
pub const ENV_WAYLAND_DISPLAY: &str = ENV_VAR_PREFIX!("WAYLAND_DISPLAY");

/// Container name
pub const ENV_CONTAINER: &str = ENV_VAR_PREFIX!("CONTAINER");

/// Suffix added to each unnamed container created
pub const ENV_CONTAINER_SUFFIX: &str = ENV_VAR_PREFIX!("CONTAINER_SUFFIX");

/// Image or config to use by default
pub const ENV_IMAGE: &str = ENV_VAR_PREFIX!("IMAGE");

/// Directory where the app stores data
pub const ENV_APP_DIR: &str = ENV_VAR_PREFIX!("DIR");

fn main() -> anyhow::Result<()> {
let args = cli::Cli::parse();

Expand Down Expand Up @@ -87,18 +52,17 @@ fn main() -> anyhow::Result<()> {
match args.cmd {
CliCommands::Start(x) => commands::start_container(ctx, x)?,
CliCommands::Shell(x) => commands::open_shell(ctx, x)?,
// CliCommands::Exec(x) => commands::container_exec(get_engine(&args)?, args.dry_run, x.clone()),
// CliCommands::Exists(x) => commands::container_exists(get_engine(&args)?, x.clone()),
// CliCommands::Config(subcmd) => match subcmd {
// ConfigCommands::Extract(x) => commands::extract_config(get_engine(&args)?, args.dry_run, &x),
// ConfigCommands::Inspect(x) => commands::inspect_config(&x),
// ConfigCommands::Options => { commands::show_config_options(); Ok(()) },
// },
CliCommands::Exec(x) => commands::container_exec(ctx, x)?,
CliCommands::Exists(x) => commands::container_exists(ctx, x)?,
CliCommands::Config(subcmd) => match subcmd {
ConfigCommands::Extract(x) => commands::extract_config(ctx, x)?,
ConfigCommands::Inspect(x) => commands::inspect_config(x)?,
ConfigCommands::Options => commands::show_config_options(ctx),
},
CliCommands::List(x) => commands::print_containers(ctx, x)?,
CliCommands::Logs(x) => commands::print_logs(ctx, x)?,
CliCommands::Kill(x) => commands::kill_container(ctx, x)?,
CliCommands::Init(_) => unreachable!(),
_ => todo!(),
};

Ok(())
Expand Down
38 changes: 38 additions & 0 deletions src/vars.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//! File containing constants

/// Prefix env var name with proper prefix
#[macro_export]
macro_rules! ENV_VAR_PREFIX {
($($args:literal),*) => {
concat!(env!("CARGO_PKG_NAME_UPPERCASE"), "_", $($args),*)
};
}

pub const ENGINE_ERR_MSG: &str = "Failed to execute engine";

pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const FULL_VERSION: &str = concat!(env!("CARGO_PKG_VERSION"), "-", env!("VERGEN_GIT_DESCRIBE"), " (", env!("VERGEN_GIT_BRANCH"), ")");

pub const APP_NAME: &str = env!("CARGO_PKG_NAME");
pub const APP_NAME_UPPERCASE: &str = env!("CARGO_PKG_NAME_UPPERCASE");

/// Container label used to specify the host directory where container was started
pub const CONTAINER_LABEL_HOST_DIR: &str = "host_dir";

/// Container label used to specify the path to main project in the container
pub const CONTAINER_LABEL_CONTAINER_DIR: &str = "container_dir";

/// Wayland socket to pass through
pub const ENV_WAYLAND_DISPLAY: &str = ENV_VAR_PREFIX!("WAYLAND_DISPLAY");

/// Container name
pub const ENV_CONTAINER: &str = ENV_VAR_PREFIX!("CONTAINER");

/// Suffix added to each unnamed container created
pub const ENV_CONTAINER_SUFFIX: &str = ENV_VAR_PREFIX!("CONTAINER_SUFFIX");

/// Image or config to use by default
pub const ENV_IMAGE: &str = ENV_VAR_PREFIX!("IMAGE");

/// Directory where the app stores data
pub const ENV_APP_DIR: &str = ENV_VAR_PREFIX!("DIR");

0 comments on commit 4fb5c56

Please sign in to comment.