Example #1
0
    def test_merge_volume_bindings(self):
        options = [
            VolumeSpec.parse('/host/volume:/host/volume:ro'),
            VolumeSpec.parse('/host/rw/volume:/host/rw/volume'),
            VolumeSpec.parse('/new/volume'),
            VolumeSpec.parse('/existing/volume'),
        ]

        self.mock_client.inspect_image.return_value = {
            'ContainerConfig': {'Volumes': {}}
        }

        intermediate_container = Container(self.mock_client, {
            'Image': 'ababab',
            'Volumes': {'/existing/volume': '/var/lib/docker/aaaaaaaa'},
        }, has_been_inspected=True)

        expected = [
            '/host/volume:/host/volume:ro',
            '/host/rw/volume:/host/rw/volume:rw',
            '/var/lib/docker/aaaaaaaa:/existing/volume:rw',
        ]

        binds = merge_volume_bindings(options, intermediate_container)
        self.assertEqual(set(binds), set(expected))
Example #2
0
    def test_get_container_data_volumes(self):
        options = [VolumeSpec.parse(v) for v in [
            '/host/volume:/host/volume:ro',
            '/new/volume',
            '/existing/volume',
        ]]

        self.mock_client.inspect_image.return_value = {
            'ContainerConfig': {
                'Volumes': {
                    '/mnt/image/data': {},
                }
            }
        }
        container = Container(self.mock_client, {
            'Image': 'ababab',
            'Volumes': {
                '/host/volume': '/host/volume',
                '/existing/volume': '/var/lib/docker/aaaaaaaa',
                '/removed/volume': '/var/lib/docker/bbbbbbbb',
                '/mnt/image/data': '/var/lib/docker/cccccccc',
            },
        }, has_been_inspected=True)

        expected = [
            VolumeSpec.parse('/var/lib/docker/aaaaaaaa:/existing/volume:rw'),
            VolumeSpec.parse('/var/lib/docker/cccccccc:/mnt/image/data:rw'),
        ]

        volumes = get_container_data_volumes(container, options)
        assert sorted(volumes) == sorted(expected)
Example #3
0
    def test_merge_volume_bindings(self):
        options = [
            VolumeSpec.parse('/host/volume:/host/volume:ro'),
            VolumeSpec.parse('/host/rw/volume:/host/rw/volume'),
            VolumeSpec.parse('/new/volume'),
            VolumeSpec.parse('/existing/volume'),
        ]

        self.mock_client.inspect_image.return_value = {
            'ContainerConfig': {'Volumes': {}}
        }

        previous_container = Container(self.mock_client, {
            'Id': 'cdefab',
            'Image': 'ababab',
            'Mounts': [{
                'Source': '/var/lib/docker/aaaaaaaa',
                'Destination': '/existing/volume',
                'Mode': '',
                'RW': True,
                'Name': 'existingvolume',
            }],
        }, has_been_inspected=True)

        expected = [
            '/host/volume:/host/volume:ro',
            '/host/rw/volume:/host/rw/volume:rw',
            'existingvolume:/existing/volume:rw',
        ]

        binds, affinity = merge_volume_bindings(options, previous_container)
        assert sorted(binds) == sorted(expected)
        assert affinity == {'affinity:container': '=cdefab'}
Example #4
0
    def test_mount_same_host_path_to_two_volumes(self):
        service = Service(
            'web',
            image='busybox',
            volumes=[
                VolumeSpec.parse('/host/path:/data1'),
                VolumeSpec.parse('/host/path:/data2'),
            ],
            client=self.mock_client,
        )

        self.mock_client.inspect_image.return_value = {
            'Id': 'ababab',
            'ContainerConfig': {
                'Volumes': {}
            }
        }

        service._get_container_create_options(
            override_options={},
            number=1,
        )

        self.assertEqual(
            set(self.mock_client.create_host_config.call_args[1]['binds']),
            set([
                '/host/path:/data1:rw',
                '/host/path:/data2:rw',
            ]),
        )
