1
0

script.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/env python
  2. '''
  3. A CLI interface to a remote salt-api instance
  4. '''
  5. from __future__ import print_function
  6. import sys
  7. import json
  8. import logging
  9. from pepper.cli import PepperCli
  10. from pepper.retcode import PepperRetcode
  11. from pepper.exceptions import (
  12. PepperException,
  13. PepperAuthException,
  14. PepperArgumentsException,
  15. )
  16. try:
  17. import salt.loader
  18. import salt.config
  19. import salt.output
  20. HAS_SALT = True
  21. except ImportError:
  22. HAS_SALT = False
  23. logger = logging.getLogger(__name__)
  24. class Pepper(object):
  25. def __init__(self):
  26. self.cli = PepperCli()
  27. if HAS_SALT:
  28. self.opts = salt.config.client_config(self.cli.options.master)
  29. else:
  30. self.opts = {}
  31. if self.cli.options.output_file is not None:
  32. self.opts['output_file'] = self.cli.options.output_file
  33. @property
  34. def output(self):
  35. if not hasattr(self, 'modules'):
  36. self.modules = salt.loader.minion_mods(self.opts)
  37. try:
  38. oput = self.modules[self.cli.args[1]].__outputter__
  39. except (KeyError, AttributeError, TypeError):
  40. oput = 'nested'
  41. return oput
  42. def __call__(self):
  43. try:
  44. for exit_code, result in self.cli.run():
  45. if HAS_SALT and self.opts:
  46. logger.debug('Use Salt outputters')
  47. result = json.loads(result)
  48. # unwrap ret in some cases
  49. if 'return' in result:
  50. result = result['return']
  51. for ret in result:
  52. if isinstance(ret, dict):
  53. if self.cli.options.client.startswith('local'):
  54. for minionid, minionret in ret.items():
  55. # rest_tornado doesnt return full_return directly
  56. # it will always be from get_event, so the output differs slightly
  57. if isinstance(minionret, dict) and 'return' in minionret:
  58. # version >= 2017.7
  59. salt.output.display_output(
  60. {minionid: minionret['return']},
  61. self.cli.options.output or minionret.get('out', None) or 'nested',
  62. opts=self.opts
  63. )
  64. # cherrypy returns with ret via full_return
  65. elif isinstance(minionret, dict) and 'ret' in minionret:
  66. # version >= 2017.7
  67. salt.output.display_output(
  68. {minionid: minionret['ret']},
  69. self.cli.options.output or minionret.get('out', None) or 'nested',
  70. opts=self.opts
  71. )
  72. else:
  73. salt.output.display_output(
  74. {minionid: minionret},
  75. self.cli.options.output or self.output,
  76. opts=self.opts
  77. )
  78. elif 'data' in ret:
  79. # unfold runners
  80. outputter = ret.get('outputter', 'nested')
  81. if isinstance(ret['data'], dict) and 'return' in ret['data']:
  82. ret = ret['data']['return']
  83. salt.output.display_output(
  84. ret,
  85. self.cli.options.output or outputter,
  86. opts=self.opts
  87. )
  88. else:
  89. salt.output.display_output(
  90. {self.cli.options.client: ret},
  91. self.cli.options.output or ret.get('outputter', 'nested'),
  92. opts=self.opts
  93. )
  94. else:
  95. salt.output.display_output(
  96. {self.cli.options.client: ret},
  97. self.cli.options.output or 'nested',
  98. opts=self.opts,
  99. )
  100. else:
  101. if self.cli.options.output_file is not None:
  102. with open(self.cli.options.output_file, 'a') as ofile:
  103. print(result, file=ofile)
  104. else:
  105. print(result)
  106. if exit_code is not None:
  107. if exit_code == 0:
  108. return PepperRetcode().validate(self.cli.options, result)
  109. return exit_code
  110. except (PepperException, PepperAuthException, PepperArgumentsException) as exc:
  111. print('Pepper error: {0}'.format(exc), file=sys.stderr)
  112. return 1
  113. except KeyboardInterrupt:
  114. # TODO: mimic CLI and output JID on ctrl-c
  115. return 0
  116. except Exception as e:
  117. print(e)
  118. print('Uncaught Pepper error (increase verbosity for the full traceback).', file=sys.stderr)
  119. logger.debug('Uncaught traceback:', exc_info=True)
  120. return 1