Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Health check ogmios proxy #20

Merged
merged 10 commits into from
Feb 23, 2024
12 changes: 6 additions & 6 deletions operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ This operator allows demeter to run and expose ogmios

## Environment

| Key | Value |
| ------------- | ------------ |
| ADDR | 0.0.0.0:5000 |
| DNS_ZONE | demeter.run |
| INGRESS_CLASS | ogmios-v1 |
| API_KEY_SALT | ogmios-salt |
| Key | Value |
| -------------- | ------------ |
| ADDR | 0.0.0.0:5000 |
| DNS_ZONE | demeter.run |
| EXTENSION_NAME | ogmios-m1 |
| API_KEY_SALT | ogmios-salt |

## Commands

Expand Down
6 changes: 3 additions & 3 deletions operator/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub fn get_config() -> &'static Config {
#[derive(Debug, Clone)]
pub struct Config {
pub dns_zone: String,
pub ingress_class: String,
pub extension_name: String,
pub api_key_salt: String,
pub dcu_per_frame: HashMap<String, f64>,
pub metrics_delay: Duration,
Expand All @@ -22,7 +22,7 @@ pub struct Config {
impl Config {
pub fn from_env() -> Self {
let dns_zone = env::var("DNS_ZONE").unwrap_or("demeter.run".into());
let ingress_class = env::var("INGRESS_CLASS").unwrap_or("ogmios-m1".into());
let extension_name = env::var("EXTENSION_NAME").unwrap_or("ogmios-m1".into());
let api_key_salt = env::var("API_KEY_SALT").unwrap_or("ogmios-salt".into());
let dcu_per_frame = env::var("DCU_PER_FRAME")
.expect("DCU_PER_FRAME must be set")
Expand All @@ -47,7 +47,7 @@ impl Config {

Self {
dns_zone,
ingress_class,
extension_name,
api_key_salt,
dcu_per_frame,
metrics_delay,
Expand Down
6 changes: 3 additions & 3 deletions operator/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ pub async fn patch_resource_status(

pub fn build_hostname(network: &Network, version: &u8, key: &str) -> (String, String) {
let config = get_config();
let ingress_class = &config.ingress_class;
let extension_name = &config.extension_name;
let dns_zone = &config.dns_zone;

let hostname = format!("{network}-v{version}.{ingress_class}.{dns_zone}");
let hostname_key = format!("{key}.{network}-v{version}.{ingress_class}.{dns_zone}");
let hostname = format!("{network}-v{version}.{extension_name}.{dns_zone}");
let hostname_key = format!("{key}.{network}-v{version}.{extension_name}.{dns_zone}");

(hostname, hostname_key)
}
Expand Down
77 changes: 48 additions & 29 deletions proxy/src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use hyper::header::{
HeaderValue, CONNECTION, HOST, SEC_WEBSOCKET_ACCEPT, SEC_WEBSOCKET_KEY, UPGRADE,
};
use hyper::service::service_fn;
use hyper::{Request, Response, StatusCode};
use hyper::{Method, Request, Response, StatusCode};
use hyper_util::rt::{TokioExecutor, TokioIo};
use hyper_util::server::conn::auto::Builder;
use rustls::ServerConfig;
Expand Down Expand Up @@ -94,31 +94,43 @@ async fn handle(
mut hyper_req: Request<Incoming>,
rw_state: Arc<RwLock<State>>,
) -> Result<ProxyResponse, hyper::Error> {
let state = rw_state.read().await.clone();
let proxy_req = ProxyRequest::new(&mut hyper_req, &state);
match (hyper_req.method(), hyper_req.uri().path()) {
(&Method::GET, "/healthz") => handle_healthz().await,
_ => {
let state = rw_state.read().await.clone();
let proxy_req_result = ProxyRequest::new(&mut hyper_req, &state);
if proxy_req_result.is_none() {
return Ok(Response::builder()
.status(StatusCode::BAD_GATEWAY)
.body(full("Invalid hostname"))
.unwrap());
}

if proxy_req.consumer.is_none() {
return Ok(Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body(full("Unauthorized"))
.unwrap());
}
let proxy_req = proxy_req_result.unwrap();
if proxy_req.consumer.is_none() {
return Ok(Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body(full("Unauthorized"))
.unwrap());
}

let response_result = match proxy_req.protocol {
Protocol::Http => handle_http(hyper_req, &proxy_req).await,
Protocol::Websocket => handle_websocket(hyper_req, &proxy_req, rw_state).await,
};
let response_result = match proxy_req.protocol {
Protocol::Http => handle_http(hyper_req, &proxy_req).await,
Protocol::Websocket => handle_websocket(hyper_req, &proxy_req, rw_state).await,
};

match &response_result {
Ok(response) => {
state
.metrics
.count_http_total_request(&proxy_req, response.status());
}
Err(_) => todo!("send error to prometheus"),
};
match &response_result {
Ok(response) => {
state
.metrics
.count_http_total_request(&proxy_req, response.status());
}
Err(_) => todo!("send error to prometheus"),
};

response_result
response_result
}
}
}

async fn handle_http(
Expand Down Expand Up @@ -204,6 +216,13 @@ async fn handle_websocket(
Ok(res)
}

async fn handle_healthz() -> Result<ProxyResponse, hyper::Error> {
Ok(Response::builder()
.status(StatusCode::OK)
.body(full("pong"))
.unwrap())
}

#[derive(Debug, Clone)]
pub enum Protocol {
Http,
Expand All @@ -227,13 +246,13 @@ pub struct ProxyRequest {
pub protocol: Protocol,
}
impl ProxyRequest {
pub fn new(hyper_req: &mut Request<Incoming>, state: &State) -> Self {
let mut host = get_header(hyper_req, HOST.as_str()).unwrap();
pub fn new(hyper_req: &mut Request<Incoming>, state: &State) -> Option<Self> {
let mut host = get_header(hyper_req, HOST.as_str())?;
let host_regex = host.clone();

let captures = state.host_regex.captures(&host_regex).unwrap();
let network = captures.get(2).unwrap().as_str().to_string();
let version = captures.get(3).unwrap().as_str().to_string();
let captures = state.host_regex.captures(&host_regex)?;
let network = captures.get(2)?.as_str().to_string();
let version = captures.get(3)?.as_str().to_string();

let instance = format!("ogmios-{network}-{version}:{}", state.config.ogmios_port);
let namespace = state.config.proxy_namespace.clone();
Expand All @@ -259,13 +278,13 @@ impl ProxyRequest {
let token = get_header(hyper_req, DMTR_API_KEY).unwrap_or_default();
let consumer = state.get_auth_token(&network, &version, &token);

Self {
Some(Self {
namespace,
instance,
consumer,
protocol,
host,
}
})
}
}

Expand Down
Loading