src/bin/dump-backup-api.rs: helper to generate backup API docs
This commit is contained in:
parent
5e0f305142
commit
22e5aa1d3e
|
@ -1,4 +1,8 @@
|
||||||
|
use failure::*;
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
use crate::api_schema::*;
|
use crate::api_schema::*;
|
||||||
|
use crate::api_schema::router::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum ParameterDisplayStyle {
|
pub enum ParameterDisplayStyle {
|
||||||
|
@ -134,3 +138,158 @@ pub fn get_property_description(
|
||||||
text
|
text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dump_api_parameters(param: &ObjectSchema) -> String {
|
||||||
|
|
||||||
|
let mut res = wrap_text("", "", param.description, 80);
|
||||||
|
|
||||||
|
let properties = ¶m.properties;
|
||||||
|
|
||||||
|
let mut prop_names: Vec<&str> = properties.keys().map(|v| *v).collect();
|
||||||
|
prop_names.sort();
|
||||||
|
|
||||||
|
let mut required_list: Vec<String> = vec![];
|
||||||
|
let mut optional_list: Vec<String> = vec![];
|
||||||
|
|
||||||
|
for prop in prop_names {
|
||||||
|
let (optional, schema) = properties.get(prop).unwrap();
|
||||||
|
|
||||||
|
let param_descr = get_property_description(
|
||||||
|
prop, &schema, ParameterDisplayStyle::Config, DocumentationFormat::ReST);
|
||||||
|
|
||||||
|
if *optional {
|
||||||
|
optional_list.push(param_descr);
|
||||||
|
} else {
|
||||||
|
required_list.push(param_descr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if required_list.len() > 0 {
|
||||||
|
|
||||||
|
res.push_str("\n*Required properties:*\n\n");
|
||||||
|
|
||||||
|
for text in required_list {
|
||||||
|
res.push_str(&text);
|
||||||
|
res.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if optional_list.len() > 0 {
|
||||||
|
|
||||||
|
res.push_str("\n*Optional properties:*\n\n");
|
||||||
|
|
||||||
|
for text in optional_list {
|
||||||
|
res.push_str(&text);
|
||||||
|
res.push('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump_api_return_schema(schema: &Schema) -> String {
|
||||||
|
|
||||||
|
let mut res = String::from("*Returns*: ");
|
||||||
|
|
||||||
|
let type_text = get_schema_type_text(schema, ParameterDisplayStyle::Config);
|
||||||
|
res.push_str(&format!("**{}**\n\n", type_text));
|
||||||
|
|
||||||
|
match schema {
|
||||||
|
Schema::Null => {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
Schema::Boolean(schema) => {
|
||||||
|
let description = wrap_text("", "", schema.description, 80);
|
||||||
|
res.push_str(&description);
|
||||||
|
}
|
||||||
|
Schema::Integer(schema) => {
|
||||||
|
let description = wrap_text("", "", schema.description, 80);
|
||||||
|
res.push_str(&description);
|
||||||
|
}
|
||||||
|
Schema::String(schema) => {
|
||||||
|
let description = wrap_text("", "", schema.description, 80);
|
||||||
|
res.push_str(&description);
|
||||||
|
}
|
||||||
|
Schema::Array(schema) => {
|
||||||
|
let description = wrap_text("", "", schema.description, 80);
|
||||||
|
res.push_str(&description);
|
||||||
|
}
|
||||||
|
Schema::Object(obj_schema) => {
|
||||||
|
res.push_str(&dump_api_parameters(obj_schema));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res.push('\n');
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump_method_definition(method: &str, path: &str, def: &MethodDefinition) -> Option<String> {
|
||||||
|
|
||||||
|
match def {
|
||||||
|
MethodDefinition::None => return None,
|
||||||
|
MethodDefinition::Simple(simple_method) => {
|
||||||
|
let param_descr = dump_api_parameters(&simple_method.parameters);
|
||||||
|
|
||||||
|
let return_descr = dump_api_return_schema(&simple_method.returns);
|
||||||
|
|
||||||
|
let res = format!("**{} {}**\n\n{}\n\n{}", method, path, param_descr, return_descr);
|
||||||
|
return Some(res);
|
||||||
|
}
|
||||||
|
MethodDefinition::Async(async_method) => {
|
||||||
|
let method = if method == "POST" { "UPLOAD" } else { method };
|
||||||
|
let method = if method == "GET" { "DOWNLOAD" } else { method };
|
||||||
|
|
||||||
|
let param_descr = dump_api_parameters(&async_method.parameters);
|
||||||
|
|
||||||
|
let return_descr = dump_api_return_schema(&async_method.returns);
|
||||||
|
|
||||||
|
let res = format!("**{} {}**\n\n{}\n\n{}", method, path, param_descr, return_descr);
|
||||||
|
return Some(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dump_api(output: &mut dyn Write, router: &Router, path: &str, mut pos: usize) -> Result<(), Error> {
|
||||||
|
|
||||||
|
let mut cond_print = |x| -> Result<_, Error> {
|
||||||
|
if let Some(text) = x {
|
||||||
|
if pos > 0 {
|
||||||
|
writeln!(output, "-----\n")?;
|
||||||
|
}
|
||||||
|
writeln!(output, "{}", text)?;
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
cond_print(dump_method_definition("GET", path, &router.get))?;
|
||||||
|
cond_print(dump_method_definition("POST", path, &router.post))?;
|
||||||
|
cond_print(dump_method_definition("PUT", path, &router.put))?;
|
||||||
|
cond_print(dump_method_definition("DELETE", path, &router.delete))?;
|
||||||
|
|
||||||
|
match &router.subroute {
|
||||||
|
SubRoute::None => return Ok(()),
|
||||||
|
SubRoute::MatchAll { router, param_name } => {
|
||||||
|
let sub_path = if path == "." {
|
||||||
|
format!("<{}>", param_name)
|
||||||
|
} else {
|
||||||
|
format!("{}/<{}>", path, param_name)
|
||||||
|
};
|
||||||
|
dump_api(output, router, &sub_path, pos)?;
|
||||||
|
}
|
||||||
|
SubRoute::Hash(map) => {
|
||||||
|
let mut keys: Vec<&String> = map.keys().collect();
|
||||||
|
keys.sort_unstable_by(|a, b| a.cmp(b));
|
||||||
|
for key in keys {
|
||||||
|
let sub_router = &map[key];
|
||||||
|
let sub_path = if path == "." { key.to_owned() } else { format!("{}/{}", path, key) };
|
||||||
|
dump_api(output, sub_router, &sub_path, pos)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
use failure::*;
|
||||||
|
|
||||||
|
use proxmox_backup::api2;
|
||||||
|
use proxmox_backup::api_schema::format::*;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Error> {
|
||||||
|
|
||||||
|
let api = api2::admin::datastore::backup::backup_api();
|
||||||
|
|
||||||
|
dump_api(&mut std::io::stdout(), &api, ".", 0)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue