mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-10 06:26:52 +00:00
admi api: remove info about local node from GetClusterStatus and add specific GetNodeInfo endpoint
This commit is contained in:
+18
-7
@@ -10,10 +10,9 @@ use garage_rpc::*;
|
||||
|
||||
use garage_model::garage::Garage;
|
||||
|
||||
use garage_api_common::common_error::CommonErrorDerivative;
|
||||
use garage_api_common::helpers::is_default;
|
||||
|
||||
use crate::api_server::{AdminRpc, AdminRpcResponse};
|
||||
use crate::api_server::{find_matching_nodes, AdminRpc, AdminRpcResponse};
|
||||
use crate::error::Error;
|
||||
use crate::macros::*;
|
||||
use crate::{Admin, RequestHandler};
|
||||
@@ -77,6 +76,7 @@ admin_endpoints![
|
||||
RemoveBucketAlias,
|
||||
|
||||
// Node operations
|
||||
GetNodeInfo,
|
||||
CreateMetadataSnapshot,
|
||||
GetNodeStatistics,
|
||||
GetClusterStatistics,
|
||||
@@ -97,6 +97,7 @@ admin_endpoints![
|
||||
|
||||
local_admin_endpoints![
|
||||
// Node operations
|
||||
GetNodeInfo,
|
||||
CreateMetadataSnapshot,
|
||||
GetNodeStatistics,
|
||||
LaunchRepairOperation,
|
||||
@@ -157,11 +158,6 @@ pub struct GetClusterStatusRequest;
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetClusterStatusResponse {
|
||||
pub node: String,
|
||||
pub garage_version: String,
|
||||
pub garage_features: Option<Vec<String>>,
|
||||
pub rust_version: String,
|
||||
pub db_engine: String,
|
||||
pub layout_version: u64,
|
||||
pub nodes: Vec<NodeResp>,
|
||||
}
|
||||
@@ -636,6 +632,21 @@ pub struct RemoveBucketAliasResponse(pub GetBucketInfoResponse);
|
||||
// Node operations
|
||||
// **********************************************
|
||||
|
||||
// ---- GetNodeInfo ----
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
pub struct LocalGetNodeInfoRequest;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct LocalGetNodeInfoResponse {
|
||||
pub node_id: String,
|
||||
pub garage_version: String,
|
||||
pub garage_features: Option<Vec<String>>,
|
||||
pub rust_version: String,
|
||||
pub db_engine: String,
|
||||
}
|
||||
|
||||
// ---- CreateMetadataSnapshot ----
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
|
||||
@@ -16,6 +16,7 @@ use opentelemetry_prometheus::PrometheusExporter;
|
||||
use garage_model::garage::Garage;
|
||||
use garage_rpc::{Endpoint as RpcEndpoint, *};
|
||||
use garage_util::background::BackgroundRunner;
|
||||
use garage_util::data::Uuid;
|
||||
use garage_util::error::Error as GarageError;
|
||||
use garage_util::socket_address::UnixOrTCPSocketAddress;
|
||||
|
||||
@@ -265,3 +266,40 @@ fn verify_bearer_token(token: &hyper::http::HeaderValue, password_hash: &str) ->
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn find_matching_nodes(garage: &Garage, spec: &str) -> Result<Vec<Uuid>, Error> {
|
||||
let mut res = vec![];
|
||||
if spec == "*" {
|
||||
res = garage.system.cluster_layout().all_nodes().to_vec();
|
||||
for node in garage.system.get_known_nodes() {
|
||||
if node.is_up && !res.contains(&node.id) {
|
||||
res.push(node.id);
|
||||
}
|
||||
}
|
||||
} else if spec == "self" {
|
||||
res.push(garage.system.id);
|
||||
} else {
|
||||
let layout = garage.system.cluster_layout();
|
||||
let known_nodes = garage.system.get_known_nodes();
|
||||
let all_nodes = layout
|
||||
.all_nodes()
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(known_nodes.iter().filter(|x| x.is_up).map(|x| x.id));
|
||||
for node in all_nodes {
|
||||
if !res.contains(&node) && hex::encode(node).starts_with(spec) {
|
||||
res.push(node);
|
||||
}
|
||||
}
|
||||
if res.is_empty() {
|
||||
return Err(Error::bad_request(format!("No nodes matching {}", spec)));
|
||||
}
|
||||
if res.len() > 1 {
|
||||
return Err(Error::bad_request(format!(
|
||||
"Multiple nodes matching {}: {:?}",
|
||||
spec, res
|
||||
)));
|
||||
}
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
@@ -105,12 +105,6 @@ impl RequestHandler for GetClusterStatusRequest {
|
||||
nodes.sort_by(|x, y| x.id.cmp(&y.id));
|
||||
|
||||
Ok(GetClusterStatusResponse {
|
||||
node: hex::encode(garage.system.id),
|
||||
garage_version: garage_util::version::garage_version().to_string(),
|
||||
garage_features: garage_util::version::garage_features()
|
||||
.map(|features| features.iter().map(ToString::to_string).collect()),
|
||||
rust_version: garage_util::version::rust_version().to_string(),
|
||||
db_engine: garage.db.engine(),
|
||||
layout_version: layout.current().version,
|
||||
nodes,
|
||||
})
|
||||
|
||||
+1
-14
@@ -136,20 +136,7 @@ macro_rules! local_admin_endpoints {
|
||||
type Response = [< $endpoint Response >];
|
||||
|
||||
async fn handle(self, garage: &Arc<Garage>, admin: &Admin) -> Result<Self::Response, Error> {
|
||||
let to = match self.node.as_str() {
|
||||
"*" => garage.system.cluster_layout().all_nodes().to_vec(),
|
||||
id => {
|
||||
let nodes = garage.system.cluster_layout().all_nodes()
|
||||
.iter()
|
||||
.filter(|x| hex::encode(x).starts_with(id))
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
if nodes.len() != 1 {
|
||||
return Err(Error::bad_request(format!("Zero or multiple nodes matching {}: {:?}", id, nodes)));
|
||||
}
|
||||
nodes
|
||||
}
|
||||
};
|
||||
let to = find_matching_nodes(garage, self.node.as_str())?;
|
||||
|
||||
let resps = garage.system.rpc_helper().call_many(&admin.endpoint,
|
||||
&to,
|
||||
|
||||
@@ -18,6 +18,25 @@ use crate::api::*;
|
||||
use crate::error::Error;
|
||||
use crate::{Admin, RequestHandler};
|
||||
|
||||
impl RequestHandler for LocalGetNodeInfoRequest {
|
||||
type Response = LocalGetNodeInfoResponse;
|
||||
|
||||
async fn handle(
|
||||
self,
|
||||
garage: &Arc<Garage>,
|
||||
_admin: &Admin,
|
||||
) -> Result<LocalGetNodeInfoResponse, Error> {
|
||||
Ok(LocalGetNodeInfoResponse {
|
||||
node_id: hex::encode(garage.system.id),
|
||||
garage_version: garage_util::version::garage_version().to_string(),
|
||||
garage_features: garage_util::version::garage_features()
|
||||
.map(|features| features.iter().map(ToString::to_string).collect()),
|
||||
rust_version: garage_util::version::rust_version().to_string(),
|
||||
db_engine: garage.db.engine(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl RequestHandler for LocalCreateMetadataSnapshotRequest {
|
||||
type Response = LocalCreateMetadataSnapshotResponse;
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ impl AdminApiRequest {
|
||||
POST AddBucketAlias (body),
|
||||
POST RemoveBucketAlias (body),
|
||||
// Node APIs
|
||||
GET GetNodeInfo (default::body, query::node),
|
||||
POST CreateMetadataSnapshot (default::body, query::node),
|
||||
GET GetNodeStatistics (default::body, query::node),
|
||||
GET GetClusterStatistics (),
|
||||
@@ -93,9 +94,8 @@ impl AdminApiRequest {
|
||||
use router_v1::Endpoint;
|
||||
|
||||
match v1_endpoint {
|
||||
Endpoint::GetClusterStatus => {
|
||||
Ok(AdminApiRequest::GetClusterStatus(GetClusterStatusRequest))
|
||||
}
|
||||
// GetClusterStatus semantics changed:
|
||||
// info about local node is no longer returned
|
||||
Endpoint::GetClusterHealth => {
|
||||
Ok(AdminApiRequest::GetClusterHealth(GetClusterHealthRequest))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user