main.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import datetime
  2. import logging
  3. import sys
  4. import os
  5. import re
  6. from docopt import docopt
  7. from inspect import getdoc
  8. from .. import __version__
  9. from ..service import get_container_name
  10. from ..service_collection import ServiceCollection
  11. from .command import Command
  12. from .log_printer import LogPrinter
  13. from .errors import UserError
  14. from .docopt_command import NoSuchCommand
  15. log = logging.getLogger(__name__)
  16. def main():
  17. console_handler = logging.StreamHandler()
  18. console_handler.setFormatter(logging.Formatter())
  19. console_handler.setLevel(logging.INFO)
  20. root_logger = logging.getLogger()
  21. root_logger.addHandler(console_handler)
  22. root_logger.setLevel(logging.DEBUG)
  23. # Disable requests logging
  24. logging.getLogger("requests").propagate = False
  25. try:
  26. command = TopLevelCommand()
  27. command.sys_dispatch()
  28. except KeyboardInterrupt:
  29. log.error("\nAborting.")
  30. exit(1)
  31. except UserError, e:
  32. log.error(e.msg)
  33. exit(1)
  34. except NoSuchCommand, e:
  35. log.error("No such command: %s", e.command)
  36. log.error("")
  37. log.error("\n".join(parse_doc_section("commands:", getdoc(e.supercommand))))
  38. exit(1)
  39. # stolen from docopt master
  40. def parse_doc_section(name, source):
  41. pattern = re.compile('^([^\n]*' + name + '[^\n]*\n?(?:[ \t].*?(?:\n|$))*)',
  42. re.IGNORECASE | re.MULTILINE)
  43. return [s.strip() for s in pattern.findall(source)]
  44. class TopLevelCommand(Command):
  45. """.
  46. Usage:
  47. plum [options] [COMMAND] [ARGS...]
  48. plum -h|--help
  49. Options:
  50. --verbose Show more output
  51. --version Print version and exit
  52. Commands:
  53. ps List services and containers
  54. run Run a one-off command
  55. start Start services
  56. stop Stop services
  57. """
  58. def ps(self, options):
  59. """
  60. List services and containers.
  61. Usage: ps
  62. """
  63. for container in self._get_containers(all=False):
  64. print container.name
  65. def run(self, options):
  66. """
  67. Run a one-off command.
  68. Usage: run SERVICE COMMAND [ARGS...]
  69. """
  70. service = self.service_collection.get(options['SERVICE'])
  71. if service is None:
  72. raise UserError("No such service: %s" % options['SERVICE'])
  73. container_options = {
  74. 'command': [options['COMMAND']] + options['ARGS'],
  75. }
  76. container = service.create_container(**container_options)
  77. stream = self.client.logs(container, stream=True)
  78. for data in stream:
  79. if data is None:
  80. break
  81. print data
  82. def start(self, options):
  83. """
  84. Start all services
  85. Usage: start
  86. """
  87. self.service_collection.start()
  88. def stop(self, options):
  89. """
  90. Stop all services
  91. Usage: stop
  92. """
  93. self.service_collection.stop()
  94. def logs(self, options):
  95. """
  96. View containers' output
  97. Usage: logs
  98. """
  99. containers = self._get_containers(all=False)
  100. print "Attaching to", ", ".join(get_container_name(c) for c in containers)
  101. LogPrinter(client=self.client).attach(containers)
  102. def _get_containers(self, all):
  103. return [c for s in self.service_collection for c in s.containers(all=all)]