PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/salt/modules/pyenv.py

https://gitlab.com/ricardo.hernandez/salt
Python | 326 lines | 278 code | 19 blank | 29 comment | 6 complexity | 17ce774bfaa20e3149d2a2deb9b302bc MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. '''
  3. Manage python installations with pyenv.
  4. .. note::
  5. Git needs to be installed and available via PATH if pyenv is to be
  6. installed automatically by the module.
  7. .. versionadded:: v2014.04
  8. '''
  9. from __future__ import absolute_import
  10. # Import python libs
  11. import os
  12. import re
  13. import logging
  14. try:
  15. from shlex import quote as _cmd_quote # pylint: disable=E0611
  16. except ImportError:
  17. from pipes import quote as _cmd_quote
  18. # Set up logger
  19. log = logging.getLogger(__name__)
  20. __func_alias__ = {
  21. 'list_': 'list'
  22. }
  23. __opts__ = {
  24. 'pyenv.root': None,
  25. 'pyenv.build_env': None,
  26. }
  27. def _pyenv_exec(command, args='', env=None, runas=None, ret=None):
  28. if not is_installed(runas):
  29. return False
  30. binary = _pyenv_bin(runas)
  31. path = _pyenv_path(runas)
  32. if env:
  33. env = ' {0}'.format(env)
  34. env = env or ''
  35. binary = 'env PYENV_ROOT={0}{1} {2}'.format(path, env, binary)
  36. result = __salt__['cmd.run_all'](
  37. '{0} {1} {2}'.format(binary, command, args),
  38. runas=runas
  39. )
  40. if isinstance(ret, dict):
  41. ret.update(result)
  42. return ret
  43. if result['retcode'] == 0:
  44. return result['stdout']
  45. else:
  46. return False
  47. def _pyenv_bin(runas=None):
  48. path = _pyenv_path(runas)
  49. return '{0}/bin/pyenv'.format(path)
  50. def _pyenv_path(runas=None):
  51. path = None
  52. if runas in (None, 'root'):
  53. path = __salt__['config.option']('pyenv.root') or '/usr/local/pyenv'
  54. else:
  55. path = __salt__['config.option']('pyenv.root') or '~{0}/.pyenv'.format(runas)
  56. return os.path.expanduser(path)
  57. def _install_pyenv(path, runas=None):
  58. if os.path.isdir(path):
  59. return True
  60. return 0 == __salt__['cmd.retcode'](
  61. 'git clone https://github.com/yyuu/pyenv.git {0}'.format(path), runas=runas)
  62. def _update_pyenv(path, runas=None):
  63. if not os.path.isdir(path):
  64. return False
  65. return 0 == __salt__['cmd.retcode'](
  66. 'cd {0} && git pull'.format(_cmd_quote(path)), runas=runas)
  67. def _update_python_build(path, runas=None):
  68. path = '{0}/plugins/python-build'.format(path)
  69. if not os.path.isdir(path):
  70. return False
  71. return 0 == __salt__['cmd.retcode'](
  72. 'cd {0} && git pull'.format(_cmd_quote(path)), runas=runas)
  73. def install(runas=None, path=None):
  74. '''
  75. Install pyenv systemwide
  76. CLI Example:
  77. .. code-block:: bash
  78. salt '*' pyenv.install
  79. '''
  80. path = path or _pyenv_path(runas)
  81. path = os.path.expanduser(path)
  82. return _install_pyenv(path, runas)
  83. def update(runas=None, path=None):
  84. '''
  85. Updates the current versions of pyenv and python-Build
  86. CLI Example:
  87. .. code-block:: bash
  88. salt '*' pyenv.update
  89. '''
  90. path = path or _pyenv_path(runas)
  91. path = os.path.expanduser(path)
  92. return _update_pyenv(path, runas)
  93. def is_installed(runas=None):
  94. '''
  95. Check if pyenv is installed.
  96. CLI Example:
  97. .. code-block:: bash
  98. salt '*' pyenv.is_installed
  99. '''
  100. return __salt__['cmd.has_exec'](_pyenv_bin(runas))
  101. def install_python(python, runas=None):
  102. '''
  103. Install a python implementation.
  104. python
  105. The version of python to install, should match one of the
  106. versions listed by pyenv.list
  107. CLI Example:
  108. .. code-block:: bash
  109. salt '*' pyenv.install_python 2.0.0-p0
  110. '''
  111. python = re.sub(r'^python-', '', python)
  112. env = None
  113. env_list = []
  114. if __grains__['os'] in ('FreeBSD', 'NetBSD', 'OpenBSD'):
  115. env_list.append('MAKE=gmake')
  116. if __salt__['config.option']('pyenv.build_env'):
  117. env_list.append(__salt__['config.option']('pyenv.build_env'))
  118. if env_list:
  119. env = ' '.join(env_list)
  120. ret = {}
  121. ret = _pyenv_exec('install', python, env=env, runas=runas, ret=ret)
  122. if ret['retcode'] == 0:
  123. rehash(runas=runas)
  124. return ret['stderr']
  125. else:
  126. # Cleanup the failed installation so it doesn't list as installed
  127. uninstall_python(python, runas=runas)
  128. return False
  129. def uninstall_python(python, runas=None):
  130. '''
  131. Uninstall a python implementation.
  132. python
  133. The version of python to uninstall. Should match one of the versions
  134. listed by :mod:`pyenv.versions <salt.modules.pyenv.versions>`
  135. CLI Example:
  136. .. code-block:: bash
  137. salt '*' pyenv.uninstall_python 2.0.0-p0
  138. '''
  139. python = re.sub(r'^python-', '', python)
  140. args = '--force {0}'.format(python)
  141. _pyenv_exec('uninstall', args, runas=runas)
  142. return True
  143. def versions(runas=None):
  144. '''
  145. List the installed versions of python.
  146. CLI Example:
  147. .. code-block:: bash
  148. salt '*' pyenv.versions
  149. '''
  150. ret = _pyenv_exec('versions', '--bare', runas=runas)
  151. return [] if ret is False else ret.splitlines()
  152. def default(python=None, runas=None):
  153. '''
  154. Returns or sets the currently defined default python.
  155. python=None
  156. The version to set as the default. Should match one of the versions
  157. listed by :mod:`pyenv.versions <salt.modules.pyenv.versions>`. Leave
  158. blank to return the current default.
  159. CLI Example:
  160. .. code-block:: bash
  161. salt '*' pyenv.default
  162. salt '*' pyenv.default 2.0.0-p0
  163. '''
  164. if python:
  165. _pyenv_exec('global', python, runas=runas)
  166. return True
  167. else:
  168. ret = _pyenv_exec('global', runas=runas)
  169. return '' if ret is False else ret.strip()
  170. def list_(runas=None):
  171. '''
  172. List the installable versions of python.
  173. CLI Example:
  174. .. code-block:: bash
  175. salt '*' pyenv.list
  176. '''
  177. ret = []
  178. output = _pyenv_exec('install', '--list', runas=runas)
  179. if output:
  180. for line in output.splitlines():
  181. if line == 'Available versions:':
  182. continue
  183. ret.append(line.strip())
  184. return ret
  185. def rehash(runas=None):
  186. '''
  187. Run pyenv rehash to update the installed shims.
  188. CLI Example:
  189. .. code-block:: bash
  190. salt '*' pyenv.rehash
  191. '''
  192. _pyenv_exec('rehash', runas=runas)
  193. return True
  194. def do(cmdline=None, runas=None):
  195. '''
  196. Execute a python command with pyenv's shims from the user or the system.
  197. CLI Example:
  198. .. code-block:: bash
  199. salt '*' pyenv.do 'gem list bundler'
  200. salt '*' pyenv.do 'gem list bundler' deploy
  201. '''
  202. path = _pyenv_path(runas)
  203. cmd_split = cmdline.split()
  204. quoted_line = ''
  205. for cmd in cmd_split:
  206. quoted_line = quoted_line + ' ' + _cmd_quote(cmd)
  207. result = __salt__['cmd.run_all'](
  208. 'env PATH={0}/shims:$PATH {1}'.format(_cmd_quote(path), quoted_line),
  209. runas=runas,
  210. python_shell=True
  211. )
  212. if result['retcode'] == 0:
  213. rehash(runas=runas)
  214. return result['stdout']
  215. else:
  216. return False
  217. def do_with_python(python, cmdline, runas=None):
  218. '''
  219. Execute a python command with pyenv's shims using a specific python version.
  220. CLI Example:
  221. .. code-block:: bash
  222. salt '*' pyenv.do_with_python 2.0.0-p0 'gem list bundler'
  223. salt '*' pyenv.do_with_python 2.0.0-p0 'gem list bundler' deploy
  224. '''
  225. if python:
  226. cmd = 'PYENV_VERSION={0} {1}'.format(python, cmdline)
  227. else:
  228. cmd = cmdline
  229. return do(cmd, runas=runas)