Add json spec generator

This commit is contained in:
Kload 2013-07-02 22:02:26 +02:00
parent 92b0761c8f
commit 03454f2570
3 changed files with 163 additions and 15 deletions

0
doc/README.md Normal file
View file

148
generate_api_doc.py Executable file
View file

@ -0,0 +1,148 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import yaml
import json
import requests
from yunohost import str_to_func
def main():
"""
"""
with open('action_map.yml') as f:
action_map = yaml.load(f)
try:
with open('/etc/yunohost/current_host', 'r') as f:
domain = f.readline().rstrip()
except IOError:
domain = requests.get('http://ip.yunohost.org').text
with open('action_map.yml') as f:
action_map = yaml.load(f)
base_info = {
'apiVersion': '0.1',
'swaggerVersion': '1.1',
'basePath': 'http://'+ domain + ':6767',
'apis': []
}
resource_list = base_info
resources = {}
for category, category_params in action_map.items():
if 'category_help' not in category_params: category_params['category_help'] = ''
resource_path = '/'+ category
resource_list['apis'].append({
'path': resource_path,
'description': category_params['category_help']
})
resources[category] = base_info
resources[category]['resourcePath'] = resource_path
registered_paths = {}
for action, action_params in category_params['actions'].items():
if 'action_help' not in action_params:
action_params['action_help'] = ''
if 'api' not in action_params:
action_params['api'] = 'GET /'+ category +'/'+ action
method, path = action_params['api'].split(' ')
path = path.replace('(?P<', '{').replace('>[^/]+)', '}')
key_param = ''
if '{' in path:
key_param = path[path.find("{")+1:path.find("}")]
notes = ''
if str_to_func('yunohost_'+ category +'.'+ category +'_'+ action) is None:
notes = 'Not yet implemented'
operation = {
'httpMethod': method,
'nickname': category +'_'+ action,
'responseClass': 'container',
'summary': action_params['action_help'],
'notes': notes,
'parameters': [],
'errorResponses': []
}
if 'arguments' in action_params:
for arg_name, arg_params in action_params['arguments'].items():
if 'help' not in arg_params:
arg_params['help'] = ''
param_type = 'query'
allow_multiple = False
required = True
allowable_values = {}
name = arg_name.replace('-', '_')
if name[0] == '_':
required = False
if 'nargs' not in arg_params:
allow_multiple = False
if 'full' in arg_params:
name = arg_params['full'][2:].replace('-', '_')
else:
name = arg_params[2:].replace('-', '_')
if name == key_param:
param_type = 'path'
required = True
allow_multiple = False
if 'nargs' in arg_params:
if arg_params['nargs'] == '*':
allow_multiple = True
required = False
if arg_params['nargs'] == '+':
allow_multiple = False
required = True
if 'choices' in arg_params:
allowable_values = {
'valueType': 'LIST',
'values': arg_params['choices']
}
if 'action' in arg_params and arg_params['action'] == 'store_true':
allowable_values = {
'valueType': 'LIST',
'values': ['true', 'True', 'yes', 'Yes']
}
operation['parameters'].append({
'paramType': param_type,
'name': name,
'description': arg_params['help'],
'dataType': 'string',
'required': required,
'allowableValues': allowable_values,
'allowMultiple': allow_multiple
})
if path in registered_paths:
resources[category]['apis'][registered_paths[path]]['operations'].append(operation)
resources[category]['apis'][registered_paths[path]]['description'] = ''
else:
registered_paths[path] = len(resources[category]['apis'])
resources[category]['apis'].append({
'path': path,
'description': action_params['action_help'],
'operations': operation
})
for category, api_dict in resources.items():
with open(os.getcwd() +'/doc/'+ category +'.json', 'w') as f:
json.dump(api_dict, f)
with open(os.getcwd() +'/doc/'+ resources +'.json', 'w') as f:
json.dump(resource_list, f)
if __name__ == '__main__':
sys.exit(main())

View file

@ -32,7 +32,7 @@ def http_exec(request, **kwargs):
request.setResponseCode(200, 'OK')
request.setHeader('Access-Control-Allow-Headers', 'Authorization')
return ''
# Simple HTTP auth
else:
authorized = request.getUser() == 'admin'
@ -45,7 +45,7 @@ def http_exec(request, **kwargs):
request.setHeader('Access-Control-Allow-Origin', '*')
request.setHeader('www-authenticate', 'Basic realm="Restricted Area"')
return 'Unauthorized'
path = request.path
given_args = request.args
if kwargs:
@ -53,9 +53,9 @@ def http_exec(request, **kwargs):
dynamic_key = path.split('/')[-1]
path = path.replace(dynamic_key, '(?P<'+ k +'>[^/]+)')
given_args[k] = [v]
print given_args
# Sanitize arguments
# Sanitize arguments
dict = action_dict[request.method +' '+ path]
if 'arguments' in dict: possible_args = dict['arguments']
else: possible_args = {}
@ -69,10 +69,10 @@ def http_exec(request, **kwargs):
if 'nargs' not in params:
possible_args[arg]['nargs'] = '*'
if 'full' in params:
new_key = params['full'][2:]
new_key = params['full'][2:].replace('-', '_')
else:
new_key = arg[2:]
possible_args[new_key] = possible_args[arg]
new_key = arg[2:].replace('-', '_')
possible_args[new_key] = possible_args[arg]
del possible_args[arg]
try:
@ -90,7 +90,7 @@ def http_exec(request, **kwargs):
raise YunoHostError(22, _('Invalid argument') + ' ' + value)
if 'action' in possible_args[key] and possible_args[key]['action'] == 'store_true':
yes = ['true', 'True', 'yes', 'Yes']
value = value in yes
value = value in yes
validated_args[key] = value
func = str_to_func(dict['function'])
@ -113,7 +113,7 @@ def http_exec(request, **kwargs):
request.setResponseCode(204, 'No Content')
else:
request.setResponseCode(200, 'OK')
except YunoHostError, error:
# Set response code with function's raised code
@ -123,7 +123,7 @@ def http_exec(request, **kwargs):
request.setResponseCode(400, 'Bad Request')
else:
request.setResponseCode(500, 'Internal Server Error')
result = { 'error' : error.message }
return json.dumps(result)
@ -140,8 +140,8 @@ def main():
del action_map['general_arguments']
for category, category_params in action_map.items():
for action, action_params in category_params['actions'].items():
if 'help' not in action_params:
action_params['help'] = ''
if 'action_help' not in action_params:
action_params['action_help'] = ''
if 'api' not in action_params:
action_params['api'] = 'GET /'+ category +'/'+ action
method, path = action_params['api'].split(' ')
@ -150,12 +150,12 @@ def main():
api.register('OPTIONS', path, http_exec)
action_dict[action_params['api']] = {
'function': 'yunohost_'+ category +'.'+ category +'_'+ action,
'help' : action_params['help']
'help' : action_params['action_help']
}
if 'arguments' in action_params:
if 'arguments' in action_params:
action_dict[action_params['api']]['arguments'] = action_params['arguments']
# Register only postinstall action if YunoHost isn't completely set up
try:
with open('/etc/yunohost/installed') as f: pass