deploy.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  2. import argparse
  3. import os
  4. import requests
  5. import sys
  6. import tempfile
  7. import zipfile
  8. from pathlib import Path
  9. from . import Command
  10. class Deploy(Command):
  11. """Deploy a module on an Odoo instance"""
  12. def __init__(self):
  13. super(Deploy, self).__init__()
  14. self.session = requests.session()
  15. def deploy_module(self, module_path, url, login, password, db='', force=False):
  16. url = url.rstrip('/')
  17. module_file = self.zip_module(module_path)
  18. try:
  19. return self.login_upload_module(module_file, url, login, password, db, force=force)
  20. finally:
  21. os.remove(module_file)
  22. def login_upload_module(self, module_file, url, login, password, db, force=False):
  23. print("Uploading module file...")
  24. self.session.get(f'{url}/web/login?db={db}', allow_redirects=False) # this set the db in the session
  25. endpoint = url + '/base_import_module/login_upload'
  26. post_data = {
  27. 'login': login,
  28. 'password': password,
  29. 'db': db,
  30. 'force': '1' if force else '',
  31. }
  32. with open(module_file, 'rb') as f:
  33. res = self.session.post(endpoint, files={'mod_file': f}, data=post_data)
  34. if res.status_code == 404:
  35. raise Exception(
  36. "The server '%s' does not have the 'base_import_module' installed or is not up-to-date." % url)
  37. res.raise_for_status()
  38. return res.text
  39. def zip_module(self, path):
  40. path = os.path.abspath(path)
  41. if not os.path.isdir(path):
  42. raise Exception("Could not find module directory '%s'" % path)
  43. container, module_name = os.path.split(path)
  44. temp = tempfile.mktemp(suffix='.zip')
  45. try:
  46. print("Zipping module directory...")
  47. with zipfile.ZipFile(temp, 'w') as zfile:
  48. for root, dirs, files in os.walk(path):
  49. for file in files:
  50. file_path = os.path.join(root, file)
  51. zfile.write(file_path, file_path.split(container).pop())
  52. return temp
  53. except Exception:
  54. os.remove(temp)
  55. raise
  56. def run(self, cmdargs):
  57. parser = argparse.ArgumentParser(
  58. prog=f'{Path(sys.argv[0]).name} {self.name}',
  59. description=self.__doc__
  60. )
  61. parser.add_argument('path', help="Path of the module to deploy")
  62. parser.add_argument('url', nargs='?', help='Url of the server (default=http://localhost:8069)', default="http://localhost:8069")
  63. parser.add_argument('--db', dest='db', help='Database to use if server does not use db-filter.')
  64. parser.add_argument('--login', dest='login', default="admin", help='Login (default=admin)')
  65. parser.add_argument('--password', dest='password', default="admin", help='Password (default=admin)')
  66. parser.add_argument('--verify-ssl', action='store_true', help='Verify SSL certificate')
  67. parser.add_argument('--force', action='store_true', help='Force init even if module is already installed. (will update `noupdate="1"` records)')
  68. if not cmdargs:
  69. sys.exit(parser.print_help())
  70. args = parser.parse_args(args=cmdargs)
  71. if not args.verify_ssl:
  72. self.session.verify = False
  73. try:
  74. if not args.url.startswith(('http://', 'https://')):
  75. args.url = 'https://%s' % args.url
  76. result = self.deploy_module(args.path, args.url, args.login, args.password, args.db, force=args.force)
  77. print(result)
  78. except Exception as e:
  79. sys.exit("ERROR: %s" % e)