From e89826fe43969dcc450d98b397e6222b1414e103 Mon Sep 17 00:00:00 2001 From: Ben Firshman Date: Wed, 17 Dec 2014 18:31:22 -0800 Subject: [PATCH] Don't attach stdin and stdout when in detach mode This is primarily to make it work with Swarm, which checks that AttachStd{in,out,err} is false when creating containers. Signed-off-by: Ben Firshman --- fig/cli/main.py | 3 +++ fig/project.py | 6 +++--- fig/service.py | 10 +++++++--- tests/integration/cli_test.py | 13 +++++++++++++ tests/integration/service_test.py | 8 ++++++++ 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/fig/cli/main.py b/fig/cli/main.py index 2c6a0402..5f5861c3 100644 --- a/fig/cli/main.py +++ b/fig/cli/main.py @@ -294,6 +294,7 @@ class TopLevelCommand(Command): start_links=True, recreate=False, insecure_registry=insecure_registry, + detach=options['-d'] ) tty = True @@ -309,6 +310,7 @@ class TopLevelCommand(Command): 'command': command, 'tty': tty, 'stdin_open': not options['-d'], + 'detach': options['-d'], } if options['-e']: @@ -432,6 +434,7 @@ class TopLevelCommand(Command): start_links=start_links, recreate=recreate, insecure_registry=insecure_registry, + detach=options['-d'] ) to_attach = [c for s in project.get_services(service_names) for c in s.containers()] diff --git a/fig/project.py b/fig/project.py index 93c102c7..8d71a4c2 100644 --- a/fig/project.py +++ b/fig/project.py @@ -167,14 +167,14 @@ class Project(object): else: log.info('%s uses an image, skipping' % service.name) - def up(self, service_names=None, start_links=True, recreate=True, insecure_registry=False): + def up(self, service_names=None, start_links=True, recreate=True, insecure_registry=False, detach=False): running_containers = [] for service in self.get_services(service_names, include_links=start_links): if recreate: - for (_, container) in service.recreate_containers(insecure_registry=insecure_registry): + for (_, container) in service.recreate_containers(insecure_registry=insecure_registry, detach=detach): running_containers.append(container) else: - for container in service.start_or_create_containers(insecure_registry=insecure_registry): + for container in service.start_or_create_containers(insecure_registry=insecure_registry, detach=detach): running_containers.append(container) return running_containers diff --git a/fig/service.py b/fig/service.py index 2abcc6d4..5693083d 100644 --- a/fig/service.py +++ b/fig/service.py @@ -157,7 +157,7 @@ class Service(object): # Create enough containers containers = self.containers(stopped=True) while len(containers) < desired_num: - containers.append(self.create_container()) + containers.append(self.create_container(detach=True)) running_containers = [] stopped_containers = [] @@ -251,6 +251,7 @@ class Service(object): image=container.image, entrypoint=['/bin/echo'], command=[], + detach=True, ) intermediate_container.start(volumes_from=container.id) intermediate_container.wait() @@ -303,12 +304,15 @@ class Service(object): ) return container - def start_or_create_containers(self, insecure_registry=False): + def start_or_create_containers(self, insecure_registry=False, detach=False): containers = self.containers(stopped=True) if not containers: log.info("Creating %s..." % self._next_container_name(containers)) - new_container = self.create_container(insecure_registry=insecure_registry) + new_container = self.create_container( + insecure_registry=insecure_registry, + detach=detach + ) return [self.start_container(new_container)] else: return [self.start_container_if_stopped(c) for c in containers] diff --git a/tests/integration/cli_test.py b/tests/integration/cli_test.py index f03d72d2..76e033c4 100644 --- a/tests/integration/cli_test.py +++ b/tests/integration/cli_test.py @@ -92,6 +92,12 @@ class CLITestCase(DockerClientTestCase): self.assertEqual(len(service.containers()), 1) self.assertEqual(len(another.containers()), 1) + # Ensure containers don't have stdin and stdout connected in -d mode + config = service.containers()[0].inspect()['Config'] + self.assertFalse(config['AttachStderr']) + self.assertFalse(config['AttachStdout']) + self.assertFalse(config['AttachStdin']) + def test_up_with_links(self): self.command.base_dir = 'tests/fixtures/links-figfile' self.command.dispatch(['up', '-d', 'web'], None) @@ -146,6 +152,13 @@ class CLITestCase(DockerClientTestCase): self.command.dispatch(['run', 'console', '/bin/true'], None) self.assertEqual(len(self.project.containers()), 0) + # Ensure stdin/out was open + container = self.project.containers(stopped=True, one_off=True)[0] + config = container.inspect()['Config'] + self.assertTrue(config['AttachStderr']) + self.assertTrue(config['AttachStdout']) + self.assertTrue(config['AttachStdin']) + @patch('dockerpty.start') def test_run_service_with_links(self, __): self.command.base_dir = 'tests/fixtures/links-figfile' diff --git a/tests/integration/service_test.py b/tests/integration/service_test.py index 864b30a9..e29ee7e9 100644 --- a/tests/integration/service_test.py +++ b/tests/integration/service_test.py @@ -332,6 +332,14 @@ class ServiceTest(DockerClientTestCase): service = self.create_service('web') service.scale(1) self.assertEqual(len(service.containers()), 1) + + # Ensure containers don't have stdout or stdin connected + container = service.containers()[0] + config = container.inspect()['Config'] + self.assertFalse(config['AttachStderr']) + self.assertFalse(config['AttachStdout']) + self.assertFalse(config['AttachStdin']) + service.scale(3) self.assertEqual(len(service.containers()), 3) service.scale(1)