Don't break when volume binds contain unicode characters

Also includes a few unit tests for utils.convert_volume_binds

Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
Joffrey F 2015-09-23 14:05:03 -07:00
parent 1c97c691bf
commit a1393ee8ac
2 changed files with 104 additions and 6 deletions

View File

@ -242,6 +242,9 @@ def convert_volume_binds(binds):
result = [] result = []
for k, v in binds.items(): for k, v in binds.items():
if isinstance(k, six.binary_type):
k = k.decode('utf-8')
if isinstance(v, dict): if isinstance(v, dict):
if 'ro' in v and 'mode' in v: if 'ro' in v and 'mode' in v:
raise ValueError( raise ValueError(
@ -249,6 +252,10 @@ def convert_volume_binds(binds):
.format(repr(v)) .format(repr(v))
) )
bind = v['bind']
if isinstance(bind, six.binary_type):
bind = bind.decode('utf-8')
if 'ro' in v: if 'ro' in v:
mode = 'ro' if v['ro'] else 'rw' mode = 'ro' if v['ro'] else 'rw'
elif 'mode' in v: elif 'mode' in v:
@ -256,11 +263,15 @@ def convert_volume_binds(binds):
else: else:
mode = 'rw' mode = 'rw'
result.append('{0}:{1}:{2}'.format( result.append(
k, v['bind'], mode six.text_type('{0}:{1}:{2}').format(k, bind, mode)
)) )
else: else:
result.append('{0}:{1}:rw'.format(k, v)) if isinstance(v, six.binary_type):
v = v.decode('utf-8')
result.append(
six.text_type('{0}:{1}:rw').format(k, v)
)
return result return result

View File

@ -1,15 +1,20 @@
# -*- coding: utf-8 -*-
import os import os
import os.path import os.path
import shutil import shutil
import tempfile import tempfile
import pytest
import six
from docker.client import Client from docker.client import Client
from docker.constants import DEFAULT_DOCKER_API_VERSION from docker.constants import DEFAULT_DOCKER_API_VERSION
from docker.errors import DockerException from docker.errors import DockerException
from docker.utils import ( from docker.utils import (
parse_repository_tag, parse_host, convert_filters, kwargs_from_env, parse_repository_tag, parse_host, convert_filters, kwargs_from_env,
create_host_config, Ulimit, LogConfig, parse_bytes, parse_env_file, create_host_config, Ulimit, LogConfig, parse_bytes, parse_env_file,
exclude_paths, exclude_paths, convert_volume_binds,
) )
from docker.utils.ports import build_port_bindings, split_port from docker.utils.ports import build_port_bindings, split_port
from docker.auth import resolve_repository_name, resolve_authconfig from docker.auth import resolve_repository_name, resolve_authconfig
@ -17,7 +22,6 @@ from docker.auth import resolve_repository_name, resolve_authconfig
from . import base from . import base
from .helpers import make_tree from .helpers import make_tree
import pytest
TEST_CERT_DIR = os.path.join( TEST_CERT_DIR = os.path.join(
os.path.dirname(__file__), os.path.dirname(__file__),
@ -192,6 +196,89 @@ class UtilsTest(base.BaseTestCase):
local_tempfile.close() local_tempfile.close()
return local_tempfile.name return local_tempfile.name
def test_convert_volume_binds_empty(self):
self.assertEqual(convert_volume_binds({}), [])
self.assertEqual(convert_volume_binds([]), [])
def test_convert_volume_binds_list(self):
data = ['/a:/a:ro', '/b:/c:z']
self.assertEqual(convert_volume_binds(data), data)
def test_convert_volume_binds_complete(self):
data = {
'/mnt/vol1': {
'bind': '/data',
'mode': 'ro'
}
}
self.assertEqual(convert_volume_binds(data), ['/mnt/vol1:/data:ro'])
def test_convert_volume_binds_compact(self):
data = {
'/mnt/vol1': '/data'
}
self.assertEqual(convert_volume_binds(data), ['/mnt/vol1:/data:rw'])
def test_convert_volume_binds_no_mode(self):
data = {
'/mnt/vol1': {
'bind': '/data'
}
}
self.assertEqual(convert_volume_binds(data), ['/mnt/vol1:/data:rw'])
def test_convert_volume_binds_unicode_bytes_input(self):
if six.PY2:
expected = [unicode('/mnt/지연:/unicode/박:rw', 'utf-8')]
data = {
'/mnt/지연': {
'bind': '/unicode/박',
'mode': 'rw'
}
}
self.assertEqual(
convert_volume_binds(data), expected
)
else:
expected = ['/mnt/지연:/unicode/박:rw']
data = {
bytes('/mnt/지연', 'utf-8'): {
'bind': bytes('/unicode/박', 'utf-8'),
'mode': 'rw'
}
}
self.assertEqual(
convert_volume_binds(data), expected
)
def test_convert_volume_binds_unicode_unicode_input(self):
if six.PY2:
expected = [unicode('/mnt/지연:/unicode/박:rw', 'utf-8')]
data = {
unicode('/mnt/지연', 'utf-8'): {
'bind': unicode('/unicode/박', 'utf-8'),
'mode': 'rw'
}
}
self.assertEqual(
convert_volume_binds(data), expected
)
else:
expected = ['/mnt/지연:/unicode/박:rw']
data = {
'/mnt/지연': {
'bind': '/unicode/박',
'mode': 'rw'
}
}
self.assertEqual(
convert_volume_binds(data), expected
)
def test_parse_repository_tag(self): def test_parse_repository_tag(self):
self.assertEqual(parse_repository_tag("root"), self.assertEqual(parse_repository_tag("root"),
("root", None)) ("root", None))