Example #5
0
    def test_get_container_data_volumes(self):
        options = [VolumeSpec.parse(v) for v in [
            '/host/volume:/host/volume:ro',
            '/new/volume',
            '/existing/volume',
            'named:/named/vol',
            '/dev/tmpfs'
        ]]

        self.mock_client.inspect_image.return_value = {
            'ContainerConfig': {
                'Volumes': {
                    '/mnt/image/data': {},
                }
            }
        }
        container = Container(self.mock_client, {
            'Image': 'ababab',
            'Mounts': [
                {
                    'Source': '/host/volume',
                    'Destination': '/host/volume',
                    'Mode': '',
                    'RW': True,
                    'Name': 'hostvolume',
                }, {
                    'Source': '/var/lib/docker/aaaaaaaa',
                    'Destination': '/existing/volume',
                    'Mode': '',
                    'RW': True,
                    'Name': 'existingvolume',
                }, {
                    'Source': '/var/lib/docker/bbbbbbbb',
                    'Destination': '/removed/volume',
                    'Mode': '',
                    'RW': True,
                    'Name': 'removedvolume',
                }, {
                    'Source': '/var/lib/docker/cccccccc',
                    'Destination': '/mnt/image/data',
                    'Mode': '',
                    'RW': True,
                    'Name': 'imagedata',
                },
            ]
        }, has_been_inspected=True)

        expected = [
            VolumeSpec.parse('existingvolume:/existing/volume:rw'),
            VolumeSpec.parse('imagedata:/mnt/image/data:rw'),
        ]

        volumes = get_container_data_volumes(container, options, ['/dev/tmpfs'])
        assert sorted(volumes) == sorted(expected)
Example #6
0
 def test_parse_volume_windows_absolute_path_native(self):
     windows_path = "c:\\Users\\me\\Documents\\shiny\\config:/opt/shiny/config:ro"
     assert VolumeSpec._parse_win32(windows_path, False) == (
         "c:\\Users\\me\\Documents\\shiny\\config",
         "/opt/shiny/config",
         "ro"
     )
Example #7
0
 def test_parse_volume_windows_absolute_path_normalized(self):
     windows_path = "c:\\Users\\me\\Documents\\shiny\\config:/opt/shiny/config:ro"
     assert VolumeSpec._parse_win32(windows_path, True) == (
         "/c/Users/me/Documents/shiny/config",
         "/opt/shiny/config",
         "ro"
     )
Example #8
0
 def test_parse_volume_windows_just_drives_native(self):
     windows_path = 'E:\\:C:\\:ro'
     assert VolumeSpec._parse_win32(windows_path, False) == (
         'E:\\',
         'C:\\',
         'ro'
     )
Example #9
0
 def test_parse_volume_windows_mixed_notations_normalized(self):
     windows_path = 'C:\\Foo:/root/foo'
     assert VolumeSpec._parse_win32(windows_path, True) == (
         '/c/Foo',
         '/root/foo',
         'rw'
     )
Example #10
0
    def test_duplicate_volume_trailing_slash(self):
        """
        When an image specifies a volume, and the Compose file specifies a host path
        but adds a trailing slash, make sure that we don't create duplicate binds.
        """
        host_path = "/tmp/data"
        container_path = "/data"
        volumes = [VolumeSpec.parse("{}:{}/".format(host_path, container_path))]

        tmp_container = self.client.create_container(
            "busybox", "true", volumes={container_path: {}}, labels={"com.docker.compose.test_image": "true"}
        )
        image = self.client.commit(tmp_container)["Id"]

        service = self.create_service("db", image=image, volumes=volumes)
        old_container = create_and_start_container(service)

        self.assertEqual(old_container.get("Config.Volumes"), {container_path: {}})

        service = self.create_service("db", image=image, volumes=volumes)
        new_container = service.recreate_container(old_container)

        self.assertEqual(new_container.get("Config.Volumes"), {container_path: {}})

        self.assertEqual(service.containers(stopped=False), [new_container])
Example #11
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)
Example #12
0
 def test_parse_volume_windows_just_drives_normalized(self):
     windows_path = 'E:\\:C:\\:ro'
     assert VolumeSpec._parse_win32(windows_path, True) == (
         '/e/',
         'C:\\',
         'ro'
     )
Example #13
0
 def test_parse_volume_windows_internal_path_normalized(self):
     windows_path = 'C:\\Users\\reimu\\scarlet:C:\\scarlet\\app:ro'
     assert VolumeSpec._parse_win32(windows_path, True) == (
         '/c/Users/reimu/scarlet',
         'C:\\scarlet\\app',
         'ro'
     )
