mirror of https://github.com/docker/compose.git
'plum up' is now the special magic
'start' and 'stop' are now analogous to their Docker namesakes.
This commit is contained in:
parent
3bebd18de7
commit
a4710fa9e1
|
@ -140,37 +140,43 @@ class TopLevelCommand(Command):
|
|||
service.start_container(container, ports=None)
|
||||
c.run()
|
||||
|
||||
def start(self, options):
|
||||
def up(self, options):
|
||||
"""
|
||||
Start all services
|
||||
Create and start containers
|
||||
|
||||
Usage: start [options]
|
||||
Usage: up [options]
|
||||
|
||||
Options:
|
||||
-d Detached mode: Run containers in the background, print new container names
|
||||
"""
|
||||
if options['-d']:
|
||||
self.project.start()
|
||||
return
|
||||
detached = options['-d']
|
||||
|
||||
running = []
|
||||
unstarted = []
|
||||
unstarted = self.project.create_containers()
|
||||
|
||||
for s in self.project.services:
|
||||
if len(s.containers()) == 0:
|
||||
unstarted.append((s, s.create_container()))
|
||||
else:
|
||||
running += s.containers(stopped=False)
|
||||
|
||||
log_printer = LogPrinter(running + [c for (s, c) in unstarted])
|
||||
if not detached:
|
||||
to_attach = self.project.containers() + [c for (s, c) in unstarted]
|
||||
print "Attaching to", list_containers(to_attach)
|
||||
log_printer = LogPrinter(to_attach, attach_params={'logs': True})
|
||||
|
||||
for (s, c) in unstarted:
|
||||
s.start_container(c)
|
||||
|
||||
try:
|
||||
log_printer.run()
|
||||
finally:
|
||||
self.project.stop()
|
||||
if detached:
|
||||
for (s, c) in unstarted:
|
||||
print c.name
|
||||
else:
|
||||
try:
|
||||
log_printer.run()
|
||||
finally:
|
||||
self.project.kill_and_remove(unstarted)
|
||||
|
||||
def start(self, options):
|
||||
"""
|
||||
Start all services
|
||||
|
||||
Usage: start
|
||||
"""
|
||||
self.project.start()
|
||||
|
||||
def stop(self, options):
|
||||
"""
|
||||
|
|
|
@ -83,13 +83,18 @@ class Container(object):
|
|||
out[k] = v
|
||||
return out
|
||||
|
||||
@property
|
||||
def is_running(self):
|
||||
self.inspect_if_not_inspected()
|
||||
return self.dictionary['State']['Running']
|
||||
|
||||
def start(self, **options):
|
||||
log.info("Starting %s..." % self.name)
|
||||
return self.client.start(self.id, **options)
|
||||
|
||||
def stop(self):
|
||||
def stop(self, **options):
|
||||
log.info("Stopping %s..." % self.name)
|
||||
return self.client.stop(self.id)
|
||||
return self.client.stop(self.id, **options)
|
||||
|
||||
def kill(self):
|
||||
log.info("Killing %s..." % self.name)
|
||||
|
|
|
@ -50,13 +50,29 @@ class Project(object):
|
|||
if service.name == name:
|
||||
return service
|
||||
|
||||
def start(self):
|
||||
def create_containers(self):
|
||||
"""
|
||||
Returns a list of (service, container) tuples,
|
||||
one for each service with no running containers.
|
||||
"""
|
||||
containers = []
|
||||
for service in self.services:
|
||||
service.start()
|
||||
if len(service.containers()) == 0:
|
||||
containers.append((service, service.create_container()))
|
||||
return containers
|
||||
|
||||
def stop(self):
|
||||
def kill_and_remove(self, tuples):
|
||||
for (service, container) in tuples:
|
||||
container.kill()
|
||||
container.remove()
|
||||
|
||||
def start(self, **options):
|
||||
for service in self.services:
|
||||
service.stop()
|
||||
service.start(**options)
|
||||
|
||||
def stop(self, **options):
|
||||
for service in self.services:
|
||||
service.stop(**options)
|
||||
|
||||
def containers(self, *args, **kwargs):
|
||||
l = []
|
||||
|
|
|
@ -38,19 +38,14 @@ class Service(object):
|
|||
l.append(Container.from_ps(self.client, container))
|
||||
return l
|
||||
|
||||
def start(self):
|
||||
if len(self.containers()) == 0:
|
||||
return self.start_container()
|
||||
def start(self, **options):
|
||||
for c in self.containers(stopped=True):
|
||||
if not c.is_running:
|
||||
self.start_container(c, **options)
|
||||
|
||||
def stop(self):
|
||||
self.scale(0)
|
||||
|
||||
def scale(self, num):
|
||||
while len(self.containers()) < num:
|
||||
self.start_container()
|
||||
|
||||
while len(self.containers()) > num:
|
||||
self.stop_container()
|
||||
def stop(self, **options):
|
||||
for c in self.containers():
|
||||
c.stop(**options)
|
||||
|
||||
def create_container(self, one_off=False, **override_options):
|
||||
"""
|
||||
|
@ -99,11 +94,6 @@ class Service(object):
|
|||
)
|
||||
return container
|
||||
|
||||
def stop_container(self):
|
||||
container = self.containers()[-1]
|
||||
container.kill()
|
||||
container.remove()
|
||||
|
||||
def next_container_name(self, one_off=False):
|
||||
bits = [self.project, self.name]
|
||||
if one_off:
|
||||
|
|
|
@ -42,18 +42,52 @@ class ProjectTest(DockerClientTestCase):
|
|||
project = Project('test', [web], self.client)
|
||||
self.assertEqual(project.get_service('web'), web)
|
||||
|
||||
def test_up(self):
|
||||
web = self.create_service('web')
|
||||
db = self.create_service('db')
|
||||
project = Project('test', [web, db], self.client)
|
||||
|
||||
web.create_container()
|
||||
|
||||
self.assertEqual(len(web.containers()), 0)
|
||||
self.assertEqual(len(db.containers()), 0)
|
||||
self.assertEqual(len(web.containers(stopped=True)), 1)
|
||||
self.assertEqual(len(db.containers(stopped=True)), 0)
|
||||
|
||||
unstarted = project.create_containers()
|
||||
self.assertEqual(len(unstarted), 2)
|
||||
self.assertEqual(unstarted[0][0], web)
|
||||
self.assertEqual(unstarted[1][0], db)
|
||||
|
||||
self.assertEqual(len(web.containers()), 0)
|
||||
self.assertEqual(len(db.containers()), 0)
|
||||
self.assertEqual(len(web.containers(stopped=True)), 2)
|
||||
self.assertEqual(len(db.containers(stopped=True)), 1)
|
||||
|
||||
project.kill_and_remove(unstarted)
|
||||
|
||||
self.assertEqual(len(web.containers()), 0)
|
||||
self.assertEqual(len(db.containers()), 0)
|
||||
self.assertEqual(len(web.containers(stopped=True)), 1)
|
||||
self.assertEqual(len(db.containers(stopped=True)), 0)
|
||||
|
||||
def test_start_stop(self):
|
||||
project = Project('test', [
|
||||
self.create_service('web'),
|
||||
self.create_service('db'),
|
||||
], self.client)
|
||||
web = self.create_service('web')
|
||||
db = self.create_service('db')
|
||||
project = Project('test', [web, db], self.client)
|
||||
|
||||
project.start()
|
||||
|
||||
self.assertEqual(len(project.get_service('web').containers()), 1)
|
||||
self.assertEqual(len(project.get_service('db').containers()), 1)
|
||||
self.assertEqual(len(web.containers()), 0)
|
||||
self.assertEqual(len(db.containers()), 0)
|
||||
|
||||
project.stop()
|
||||
web.create_container()
|
||||
project.start()
|
||||
|
||||
self.assertEqual(len(project.get_service('web').containers()), 0)
|
||||
self.assertEqual(len(project.get_service('db').containers()), 0)
|
||||
self.assertEqual(len(web.containers()), 1)
|
||||
self.assertEqual(len(db.containers()), 0)
|
||||
|
||||
project.stop(timeout=1)
|
||||
|
||||
self.assertEqual(len(web.containers()), 0)
|
||||
self.assertEqual(len(db.containers()), 0)
|
||||
|
|
|
@ -26,13 +26,14 @@ class ServiceTest(DockerClientTestCase):
|
|||
foo = self.create_service('foo')
|
||||
bar = self.create_service('bar')
|
||||
|
||||
foo.start()
|
||||
foo.start_container()
|
||||
|
||||
self.assertEqual(len(foo.containers()), 1)
|
||||
self.assertEqual(foo.containers()[0].name, '/default_foo_1')
|
||||
self.assertEqual(len(bar.containers()), 0)
|
||||
|
||||
bar.scale(2)
|
||||
bar.start_container()
|
||||
bar.start_container()
|
||||
|
||||
self.assertEqual(len(foo.containers()), 1)
|
||||
self.assertEqual(len(bar.containers()), 2)
|
||||
|
@ -49,30 +50,28 @@ class ServiceTest(DockerClientTestCase):
|
|||
|
||||
def test_project_is_added_to_container_name(self):
|
||||
service = self.create_service('web', project='myproject')
|
||||
service.start()
|
||||
service.start_container()
|
||||
self.assertEqual(service.containers()[0].name, '/myproject_web_1')
|
||||
|
||||
def test_up_scale_down(self):
|
||||
def test_start_stop(self):
|
||||
service = self.create_service('scalingtest')
|
||||
self.assertEqual(len(service.containers(stopped=True)), 0)
|
||||
|
||||
service.create_container()
|
||||
self.assertEqual(len(service.containers()), 0)
|
||||
self.assertEqual(len(service.containers(stopped=True)), 1)
|
||||
|
||||
service.start()
|
||||
self.assertEqual(len(service.containers()), 1)
|
||||
self.assertEqual(len(service.containers(stopped=True)), 1)
|
||||
|
||||
service.start()
|
||||
self.assertEqual(len(service.containers()), 1)
|
||||
|
||||
service.scale(2)
|
||||
self.assertEqual(len(service.containers()), 2)
|
||||
|
||||
service.scale(1)
|
||||
self.assertEqual(len(service.containers()), 1)
|
||||
|
||||
service.stop()
|
||||
service.stop(timeout=1)
|
||||
self.assertEqual(len(service.containers()), 0)
|
||||
self.assertEqual(len(service.containers(stopped=True)), 1)
|
||||
|
||||
service.stop()
|
||||
service.stop(timeout=1)
|
||||
self.assertEqual(len(service.containers()), 0)
|
||||
self.assertEqual(len(service.containers(stopped=True)), 1)
|
||||
|
||||
def test_create_container_with_one_off(self):
|
||||
db = self.create_service('db')
|
||||
|
@ -101,8 +100,8 @@ class ServiceTest(DockerClientTestCase):
|
|||
db.start_container()
|
||||
web.start_container()
|
||||
self.assertIn('default_db_1', web.containers()[0].links())
|
||||
db.stop()
|
||||
web.stop()
|
||||
db.stop(timeout=1)
|
||||
web.stop(timeout=1)
|
||||
|
||||
def test_start_container_builds_images(self):
|
||||
service = Service(
|
||||
|
@ -110,7 +109,7 @@ class ServiceTest(DockerClientTestCase):
|
|||
client=self.client,
|
||||
build='tests/fixtures/simple-dockerfile',
|
||||
)
|
||||
container = service.start()
|
||||
container = service.start_container()
|
||||
container.wait()
|
||||
self.assertIn('success', container.logs())
|
||||
self.assertEqual(len(self.client.images(name='default_test')), 1)
|
||||
|
|
Loading…
Reference in New Issue