mirror of
https://git.proxmox.com/git/pve-docs
synced 2025-05-30 22:41:09 +00:00
add api doc viewer (moved from package pve2-api-doc)
This commit is contained in:
parent
9015f48fde
commit
61568a650e
14
Makefile
14
Makefile
@ -159,6 +159,12 @@ pve-admin-guide.epub: ${PVE_ADMIN_GUIDE_SOURCES}
|
|||||||
a2x -f epub pve-admin-guide.adoc
|
a2x -f epub pve-admin-guide.adoc
|
||||||
test -n "$${NOVIEW}" || $(BROWSER) $@ &
|
test -n "$${NOVIEW}" || $(BROWSER) $@ &
|
||||||
|
|
||||||
|
apidata.js: extractapi.pl
|
||||||
|
./extractapi.pl >$@
|
||||||
|
|
||||||
|
apidoc.js: apidata.js PVEAPI.js
|
||||||
|
cat apidata.js PVEAPI.js >$@
|
||||||
|
|
||||||
.PHONY: dinstall
|
.PHONY: dinstall
|
||||||
dinstall: ${GEN_DEB}
|
dinstall: ${GEN_DEB}
|
||||||
dpkg -i ${GEN_DEB}
|
dpkg -i ${GEN_DEB}
|
||||||
@ -179,7 +185,7 @@ DOC_DEB_FILES= \
|
|||||||
pve-admin-guide.epub \
|
pve-admin-guide.epub \
|
||||||
index.html
|
index.html
|
||||||
|
|
||||||
${DOC_DEB}: index.adoc ${PVE_ADMIN_GUIDE_SOURCES}
|
${DOC_DEB}: index.adoc ${PVE_ADMIN_GUIDE_SOURCES} apidoc.js apidoc.html
|
||||||
$(MAKE) NOVIEW=1 pve-admin-guide.pdf pve-admin-guide.html pve-admin-guide.epub
|
$(MAKE) NOVIEW=1 pve-admin-guide.pdf pve-admin-guide.html pve-admin-guide.epub
|
||||||
$(MAKE) NOVIEW=1 $(addsuffix .1.html, ${COMMAND_LIST}) $(addsuffix .8.html, ${SERVICE_LIST}) $(addsuffix .5.html, ${CONFIG_LIST})
|
$(MAKE) NOVIEW=1 $(addsuffix .1.html, ${COMMAND_LIST}) $(addsuffix .8.html, ${SERVICE_LIST}) $(addsuffix .5.html, ${CONFIG_LIST})
|
||||||
asciidoc -a "date=$(shell date)" -a "revnumber=${DOCRELEASE}" index.adoc
|
asciidoc -a "date=$(shell date)" -a "revnumber=${DOCRELEASE}" index.adoc
|
||||||
@ -192,6 +198,10 @@ ${DOC_DEB}: index.adoc ${PVE_ADMIN_GUIDE_SOURCES}
|
|||||||
# install doc files
|
# install doc files
|
||||||
install -m 0644 ${DOC_DEB_FILES} build/usr/share/${DOC_PACKAGE}
|
install -m 0644 ${DOC_DEB_FILES} build/usr/share/${DOC_PACKAGE}
|
||||||
install -m 0644 index.html build/usr/share/${DOC_PACKAGE}
|
install -m 0644 index.html build/usr/share/${DOC_PACKAGE}
|
||||||
|
# install api doc viewer
|
||||||
|
mkdir build/usr/share/${DOC_PACKAGE}/pve2-api-doc
|
||||||
|
install -m 0644 apidoc.html build/usr/share/${DOC_PACKAGE}/pve2-api-doc/index.html
|
||||||
|
install -m 0644 apidoc.js build/usr/share/${DOC_PACKAGE}/pve2-api-doc/
|
||||||
cd build; dpkg-buildpackage -rfakeroot -b -us -uc
|
cd build; dpkg-buildpackage -rfakeroot -b -us -uc
|
||||||
lintian ${DOC_DEB}
|
lintian ${DOC_DEB}
|
||||||
|
|
||||||
@ -223,5 +233,5 @@ update: clean
|
|||||||
make all
|
make all
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf *~ *.html *.pdf *.epub *.tmp *.1 *.5 *.8 *.deb *.changes build
|
rm -rf *~ *.html *.pdf *.epub *.tmp *.1 *.5 *.8 *.deb *.changes build apidata.js apidoc.js
|
||||||
|
|
||||||
|
279
PVEAPI.js
Normal file
279
PVEAPI.js
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
// avoid errors when running without development tools
|
||||||
|
if (!Ext.isDefined(Ext.global.console)) {
|
||||||
|
var console = {
|
||||||
|
dir: function() {},
|
||||||
|
log: function() {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ext.onReady(function() {
|
||||||
|
|
||||||
|
Ext.define('pve-param-schema', {
|
||||||
|
extend: 'Ext.data.Model',
|
||||||
|
fields: [
|
||||||
|
'name', 'type', 'typetext', 'description', 'enum',
|
||||||
|
'minimum', 'maximum', 'minLength', 'maxLength',
|
||||||
|
'pattern', 'title', 'requires', 'format', 'default',
|
||||||
|
'disallow', 'extends', 'links',
|
||||||
|
{
|
||||||
|
name: 'optional',
|
||||||
|
type: 'boolean'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
var store = Ext.create('Ext.data.TreeStore', {
|
||||||
|
model: Ext.define('pve-api-doc', {
|
||||||
|
extend: 'Ext.data.Model',
|
||||||
|
fields: [
|
||||||
|
'path', 'info', 'text',
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
proxy: {
|
||||||
|
type: 'memory',
|
||||||
|
data: pveapi
|
||||||
|
},
|
||||||
|
sorters: [{
|
||||||
|
property: 'leaf',
|
||||||
|
direction: 'ASC'
|
||||||
|
}, {
|
||||||
|
property: 'text',
|
||||||
|
direction: 'ASC'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
var render_text = function(value, metaData, record) {
|
||||||
|
var pdef = record.data;
|
||||||
|
|
||||||
|
metaData.style = 'white-space:pre-wrap;'
|
||||||
|
|
||||||
|
return Ext.htmlEncode(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
var render_type = function(value, metaData, record) {
|
||||||
|
var pdef = record.data;
|
||||||
|
|
||||||
|
return pdef['enum'] ? 'enum' : (pdef.type || 'string');
|
||||||
|
};
|
||||||
|
|
||||||
|
var render_format = function(value, metaData, record) {
|
||||||
|
var pdef = record.data;
|
||||||
|
|
||||||
|
metaData.style = 'white-space:normal;'
|
||||||
|
|
||||||
|
if (pdef.typetext)
|
||||||
|
return pdef.typetext;
|
||||||
|
|
||||||
|
if (pdef['enum'])
|
||||||
|
return pdef['enum'].join(' | ');
|
||||||
|
|
||||||
|
if (pdef.format)
|
||||||
|
return pdef.format;
|
||||||
|
|
||||||
|
if (pdef.pattern)
|
||||||
|
return pdef.pattern;
|
||||||
|
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
var render_docu = function(data) {
|
||||||
|
var md = data.info;
|
||||||
|
|
||||||
|
// console.dir(data);
|
||||||
|
|
||||||
|
var items = [];
|
||||||
|
|
||||||
|
var clicmdhash = {
|
||||||
|
GET: 'get',
|
||||||
|
POST: 'create',
|
||||||
|
PUT: 'set',
|
||||||
|
DELETE: 'delete'
|
||||||
|
};
|
||||||
|
|
||||||
|
Ext.Array.each(['GET', 'POST', 'PUT', 'DELETE'], function(method) {
|
||||||
|
var info = md[method];
|
||||||
|
if (info) {
|
||||||
|
|
||||||
|
var usage = "";
|
||||||
|
|
||||||
|
usage += "<table><tr><td>HTTP: </td><td>" + method + " /api2/json" + data.path + "</td></tr><tr><td> </td></tr>";
|
||||||
|
usage += "<tr><td>CLI:</td><td>pvesh " + clicmdhash[method] + " " + data.path + "</td></tr></table>";
|
||||||
|
|
||||||
|
var sections = [
|
||||||
|
{
|
||||||
|
title: 'Description',
|
||||||
|
html: Ext.htmlEncode(info.description),
|
||||||
|
bodyPadding: 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Usage',
|
||||||
|
html: usage,
|
||||||
|
bodyPadding: 10
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
if (info.parameters && info.parameters.properties) {
|
||||||
|
|
||||||
|
var pstore = Ext.create('Ext.data.Store', {
|
||||||
|
model: 'pve-param-schema',
|
||||||
|
proxy: {
|
||||||
|
type: 'memory'
|
||||||
|
},
|
||||||
|
groupField: 'optional',
|
||||||
|
sorters: [
|
||||||
|
{
|
||||||
|
property: 'name',
|
||||||
|
direction: 'ASC'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
Ext.Object.each(info.parameters.properties, function(name, pdef) {
|
||||||
|
pdef.name = name;
|
||||||
|
pstore.add(pdef);
|
||||||
|
});
|
||||||
|
|
||||||
|
pstore.sort();
|
||||||
|
|
||||||
|
var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
|
||||||
|
enableGroupingMenu: false,
|
||||||
|
groupHeaderTpl: '<tpl if="name">Optional</tpl><tpl if="!name">Required</tpl>'
|
||||||
|
});
|
||||||
|
|
||||||
|
sections.push({
|
||||||
|
xtype: 'gridpanel',
|
||||||
|
title: 'Parameters',
|
||||||
|
features: [groupingFeature],
|
||||||
|
store: pstore,
|
||||||
|
viewConfig: {
|
||||||
|
trackOver: false,
|
||||||
|
stripeRows: true
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
header: 'Name',
|
||||||
|
dataIndex: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Type',
|
||||||
|
dataIndex: 'type',
|
||||||
|
renderer: render_type,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Format',
|
||||||
|
dataIndex: 'type',
|
||||||
|
renderer: render_format,
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Description',
|
||||||
|
dataIndex: 'description',
|
||||||
|
renderer: render_text,
|
||||||
|
flex: 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.returns) {
|
||||||
|
|
||||||
|
var rtype = info.returns.type;
|
||||||
|
if (!rtype && info.returns.items)
|
||||||
|
rtype = 'array';
|
||||||
|
if (!rtype)
|
||||||
|
rtype = 'object';
|
||||||
|
|
||||||
|
sections.push({
|
||||||
|
title: 'Returns: ' + rtype
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var permhtml = '';
|
||||||
|
if (!info.permissions) {
|
||||||
|
permhtml = "Root only.";
|
||||||
|
} else {
|
||||||
|
if (info.permissions.description) {
|
||||||
|
permhtml += "<div style='white-space:pre-wrap;padding-bottom:10px;'>" +
|
||||||
|
Ext.htmlEncode(info.permissions.description) + "</div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.permissions.user) {
|
||||||
|
if (!info.permissions.description) {
|
||||||
|
if (info.permissions.user === 'world') {
|
||||||
|
permhtml += "Accessible without any authententification.";
|
||||||
|
} else if (info.permissions.user === 'all') {
|
||||||
|
permhtml += "Accessible by all authententicated users.";
|
||||||
|
} else {
|
||||||
|
permhtml += 'Onyl accessible by user "' +
|
||||||
|
info.permissions.user + '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (info.permissions.check) {
|
||||||
|
permhtml += "<pre>Check: " +
|
||||||
|
Ext.htmlEncode(Ext.JSON.encode(info.permissions.check)) + "</pre>";
|
||||||
|
} else {
|
||||||
|
permhtml += "Unknown systax!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sections.push({
|
||||||
|
title: 'Required permissions',
|
||||||
|
bodyPadding: 10,
|
||||||
|
html: permhtml
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
items.push({
|
||||||
|
title: method,
|
||||||
|
autoScroll: true,
|
||||||
|
defaults: {
|
||||||
|
border: false
|
||||||
|
},
|
||||||
|
items: sections
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var ct = Ext.getCmp('docview');
|
||||||
|
ct.setTitle("Path: " + data.path);
|
||||||
|
ct.removeAll(true);
|
||||||
|
ct.add(items);
|
||||||
|
};
|
||||||
|
|
||||||
|
var tree = Ext.create('Ext.tree.Panel', {
|
||||||
|
title: 'Resource Tree',
|
||||||
|
store: store,
|
||||||
|
width: 200,
|
||||||
|
region: 'west',
|
||||||
|
split: true,
|
||||||
|
margins: '5 0 5 5',
|
||||||
|
rootVisible: false,
|
||||||
|
listeners: {
|
||||||
|
selectionchange: function(v, selections) {
|
||||||
|
if (!selections[0])
|
||||||
|
return;
|
||||||
|
var rec = selections[0];
|
||||||
|
render_docu(rec.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ext.create('Ext.container.Viewport', {
|
||||||
|
layout: 'border',
|
||||||
|
renderTo: Ext.getBody(),
|
||||||
|
items: [
|
||||||
|
tree,
|
||||||
|
{
|
||||||
|
xtype: 'tabpanel',
|
||||||
|
title: 'Documentation',
|
||||||
|
id: 'docview',
|
||||||
|
region: 'center',
|
||||||
|
margins: '5 5 5 0',
|
||||||
|
layout: 'fit',
|
||||||
|
items: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -5,3 +5,6 @@
|
|||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
Alias /pve-docs /usr/share/pve-docs/
|
Alias /pve-docs /usr/share/pve-docs/
|
||||||
|
|
||||||
|
Alias /pve2-api-doc /usr/share/pve-docs/pve2-api-doc/
|
||||||
|
|
||||||
|
44
extractapi.pl
Executable file
44
extractapi.pl
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use PVE::RESTHandler;
|
||||||
|
use PVE::API2;
|
||||||
|
use JSON;
|
||||||
|
|
||||||
|
sub cleanup_tree {
|
||||||
|
my ($h) = @_;
|
||||||
|
|
||||||
|
my $class = ref($h);
|
||||||
|
return $h if !$class;
|
||||||
|
|
||||||
|
if ($class eq 'ARRAY') {
|
||||||
|
my $res = [];
|
||||||
|
foreach my $el (@$h) {
|
||||||
|
push @$res, cleanup_tree($el);
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
} elsif ($class eq 'HASH') {
|
||||||
|
my $res = {};
|
||||||
|
foreach my $k (keys %$h) {
|
||||||
|
if (my $class = ref($h->{$k})) {
|
||||||
|
if ($class eq 'CODE') {
|
||||||
|
next if $k eq 'completion';
|
||||||
|
}
|
||||||
|
$res->{$k} = cleanup_tree($h->{$k});
|
||||||
|
} else {
|
||||||
|
$res->{$k} = $h->{$k};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
} elsif ($class eq 'Regexp') {
|
||||||
|
return "$h"; # return string representation
|
||||||
|
} else {
|
||||||
|
die "unknown class '$class'\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $tree = cleanup_tree(PVE::RESTHandler::api_dump('PVE::API2'));
|
||||||
|
|
||||||
|
print "var pveapi = " . to_json($tree, {pretty => 1}) . ";\n\n";
|
||||||
|
|
||||||
|
exit(0);
|
Loading…
Reference in New Issue
Block a user