mirror of
https://github.com/docker/compose.git
synced 2025-04-08 17:05:13 +02:00
Adds pause and unpause-commands
Signed-off-by: Frank Sachsenheim <funkyfuture@riseup.net>
This commit is contained in:
parent
59d024f4f2
commit
227584b864
@ -172,6 +172,14 @@ class TopLevelCommand(Command):
|
|||||||
print("Attaching to", list_containers(containers))
|
print("Attaching to", list_containers(containers))
|
||||||
LogPrinter(containers, attach_params={'logs': True}, monochrome=monochrome).run()
|
LogPrinter(containers, attach_params={'logs': True}, monochrome=monochrome).run()
|
||||||
|
|
||||||
|
def pause(self, project, options):
|
||||||
|
"""
|
||||||
|
Pause services.
|
||||||
|
|
||||||
|
Usage: pause [SERVICE...]
|
||||||
|
"""
|
||||||
|
project.pause(service_names=options['SERVICE'])
|
||||||
|
|
||||||
def port(self, project, options):
|
def port(self, project, options):
|
||||||
"""
|
"""
|
||||||
Print the public port for a port binding.
|
Print the public port for a port binding.
|
||||||
@ -444,6 +452,14 @@ class TopLevelCommand(Command):
|
|||||||
timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT)
|
timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT)
|
||||||
project.restart(service_names=options['SERVICE'], timeout=timeout)
|
project.restart(service_names=options['SERVICE'], timeout=timeout)
|
||||||
|
|
||||||
|
def unpause(self, project, options):
|
||||||
|
"""
|
||||||
|
Unpause services.
|
||||||
|
|
||||||
|
Usage: unpause [SERVICE...]
|
||||||
|
"""
|
||||||
|
project.unpause(service_names=options['SERVICE'])
|
||||||
|
|
||||||
def up(self, project, options):
|
def up(self, project, options):
|
||||||
"""
|
"""
|
||||||
Builds, (re)creates, starts, and attaches to containers for a service.
|
Builds, (re)creates, starts, and attaches to containers for a service.
|
||||||
|
@ -100,6 +100,8 @@ class Container(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def human_readable_state(self):
|
def human_readable_state(self):
|
||||||
|
if self.is_paused:
|
||||||
|
return 'Paused'
|
||||||
if self.is_running:
|
if self.is_running:
|
||||||
return 'Ghost' if self.get('State.Ghost') else 'Up'
|
return 'Ghost' if self.get('State.Ghost') else 'Up'
|
||||||
else:
|
else:
|
||||||
@ -119,6 +121,10 @@ class Container(object):
|
|||||||
def is_running(self):
|
def is_running(self):
|
||||||
return self.get('State.Running')
|
return self.get('State.Running')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_paused(self):
|
||||||
|
return self.get('State.Paused')
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
"""Return a value from the container or None if the value is not set.
|
"""Return a value from the container or None if the value is not set.
|
||||||
|
|
||||||
@ -142,6 +148,12 @@ class Container(object):
|
|||||||
def stop(self, **options):
|
def stop(self, **options):
|
||||||
return self.client.stop(self.id, **options)
|
return self.client.stop(self.id, **options)
|
||||||
|
|
||||||
|
def pause(self, **options):
|
||||||
|
return self.client.pause(self.id, **options)
|
||||||
|
|
||||||
|
def unpause(self, **options):
|
||||||
|
return self.client.unpause(self.id, **options)
|
||||||
|
|
||||||
def kill(self, **options):
|
def kill(self, **options):
|
||||||
return self.client.kill(self.id, **options)
|
return self.client.kill(self.id, **options)
|
||||||
|
|
||||||
|
@ -205,6 +205,14 @@ class Project(object):
|
|||||||
msg="Stopping"
|
msg="Stopping"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def pause(self, service_names=None, **options):
|
||||||
|
for service in reversed(self.get_services(service_names)):
|
||||||
|
service.pause(**options)
|
||||||
|
|
||||||
|
def unpause(self, service_names=None, **options):
|
||||||
|
for service in self.get_services(service_names):
|
||||||
|
service.unpause(**options)
|
||||||
|
|
||||||
def kill(self, service_names=None, **options):
|
def kill(self, service_names=None, **options):
|
||||||
parallel_execute(
|
parallel_execute(
|
||||||
objects=self.containers(service_names),
|
objects=self.containers(service_names),
|
||||||
|
@ -96,12 +96,14 @@ class Service(object):
|
|||||||
self.net = net or None
|
self.net = net or None
|
||||||
self.options = options
|
self.options = options
|
||||||
|
|
||||||
def containers(self, stopped=False, one_off=False):
|
def containers(self, stopped=False, one_off=False, filters={}):
|
||||||
|
filters.update({'label': self.labels(one_off=one_off)})
|
||||||
|
|
||||||
containers = filter(None, [
|
containers = filter(None, [
|
||||||
Container.from_ps(self.client, container)
|
Container.from_ps(self.client, container)
|
||||||
for container in self.client.containers(
|
for container in self.client.containers(
|
||||||
all=stopped,
|
all=stopped,
|
||||||
filters={'label': self.labels(one_off=one_off)})])
|
filters=filters)])
|
||||||
|
|
||||||
if not containers:
|
if not containers:
|
||||||
check_for_legacy_containers(
|
check_for_legacy_containers(
|
||||||
@ -132,6 +134,16 @@ class Service(object):
|
|||||||
log.info("Stopping %s..." % c.name)
|
log.info("Stopping %s..." % c.name)
|
||||||
c.stop(**options)
|
c.stop(**options)
|
||||||
|
|
||||||
|
def pause(self, **options):
|
||||||
|
for c in self.containers(filters={'status': 'running'}):
|
||||||
|
log.info("Pausing %s..." % c.name)
|
||||||
|
c.pause(**options)
|
||||||
|
|
||||||
|
def unpause(self, **options):
|
||||||
|
for c in self.containers(filters={'status': 'paused'}):
|
||||||
|
log.info("Unpausing %s..." % c.name)
|
||||||
|
c.unpause()
|
||||||
|
|
||||||
def kill(self, **options):
|
def kill(self, **options):
|
||||||
for c in self.containers():
|
for c in self.containers():
|
||||||
log.info("Killing %s..." % c.name)
|
log.info("Killing %s..." % c.name)
|
||||||
|
@ -68,6 +68,11 @@ __docker_compose_services_with() {
|
|||||||
COMPREPLY=( $(compgen -W "${names[*]}" -- "$cur") )
|
COMPREPLY=( $(compgen -W "${names[*]}" -- "$cur") )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# The services for which at least one paused container exists
|
||||||
|
__docker_compose_services_paused() {
|
||||||
|
__docker_compose_services_with '.State.Paused'
|
||||||
|
}
|
||||||
|
|
||||||
# The services for which at least one running container exists
|
# The services for which at least one running container exists
|
||||||
__docker_compose_services_running() {
|
__docker_compose_services_running() {
|
||||||
__docker_compose_services_with '.State.Running'
|
__docker_compose_services_with '.State.Running'
|
||||||
@ -158,6 +163,18 @@ _docker_compose_migrate_to_labels() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_docker_compose_pause() {
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
__docker_compose_services_running
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_docker_compose_port() {
|
_docker_compose_port() {
|
||||||
case "$prev" in
|
case "$prev" in
|
||||||
--protocol)
|
--protocol)
|
||||||
@ -306,6 +323,18 @@ _docker_compose_stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_docker_compose_unpause() {
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
__docker_compose_services_paused
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_docker_compose_up() {
|
_docker_compose_up() {
|
||||||
case "$prev" in
|
case "$prev" in
|
||||||
-t | --timeout)
|
-t | --timeout)
|
||||||
@ -343,6 +372,7 @@ _docker_compose() {
|
|||||||
kill
|
kill
|
||||||
logs
|
logs
|
||||||
migrate-to-labels
|
migrate-to-labels
|
||||||
|
pause
|
||||||
port
|
port
|
||||||
ps
|
ps
|
||||||
pull
|
pull
|
||||||
@ -352,6 +382,7 @@ _docker_compose() {
|
|||||||
scale
|
scale
|
||||||
start
|
start
|
||||||
stop
|
stop
|
||||||
|
unpause
|
||||||
up
|
up
|
||||||
version
|
version
|
||||||
)
|
)
|
||||||
|
@ -28,6 +28,7 @@ Commands:
|
|||||||
help Get help on a command
|
help Get help on a command
|
||||||
kill Kill containers
|
kill Kill containers
|
||||||
logs View output from containers
|
logs View output from containers
|
||||||
|
pause Pause services
|
||||||
port Print the public port for a port binding
|
port Print the public port for a port binding
|
||||||
ps List containers
|
ps List containers
|
||||||
pull Pulls service images
|
pull Pulls service images
|
||||||
@ -37,6 +38,7 @@ Commands:
|
|||||||
scale Set number of containers for a service
|
scale Set number of containers for a service
|
||||||
start Start services
|
start Start services
|
||||||
stop Stop services
|
stop Stop services
|
||||||
|
unpause Unpause services
|
||||||
up Create and start containers
|
up Create and start containers
|
||||||
migrate-to-labels Recreate containers to add labels
|
migrate-to-labels Recreate containers to add labels
|
||||||
```
|
```
|
||||||
|
18
docs/reference/pause.md
Normal file
18
docs/reference/pause.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!--[metadata]>
|
||||||
|
+++
|
||||||
|
title = "pause"
|
||||||
|
description = "Pauses running containers for a service."
|
||||||
|
keywords = ["fig, composition, compose, docker, orchestration, cli, pause"]
|
||||||
|
[menu.main]
|
||||||
|
identifier="pause.compose"
|
||||||
|
parent = "smn_compose_cli"
|
||||||
|
+++
|
||||||
|
<![end-metadata]-->
|
||||||
|
|
||||||
|
# pause
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage: pause [SERVICE...]
|
||||||
|
```
|
||||||
|
|
||||||
|
Pauses running containers of a service. They can be unpaused with `docker-compose unpause`.
|
18
docs/reference/unpause.md
Normal file
18
docs/reference/unpause.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!--[metadata]>
|
||||||
|
+++
|
||||||
|
title = "unpause"
|
||||||
|
description = "Unpauses paused containers for a service."
|
||||||
|
keywords = ["fig, composition, compose, docker, orchestration, cli, unpause"]
|
||||||
|
[menu.main]
|
||||||
|
identifier="unpause.compose"
|
||||||
|
parent = "smn_compose_cli"
|
||||||
|
+++
|
||||||
|
<![end-metadata]-->
|
||||||
|
|
||||||
|
# pause
|
||||||
|
|
||||||
|
```
|
||||||
|
Usage: unpause [SERVICE...]
|
||||||
|
```
|
||||||
|
|
||||||
|
Unpauses paused containers of a service.
|
@ -415,6 +415,17 @@ class CLITestCase(DockerClientTestCase):
|
|||||||
self.assertEqual(len(service.containers(stopped=True)), 1)
|
self.assertEqual(len(service.containers(stopped=True)), 1)
|
||||||
self.assertFalse(service.containers(stopped=True)[0].is_running)
|
self.assertFalse(service.containers(stopped=True)[0].is_running)
|
||||||
|
|
||||||
|
def test_pause_unpause(self):
|
||||||
|
self.command.dispatch(['up', '-d'], None)
|
||||||
|
service = self.project.get_service('simple')
|
||||||
|
self.assertFalse(service.containers()[0].is_paused)
|
||||||
|
|
||||||
|
self.command.dispatch(['pause'], None)
|
||||||
|
self.assertTrue(service.containers()[0].is_paused)
|
||||||
|
|
||||||
|
self.command.dispatch(['unpause'], None)
|
||||||
|
self.assertFalse(service.containers()[0].is_paused)
|
||||||
|
|
||||||
def test_logs_invalid_service_name(self):
|
def test_logs_invalid_service_name(self):
|
||||||
with self.assertRaises(NoSuchService):
|
with self.assertRaises(NoSuchService):
|
||||||
self.command.dispatch(['logs', 'madeupname'], None)
|
self.command.dispatch(['logs', 'madeupname'], None)
|
||||||
|
@ -140,7 +140,7 @@ class ProjectTest(DockerClientTestCase):
|
|||||||
web = project.get_service('web')
|
web = project.get_service('web')
|
||||||
self.assertEqual(web._get_net(), 'container:' + net_container.id)
|
self.assertEqual(web._get_net(), 'container:' + net_container.id)
|
||||||
|
|
||||||
def test_start_stop_kill_remove(self):
|
def test_start_pause_unpause_stop_kill_remove(self):
|
||||||
web = self.create_service('web')
|
web = self.create_service('web')
|
||||||
db = self.create_service('db')
|
db = self.create_service('db')
|
||||||
project = Project('composetest', [web, db], self.client)
|
project = Project('composetest', [web, db], self.client)
|
||||||
@ -158,7 +158,22 @@ class ProjectTest(DockerClientTestCase):
|
|||||||
self.assertEqual(set(c.name for c in project.containers()), set([web_container_1.name, web_container_2.name]))
|
self.assertEqual(set(c.name for c in project.containers()), set([web_container_1.name, web_container_2.name]))
|
||||||
|
|
||||||
project.start()
|
project.start()
|
||||||
self.assertEqual(set(c.name for c in project.containers()), set([web_container_1.name, web_container_2.name, db_container.name]))
|
self.assertEqual(set(c.name for c in project.containers()),
|
||||||
|
set([web_container_1.name, web_container_2.name, db_container.name]))
|
||||||
|
|
||||||
|
project.pause(service_names=['web'])
|
||||||
|
self.assertEqual(set([c.name for c in project.containers() if c.is_paused]),
|
||||||
|
set([web_container_1.name, web_container_2.name]))
|
||||||
|
|
||||||
|
project.pause()
|
||||||
|
self.assertEqual(set([c.name for c in project.containers() if c.is_paused]),
|
||||||
|
set([web_container_1.name, web_container_2.name, db_container.name]))
|
||||||
|
|
||||||
|
project.unpause(service_names=['db'])
|
||||||
|
self.assertEqual(len([c.name for c in project.containers() if c.is_paused]), 2)
|
||||||
|
|
||||||
|
project.unpause()
|
||||||
|
self.assertEqual(len([c.name for c in project.containers() if c.is_paused]), 0)
|
||||||
|
|
||||||
project.stop(service_names=['web'], timeout=1)
|
project.stop(service_names=['web'], timeout=1)
|
||||||
self.assertEqual(set(c.name for c in project.containers()), set([db_container.name]))
|
self.assertEqual(set(c.name for c in project.containers()), set([db_container.name]))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user