Skip to content

Commit

Permalink
feat: Health check command (#134)
Browse files Browse the repository at this point in the history
This PR adds a `health-check` command to the CLI. You can call
`rss-funnel health-check` to check if the server is running and healthy.
The Docker image now also includes the `HEALTHCHECK CMD` directive.

Internally it does a simple GET request to the `/_health` endpoint.

Options:

- `-s`/`--server`/`RSS_FUNNEL_HEALTH_CHECK_SERVER` - The server to
check. Default: `http://127.0.0.1:4080`.

Closes #128.
  • Loading branch information
shouya authored Jul 20, 2024
1 parent 03a2124 commit 4feeab9
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 2 deletions.
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM scratch
COPY %RELEASE_BINARY% /rss-funnel
ENTRYPOINT ["/rss-funnel"]
EXPOSE 8080
HEALTHCHECK CMD ["/rss-funnel", "health-check"]
CMD ["server"]
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@ $(IMAGE_NAME)\:latest-% $(IMAGE_NAME)\:nightly-%: $(IMAGE_NAME)\:$(VERSION)-%
podman tag $< $@

$(IMAGE_NAME)\:$(VERSION)-%: target/%/release/$(APP_NAME)
echo "FROM scratch\nCOPY $< /$(APP_NAME)\nENTRYPOINT [\"/$(APP_NAME)\"]\nCMD [\"server\"]\n" | \
podman build -f - . --platform $(PLATFORM_$*) -t $@
cat Dockerfile | \
sed -e "s|%RELEASE_BINARY%|$<|g" | \
podman build -f - . \
--format docker \
--platform $(PLATFORM_$*) -t $@

# building multiarch manifest requires the image to be pushed to the
# registry first.
Expand Down
40 changes: 40 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,24 @@ pub struct Cli {
enum SubCommand {
/// Start the server
Server(ServerConfig),
HealthCheck(HealthCheckConfig),
/// Test an endpoint
// boxed because of the clippy::large_enum_variant warning
Test(Box<TestConfig>),
}

#[derive(Parser)]
struct HealthCheckConfig {
/// The endpoint to test
#[clap(
long,
short,
default_value = "127.0.0.1:4080",
env = "RSS_FUNNEL_HEALTH_CHECK_SERVER"
)]
server: String,
}

#[derive(Parser)]
struct TestConfig {
/// The endpoint to test
Expand Down Expand Up @@ -115,6 +128,9 @@ impl Cli {
test_endpoint(feed_defn, &test_config).await;
Ok(())
}
SubCommand::HealthCheck(health_check_config) => {
health_check(health_check_config).await
}
}
}
}
Expand Down Expand Up @@ -144,3 +160,27 @@ async fn test_endpoint(feed_defn: RootConfig, test_config: &TestConfig) {
println!("{}", feed.serialize(true).expect("failed serializing feed"));
}
}

async fn health_check(health_check_config: HealthCheckConfig) -> Result<()> {
let mut server = health_check_config.server;
if !server.starts_with("http://") && !server.starts_with("https://") {
server = format!("http://{server}");
}

let url = Url::parse(&server)?.join("/_health")?;
match reqwest::get(url.clone()).await {
Ok(res) if res.status().is_success() => {
eprintln!("{server} is healthy");
Ok(())
}
Err(e) => {
eprintln!("failed to check health: {e}");
std::process::exit(1);
}
Ok(res) => {
let status = res.status();
eprintln!("{url} returned {status}");
std::process::exit(1);
}
}
}
2 changes: 2 additions & 0 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ impl ServerConfig {
.layer(CompressionLayer::new().gzip(true));

app = app
// deprecated, will be removed on 0.2
.route("/health", get(|| async { "ok" }))
.route("/_health", get(|| async { "ok" }))
.merge(image_proxy::router())
.merge(feed_service_router)
.layer(Extension(feed_service));
Expand Down

0 comments on commit 4feeab9

Please sign in to comment.