diff --git a/.cargo/config.toml b/.cargo/config.toml index eff45697d..c34b69ed9 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -10,3 +10,4 @@ linker = "aarch64-linux-gnu-gcc" [alias] windsock = "test --release --bench windsock --features alpha-transforms --" windsock-debug = "test --bench windsock --features alpha-transforms --" +windsock-cloud-docker = "run --package windsock-cloud-docker --" diff --git a/Cargo.lock b/Cargo.lock index d12ea55c7..b0e773962 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5718,6 +5718,13 @@ dependencies = [ "tokio", ] +[[package]] +name = "windsock-cloud-docker" +version = "0.1.0" +dependencies = [ + "test-helpers", +] + [[package]] name = "winnow" version = "0.5.15" diff --git a/Cargo.toml b/Cargo.toml index 1e68afcae..149ce40dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,13 @@ [workspace] -members = ["windsock", "shotover", "shotover-proxy", "test-helpers", "custom-transforms-example", "ec2-cargo"] +members = [ + "windsock", + "shotover", + "shotover-proxy", + "test-helpers", + "custom-transforms-example", + "ec2-cargo", + "windsock-cloud-docker" +] resolver = "2" # https://deterministic.space/high-performance-rust.html diff --git a/test-helpers/src/lib.rs b/test-helpers/src/lib.rs index 87a4e7d12..1e3c7837e 100644 --- a/test-helpers/src/lib.rs +++ b/test-helpers/src/lib.rs @@ -17,7 +17,7 @@ use subprocess::{Exec, Redirection}; /// # Arguments /// * `command` - The system command to run /// * `args` - An array of command line arguments for the command -pub(crate) fn run_command(command: &str, args: &[&str]) -> Result { +pub fn run_command(command: &str, args: &[&str]) -> Result { tracing::trace!("executing {}", command); let data = Exec::cmd(command) .args(args) diff --git a/windsock-cloud-docker/Cargo.toml b/windsock-cloud-docker/Cargo.toml new file mode 100644 index 000000000..21bf1ae0c --- /dev/null +++ b/windsock-cloud-docker/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "windsock-cloud-docker" +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +test-helpers = {path = "../test-helpers"} \ No newline at end of file diff --git a/windsock-cloud-docker/src/main.rs b/windsock-cloud-docker/src/main.rs new file mode 100644 index 000000000..0632957d7 --- /dev/null +++ b/windsock-cloud-docker/src/main.rs @@ -0,0 +1,86 @@ +// A helper to run `windsock --cloud` within docker to workaround libc issues +// It is not possible to use this helper to run windsock locally as that would involve running docker within docker + +use test_helpers::run_command; + +fn main() { + let mut args = std::env::args(); + args.next(); // skip binary name + let args: Vec = args.collect(); + let args = args.join(" "); + + // ensure container is setup + let container_status = docker(&[ + "container", + "ls", + "-a", + "--filter", + "Name=windsock-cloud", + "--format", + "{{.Status}}", + ]); + if container_status.starts_with("Exited") { + docker(&["start", "windsock-cloud"]); + } else if !container_status.starts_with("Up") { + docker(&[ + "run", + "-d", + "--name", + "windsock-cloud", + "ubuntu:20.04", + "sleep", + "infinity", + ]); + container_bash("apt-get update"); + container_bash( + "DEBIAN_FRONTEND=noninteractive apt-get install -y curl git cmake pkg-config g++ libssl-dev librdkafka-dev uidmap", + ); + container_bash("curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y"); + } + + // copy in shotover project + let root = std::env::current_dir().unwrap(); + container_bash("rm -r /shotover-proxy"); + // TODO: This copy will be very expensive if the user doesnt have their target directory setup as a symlink + // Maybe we should do something like: + // 1. rsync to target/shotover-copy-for-docker with the target directory filtered out + // 2. `docker cp target/shotover-copy-for-docker windsock-cloud:/shotover-proxy` + docker(&[ + "cp", + root.to_str().unwrap(), + "windsock-cloud:/shotover-proxy", + ]); + container_bash("rm -r /shotover-proxy/target"); + + // run windsock + let access_key_id = std::env::var("AWS_ACCESS_KEY_ID").unwrap(); + let secret_access_key = std::env::var("AWS_SECRET_ACCESS_KEY").unwrap(); + container_bash(&format!( + r#"cd shotover-proxy; +source "$HOME/.cargo/env"; +AWS_ACCESS_KEY_ID={access_key_id} AWS_SECRET_ACCESS_KEY={secret_access_key} CARGO_TERM_COLOR=always cargo test --target-dir /target --release --bench windsock --features alpha-transforms -- {args}"# + )); +} + +pub fn docker(args: &[&str]) -> String { + run_command("docker", args).unwrap() +} + +pub fn container_bash(command: &str) { + run_command_to_stdout("docker", &["exec", "windsock-cloud", "bash", "-c", command]) +} + +pub fn run_command_to_stdout(command: &str, args: &[&str]) { + let status = std::process::Command::new("docker") + .args(args) + .status() + .unwrap(); + + if !status.success() { + println!( + "Failed to run windsock, command {} {:?} exited with {:?}", + command, args, status + ); + std::process::exit(status.code().unwrap_or(1)) + } +} diff --git a/windsock/src/tables.rs b/windsock/src/tables.rs index 3b9f3a459..95431d0ed 100644 --- a/windsock/src/tables.rs +++ b/windsock/src/tables.rs @@ -141,6 +141,14 @@ pub(crate) fn display_results_table(reports: &[ReportColumn]) { } fn base(reports: &[ReportColumn], table_type: &str) { + // if the user has set CARGO_TERM_COLOR to force cargo to use colors then they probably want us to use colors too + if std::env::var("CARGO_TERM_COLOR") + .map(|x| x.to_lowercase() == "always") + .unwrap_or(false) + { + console::set_colors_enabled(true); + } + let mut intersection = reports[0].current.tags.clone(); for report in reports { intersection = intersection.intersection(&report.current.tags);