Example #14
0
    def test_different_host_path_in_container_json(self):
        service = Service(
            'web',
            image='busybox',
            volumes=[VolumeSpec.parse('/host/path:/data')],
            client=self.mock_client,
        )

        self.mock_client.inspect_image.return_value = {
            'Id': 'ababab',
            'ContainerConfig': {
                'Volumes': {
                    '/data': {},
                }
            }
        }

        self.mock_client.inspect_container.return_value = {
            'Id': '123123123',
            'Image': 'ababab',
            'Volumes': {
                '/data': '/mnt/sda1/host/path',
            },
        }

        service._get_container_create_options(
            override_options={},
            number=1,
            previous_container=Container(self.mock_client, {'Id': '123123123'}),
        )

        self.assertEqual(
            self.mock_client.create_host_config.call_args[1]['binds'],
            ['/mnt/sda1/host/path:/data:rw'],
        )
Example #15
0
    def test_duplicate_volume_trailing_slash(self):
        """
        When an image specifies a volume, and the Compose file specifies a host path
        but adds a trailing slash, make sure that we don't create duplicate binds.
        """
        host_path = '/tmp/data'
        container_path = '/data'
        volumes = [VolumeSpec.parse('{}:{}/'.format(host_path, container_path))]

        tmp_container = self.client.create_container(
            'busybox', 'true',
            volumes={container_path: {}},
            labels={'com.docker.compose.test_image': 'true'},
        )
        image = self.client.commit(tmp_container)['Id']

        service = self.create_service('db', image=image, volumes=volumes)
        old_container = create_and_start_container(service)

        self.assertEqual(
            old_container.get('Config.Volumes'),
            {container_path: {}},
        )

        service = self.create_service('db', image=image, volumes=volumes)
        new_container = service.recreate_container(old_container)

        self.assertEqual(
            new_container.get('Config.Volumes'),
            {container_path: {}},
        )

        self.assertEqual(service.containers(stopped=False), [new_container])
Example #16
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)
Example #17
0
 def test_parse_volume_windows_absolute_path(self):
     windows_path = "c:\\Users\\me\\Documents\\shiny\\config:\\opt\\shiny\\config:ro"
     assert VolumeSpec.parse(windows_path) == (
         "/c/Users/me/Documents/shiny/config",
         "/opt/shiny/config",
         "ro"
     )
Example #18
0
    def test_project_up_with_no_recreate_stopped(self):
        web = self.create_service('web')
        db = self.create_service('db', volumes=[VolumeSpec.parse('/var/db')])
        project = Project('composetest', [web, db], self.client)
        project.start()
        self.assertEqual(len(project.containers()), 0)

        project.up(['db'])
        project.kill()

        old_containers = project.containers(stopped=True)

        self.assertEqual(len(old_containers), 1)
        old_container, = old_containers
        old_db_id = old_container.id
        db_volume_path = old_container.get_mount('/var/db')['Source']

        project.up(strategy=ConvergenceStrategy.never)

        new_containers = project.containers(stopped=True)
        self.assertEqual(len(new_containers), 2)
        self.assertEqual([c.is_running for c in new_containers], [True, True])

        db_container = [c for c in new_containers if 'db' in c.name][0]
        self.assertEqual(db_container.id, old_db_id)
        self.assertEqual(
            db_container.get_mount('/var/db')['Source'],
            db_volume_path)
Example #19
0
 def test_parse_volume_windows_internal_path_native(self):
     windows_path = 'C:\\Users\\reimu\\scarlet:C:\\scarlet\\app:ro'
     assert VolumeSpec._parse_win32(windows_path, False) == (
         'C:\\Users\\reimu\\scarlet',
         'C:\\scarlet\\app',
         'ro'
     )
Example #20
0
 def test_parse_volume_windows_mixed_notations_native(self):
     windows_path = 'C:\\Foo:/root/foo'
     assert VolumeSpec._parse_win32(windows_path, False) == (
         'C:\\Foo',
         '/root/foo',
         'rw'
     )
Example #21
0
    def setUp(self):
        self.db = self.create_service(
            'db',
            volumes=[VolumeSpec.parse('/var/db')],
            command='top')
        self.project = Project('composetest', [self.db], self.client)

        container = self.db.create_container()
        container.start()
        self.host_path = container.get_mount('/var/db')['Source']
Example #22
0
    def test_recreate_preserves_volume_with_trailing_slash(self):
        """When the Compose file specifies a trailing slash in the container path, make
        sure we copy the volume over when recreating.
        """
        service = self.create_service('data', volumes=[VolumeSpec.parse('/data/')])
        old_container = create_and_start_container(service)
        volume_path = old_container.get_mount('/data')['Source']

        new_container = service.recreate_container(old_container)
        self.assertEqual(new_container.get_mount('/data')['Source'], volume_path)
