remove api_schema submodule
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
e57e1cd82d
commit
be2bb37205
@ -35,7 +35,6 @@ serde_json = "1.0"
|
|||||||
shellwords = "1.0"
|
shellwords = "1.0"
|
||||||
siphasher = "0.3"
|
siphasher = "0.3"
|
||||||
syslog = "4.0"
|
syslog = "4.0"
|
||||||
textwrap = "0.11"
|
|
||||||
tokio = { version = "0.2.0-alpha.4" }
|
tokio = { version = "0.2.0-alpha.4" }
|
||||||
tokio-executor = { version = "0.2.0-alpha.4" }
|
tokio-executor = { version = "0.2.0-alpha.4" }
|
||||||
tokio-net = { version = "0.2.0-alpha.4", features = ["signal"] }
|
tokio-net = { version = "0.2.0-alpha.4", features = ["signal"] }
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
//! API definition helper
|
|
||||||
//!
|
|
||||||
//! This module contains helper classes to define REST APIs. Method
|
|
||||||
//! parameters and return types are described using a
|
|
||||||
//! [Schema](schema/enum.Schema.html).
|
|
||||||
//!
|
|
||||||
//! The [Router](router/struct.Router.html) is used to define a
|
|
||||||
//! hierarchy of API entries, and provides ways to find an API
|
|
||||||
//! definition by path.
|
|
||||||
|
|
||||||
pub mod format;
|
|
@ -1,282 +0,0 @@
|
|||||||
use failure::*;
|
|
||||||
|
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
use proxmox::api::{ApiHandler, ApiMethod};
|
|
||||||
use proxmox::api::router::{Router, SubRoute};
|
|
||||||
use proxmox::api::schema::*;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub enum ParameterDisplayStyle {
|
|
||||||
Config,
|
|
||||||
//SonfigSub,
|
|
||||||
Arg,
|
|
||||||
Fixed,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// CLI usage information format
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
|
||||||
pub enum DocumentationFormat {
|
|
||||||
/// text, command line only (one line)
|
|
||||||
Short,
|
|
||||||
/// text, list all options
|
|
||||||
Long,
|
|
||||||
/// text, include description
|
|
||||||
Full,
|
|
||||||
/// like full, but in reStructuredText format
|
|
||||||
ReST,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// line wrapping to form simple list of paragraphs
|
|
||||||
pub fn wrap_text(initial_indent: &str, subsequent_indent: &str, text: &str, columns: usize) -> String {
|
|
||||||
|
|
||||||
let wrapper1 = textwrap::Wrapper::new(columns)
|
|
||||||
.initial_indent(initial_indent)
|
|
||||||
.subsequent_indent(subsequent_indent);
|
|
||||||
|
|
||||||
let wrapper2 = textwrap::Wrapper::new(columns)
|
|
||||||
.initial_indent(subsequent_indent)
|
|
||||||
.subsequent_indent(subsequent_indent);
|
|
||||||
|
|
||||||
text.split("\n\n")
|
|
||||||
.map(|p| p.trim())
|
|
||||||
.filter(|p| !p.is_empty())
|
|
||||||
.fold(String::new(), |mut acc, p| {
|
|
||||||
if acc.is_empty() {
|
|
||||||
acc.push_str(&wrapper1.wrap(p).concat());
|
|
||||||
} else {
|
|
||||||
acc.push_str(&wrapper2.wrap(p).concat());
|
|
||||||
}
|
|
||||||
acc.push_str("\n\n");
|
|
||||||
acc
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_schema_type_text(schema: &Schema, _style: ParameterDisplayStyle) -> String {
|
|
||||||
match schema {
|
|
||||||
Schema::Null => String::from("<null>"), // should not happen
|
|
||||||
Schema::String(_) => String::from("<string>"),
|
|
||||||
Schema::Boolean(_) => String::from("<boolean>"),
|
|
||||||
Schema::Integer(integer_schema) => {
|
|
||||||
match (integer_schema.minimum, integer_schema.maximum) {
|
|
||||||
(Some(min), Some(max)) => format!("<integer> ({} - {})", min, max),
|
|
||||||
(Some(min), None) => format!("<integer> ({} - N)", min),
|
|
||||||
(None, Some(max)) => format!("<integer> (-N - {})", max),
|
|
||||||
_ => String::from("<integer>"),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Schema::Object(_) => String::from("<object>"),
|
|
||||||
Schema::Array(_) => String::from("<array>"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_property_description(
|
|
||||||
name: &str,
|
|
||||||
schema: &Schema,
|
|
||||||
style: ParameterDisplayStyle,
|
|
||||||
format: DocumentationFormat,
|
|
||||||
) -> String {
|
|
||||||
|
|
||||||
let type_text = get_schema_type_text(schema, style);
|
|
||||||
|
|
||||||
let (descr, default) = match schema {
|
|
||||||
Schema::Null => ("null", None),
|
|
||||||
Schema::String(ref schema) => (schema.description, schema.default.map(|v| v.to_owned())),
|
|
||||||
Schema::Boolean(ref schema) => (schema.description, schema.default.map(|v| v.to_string())),
|
|
||||||
Schema::Integer(ref schema) => (schema.description, schema.default.map(|v| v.to_string())),
|
|
||||||
Schema::Object(ref schema) => (schema.description, None),
|
|
||||||
Schema::Array(ref schema) => (schema.description, None),
|
|
||||||
};
|
|
||||||
|
|
||||||
let default_text = match default {
|
|
||||||
Some(text) => format!(" (default={})", text),
|
|
||||||
None => String::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if format == DocumentationFormat::ReST {
|
|
||||||
|
|
||||||
let mut text = match style {
|
|
||||||
ParameterDisplayStyle::Config => {
|
|
||||||
format!(":``{} {}{}``: ", name, type_text, default_text)
|
|
||||||
}
|
|
||||||
ParameterDisplayStyle::Arg => {
|
|
||||||
format!(":``--{} {}{}``: ", name, type_text, default_text)
|
|
||||||
}
|
|
||||||
ParameterDisplayStyle::Fixed => {
|
|
||||||
format!(":``<{}> {}{}``: ", name, type_text, default_text)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
text.push_str(&wrap_text("", "", descr, 80));
|
|
||||||
text.push('\n');
|
|
||||||
text.push('\n');
|
|
||||||
|
|
||||||
text
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
let display_name = match style {
|
|
||||||
ParameterDisplayStyle::Config => {
|
|
||||||
format!("{}:", name)
|
|
||||||
}
|
|
||||||
ParameterDisplayStyle::Arg => {
|
|
||||||
format!("--{}", name)
|
|
||||||
}
|
|
||||||
ParameterDisplayStyle::Fixed => {
|
|
||||||
format!("<{}>", name)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut text = format!(" {:-10} {}{}", display_name, type_text, default_text);
|
|
||||||
let indent = " ";
|
|
||||||
text.push('\n');
|
|
||||||
text.push_str(&wrap_text(indent, indent, descr, 80));
|
|
||||||
text.push('\n');
|
|
||||||
text.push('\n');
|
|
||||||
|
|
||||||
text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dump_api_parameters(param: &ObjectSchema) -> String {
|
|
||||||
|
|
||||||
let mut res = wrap_text("", "", param.description, 80);
|
|
||||||
|
|
||||||
let mut required_list: Vec<String> = Vec::new();
|
|
||||||
let mut optional_list: Vec<String> = Vec::new();
|
|
||||||
|
|
||||||
for (prop, optional, schema) in param.properties {
|
|
||||||
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.is_empty() {
|
|
||||||
|
|
||||||
res.push_str("\n*Required properties:*\n\n");
|
|
||||||
|
|
||||||
for text in required_list {
|
|
||||||
res.push_str(&text);
|
|
||||||
res.push('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if !optional_list.is_empty() {
|
|
||||||
|
|
||||||
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: Option<&ApiMethod>) -> Option<String> {
|
|
||||||
|
|
||||||
match def {
|
|
||||||
None => None,
|
|
||||||
Some(api_method) => {
|
|
||||||
let param_descr = dump_api_parameters(api_method.parameters);
|
|
||||||
|
|
||||||
let return_descr = dump_api_return_schema(api_method.returns);
|
|
||||||
|
|
||||||
let mut method = method;
|
|
||||||
|
|
||||||
if let ApiHandler::Async(_) = api_method.handler {
|
|
||||||
method = if method == "POST" { "UPLOAD" } else { method };
|
|
||||||
method = if method == "GET" { "DOWNLOAD" } else { method };
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = format!("**{} {}**\n\n{}\n\n{}", method, path, param_descr, return_descr);
|
|
||||||
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 {
|
|
||||||
None => return Ok(()),
|
|
||||||
Some(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)?;
|
|
||||||
}
|
|
||||||
Some(SubRoute::Map(dirmap)) => {
|
|
||||||
//let mut keys: Vec<&String> = map.keys().collect();
|
|
||||||
//keys.sort_unstable_by(|a, b| a.cmp(b));
|
|
||||||
for (key, sub_router) in dirmap.iter() {
|
|
||||||
let sub_path = if path == "." { key.to_string() } else { format!("{}/{}", path, key) };
|
|
||||||
dump_api(output, sub_router, &sub_path, pos)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,7 +1,8 @@
|
|||||||
use failure::*;
|
use failure::*;
|
||||||
|
|
||||||
|
use proxmox::api::format::*;
|
||||||
|
|
||||||
use proxmox_backup::api2;
|
use proxmox_backup::api2;
|
||||||
use proxmox_backup::api_schema::format::*;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use failure::*;
|
use failure::*;
|
||||||
|
|
||||||
|
use proxmox::api::format::dump_api;
|
||||||
|
|
||||||
use proxmox_backup::api2;
|
use proxmox_backup::api2;
|
||||||
use proxmox_backup::api_schema::format::*;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@ use serde_json::Value;
|
|||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use proxmox::api::format::*;
|
||||||
use proxmox::api::schema::*;
|
use proxmox::api::schema::*;
|
||||||
use proxmox::api::{ApiHandler, ApiMethod};
|
use proxmox::api::{ApiHandler, ApiMethod};
|
||||||
|
|
||||||
use crate::api_schema::format::*;
|
|
||||||
use super::environment::CliEnvironment;
|
use super::environment::CliEnvironment;
|
||||||
|
|
||||||
use super::getopts;
|
use super::getopts;
|
||||||
|
@ -4,9 +4,6 @@ pub mod buildcfg;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod tools;
|
pub mod tools;
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
pub mod api_schema;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user