예제 #1
0
    def test_execute_convergence_plan_recreate(self):
        service = self.create_service('db',
                                      environment={'FOO': '1'},
                                      volumes=[VolumeSpec.parse('/etc')],
                                      entrypoint=['top'],
                                      command=['-d', '1'])
        old_container = service.create_container()
        self.assertEqual(old_container.get('Config.Entrypoint'), ['top'])
        self.assertEqual(old_container.get('Config.Cmd'), ['-d', '1'])
        self.assertIn('FOO=1', old_container.get('Config.Env'))
        self.assertEqual(old_container.name, 'composetest_db_1')
        service.start_container(old_container)
        old_container.inspect()  # reload volume data
        volume_path = old_container.get_mount('/etc')['Source']

        num_containers_before = len(self.client.containers(all=True))

        service.options['environment']['FOO'] = '2'
        new_container, = service.execute_convergence_plan(
            ConvergencePlan('recreate', [old_container]))

        self.assertEqual(new_container.get('Config.Entrypoint'), ['top'])
        self.assertEqual(new_container.get('Config.Cmd'), ['-d', '1'])
        self.assertIn('FOO=2', new_container.get('Config.Env'))
        self.assertEqual(new_container.name, 'composetest_db_1')
        self.assertEqual(
            new_container.get_mount('/etc')['Source'], volume_path)
        self.assertIn('affinity:container==%s' % old_container.id,
                      new_container.get('Config.Env'))

        self.assertEqual(len(self.client.containers(all=True)),
                         num_containers_before)
        self.assertNotEqual(old_container.id, new_container.id)
        self.assertRaises(APIError, self.client.inspect_container,
                          old_container.id)
예제 #2
0
    def test_execute_convergence_plan_when_image_volume_masks_config(self):
        service = self.create_service(
            'db',
            build={'context': 'tests/fixtures/dockerfile-with-volume'},
        )

        old_container = create_and_start_container(service)
        self.assertEqual(
            [mount['Destination'] for mount in old_container.get('Mounts')],
            ['/data'])
        volume_path = old_container.get_mount('/data')['Source']

        service.options['volumes'] = [VolumeSpec.parse('/tmp:/data')]

        with mock.patch('compose.service.log') as mock_log:
            new_container, = service.execute_convergence_plan(
                ConvergencePlan('recreate', [old_container]))

        mock_log.warn.assert_called_once_with(mock.ANY)
        _, args, kwargs = mock_log.warn.mock_calls[0]
        self.assertIn(
            "Service \"db\" is using volume \"/data\" from the previous container",
            args[0])

        self.assertEqual(
            [mount['Destination'] for mount in new_container.get('Mounts')],
            ['/data'])
        self.assertEqual(
            new_container.get_mount('/data')['Source'], volume_path)
예제 #3
0
    def test_execute_convergence_plan_without_start(self):
        service = self.create_service(
            'db',
            build={'context': 'tests/fixtures/dockerfile-with-volume'}
        )

        containers = service.execute_convergence_plan(ConvergencePlan('create', []), start=False)
        self.assertEqual(len(service.containers()), 0)
        self.assertEqual(len(service.containers(stopped=True)), 1)

        containers = service.execute_convergence_plan(ConvergencePlan('recreate', containers), start=False)
        self.assertEqual(len(service.containers()), 0)
        self.assertEqual(len(service.containers(stopped=True)), 1)

        service.execute_convergence_plan(ConvergencePlan('start', containers), start=False)
        self.assertEqual(len(service.containers()), 0)
        self.assertEqual(len(service.containers(stopped=True)), 1)
예제 #4
0
    def test_execute_convergence_plan_with_image_declared_volume(self):
        service = Service(
            project='composetest',
            name='db',
            client=self.client,
            build='tests/fixtures/dockerfile-with-volume',
        )

        old_container = create_and_start_container(service)
        self.assertEqual(list(old_container.get('Volumes').keys()), ['/data'])
        volume_path = old_container.get('Volumes')['/data']

        new_container, = service.execute_convergence_plan(
            ConvergencePlan('recreate', [old_container]))
        self.assertEqual(list(new_container.get('Volumes')), ['/data'])
        self.assertEqual(new_container.get('Volumes')['/data'], volume_path)
예제 #5
0
    def test_execute_convergence_plan_when_containers_are_stopped(self):
        service = self.create_service('db',
                                      environment={'FOO': '1'},
                                      volumes=[VolumeSpec.parse('/var/db')],
                                      entrypoint=['top'],
                                      command=['-d', '1'])
        service.create_container()

        containers = service.containers(stopped=True)
        self.assertEqual(len(containers), 1)
        container, = containers
        self.assertFalse(container.is_running)

        service.execute_convergence_plan(ConvergencePlan('start', [container]))

        containers = service.containers()
        self.assertEqual(len(containers), 1)
        container.inspect()
        self.assertEqual(container, containers[0])
        self.assertTrue(container.is_running)
예제 #6
0
    def test_execute_convergence_plan_when_host_volume_is_removed(self):
        host_path = '/tmp/host-path'
        service = self.create_service(
            'db',
            build={'context': 'tests/fixtures/dockerfile-with-volume'},
            volumes=[VolumeSpec(host_path, '/data', 'rw')])

        old_container = create_and_start_container(service)
        assert ([
            mount['Destination'] for mount in old_container.get('Mounts')
        ] == ['/data'])
        service.options['volumes'] = []

        with mock.patch('compose.service.log', autospec=True) as mock_log:
            new_container, = service.execute_convergence_plan(
                ConvergencePlan('recreate', [old_container]))

        assert not mock_log.warn.called
        assert ([
            mount['Destination'] for mount in new_container.get('Mounts')
        ], ['/data'])
        assert new_container.get_mount('/data')['Source'] != host_path
예제 #7
0
    def test_execute_convergence_plan_with_image_declared_volume(self):
        service = Service(
            project='composetest',
            name='db',
            client=self.client,
            build={'context': 'tests/fixtures/dockerfile-with-volume'},
        )

        old_container = create_and_start_container(service)
        self.assertEqual(
            [mount['Destination'] for mount in old_container.get('Mounts')],
            ['/data'])
        volume_path = old_container.get_mount('/data')['Source']

        new_container, = service.execute_convergence_plan(
            ConvergencePlan('recreate', [old_container]))

        self.assertEqual(
            [mount['Destination'] for mount in new_container.get('Mounts')],
            ['/data'])
        self.assertEqual(
            new_container.get_mount('/data')['Source'], volume_path)
예제 #8
0
    def test_execute_convergence_plan_recreate_twice(self):
        service = self.create_service('db',
                                      volumes=[VolumeSpec.parse('/etc')],
                                      entrypoint=['top'],
                                      command=['-d', '1'])

        orig_container = service.create_container()
        service.start_container(orig_container)

        orig_container.inspect()  # reload volume data
        volume_path = orig_container.get_mount('/etc')['Source']

        # Do this twice to reproduce the bug
        for _ in range(2):
            new_container, = service.execute_convergence_plan(
                ConvergencePlan('recreate', [orig_container]))

            assert new_container.get_mount('/etc')['Source'] == volume_path
            assert ('affinity:container==%s' % orig_container.id
                    in new_container.get('Config.Env'))

            orig_container = new_container