saltsh.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. '''\
  4. Welcome to the Salt repl which exposes the execution environment of a minion in
  5. a pre-configured Python shell
  6. __opts__, __salt__, __grains__, and __pillar__ are available.
  7. Jinja can be tested with full access to the above structures in the usual way:
  8. JINJA("""\\
  9. I am {{ salt['cmd.run']('whoami') }}.
  10. {% if otherstuff %}
  11. Some other stuff here
  12. {% endif %}
  13. """, otherstuff=True)
  14. A history file is maintained in ~/.saltsh_history.
  15. completion behavior can be customized via the ~/.inputrc file.
  16. '''
  17. # pylint: disable=file-perms
  18. # Import python libs
  19. from __future__ import absolute_import
  20. import atexit
  21. import os
  22. import readline
  23. import sys
  24. from code import InteractiveConsole
  25. # Import salt libs
  26. import salt.client
  27. import salt.config
  28. import salt.loader
  29. import salt.output
  30. import salt.pillar
  31. import salt.runner
  32. # Import 3rd party libs
  33. import jinja2
  34. from salt.ext.six.moves import builtins # pylint: disable=import-error
  35. # pylint: disable=unused-import
  36. # These are imported to be available in the spawned shell
  37. import salt.utils.yaml
  38. import pprint
  39. # pylint: enable=unused-import
  40. HISTFILE = '{HOME}/.saltsh_history'.format(**os.environ)
  41. def savehist():
  42. '''
  43. Save the history file
  44. '''
  45. readline.write_history_file(HISTFILE)
  46. def get_salt_vars():
  47. '''
  48. Return all the Salt-usual double-under data structures for a minion
  49. '''
  50. # Create the Salt __opts__ variable
  51. __opts__ = salt.config.client_config(
  52. os.environ.get('SALT_MINION_CONFIG', '/etc/salt/minion'))
  53. # Populate grains if it hasn't been done already
  54. if 'grains' not in __opts__ or not __opts__['grains']:
  55. __opts__['grains'] = salt.loader.grains(__opts__)
  56. # file_roots and pillar_roots should be set in the minion config
  57. if 'file_client' not in __opts__ or not __opts__['file_client']:
  58. __opts__['file_client'] = 'local'
  59. # ensure we have a minion id
  60. if 'id' not in __opts__ or not __opts__['id']:
  61. __opts__['id'] = 'saltsh_mid'
  62. # Populate template variables
  63. __salt__ = salt.loader.minion_mods(__opts__)
  64. __grains__ = __opts__['grains']
  65. if __opts__['file_client'] == 'local':
  66. __pillar__ = salt.pillar.get_pillar(
  67. __opts__,
  68. __grains__,
  69. __opts__.get('id'),
  70. __opts__.get('saltenv'),
  71. ).compile_pillar()
  72. else:
  73. __pillar__ = {}
  74. JINJA = lambda x, **y: jinja2.Template(x).render( # pylint: disable=C0103,W0612
  75. grains=__grains__,
  76. salt=__salt__,
  77. opts=__opts__,
  78. pillar=__pillar__,
  79. **y)
  80. return locals()
  81. def main():
  82. '''
  83. The main entry point
  84. '''
  85. salt_vars = get_salt_vars()
  86. def salt_outputter(value):
  87. '''
  88. Use Salt's outputters to print values to the shell
  89. '''
  90. if value is not None:
  91. builtins._ = value
  92. salt.output.display_output(value, '', salt_vars['__opts__'])
  93. sys.displayhook = salt_outputter
  94. # Set maximum number of items that will be written to the history file
  95. readline.set_history_length(300)
  96. if os.path.exists(HISTFILE):
  97. readline.read_history_file(HISTFILE)
  98. atexit.register(savehist)
  99. atexit.register(lambda: sys.stdout.write('Salt you later!\n'))
  100. saltrepl = InteractiveConsole(locals=salt_vars)
  101. saltrepl.interact(banner=__doc__)
  102. if __name__ == '__main__':
  103. main()