more complete admin API #298

Merged
lx merged 48 commits from admin-api into main 2022-05-24 10:16:40 +00:00
5 changed files with 74 additions and 4 deletions
Showing only changes of commit 70383b4363 - Show all commits

View file

@ -94,6 +94,36 @@ Example response body:
} }
``` ```
### ConnectClusterNodes `POST /v0/connect`
Instructs this Garage node to connect to other Garage nodes at specified addresses.
Example request body:
```json
[
"ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f@10.0.0.11:3901",
"4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff@10.0.0.12:3901"
]
```
The format of the string for a node to connect to is: `<node ID>@<ip address>:<port>`, same as in the `garage node connect` CLI call.
Example response:
```json
[
{
"success": true,
"error": null,
},
{
"success": false,
"error": "Handshake error",
}
]
```
### GetClusterLayout `GET /v0/layout` ### GetClusterLayout `GET /v0/layout`
Returns the cluster's current layout in JSON, including: Returns the cluster's current layout in JSON, including:

View file

@ -124,6 +124,7 @@ impl ApiHandler for AdminApiServer {
Endpoint::Options => self.handle_options(&req), Endpoint::Options => self.handle_options(&req),
Endpoint::Metrics => self.handle_metrics(), Endpoint::Metrics => self.handle_metrics(),
Endpoint::GetClusterStatus => handle_get_cluster_status(&self.garage).await, Endpoint::GetClusterStatus => handle_get_cluster_status(&self.garage).await,
Endpoint::ConnectClusterNodes => handle_connect_cluster_nodes(&self.garage, req).await,
// Layout // Layout
Endpoint::GetClusterLayout => handle_get_cluster_layout(&self.garage).await, Endpoint::GetClusterLayout => handle_get_cluster_layout(&self.garage).await,
Endpoint::UpdateClusterLayout => handle_update_cluster_layout(&self.garage, req).await, Endpoint::UpdateClusterLayout => handle_update_cluster_layout(&self.garage, req).await,

View file

@ -45,6 +45,33 @@ pub async fn handle_get_cluster_status(garage: &Arc<Garage>) -> Result<Response<
.body(Body::from(resp_json))?) .body(Body::from(resp_json))?)
} }
pub async fn handle_connect_cluster_nodes(
garage: &Arc<Garage>,
req: Request<Body>,
) -> Result<Response<Body>, Error> {
let req = parse_json_body::<Vec<String>>(req).await?;
let res = futures::future::join_all(req.iter().map(|node| garage.system.connect(node)))
.await
.into_iter()
.map(|r| match r {
Ok(()) => ConnectClusterNodesResponse {
success: true,
error: None,
},
Err(e) => ConnectClusterNodesResponse {
success: false,
error: Some(format!("{}", e)),
},
})
.collect::<Vec<_>>();
let resp_json = serde_json::to_string_pretty(&res).map_err(GarageError::from)?;
Ok(Response::builder()
.status(StatusCode::OK)
.body(Body::from(resp_json))?)
}
pub async fn handle_get_cluster_layout(garage: &Arc<Garage>) -> Result<Response<Body>, Error> { pub async fn handle_get_cluster_layout(garage: &Arc<Garage>) -> Result<Response<Body>, Error> {
let res = get_cluster_layout(garage); let res = get_cluster_layout(garage);
let resp_json = serde_json::to_string_pretty(&res).map_err(GarageError::from)?; let resp_json = serde_json::to_string_pretty(&res).map_err(GarageError::from)?;
@ -84,6 +111,12 @@ struct GetClusterStatusResponse {
layout: GetClusterLayoutResponse, layout: GetClusterLayoutResponse,
} }
#[derive(Serialize)]
struct ConnectClusterNodesResponse {
success: bool,
error: Option<String>,
}
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GetClusterLayoutResponse { struct GetClusterLayoutResponse {

View file

@ -18,6 +18,7 @@ pub enum Endpoint {
Options, Options,
Metrics, Metrics,
GetClusterStatus, GetClusterStatus,
ConnectClusterNodes,
// Layout // Layout
GetClusterLayout, GetClusterLayout,
UpdateClusterLayout, UpdateClusterLayout,
@ -91,6 +92,7 @@ impl Endpoint {
OPTIONS _ => Options, OPTIONS _ => Options,
GET "/metrics" => Metrics, GET "/metrics" => Metrics,
GET "/v0/status" => GetClusterStatus, GET "/v0/status" => GetClusterStatus,
POST "/v0/connect" => ConnectClusterNodes,
// Layout endpoints // Layout endpoints
GET "/v0/layout" => GetClusterLayout, GET "/v0/layout" => GetClusterLayout,
POST "/v0/layout" => UpdateClusterLayout, POST "/v0/layout" => UpdateClusterLayout,

View file

@ -383,10 +383,14 @@ impl System {
} }
} }
} }
return Err(Error::Message(format!( if errors.len() == 1 {
"Could not connect to specified peers. Errors: {:?}", return Err(Error::Message(errors[0].1.to_string()));
errors } else {
))); return Err(Error::Message(format!(
"Could not connect to specified peers. Errors: {:?}",
errors
)));
}
} }
// ---- INTERNALS ---- // ---- INTERNALS ----