mirror of
https://git.deuxfleurs.fr/Deuxfleurs/garage.git
synced 2025-04-13 04:44:07 +00:00
admi api: remove info about local node from GetClusterStatus and add specific GetNodeInfo endpoint
This commit is contained in:
parent
29ce490dd6
commit
2e03d90585
8 changed files with 85 additions and 85 deletions
|
@ -84,34 +84,12 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [ node, garageVersion, garageFeatures, rustVersion, dbEngine, knownNodes, layout ]
|
||||
required: [ layoutVersion, nodes ]
|
||||
properties:
|
||||
node:
|
||||
type: string
|
||||
example: "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f"
|
||||
garageVersion:
|
||||
type: string
|
||||
example: "v2.0.0"
|
||||
garageFeatures:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example:
|
||||
- "k2v"
|
||||
- "lmdb"
|
||||
- "sqlite"
|
||||
- "consul-discovery"
|
||||
- "kubernetes-discovery"
|
||||
- "metrics"
|
||||
- "telemetry-otlp"
|
||||
- "bundled-libs"
|
||||
rustVersion:
|
||||
type: string
|
||||
example: "1.68.0"
|
||||
dbEngine:
|
||||
type: string
|
||||
example: "LMDB (using Heed crate)"
|
||||
knownNodes:
|
||||
layoutVersion:
|
||||
type: integer
|
||||
example: 1
|
||||
nodes:
|
||||
type: array
|
||||
example:
|
||||
- id: "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f"
|
||||
|
@ -131,8 +109,6 @@ paths:
|
|||
hostname: neptune
|
||||
items:
|
||||
$ref: '#/components/schemas/NodeNetworkInfo'
|
||||
layout:
|
||||
$ref: '#/components/schemas/ClusterLayout'
|
||||
|
||||
/ConnectClusterNodes:
|
||||
post:
|
||||
|
|
|
@ -68,26 +68,13 @@ Returns HTTP 200 Ok if yes, or HTTP 4xx if no website is available for this doma
|
|||
|
||||
Returns the cluster's current status in JSON, including:
|
||||
|
||||
- ID of the node being queried and its version of the Garage daemon
|
||||
- Live nodes
|
||||
- Currently configured cluster layout
|
||||
- Staged changes to the cluster layout
|
||||
|
||||
Example response body:
|
||||
|
||||
```json
|
||||
{
|
||||
"node": "b10c110e4e854e5aa3f4637681befac755154b20059ec163254ddbfae86b09df",
|
||||
"garageVersion": "v2.0.0",
|
||||
"garageFeatures": [
|
||||
"k2v",
|
||||
"lmdb",
|
||||
"sqlite",
|
||||
"metrics",
|
||||
"bundled-libs"
|
||||
],
|
||||
"rustVersion": "1.68.0",
|
||||
"dbEngine": "LMDB (using Heed crate)",
|
||||
"layoutVersion": 5,
|
||||
"nodes": [
|
||||
{
|
||||
|
@ -362,19 +349,7 @@ layout, as well as the description of the layout as returned by GetClusterLayout
|
|||
|
||||
Clears all of the staged layout changes.
|
||||
|
||||
Request body format:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 13
|
||||
}
|
||||
```
|
||||
|
||||
Reverting the staged changes is done by incrementing the version number
|
||||
and clearing the contents of the staged change list.
|
||||
Similarly to the CLI, the body must include the incremented
|
||||
version number, which MUST be 1 + the value of the currently
|
||||
existing layout in the cluster.
|
||||
This requests contains an empty body.
|
||||
|
||||
This returns the new cluster layout with all changes reverted,
|
||||
as returned by GetClusterLayout.
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue