Skip to content

Commit 307b41d

Browse files
committed
ci: [#384] add container healthcheck for index service
1 parent 04b70ba commit 307b41d

File tree

6 files changed

+86
-11
lines changed

6 files changed

+86
-11
lines changed

Containerfile

Lines changed: 8 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,14 +101,17 @@ 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 HEALTH_CHECK_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 HEALTH_CHECK_PORT=${HEALTH_CHECK_PORT}
107111
ENV TZ=Etc/UTC
108112

109113
EXPOSE ${API_PORT}/tcp
114+
EXPOSE ${HEALTH_CHECK_PORT}/tcp
110115

111116
RUN mkdir -p /var/lib/torrust/index /var/log/torrust/index /etc/torrust/index
112117

@@ -130,5 +135,6 @@ CMD ["sh"]
130135
FROM runtime as release
131136
ENV RUNTIME="release"
132137
COPY --from=test /app/ /usr/
133-
# HEALTHCHECK CMD ["/usr/bin/wget", "--no-verbose", "--tries=1", "--spider", "localhost:${API_PORT}/version"]
138+
HEALTHCHECK --interval=5s --timeout=5s --start-period=3s --retries=3 \
139+
CMD ["/usr/bin/health_check", "http://localhost:${HEALTHCHECK_PORT}/health_check"]
134140
CMD ["/usr/bin/torrust-index"]

compose.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ services:
1616
- server_side
1717
ports:
1818
- 3001:3001
19+
- 3002:3002
1920
volumes:
2021
- ./storage/index/lib:/var/lib/torrust/index:Z
2122
- ./storage/index/log:/var/log/torrust/index:Z

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ echo "Running E2E tests using MySQL ..."
2626

2727
# Wait for conatiners to be healthy
2828
./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
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
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: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ echo "Running E2E tests using SQLite ..."
2727

2828
# Wait for conatiners to be healthy
2929
./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
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
3333
sleep 20s
3434

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

src/app.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
use std::net::SocketAddr;
22
use std::sync::Arc;
33

4+
use axum::routing::get;
5+
use axum::{Json, Router};
6+
use log::info;
7+
use serde_json::{json, Value};
48
use tokio::task::JoinHandle;
59

610
use crate::bootstrap::logging;
@@ -159,6 +163,8 @@ pub async fn run(configuration: Configuration, api_version: &Version) -> Running
159163
let weak_tracker_statistics_importer = Arc::downgrade(&tracker_statistics_importer);
160164

161165
let tracker_statistics_importer_handle = tokio::spawn(async move {
166+
info!("Tracker statistics importer started");
167+
162168
let interval = std::time::Duration::from_secs(torrent_info_update_interval);
163169
let mut interval = tokio::time::interval(interval);
164170
interval.tick().await; // first tick is immediate...
@@ -173,12 +179,40 @@ pub async fn run(configuration: Configuration, api_version: &Version) -> Running
173179
});
174180

175181
// Start API server
176-
177182
let running_api = start(app_data, &net_ip, net_port, api_version).await;
178183

179-
Running {
184+
// Full running application
185+
let app = Running {
180186
api_socket_addr: running_api.socket_addr,
181187
api_server: running_api.api_server,
182188
tracker_data_importer_handle: tracker_statistics_importer_handle,
183-
}
189+
};
190+
191+
// Start Health Checker
192+
// This must be done after launching the other services because it does not
193+
// re-check the health of all services.
194+
let _health_check_handle = tokio::spawn(async move {
195+
let app = Router::new().route("/health_check", get(get(health_check)));
196+
197+
info!("Health checker listening on http://0.0.0.0:3002/health_check");
198+
199+
axum::Server::bind(&"0.0.0.0:3002".parse().unwrap())
200+
.serve(app.into_make_service())
201+
.await
202+
.unwrap();
203+
});
204+
205+
app
206+
}
207+
208+
/// It runs a health check on the application.
209+
///
210+
/// For the time being, we only return ok if the application services were
211+
/// launched. This services has to be launched after launching all the other
212+
/// application services.
213+
///
214+
/// It's used for container health check when the application is containerized.
215+
async fn health_check() -> Json<Value> {
216+
// todo: check that services are healthy
217+
Json(json!({ "status": "Ok" }))
184218
}

src/bin/health_check.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//! Command line tool to parse a torrent file and print the decoded torrent.
2+
//!
3+
//! It's only used for debugging purposes.
4+
use std::{env, process};
5+
6+
#[tokio::main]
7+
async fn main() {
8+
let args: Vec<String> = env::args().collect();
9+
if args.len() != 2 {
10+
eprintln!("Usage: cargo run --bin health_check <HEALTH_URL>");
11+
eprintln!("Example: cargo run --bin health_check http://localhost:3002/health_check");
12+
std::process::exit(1);
13+
}
14+
15+
println!("Health check ...");
16+
17+
let url = &args[1].clone();
18+
19+
match reqwest::get(url).await {
20+
Ok(response) => {
21+
if response.status().is_success() {
22+
println!("STATUS: {}", response.status());
23+
process::exit(0);
24+
} else {
25+
println!("Non-success status received.");
26+
process::exit(1);
27+
}
28+
}
29+
Err(err) => {
30+
println!("ERROR: {err}");
31+
process::exit(1);
32+
}
33+
}
34+
}

0 commit comments

Comments
 (0)