script.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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 not self.cli.options.userun and self.opts:
  46. logger.info('Use Salt outputters')
  47. for ret in json.loads(result)['return']:
  48. if isinstance(ret, dict):
  49. if self.cli.options.client == 'local':
  50. for minionid, minionret in ret.items():
  51. if isinstance(minionret, dict) and 'ret' in minionret:
  52. # version >= 2017.7
  53. salt.output.display_output(
  54. {minionid: minionret['ret']},
  55. self.cli.options.output or minionret.get('out', None) or 'nested',
  56. opts=self.opts
  57. )
  58. else:
  59. salt.output.display_output(
  60. {minionid: minionret},
  61. self.cli.options.output or self.output,
  62. opts=self.opts
  63. )
  64. elif 'data' in ret:
  65. salt.output.display_output(
  66. ret['data'],
  67. self.cli.options.output or ret.get('outputter', 'nested'),
  68. opts=self.opts
  69. )
  70. else:
  71. salt.output.display_output(
  72. {self.cli.options.client: ret},
  73. self.cli.options.output or ret.get('outputter', 'nested'),
  74. opts=self.opts
  75. )
  76. else:
  77. salt.output.display_output(
  78. {self.cli.options.client: ret},
  79. 'nested',
  80. opts=self.opts,
  81. )
  82. else:
  83. if self.cli.options.output_file is not None:
  84. with open(self.cli.options.output_file, 'a') as ofile:
  85. print(result, file=ofile)
  86. else:
  87. print(result)
  88. if exit_code is not None:
  89. if exit_code == 0:
  90. return PepperRetcode().validate(self.cli.options, json.loads(result)['return'])
  91. return exit_code
  92. except (PepperException, PepperAuthException, PepperArgumentsException) as exc:
  93. print('Pepper error: {0}'.format(exc), file=sys.stderr)
  94. return 1
  95. except KeyboardInterrupt:
  96. # TODO: mimic CLI and output JID on ctrl-c
  97. return 0
  98. except Exception as e:
  99. print(e)
  100. print('Uncaught Pepper error (increase verbosity for the full traceback).', file=sys.stderr)
  101. logger.debug('Uncaught traceback:', exc_info=True)
  102. return 1