codegen.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #!/usr/bin/env python3
  2. import argparse
  3. import os
  4. from os.path import join as pjoin
  5. import subprocess
  6. import sys
  7. def run_cmd(cmds):
  8. print(' '.join(cmds))
  9. proc = subprocess.Popen(
  10. cmds, stdout=subprocess.PIPE)
  11. while True:
  12. line_gen = proc.stdout.readline().rstrip()
  13. if not line_gen:
  14. break
  15. for l in line_gen:
  16. print(l)
  17. def run_generator(tool, input_dirs, out_pkg):
  18. cmd = [tool]
  19. for i in input_dirs:
  20. cmd.extend(["--input-dirs", i])
  21. cmd.extend(["--output-package", out_pkg])
  22. run_cmd(cmd)
  23. def run_model_api(input_dirs, out_pkg):
  24. return run_generator('model-api-gen', input_dirs, out_pkg)
  25. def run_swagger_gen(input_dirs, out_pkg):
  26. return run_generator('swagger-gen', input_dirs, out_pkg)
  27. def run_swagger_serve(output_dir, serve=False):
  28. def is_swagger_yaml(file):
  29. return file.endswith('.yaml') and file.startswith('swagger')
  30. yamls = [pjoin(output_dir, x) for x in os.listdir(output_dir) if is_swagger_yaml(x)]
  31. cmd = ['swagger-serve', 'generate']
  32. cmd.extend(['-i', ','.join(yamls), '-o', output_dir])
  33. if serve:
  34. cmd.extend(['-p', "40900"])
  35. cmd.append('--serve')
  36. run_cmd(cmd)
  37. def run_swagger_yaml(svc, swagger_pkg_dir, output_dir):
  38. if not os.path.exists(output_dir):
  39. os.makedirs(output_dir)
  40. work_dir = pjoin(swagger_pkg_dir, svc)
  41. cmd = ["swagger", "generate", "spec", "--scan-models"]
  42. cmd.extend(["--work-dir", work_dir])
  43. cmd.extend(["-o", pjoin(output_dir, "swagger_%s.yaml" % svc)])
  44. run_cmd(cmd)
  45. def remove_prefix(text, prefix):
  46. return text[text.startswith(prefix) and len(prefix):]
  47. class FuncDispatcher(object):
  48. def __init__(self):
  49. self.gen_dict = {}
  50. self.collect_funcs()
  51. def collect_funcs(self):
  52. gen_dict = {}
  53. for attr in dir(self):
  54. if not attr.startswith('gen_'):
  55. continue
  56. func = getattr(self, attr)
  57. if not callable(func):
  58. continue
  59. svc = remove_prefix(attr, 'gen_')
  60. gen_dict[svc] = func
  61. self.gen_dict = gen_dict
  62. def get_choices(self):
  63. svc = ["all"]
  64. svc.extend(self.gen_dict.keys())
  65. return svc
  66. def dispatcher(self, opt):
  67. def run_one(key):
  68. self.gen_dict[key]()
  69. def run_all():
  70. for key in self.gen_dict:
  71. run_one(key)
  72. if opt.service is None or 'all' in opt.service:
  73. run_all()
  74. else:
  75. for svc in opt.service:
  76. run_one(svc)
  77. def get_parser(self, subparsers, name, help):
  78. parser = subparsers.add_parser(name, help=help)
  79. parser.add_argument("-s", "--service", help="%s for services" % help,
  80. nargs='+', choices=self.get_choices())
  81. parser.set_defaults(func=self.dispatcher)
  82. class ModelAPI(FuncDispatcher):
  83. def __init__(self, pkg_dir, apis_dir):
  84. super(ModelAPI, self).__init__()
  85. self.pkg_dir = pkg_dir
  86. self.apis_dir = apis_dir
  87. def get_parser(self, subparsers):
  88. return super(ModelAPI, self).get_parser(
  89. subparsers, "model-api", "generate model struct code for api")
  90. def run(self, pkg=[], out=[]):
  91. if pkg is None:
  92. return
  93. in_dir = pjoin(self.pkg_dir, *pkg)
  94. out_dir = pjoin(self.apis_dir, *out)
  95. run_model_api([in_dir], out_dir)
  96. def run_same(self, pkg):
  97. self.run(pkg=[pkg], out=[pkg])
  98. def run_model(self, svc):
  99. self.run(pkg=[svc, "models"], out=[svc])
  100. def gen_cloudcommon(self):
  101. self.run(pkg=["cloudcommon", "db"])
  102. self.run(pkg=["cloudcommon", "db", "proxy"], out=["cloudcommon", "proxy"])
  103. run_swagger_gen(['yunion.io/x/cloudmux/pkg/cloudprovider'], 'yunion.io/x/onecloud/pkg/apis/cloudprovider')
  104. self.run(pkg=["keystone", "models"], out=["identity"])
  105. self.run_model("compute")
  106. self.run(pkg=["compute", "models", "baremetal"], out=["compute", "baremetal"])
  107. self.run_model("image")
  108. self.run_model("cloudid")
  109. self.run_model("notify")
  110. self.run_model("cloudevent")
  111. def gen_monitor(self):
  112. self.run(pkg=["monitor", "models"], out=["monitor"])
  113. def gen_yunionconf(self):
  114. self.run(pkg=["yunionconf", "models"], out=["yunionconf"])
  115. class SwaggerCode(FuncDispatcher):
  116. def __init__(self, pkg_dir, pkg_swagger):
  117. super(SwaggerCode, self).__init__()
  118. self.pkg_dir = pkg_dir
  119. self.pkg_swagger = pkg_swagger
  120. def get_parser(self, subparsers):
  121. return super(SwaggerCode, self).get_parser(
  122. subparsers, "swagger-code", "generate swagger code")
  123. def run(self, svc, pkg=[], out=''):
  124. if svc is None:
  125. return
  126. if pkg is None:
  127. return
  128. svc_pkg_dir = pjoin(self.pkg_dir, svc)
  129. input_dirs = [pjoin(svc_pkg_dir, x) for x in pkg]
  130. out_dir = pjoin(self.pkg_swagger, out)
  131. run_swagger_gen(input_dirs, out_dir)
  132. def run_svc(self, svc, pkg=[]):
  133. self.run(svc, pkg=pkg, out=svc)
  134. def gen_identity(self):
  135. self.run("keystone", pkg=["tokens", "models"], out="identity")
  136. def gen_compute(self):
  137. self.run("compute", pkg=["models"], out="compute")
  138. def gen_image(self):
  139. self.run("image", pkg=["models"], out="image")
  140. def gen_cloudid(self):
  141. self.run("cloudid", pkg=["models"], out="cloudid")
  142. def gen_monitor(self):
  143. self.run("monitor", pkg=["models"], out="monitor")
  144. def gen_yunionconf(self):
  145. self.run("yunionconf", pkg=["models"], out="yunionconf")
  146. def gen_notify(self):
  147. self.run("notify", pkg=["models"], out="notify")
  148. def gen_cloudevent(self):
  149. self.run("cloudevent", pkg=["models"], out="cloudevent")
  150. class SwaggerYAML(FuncDispatcher):
  151. def __init__(self, swagger_dir, out_dir):
  152. super(SwaggerYAML, self).__init__()
  153. self.swagger_dir = swagger_dir
  154. self.out_dir = out_dir
  155. def get_parser(self, subparsers):
  156. return super(SwaggerYAML, self).get_parser(
  157. subparsers, "swagger-yaml", "generate swagger yaml")
  158. def run(self, svc):
  159. run_swagger_yaml(svc, self.swagger_dir, self.out_dir)
  160. def gen_identity(self):
  161. self.run("identity")
  162. def gen_compute(self):
  163. self.run("compute")
  164. def gen_image(self):
  165. self.run("image")
  166. def gen_cloudid(self):
  167. self.run("cloudid")
  168. def gen_monitor(self):
  169. self.run("monitor")
  170. def gen_yunionconf(self):
  171. self.run("yunionconf")
  172. def gen_notify(self):
  173. self.run("notify")
  174. def gen_cloudevent(self):
  175. self.run("cloudevent")
  176. class SwaggerServe(object):
  177. def __init__(self, output_dir):
  178. self.output_dir = output_dir
  179. def get_parser(self, subparsers):
  180. parser = subparsers.add_parser(
  181. "swagger-serve", help="generate swagger web site and serve")
  182. parser.set_defaults(func=self.run)
  183. def run(self, opt):
  184. run_swagger_serve(self.output_dir, serve=True)
  185. class SwaggerSite(object):
  186. def __init__(self, output_dir):
  187. self.output_dir = output_dir
  188. def get_parser(self, subparsers):
  189. parser = subparsers.add_parser(
  190. "swagger-site", help="generate swagger web site")
  191. parser.set_defaults(func=self.run)
  192. def run(self, opt):
  193. run_swagger_serve(self.output_dir)
  194. if __name__ == "__main__":
  195. ONECLOUD="yunion.io/x/onecloud"
  196. PKG_ONECLOUD=pjoin(ONECLOUD, "pkg")
  197. PKG_APIS=pjoin(PKG_ONECLOUD, "apis")
  198. PKG_GENERATED=pjoin(PKG_ONECLOUD, "generated")
  199. PKG_SWAGGER=pjoin(PKG_GENERATED, "swagger")
  200. SCRIPTS_DIR=os.path.dirname(os.path.realpath(__file__))
  201. CUR_DIR=os.path.dirname(SCRIPTS_DIR)
  202. SWAGGER_PKG=pjoin(CUR_DIR, "pkg", "generated", "swagger")
  203. OUTPUT_DIR=pjoin(CUR_DIR, "_output")
  204. OUTPUT_SWAGGER_DIR=pjoin(OUTPUT_DIR, "swagger")
  205. model_api = ModelAPI(PKG_ONECLOUD, PKG_APIS)
  206. swagger_yaml = SwaggerYAML(SWAGGER_PKG, OUTPUT_SWAGGER_DIR)
  207. swagger_code = SwaggerCode(PKG_ONECLOUD, PKG_SWAGGER)
  208. swagger_serve = SwaggerServe(OUTPUT_SWAGGER_DIR)
  209. swagger_site = SwaggerSite(OUTPUT_SWAGGER_DIR)
  210. parser = argparse.ArgumentParser(description="Code generate helper.")
  211. subparsers = parser.add_subparsers(dest='cmd')
  212. subparsers.required = True
  213. for cmd in [model_api, swagger_code, swagger_yaml, swagger_serve, swagger_site]:
  214. cmd.get_parser(subparsers)
  215. if len(sys.argv) == 1:
  216. parser.print_help()
  217. sys.exit(1)
  218. options = parser.parse_args()
  219. options.func(options)