mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-06 04:47:42 +00:00
Implement /status Admin endpoint
This commit is contained in:
@@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use futures::future::Future;
|
||||
use http::header::CONTENT_TYPE;
|
||||
use http::header::{CONTENT_TYPE, ALLOW, ACCESS_CONTROL_ALLOW_METHODS, ACCESS_CONTROL_ALLOW_ORIGIN};
|
||||
use hyper::{Body, Request, Response};
|
||||
|
||||
use opentelemetry::trace::{SpanRef, Tracer};
|
||||
@@ -17,6 +17,7 @@ use crate::error::*;
|
||||
use crate::generic_server::*;
|
||||
|
||||
use crate::admin::router::{Authorization, Endpoint};
|
||||
use crate::admin::cluster::*;
|
||||
|
||||
pub struct AdminApiServer {
|
||||
garage: Arc<Garage>,
|
||||
@@ -56,6 +57,15 @@ impl AdminApiServer {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_options(&self, _req: &Request<Body>) -> Result<Response<Body>, Error> {
|
||||
Ok(Response::builder()
|
||||
.status(204)
|
||||
.header(ALLOW, "OPTIONS, GET, POST")
|
||||
.header(ACCESS_CONTROL_ALLOW_METHODS, "OPTIONS, GET, POST")
|
||||
.header(ACCESS_CONTROL_ALLOW_ORIGIN, "*")
|
||||
.body(Body::empty())?)
|
||||
}
|
||||
|
||||
fn handle_metrics(&self) -> Result<Response<Body>, Error> {
|
||||
let mut buffer = vec![];
|
||||
let encoder = TextEncoder::new();
|
||||
@@ -110,7 +120,9 @@ impl ApiHandler for AdminApiServer {
|
||||
}
|
||||
|
||||
match endpoint {
|
||||
Endpoint::Options => self.handle_options(&req),
|
||||
Endpoint::Metrics => self.handle_metrics(),
|
||||
Endpoint::GetClusterStatus => handle_get_cluster_status(&self.garage).await,
|
||||
_ => Err(Error::NotImplemented(format!(
|
||||
"Admin endpoint {} not implemented yet",
|
||||
endpoint.name()
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
use std::sync::Arc;
|
||||
use std::collections::HashMap;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
|
||||
use serde::{Serialize};
|
||||
|
||||
use hyper::{Body, Request, Response, StatusCode};
|
||||
|
||||
use garage_util::data::*;
|
||||
use garage_util::error::Error as GarageError;
|
||||
use garage_rpc::layout::*;
|
||||
use garage_rpc::system::*;
|
||||
|
||||
use garage_model::garage::Garage;
|
||||
|
||||
|
||||
use crate::error::*;
|
||||
|
||||
|
||||
pub async fn handle_get_cluster_status(
|
||||
garage: &Arc<Garage>,
|
||||
) -> Result<Response<Body>, Error> {
|
||||
let layout = garage.system.get_cluster_layout();
|
||||
|
||||
let res = GetClusterStatusResponse {
|
||||
known_nodes: garage.system.get_known_nodes()
|
||||
.into_iter()
|
||||
.map(|i| (hex::encode(i.id), KnownNodeResp {
|
||||
addr: i.addr,
|
||||
is_up: i.is_up,
|
||||
last_seen_secs_ago: i.last_seen_secs_ago,
|
||||
hostname: i.status.hostname,
|
||||
}))
|
||||
.collect(),
|
||||
roles: layout.roles.items()
|
||||
.iter()
|
||||
.filter(|(_, _, v)| v.0.is_some())
|
||||
.map(|(k, _, v)| (hex::encode(k), v.0.clone()))
|
||||
.collect(),
|
||||
staged_role_changes: layout.staging.items()
|
||||
.iter()
|
||||
.filter(|(k, _, v)| layout.roles.get(k) != Some(v))
|
||||
.map(|(k, _, v)| (hex::encode(k), v.0.clone()))
|
||||
.collect(),
|
||||
};
|
||||
|
||||
let resp_json = serde_json::to_string_pretty(&res).map_err(GarageError::from)?;
|
||||
Ok(Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.body(Body::from(resp_json))?)
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct GetClusterStatusResponse {
|
||||
#[serde(rename = "knownNodes")]
|
||||
known_nodes: HashMap<String, KnownNodeResp>,
|
||||
roles: HashMap<String, Option<NodeRole>>,
|
||||
#[serde(rename = "stagedRoleChanges")]
|
||||
staged_role_changes: HashMap<String, Option<NodeRole>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct KnownNodeResp {
|
||||
addr: SocketAddr,
|
||||
is_up: bool,
|
||||
last_seen_secs_ago: Option<u64>,
|
||||
hostname: String,
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
pub mod api_server;
|
||||
mod router;
|
||||
|
||||
mod cluster;
|
||||
|
||||
@@ -14,8 +14,8 @@ router_match! {@func
|
||||
/// List of all Admin API endpoints.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Endpoint {
|
||||
Metrics,
|
||||
Options,
|
||||
Metrics,
|
||||
GetClusterStatus,
|
||||
GetClusterLayout,
|
||||
UpdateClusterLayout,
|
||||
|
||||
Reference in New Issue
Block a user