No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

303 líneas
8.3 KiB

  1. # imports - standard imports
  2. import hashlib
  3. import os
  4. import random
  5. import string
  6. # imports - third party imports
  7. import click
  8. # imports - module imports
  9. import bench
  10. import bench.config
  11. from bench.bench import Bench
  12. from bench.utils import get_bench_name
  13. def make_nginx_conf(bench_path, yes=False, logging=None, log_format=None):
  14. conf_path = os.path.join(bench_path, "config", "nginx.conf")
  15. if not yes and os.path.exists(conf_path):
  16. if not click.confirm(
  17. "nginx.conf already exists and this will overwrite it. Do you want to continue?"
  18. ):
  19. return
  20. template = bench.config.env().get_template("nginx.conf")
  21. bench_path = os.path.abspath(bench_path)
  22. sites_path = os.path.join(bench_path, "sites")
  23. config = Bench(bench_path).conf
  24. sites = prepare_sites(config, bench_path)
  25. bench_name = get_bench_name(bench_path)
  26. allow_rate_limiting = config.get("allow_rate_limiting", False)
  27. template_vars = {
  28. "sites_path": sites_path,
  29. "http_timeout": config.get("http_timeout"),
  30. "sites": sites,
  31. "webserver_port": config.get("webserver_port"),
  32. "socketio_port": config.get("socketio_port"),
  33. "bench_name": bench_name,
  34. "error_pages": get_error_pages(),
  35. "allow_rate_limiting": allow_rate_limiting,
  36. # for nginx map variable
  37. "random_string": "".join(random.choice(string.ascii_lowercase) for i in range(7)),
  38. }
  39. if logging and logging != "none":
  40. _log_format = ""
  41. if log_format and log_format != "none":
  42. _log_format = log_format
  43. template_vars["logging"] = {"level": logging, "log_format": _log_format}
  44. if allow_rate_limiting:
  45. template_vars.update(
  46. {
  47. "bench_name_hash": hashlib.sha256(bench_name).hexdigest()[:16],
  48. "limit_conn_shared_memory": get_limit_conn_shared_memory(),
  49. }
  50. )
  51. nginx_conf = template.render(**template_vars)
  52. with open(conf_path, "w") as f:
  53. f.write(nginx_conf)
  54. def make_bench_manager_nginx_conf(bench_path, yes=False, port=23624, domain=None):
  55. from bench.config.site_config import get_site_config
  56. template = bench.config.env().get_template("bench_manager_nginx.conf")
  57. bench_path = os.path.abspath(bench_path)
  58. sites_path = os.path.join(bench_path, "sites")
  59. config = Bench(bench_path).conf
  60. site_config = get_site_config(domain, bench_path=bench_path)
  61. bench_name = get_bench_name(bench_path)
  62. template_vars = {
  63. "port": port,
  64. "domain": domain,
  65. "bench_manager_site_name": "bench-manager.local",
  66. "sites_path": sites_path,
  67. "http_timeout": config.get("http_timeout"),
  68. "webserver_port": config.get("webserver_port"),
  69. "socketio_port": config.get("socketio_port"),
  70. "bench_name": bench_name,
  71. "error_pages": get_error_pages(),
  72. "ssl_certificate": site_config.get("ssl_certificate"),
  73. "ssl_certificate_key": site_config.get("ssl_certificate_key"),
  74. }
  75. bench_manager_nginx_conf = template.render(**template_vars)
  76. conf_path = os.path.join(bench_path, "config", "nginx.conf")
  77. if not yes and os.path.exists(conf_path):
  78. click.confirm(
  79. "nginx.conf already exists and bench-manager configuration will be appended to it. Do you want to continue?",
  80. abort=True,
  81. )
  82. with open(conf_path, "a") as myfile:
  83. myfile.write(bench_manager_nginx_conf)
  84. def prepare_sites(config, bench_path):
  85. sites = {
  86. "that_use_port": [],
  87. "that_use_dns": [],
  88. "that_use_ssl": [],
  89. "that_use_wildcard_ssl": [],
  90. }
  91. domain_map = {}
  92. ports_in_use = {}
  93. dns_multitenant = config.get("dns_multitenant")
  94. shared_port_exception_found = False
  95. sites_configs = get_sites_with_config(bench_path=bench_path)
  96. # preload all preset site ports to avoid conflicts
  97. if not dns_multitenant:
  98. for site in sites_configs:
  99. if site.get("port"):
  100. if not site["port"] in ports_in_use:
  101. ports_in_use[site["port"]] = []
  102. ports_in_use[site["port"]].append(site["name"])
  103. for site in sites_configs:
  104. if dns_multitenant:
  105. domain = site.get("domain")
  106. if domain:
  107. # when site's folder name is different than domain name
  108. domain_map[domain] = site["name"]
  109. site_name = domain or site["name"]
  110. if site.get("wildcard"):
  111. sites["that_use_wildcard_ssl"].append(site_name)
  112. if not sites.get("wildcard_ssl_certificate"):
  113. sites["wildcard_ssl_certificate"] = site["ssl_certificate"]
  114. sites["wildcard_ssl_certificate_key"] = site["ssl_certificate_key"]
  115. elif site.get("ssl_certificate") and site.get("ssl_certificate_key"):
  116. sites["that_use_ssl"].append(site)
  117. else:
  118. sites["that_use_dns"].append(site_name)
  119. else:
  120. if not site.get("port"):
  121. site["port"] = 80
  122. if site["port"] in ports_in_use:
  123. site["port"] = 8001
  124. while site["port"] in ports_in_use:
  125. site["port"] += 1
  126. if site["port"] in ports_in_use and not site["name"] in ports_in_use[site["port"]]:
  127. shared_port_exception_found = True
  128. ports_in_use[site["port"]].append(site["name"])
  129. else:
  130. ports_in_use[site["port"]] = []
  131. ports_in_use[site["port"]].append(site["name"])
  132. sites["that_use_port"].append(site)
  133. if not dns_multitenant and shared_port_exception_found:
  134. message = "Port conflicts found:"
  135. port_conflict_index = 0
  136. for port_number in ports_in_use:
  137. if len(ports_in_use[port_number]) > 1:
  138. port_conflict_index += 1
  139. message += f"\n{port_conflict_index} - Port {port_number} is shared among sites:"
  140. for site_name in ports_in_use[port_number]:
  141. message += f" {site_name}"
  142. raise Exception(message)
  143. if not dns_multitenant:
  144. message = "Port configuration list:"
  145. for site in sites_configs:
  146. message += f"\n\nSite {site['name']} assigned port: {site['port']}"
  147. print(message)
  148. sites["domain_map"] = domain_map
  149. return sites
  150. def get_sites_with_config(bench_path):
  151. from bench.bench import Bench
  152. from bench.config.site_config import get_site_config
  153. bench = Bench(bench_path)
  154. sites = bench.sites
  155. conf = bench.conf
  156. dns_multitenant = conf.get("dns_multitenant")
  157. ret = []
  158. for site in sites:
  159. try:
  160. site_config = get_site_config(site, bench_path=bench_path)
  161. except Exception as e:
  162. strict_nginx = conf.get("strict_nginx")
  163. if strict_nginx:
  164. print(
  165. f"\n\nERROR: The site config for the site {site} is broken.",
  166. "If you want this command to pass, instead of just throwing an error,",
  167. "You may remove the 'strict_nginx' flag from common_site_config.json or set it to 0",
  168. "\n\n",
  169. )
  170. raise e
  171. else:
  172. print(
  173. f"\n\nWARNING: The site config for the site {site} is broken.",
  174. "If you want this command to fail, instead of just showing a warning,",
  175. "You may add the 'strict_nginx' flag to common_site_config.json and set it to 1",
  176. "\n\n",
  177. )
  178. continue
  179. ret.append(
  180. {
  181. "name": site,
  182. "port": site_config.get("nginx_port"),
  183. "ssl_certificate": site_config.get("ssl_certificate"),
  184. "ssl_certificate_key": site_config.get("ssl_certificate_key"),
  185. }
  186. )
  187. if dns_multitenant and site_config.get("domains"):
  188. for domain in site_config.get("domains"):
  189. # domain can be a string or a dict with 'domain', 'ssl_certificate', 'ssl_certificate_key'
  190. if isinstance(domain, str):
  191. domain = {"domain": domain}
  192. domain["name"] = site
  193. ret.append(domain)
  194. use_wildcard_certificate(bench_path, ret)
  195. return ret
  196. def use_wildcard_certificate(bench_path, ret):
  197. """
  198. stored in common_site_config.json as:
  199. "wildcard": {
  200. "domain": "*.xhiveerp.com",
  201. "ssl_certificate": "/path/to/xhiveerp.com.cert",
  202. "ssl_certificate_key": "/path/to/xhiveerp.com.key"
  203. }
  204. """
  205. from bench.bench import Bench
  206. config = Bench(bench_path).conf
  207. wildcard = config.get("wildcard")
  208. if not wildcard:
  209. return
  210. domain = wildcard["domain"]
  211. ssl_certificate = wildcard["ssl_certificate"]
  212. ssl_certificate_key = wildcard["ssl_certificate_key"]
  213. # If domain is set as "*" all domains will be included
  214. if domain.startswith("*"):
  215. domain = domain[1:]
  216. else:
  217. domain = "." + domain
  218. for site in ret:
  219. if site.get("ssl_certificate"):
  220. continue
  221. if (site.get("domain") or site["name"]).endswith(domain):
  222. # example: ends with .xhiveerp.com
  223. site["ssl_certificate"] = ssl_certificate
  224. site["ssl_certificate_key"] = ssl_certificate_key
  225. site["wildcard"] = 1
  226. def get_error_pages():
  227. bench_app_path = os.path.abspath(bench.__path__[0])
  228. templates = os.path.join(bench_app_path, "config", "templates")
  229. return {502: os.path.join(templates, "502.html")}
  230. def get_limit_conn_shared_memory():
  231. """Allocate 2 percent of total virtual memory as shared memory for nginx limit_conn_zone"""
  232. total_vm = (os.sysconf("SC_PAGE_SIZE") * os.sysconf("SC_PHYS_PAGES")) / (
  233. 1024 * 1024
  234. ) # in MB
  235. return int(0.02 * total_vm)