project.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. from .service import Service
  2. def sort_service_dicts(services):
  3. # Sort in dependency order
  4. def cmp(x, y):
  5. x_deps_y = y['name'] in x.get('links', [])
  6. y_deps_x = x['name'] in y.get('links', [])
  7. if x_deps_y and not y_deps_x:
  8. return 1
  9. elif y_deps_x and not x_deps_y:
  10. return -1
  11. return 0
  12. return sorted(services, cmp=cmp)
  13. class Project(object):
  14. """
  15. A collection of services.
  16. """
  17. def __init__(self, name, services, client):
  18. self.name = name
  19. self.services = services
  20. self.client = client
  21. @classmethod
  22. def from_dicts(cls, name, service_dicts, client):
  23. """
  24. Construct a ServiceCollection from a list of dicts representing services.
  25. """
  26. project = cls(name, [], client)
  27. for service_dict in sort_service_dicts(service_dicts):
  28. # Reference links by object
  29. links = []
  30. if 'links' in service_dict:
  31. for service_name in service_dict.get('links', []):
  32. links.append(project.get_service(service_name))
  33. del service_dict['links']
  34. project.services.append(Service(client=client, project=name, links=links, **service_dict))
  35. return project
  36. @classmethod
  37. def from_config(cls, name, config, client):
  38. dicts = []
  39. for service_name, service in config.items():
  40. service['name'] = service_name
  41. dicts.append(service)
  42. return cls.from_dicts(name, dicts, client)
  43. def get_service(self, name):
  44. """
  45. Retrieve a service by name. Raises NoSuchService
  46. if the named service does not exist.
  47. """
  48. for service in self.services:
  49. if service.name == name:
  50. return service
  51. raise NoSuchService(name)
  52. def get_services(self, service_names=None):
  53. """
  54. Returns a list of this project's services filtered
  55. by the provided list of names, or all services if
  56. service_names is None or [].
  57. Preserves the original order of self.services.
  58. Raises NoSuchService if any of the named services
  59. do not exist.
  60. """
  61. if service_names is None or len(service_names) == 0:
  62. return self.services
  63. else:
  64. unsorted = [self.get_service(name) for name in service_names]
  65. return [s for s in self.services if s in unsorted]
  66. def create_containers(self, service_names=None):
  67. """
  68. For each service, creates a container if there are none.
  69. """
  70. for service in self.get_services(service_names):
  71. if len(service.containers(stopped=True)) == 0:
  72. service.create_container()
  73. def start(self, service_names=None, **options):
  74. for service in self.get_services(service_names):
  75. service.start(**options)
  76. def stop(self, service_names=None, **options):
  77. for service in self.get_services(service_names):
  78. service.stop(**options)
  79. def kill(self, service_names=None, **options):
  80. for service in self.get_services(service_names):
  81. service.kill(**options)
  82. def build(self, service_names=None, **options):
  83. for service in self.get_services(service_names):
  84. if service.can_be_built():
  85. service.build(**options)
  86. else:
  87. log.info('%s uses an image, skipping')
  88. def remove_stopped(self, service_names=None, **options):
  89. for service in self.get_services(service_names):
  90. service.remove_stopped(**options)
  91. def containers(self, service_names=None, *args, **kwargs):
  92. l = []
  93. for service in self.get_services(service_names):
  94. for container in service.containers(*args, **kwargs):
  95. l.append(container)
  96. return l
  97. class NoSuchService(Exception):
  98. def __init__(self, name):
  99. self.name = name
  100. self.msg = "No such service: %s" % self.name
  101. def __str__(self):
  102. return self.msg