Example #23
0
    def test_project_up(self):
        web = self.create_service('web')
        db = self.create_service('db', volumes=[VolumeSpec.parse('/var/db')])
        project = Project('composetest', [web, db], self.client)
        project.start()
        self.assertEqual(len(project.containers()), 0)

        project.up(['db'])
        self.assertEqual(len(project.containers()), 1)
        self.assertEqual(len(db.containers()), 1)
        self.assertEqual(len(web.containers()), 0)
def get_named_volumes(services):
    volume_specs = [
        VolumeSpec.parse(volume)
        for service in services.values()
        for volume in service.get('volumes', [])
    ]
    names = {
        spec.external
        for spec in volume_specs
        if spec.is_named_volume
    }
    return {name: {'external': True} for name in names}
Example #25
0
    def test_create_twice(self):
        web = self.create_service('web')
        db = self.create_service('db', volumes=[VolumeSpec.parse('/var/db')])
        project = Project('composetest', [web, db], self.client)

        project.create(['db', 'web'])
        project.create(['db', 'web'])
        self.assertEqual(len(project.containers()), 0)
        self.assertEqual(len(project.containers(stopped=True)), 2)
        self.assertEqual(len(db.containers()), 0)
        self.assertEqual(len(db.containers(stopped=True)), 1)
        self.assertEqual(len(web.containers()), 0)
        self.assertEqual(len(web.containers(stopped=True)), 1)
Example #26
0
    def test_project_up_starts_links(self):
        console = self.create_service('console')
        db = self.create_service('db', volumes=[VolumeSpec.parse('/var/db')])
        web = self.create_service('web', links=[(db, 'db')])

        project = Project('composetest', [web, db, console], self.client)
        project.start()
        self.assertEqual(len(project.containers()), 0)

        project.up(['web'])
        self.assertEqual(len(project.containers()), 2)
        self.assertEqual(len(web.containers()), 1)
        self.assertEqual(len(db.containers()), 1)
        self.assertEqual(len(console.containers()), 0)
Example #27
0
    def test_create_with_special_volume_mode(self):
        self.mock_client.inspect_image.return_value = {'Id': 'imageid'}

        self.mock_client.create_container.return_value = {'Id': 'containerid'}

        volume = '/tmp:/foo:z'
        Service(
            'web',
            client=self.mock_client,
            image='busybox',
            volumes=[VolumeSpec.parse(volume, True)],
        ).create_container()

        assert self.mock_client.create_container.call_count == 1
        assert self.mock_client.create_host_config.call_args[1]['binds'] == [volume]
Example #28
0
    def test_recreate_preserves_volumes(self):
        web = self.create_service('web')
        db = self.create_service('db', volumes=[VolumeSpec.parse('/etc')])
        project = Project('composetest', [web, db], self.client)
        project.start()
        self.assertEqual(len(project.containers()), 0)

        project.up(['db'])
        self.assertEqual(len(project.containers()), 1)
        old_db_id = project.containers()[0].id
        db_volume_path = project.containers()[0].get('Volumes./etc')

        project.up(strategy=ConvergenceStrategy.always)
        self.assertEqual(len(project.containers()), 2)

        db_container = [c for c in project.containers() if 'db' in c.name][0]
        self.assertNotEqual(db_container.id, old_db_id)
        self.assertEqual(db_container.get('Volumes./etc'), db_volume_path)
Example #29
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)
Example #30
0
    def test_get_container_create_options_with_different_host_path_in_container_json(self):
        service = Service(
            'web',
            image='busybox',
            volumes=[VolumeSpec.parse('/host/path:/data')],
            client=self.mock_client,
        )
        volume_name = 'abcdefff1234'

        self.mock_client.inspect_image.return_value = {
            'Id': 'ababab',
            'ContainerConfig': {
                'Volumes': {
                    '/data': {},
                }
            }
        }

        self.mock_client.inspect_container.return_value = {
            'Id': '123123123',
            'Image': 'ababab',
            'Mounts': [
                {
                    'Destination': '/data',
                    'Source': '/mnt/sda1/host/path',
                    'Mode': '',
                    'RW': True,
                    'Driver': 'local',
                    'Name': volume_name,
                },
            ]
        }

        service._get_container_create_options(
            override_options={},
            number=1,
            previous_container=Container(self.mock_client, {'Id': '123123123'}),
        )

        assert (
            self.mock_client.create_host_config.call_args[1]['binds'] ==
            ['{}:/data:rw'.format(volume_name)]
        )
