forked from torrust/torrust-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ec13fb4 ci: [torrust#634] run E2E tests in the testing workflow (Jose Celano) 4edcd2e ci: [torrust#634] new script to run E2E tests (Jose Celano) 8e43205 ci: [torrust#634] new dependency to make temp dirs (Jose Celano) Pull request description: A new binary to run E2E tests: - [x] Build the docker image. - [x] Run the docker image. - [x] Wait until the container is healthy. - [x] Parse logs to get running services. - [x] Build config file for the tracker_checker. - [x] Run the tracker_checker. - [x] Stop the container. ACKs for top commit: josecelano: ACK ec13fb4 Tree-SHA512: e3ae9d399cdf911b0ef8f14afd838c85e007996355632bf265baa640c6c611952f1feab038334a5a3fe1a567561b0fcbc81d56770d8908db9d8ae0c06f1758ab
- Loading branch information
Showing
12 changed files
with
646 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -116,6 +116,7 @@ | |
"Swatinem", | ||
"Swiftbit", | ||
"taiki", | ||
"tempfile", | ||
"thiserror", | ||
"tlsv", | ||
"Torrentstorm", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
announce_interval = 120 | ||
db_driver = "Sqlite3" | ||
db_path = "/var/lib/torrust/tracker/database/sqlite3.db" | ||
external_ip = "0.0.0.0" | ||
inactive_peer_cleanup_interval = 600 | ||
log_level = "info" | ||
max_peer_timeout = 900 | ||
min_announce_interval = 120 | ||
mode = "public" | ||
on_reverse_proxy = false | ||
persistent_torrent_completed_stat = false | ||
remove_peerless_torrents = true | ||
tracker_usage_statistics = true | ||
|
||
[[udp_trackers]] | ||
bind_address = "0.0.0.0:6969" | ||
enabled = true | ||
|
||
[[http_trackers]] | ||
bind_address = "0.0.0.0:7070" | ||
enabled = true | ||
ssl_cert_path = "/var/lib/torrust/tracker/tls/localhost.crt" | ||
ssl_enabled = false | ||
ssl_key_path = "/var/lib/torrust/tracker/tls/localhost.key" | ||
|
||
[http_api] | ||
bind_address = "0.0.0.0:1212" | ||
enabled = true | ||
ssl_cert_path = "/var/lib/torrust/tracker/tls/localhost.crt" | ||
ssl_enabled = false | ||
ssl_key_path = "/var/lib/torrust/tracker/tls/localhost.key" | ||
|
||
# Please override the admin token setting the | ||
# `TORRUST_TRACKER_API_ADMIN_TOKEN` | ||
# environmental variable! | ||
|
||
[http_api.access_tokens] | ||
admin = "MyAccessToken" | ||
|
||
[health_check_api] | ||
bind_address = "0.0.0.0:1313" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
//! Program to run E2E tests. | ||
//! | ||
//! ```text | ||
//! cargo run --bin e2e_tests_runner share/default/config/tracker.e2e.container.sqlite3.toml | ||
//! ``` | ||
use torrust_tracker::e2e; | ||
|
||
fn main() { | ||
e2e::runner::run(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
//! Docker command wrapper. | ||
use std::io; | ||
use std::process::{Command, Output}; | ||
use std::thread::sleep; | ||
use std::time::{Duration, Instant}; | ||
|
||
use log::debug; | ||
|
||
/// Docker command wrapper. | ||
pub struct Docker {} | ||
|
||
pub struct RunningContainer { | ||
pub name: String, | ||
pub output: Output, | ||
} | ||
|
||
impl Drop for RunningContainer { | ||
/// Ensures that the temporary container is stopped and removed when the | ||
/// struct goes out of scope. | ||
fn drop(&mut self) { | ||
let _unused = Docker::stop(self); | ||
let _unused = Docker::remove(&self.name); | ||
} | ||
} | ||
|
||
impl Docker { | ||
/// Builds a Docker image from a given Dockerfile. | ||
/// | ||
/// # Errors | ||
/// | ||
/// Will fail if the docker build command fails. | ||
pub fn build(dockerfile: &str, tag: &str) -> io::Result<()> { | ||
let status = Command::new("docker") | ||
.args(["build", "-f", dockerfile, "-t", tag, "."]) | ||
.status()?; | ||
|
||
if status.success() { | ||
Ok(()) | ||
} else { | ||
Err(io::Error::new( | ||
io::ErrorKind::Other, | ||
format!("Failed to build Docker image from dockerfile {dockerfile}"), | ||
)) | ||
} | ||
} | ||
|
||
/// Runs a Docker container from a given image with multiple environment variables. | ||
/// | ||
/// # Arguments | ||
/// | ||
/// * `image` - The Docker image to run. | ||
/// * `container` - The name for the Docker container. | ||
/// * `env_vars` - A slice of tuples, each representing an environment variable as ("KEY", "value"). | ||
/// | ||
/// # Errors | ||
/// | ||
/// Will fail if the docker run command fails. | ||
pub fn run(image: &str, container: &str, env_vars: &[(String, String)], ports: &[String]) -> io::Result<RunningContainer> { | ||
let initial_args = vec![ | ||
"run".to_string(), | ||
"--detach".to_string(), | ||
"--name".to_string(), | ||
container.to_string(), | ||
]; | ||
|
||
// Add environment variables | ||
let mut env_var_args: Vec<String> = vec![]; | ||
for (key, value) in env_vars { | ||
env_var_args.push("--env".to_string()); | ||
env_var_args.push(format!("{key}={value}")); | ||
} | ||
|
||
// Add port mappings | ||
let mut port_args: Vec<String> = vec![]; | ||
for port in ports { | ||
port_args.push("--publish".to_string()); | ||
port_args.push(port.to_string()); | ||
} | ||
|
||
let args = [initial_args, env_var_args, port_args, [image.to_string()].to_vec()].concat(); | ||
|
||
debug!("Docker run args: {:?}", args); | ||
|
||
let output = Command::new("docker").args(args).output()?; | ||
|
||
if output.status.success() { | ||
Ok(RunningContainer { | ||
name: container.to_owned(), | ||
output, | ||
}) | ||
} else { | ||
Err(io::Error::new( | ||
io::ErrorKind::Other, | ||
format!("Failed to run Docker image {image}"), | ||
)) | ||
} | ||
} | ||
|
||
/// Stops a Docker container. | ||
/// | ||
/// # Errors | ||
/// | ||
/// Will fail if the docker stop command fails. | ||
pub fn stop(container: &RunningContainer) -> io::Result<()> { | ||
let status = Command::new("docker").args(["stop", &container.name]).status()?; | ||
|
||
if status.success() { | ||
Ok(()) | ||
} else { | ||
Err(io::Error::new( | ||
io::ErrorKind::Other, | ||
format!("Failed to stop Docker container {}", container.name), | ||
)) | ||
} | ||
} | ||
|
||
/// Removes a Docker container. | ||
/// | ||
/// # Errors | ||
/// | ||
/// Will fail if the docker rm command fails. | ||
pub fn remove(container: &str) -> io::Result<()> { | ||
let status = Command::new("docker").args(["rm", "-f", container]).status()?; | ||
|
||
if status.success() { | ||
Ok(()) | ||
} else { | ||
Err(io::Error::new( | ||
io::ErrorKind::Other, | ||
format!("Failed to remove Docker container {container}"), | ||
)) | ||
} | ||
} | ||
|
||
/// Fetches logs from a Docker container. | ||
/// | ||
/// # Errors | ||
/// | ||
/// Will fail if the docker logs command fails. | ||
pub fn logs(container: &str) -> io::Result<String> { | ||
let output = Command::new("docker").args(["logs", container]).output()?; | ||
|
||
if output.status.success() { | ||
Ok(String::from_utf8_lossy(&output.stdout).to_string()) | ||
} else { | ||
Err(io::Error::new( | ||
io::ErrorKind::Other, | ||
format!("Failed to fetch logs from Docker container {container}"), | ||
)) | ||
} | ||
} | ||
|
||
/// Checks if a Docker container is healthy. | ||
#[must_use] | ||
pub fn wait_until_is_healthy(name: &str, timeout: Duration) -> bool { | ||
let start = Instant::now(); | ||
|
||
while start.elapsed() < timeout { | ||
let Ok(output) = Command::new("docker") | ||
.args(["ps", "-f", &format!("name={name}"), "--format", "{{.Status}}"]) | ||
.output() | ||
else { | ||
return false; | ||
}; | ||
|
||
let output_str = String::from_utf8_lossy(&output.stdout); | ||
|
||
if output_str.contains("(healthy)") { | ||
return true; | ||
} | ||
|
||
sleep(Duration::from_secs(1)); | ||
} | ||
|
||
false | ||
} | ||
} |
Oops, something went wrong.