Skip to content

Commit af06cfb

Browse files
committed
ci: [#384] add container healthcheck for index service
For both services: - The Index API - The Tracker Stattistics Importer (console cronjob) An API was added for the Importer. The Importer API has two endpoints: - GET /health_check -> to get the crobjob status. It only checks that is running periodically. - POST /heartbeat -> used by the cronjob to inform it's alive. And a new endpoint was added the the Index API: - GET /health_check -> to check API responsiveness.
1 parent 04b70ba commit af06cfb

File tree

16 files changed

+220
-34
lines changed

16 files changed

+220
-34
lines changed

Containerfile

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ COPY --from=build \
8585
RUN cargo nextest run --workspace-remap /test/src/ --extract-to /test/src/ --no-run --archive-file /test/torrust-index.tar.zst
8686
RUN cargo nextest run --workspace-remap /test/src/ --target-dir-remap /test/src/target/ --cargo-metadata /test/src/target/nextest/cargo-metadata.json --binaries-metadata /test/src/target/nextest/binaries-metadata.json
8787

88-
RUN mkdir -p /app/bin/; cp -l /test/src/target/release/torrust-index /app/bin/torrust-index
88+
RUN mkdir -p /app/bin/; \
89+
cp -l /test/src/target/release/torrust-index /app/bin/torrust-index; \
90+
cp -l /test/src/target/release/health_check /app/bin/health_check;
8991
# RUN mkdir -p /app/lib/; cp -l $(realpath $(ldd /app/bin/torrust-index | grep "libz\.so\.1" | awk '{print $3}')) /app/lib/libz.so.1
9092
RUN chown -R root:root /app; chmod -R u=rw,go=r,a+X /app; chmod -R a+x /app/bin
9193

@@ -99,11 +101,13 @@ ARG TORRUST_INDEX_PATH_CONFIG="/etc/torrust/index/index.toml"
99101
ARG TORRUST_INDEX_DATABASE_DRIVER="sqlite3"
100102
ARG USER_ID=1000
101103
ARG API_PORT=3001
104+
ARG IMPORTER_API_PORT=3002
102105

103106
ENV TORRUST_INDEX_PATH_CONFIG=${TORRUST_INDEX_PATH_CONFIG}
104107
ENV TORRUST_INDEX_DATABASE_DRIVER=${TORRUST_INDEX_DATABASE_DRIVER}
105108
ENV USER_ID=${USER_ID}
106109
ENV API_PORT=${API_PORT}
110+
ENV IMPORTER_API_PORT=${IMPORTER_API_PORT}
107111
ENV TZ=Etc/UTC
108112

109113
EXPOSE ${API_PORT}/tcp
@@ -130,5 +134,6 @@ CMD ["sh"]
130134
FROM runtime as release
131135
ENV RUNTIME="release"
132136
COPY --from=test /app/ /usr/
133-
# HEALTHCHECK CMD ["/usr/bin/wget", "--no-verbose", "--tries=1", "--spider", "localhost:${API_PORT}/version"]
137+
HEALTHCHECK --interval=5s --timeout=5s --start-period=3s --retries=3 \
138+
CMD /usr/bin/health_check http://localhost:${API_PORT}/health_check && /usr/bin/health_check http://localhost:${IMPORTER_API_PORT}/health_check || exit 1
134139
CMD ["/usr/bin/torrust-index"]

contrib/dev-tools/container/e2e/mysql/run-e2e-tests.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ echo "Running E2E tests using MySQL ..."
2525
./contrib/dev-tools/container/e2e/mysql/e2e-env-up.sh || exit 1
2626

2727
# Wait for conatiners to be healthy
28-
./contrib/dev-tools/container/functions/wait_for_container_to_be_healthy.sh torrust-mysql-1 10 3
29-
# todo: implement healthchecks for tracker and index and wait until they are healthy
30-
#wait_for_container torrust-tracker-1 10 3
31-
#wait_for_container torrust-idx-back-1 10 3
28+
./contrib/dev-tools/container/functions/wait_for_container_to_be_healthy.sh torrust-mysql-1 10 3 || exit 1
29+
# todo: implement healthchecks for the tracker and wait until it's healthy
30+
#./contrib/dev-tools/container/functions/wait_for_container_to_be_healthy.sh torrust-tracker-1 10 3
31+
./contrib/dev-tools/container/functions/wait_for_container_to_be_healthy.sh torrust-index-1 10 3 || exit 1
3232
sleep 20s
3333

3434
# Just to make sure that everything is up and running

contrib/dev-tools/container/e2e/sqlite/run-e2e-tests.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ echo "Running E2E tests using SQLite ..."
2626
./contrib/dev-tools/container/e2e/sqlite/e2e-env-up.sh || exit 1
2727

2828
# Wait for conatiners to be healthy
29-
./contrib/dev-tools/container/functions/wait_for_container_to_be_healthy.sh torrust-mysql-1 10 3
30-
# todo: implement healthchecks for tracker and index and wait until they are healthy
31-
#wait_for_container torrust-tracker-1 10 3
32-
#wait_for_container torrust-idx-back-1 10 3
29+
./contrib/dev-tools/container/functions/wait_for_container_to_be_healthy.sh torrust-mysql-1 10 3 || exit 1
30+
# todo: implement healthchecks for the tracker and wait until it's healthy
31+
#./contrib/dev-tools/container/functions/wait_for_container_to_be_healthy.sh torrust-tracker-1 10 3
32+
./contrib/dev-tools/container/functions/wait_for_container_to_be_healthy.sh torrust-index-1 10 3 || exit 1
3333
sleep 20s
3434

3535
# Just to make sure that everything is up and running

share/default/config/index.container.mysql.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,4 @@ max_torrent_page_size = 30
4848

4949
[tracker_statistics_importer]
5050
torrent_info_update_interval = 3600
51+
port = 3002

share/default/config/index.container.sqlite3.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,4 @@ max_torrent_page_size = 30
4848

4949
[tracker_statistics_importer]
5050
torrent_info_update_interval = 3600
51+
port = 3002

share/default/config/index.development.sqlite3.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@ max_torrent_page_size = 30
4444

4545
[tracker_statistics_importer]
4646
torrent_info_update_interval = 3600
47+
port = 3002

src/app.rs

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ use crate::services::user::{self, DbBannedUserList, DbUserProfileRepository, DbU
1919
use crate::services::{proxy, settings, torrent};
2020
use crate::tracker::statistics_importer::StatisticsImporter;
2121
use crate::web::api::v1::auth::Authentication;
22-
use crate::web::api::{start, Version};
23-
use crate::{mailer, tracker};
22+
use crate::web::api::Version;
23+
use crate::{console, mailer, tracker, web};
2424

2525
pub struct Running {
2626
pub api_socket_addr: SocketAddr,
@@ -46,8 +46,12 @@ pub async fn run(configuration: Configuration, api_version: &Version) -> Running
4646

4747
let settings = configuration.settings.read().await;
4848

49+
// From [database] config
4950
let database_connect_url = settings.database.connect_url.clone();
50-
let torrent_info_update_interval = settings.tracker_statistics_importer.torrent_info_update_interval;
51+
// From [importer] config
52+
let importer_torrent_info_update_interval = settings.tracker_statistics_importer.torrent_info_update_interval;
53+
let importer_port = settings.tracker_statistics_importer.port;
54+
// From [net] config
5155
let net_ip = "0.0.0.0".to_string();
5256
let net_port = settings.net.port;
5357

@@ -153,29 +157,18 @@ pub async fn run(configuration: Configuration, api_version: &Version) -> Running
153157
ban_service,
154158
));
155159

156-
// Start repeating task to import tracker torrent data and updating
160+
// Start cronjob to import tracker torrent data and updating
157161
// seeders and leechers info.
158-
159-
let weak_tracker_statistics_importer = Arc::downgrade(&tracker_statistics_importer);
160-
161-
let tracker_statistics_importer_handle = tokio::spawn(async move {
162-
let interval = std::time::Duration::from_secs(torrent_info_update_interval);
163-
let mut interval = tokio::time::interval(interval);
164-
interval.tick().await; // first tick is immediate...
165-
loop {
166-
interval.tick().await;
167-
if let Some(tracker) = weak_tracker_statistics_importer.upgrade() {
168-
drop(tracker.import_all_torrents_statistics().await);
169-
} else {
170-
break;
171-
}
172-
}
173-
});
162+
let tracker_statistics_importer_handle = console::tracker_statistics_importer::start(
163+
importer_port,
164+
importer_torrent_info_update_interval,
165+
&tracker_statistics_importer,
166+
);
174167

175168
// Start API server
169+
let running_api = web::api::start(app_data, &net_ip, net_port, api_version).await;
176170

177-
let running_api = start(app_data, &net_ip, net_port, api_version).await;
178-
171+
// Full running application
179172
Running {
180173
api_socket_addr: running_api.socket_addr,
181174
api_server: running_api.api_server,

src/bin/health_check.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//! Minimal `curl` or `wget` to be used for container health checks.
2+
//!
3+
//! It's convenient to avoid using third-party libraries because:
4+
//!
5+
//! - They are harder to maintain.
6+
//! - They introduce new attack vectors.
7+
use std::{env, process};
8+
9+
#[tokio::main]
10+
async fn main() {
11+
let args: Vec<String> = env::args().collect();
12+
if args.len() != 2 {
13+
eprintln!("Usage: cargo run --bin health_check <HEALTH_URL>");
14+
eprintln!("Example: cargo run --bin health_check http://localhost:3002/health_check");
15+
std::process::exit(1);
16+
}
17+
18+
println!("Health check ...");
19+
20+
let url = &args[1].clone();
21+
22+
match reqwest::get(url).await {
23+
Ok(response) => {
24+
if response.status().is_success() {
25+
println!("STATUS: {}", response.status());
26+
process::exit(0);
27+
} else {
28+
println!("Non-success status received.");
29+
process::exit(1);
30+
}
31+
}
32+
Err(err) => {
33+
println!("ERROR: {err}");
34+
process::exit(1);
35+
}
36+
}
37+
}

src/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,12 +334,15 @@ impl Default for Api {
334334
pub struct TrackerStatisticsImporter {
335335
/// The interval in seconds to get statistics from the tracker.
336336
pub torrent_info_update_interval: u64,
337+
/// The port the Importer API is listening on. Default to `3002`.
338+
pub port: u16,
337339
}
338340

339341
impl Default for TrackerStatisticsImporter {
340342
fn default() -> Self {
341343
Self {
342344
torrent_info_update_interval: 3600,
345+
port: 3002,
343346
}
344347
}
345348
}

src/console/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod commands;
2+
pub(crate) mod tracker_statistics_importer;

0 commit comments

Comments
 (0)