Example #31
0
 def test_build_volume_binding(self):
     binding = build_volume_binding(
         VolumeSpec.parse('/outside:/inside', True))
     assert binding == ('/inside', '/outside:/inside:rw')
Example #32
0
 def test_parse_volume_windows_internal_path_native(self):
     windows_path = 'C:\\Users\\reimu\\scarlet:C:\\scarlet\\app:ro'
     assert VolumeSpec._parse_win32(windows_path,
                                    False) == ('C:\\Users\\reimu\\scarlet',
                                               'C:\\scarlet\\app', 'ro')
Example #33
0
    def test_parse_volume_spec_with_mode(self):
        spec = VolumeSpec.parse('external:interval:ro')
        assert spec == ('external', 'interval', 'ro')

        spec = VolumeSpec.parse('external:interval:z')
        assert spec == ('external', 'interval', 'z')
Example #34
0
 def test_parse_volume_spec_too_many_parts(self):
     with pytest.raises(ConfigurationError) as exc:
         VolumeSpec.parse('one:two:three:four')
     assert 'has incorrect format' in exc.exconly()
Example #35
0
 def test_parse_volume_windows_absolute_path(self):
     windows_path = "c:\\Users\\me\\Documents\\shiny\\config:\\opt\\shiny\\config:ro"
     assert VolumeSpec.parse(windows_path) == (
         "/c/Users/me/Documents/shiny/config", "/opt/shiny/config", "ro")
Example #36
0
 def test_parse_volume_windows_absolute_path_normalized(self):
     windows_path = "c:\\Users\\me\\Documents\\shiny\\config:/opt/shiny/config:ro"
     assert VolumeSpec._parse_win32(
         windows_path, True) == ("/c/Users/me/Documents/shiny/config",
                                 "/opt/shiny/config", "ro")
Example #37
0
 def test_parse_volume_windows_just_drives_normalized(self):
     windows_path = 'E:\\:C:\\:ro'
     assert VolumeSpec._parse_win32(windows_path,
                                    True) == ('/e/', 'C:\\', 'ro')
Example #38
0
 def test_parse_volume_spec_internal_and_external(self):
     spec = VolumeSpec.parse('external:interval')
     assert spec == ('external', 'interval', 'rw')
Example #39
0
 def test_parse_volume_windows_internal_path_normalized(self):
     windows_path = 'C:\\Users\\reimu\\scarlet:C:\\scarlet\\app:ro'
     assert VolumeSpec._parse_win32(windows_path,
                                    True) == ('/c/Users/reimu/scarlet',
                                              'C:\\scarlet\\app', 'ro')
Example #40
0
 def test_parse_volume_spec_only_one_path(self):
     spec = VolumeSpec.parse('/the/volume')
     assert spec == (None, '/the/volume', 'rw')
Example #41
0
 def test_create_container_with_unspecified_volume(self):
     service = self.create_service('db',
                                   volumes=[VolumeSpec.parse('/var/db')])
     container = service.create_container()
     container.start()
     self.assertIn('/var/db', container.get('Volumes'))
Example #42
0
 def test_parse_volume_windows_mixed_notations_normalized(self):
     windows_path = 'C:\\Foo:/root/foo'
     assert VolumeSpec._parse_win32(windows_path,
                                    True) == ('/c/Foo', '/root/foo', 'rw')
Example #43
0
 def test_parse_volume_windows_absolute_path_native(self):
     windows_path = "c:\\Users\\me\\Documents\\shiny\\config:/opt/shiny/config:ro"
     assert VolumeSpec._parse_win32(
         windows_path, False) == ("c:\\Users\\me\\Documents\\shiny\\config",
                                  "/opt/shiny/config", "ro")
Example #44
0
 def test_parse_volume_windows_just_drives_native(self):
     windows_path = 'E:\\:C:\\:ro'
     assert VolumeSpec._parse_win32(windows_path,
                                    False) == ('E:\\', 'C:\\', 'ro')
Example #45
0
 def test_parse_volume_windows_mixed_notations_native(self):
     windows_path = 'C:\\Foo:/root/foo'
     assert VolumeSpec._parse_win32(windows_path,
                                    False) == ('C:\\Foo', '/root/foo', 'rw')
Example #46
0
 def test_create_container_with_unspecified_volume(self):
     service = self.create_service('db',
                                   volumes=[VolumeSpec.parse('/var/db')])
     container = service.create_container()
     service.start_container(container)
     assert container.get_mount('/var/db')