Unverified Commit 2de6815c authored by Julian Antonielli's avatar Julian Antonielli Committed by GitHub
Browse files

Add `AlbHealthCheckLayer` (#2540)

## Motivation and Context
Services often need the ability to report health status via health
checks (see [ALB Health
Checks](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html)).
This PR adds a simple layer that allows configuring your service to
respond to these health check requests.

## Description
Adds `AlbHealthCheckLayer`, and `AlbHealthCheckService`.

## Testing
Added this layer to the `pokemon-service` binary, and added an
integration test for it.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
parent 07dd8d46
Loading
Loading
Loading
Loading
+21 −6
Original line number Diff line number Diff line
@@ -11,14 +11,29 @@
# meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "client | server | all"}
# author = "rcoh"

[[smithy-rs]]
message = """
Implement layer for servers to handle [ALB health checks](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html).
Take a look at `aws_smithy_http_server::plugin::alb_health_check` to learn about it.
"""
references = ["smithy-rs#2540"]
meta = { "breaking" = false, "tada" = true, "bug" = false, "target" = "server" }
author = "jjant"

[[smithy-rs]]
message = "Implement `PluginPipeline::http_layer` which allows you to apply a `tower::Layer` to all operations."
references = ["smithy-rs#2540"]
meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "server" }
author = "jjant"

[[aws-sdk-rust]]
message = "Implement std::error::Error#source() properly for the service meta Error enum"
message = "Implement std::error::Error#source() properly for the service meta Error enum."
references = ["aws-sdk-rust#784"]
meta = { "breaking" = false, "tada" = false, "bug" = false }
author = "abusch"

[[smithy-rs]]
message = "Implement std::error::Error#source() properly for the service meta Error enum"
message = "Implement std::error::Error#source() properly for the service meta Error enum."
references = ["aws-sdk-rust#784"]
meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "client" }
author = "abusch"
+3 −0
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@ async-stream = "0.3"
rand = "0.8.5"
serial_test = "1.0.0"

# We use hyper client in tests
hyper = {version = "0.14.25", features = ["server", "client"] }

# This dependency is only required for testing the `pokemon-service-tls` program.
hyper-rustls = { version = "0.23.2", features = ["http2"] }

+12 −3
Original line number Diff line number Diff line
@@ -8,11 +8,15 @@ mod plugin;
use std::{net::SocketAddr, sync::Arc};

use aws_smithy_http_server::{
    extension::OperationExtensionExt, instrumentation::InstrumentExt, plugin::PluginPipeline,
    request::request_id::ServerRequestIdProviderLayer, AddExtensionLayer,
    extension::OperationExtensionExt,
    instrumentation::InstrumentExt,
    plugin::{alb_health_check::AlbHealthCheckLayer, PluginPipeline},
    request::request_id::ServerRequestIdProviderLayer,
    AddExtensionLayer,
};
use clap::Parser;

use hyper::StatusCode;
use plugin::PrintExt;

use pokemon_service::{
@@ -47,7 +51,12 @@ pub async fn main() {
        // `Response::extensions`, or infer routing failure when it's missing.
        .insert_operation_extension()
        // Adds `tracing` spans and events to the request lifecycle.
        .instrument();
        .instrument()
        // Handle `/ping` health check requests.
        .http_layer(AlbHealthCheckLayer::from_handler("/ping", |_req| async {
            StatusCode::OK
        }));

    let app = PokemonService::builder_with_plugins(plugins)
        // Build a registry containing implementations to all the operations in the service. These
        // are async functions or async closures that take as input the operation's input and
+4 −0
Original line number Diff line number Diff line
@@ -23,6 +23,10 @@ pub async fn run_server() -> ChildDrop {
    ChildDrop(child)
}

pub fn base_url() -> String {
    format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}")
}

pub fn client() -> Client<DynConnector, DynMiddleware<DynConnector>> {
    let authority = Authority::from_str(&format!("{DEFAULT_ADDRESS}:{DEFAULT_PORT}"))
        .expect("could not parse authority");
+7 −0
Original line number Diff line number Diff line
@@ -81,4 +81,11 @@ async fn simple_integration_test() {

    let service_statistics_out = client.get_server_statistics().send().await.unwrap();
    assert_eq!(2, service_statistics_out.calls_count.unwrap());

    let hyper_client = hyper::Client::new();
    let health_check_url = format!("{}/ping", common::base_url());
    let health_check_url = hyper::Uri::try_from(health_check_url).unwrap();
    let result = hyper_client.get(health_check_url).await.unwrap();

    assert_eq!(result.status(), 200);
}
Loading