Add support for link-local IPs in service.networks definition

Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
Joffrey F 2016-06-27 17:27:31 -07:00
commit fd254caa68
9 changed files with 452 additions and 15 deletions

View file

@ -13,6 +13,7 @@ from .testcases import DockerClientTestCase
from compose.config import config
from compose.config import ConfigurationError
from compose.config.config import V2_0
from compose.config.config import V2_1
from compose.config.types import VolumeFromSpec
from compose.config.types import VolumeSpec
from compose.const import LABEL_PROJECT
@ -21,6 +22,7 @@ from compose.container import Container
from compose.project import Project
from compose.project import ProjectError
from compose.service import ConvergenceStrategy
from tests.integration.testcases import v2_1_only
from tests.integration.testcases import v2_only
@ -756,6 +758,31 @@ class ProjectTest(DockerClientTestCase):
with self.assertRaises(ProjectError):
project.up()
@v2_1_only()
def test_up_with_network_link_local_ips(self):
config_data = config.Config(
version=V2_1,
services=[{
'name': 'web',
'image': 'busybox:latest',
'networks': {
'linklocaltest': {
'link_local_ips': ['169.254.8.8']
}
}
}],
volumes={},
networks={
'linklocaltest': {'driver': 'bridge'}
}
)
project = Project.from_config(
client=self.client,
name='composetest',
config_data=config_data
)
project.up()
@v2_only()
def test_project_up_with_network_internal(self):
self.require_api_version('1.23')

View file

@ -12,6 +12,7 @@ from compose.cli.docker_client import docker_client
from compose.config.config import resolve_environment
from compose.config.config import V1
from compose.config.config import V2_0
from compose.config.config import V2_1
from compose.config.environment import Environment
from compose.const import API_VERSIONS
from compose.const import LABEL_PROJECT
@ -33,18 +34,22 @@ def get_links(container):
return [format_link(link) for link in links]
def engine_version_too_low_for_v2():
def engine_max_version():
if 'DOCKER_VERSION' not in os.environ:
return False
return V2_1
version = os.environ['DOCKER_VERSION'].partition('-')[0]
return version_lt(version, '1.10')
if version_lt(version, '1.10'):
return V1
elif version_lt(version, '1.12'):
return V2_0
return V2_1
def v2_only():
def decorator(f):
@functools.wraps(f)
def wrapper(self, *args, **kwargs):
if engine_version_too_low_for_v2():
if engine_max_version() == V1:
skip("Engine version is too low")
return
return f(self, *args, **kwargs)
@ -53,14 +58,23 @@ def v2_only():
return decorator
def v2_1_only():
def decorator(f):
@functools.wraps(f)
def wrapper(self, *args, **kwargs):
if engine_max_version() in (V1, V2_0):
skip('Engine version is too low')
return
return f(self, *args, **kwargs)
return wrapper
return decorator
class DockerClientTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
if engine_version_too_low_for_v2():
version = API_VERSIONS[V1]
else:
version = API_VERSIONS[V2_0]
version = API_VERSIONS[engine_max_version()]
cls.client = docker_client(Environment(), version)
@classmethod

View file

@ -17,6 +17,7 @@ from compose.config.config import resolve_build_args
from compose.config.config import resolve_environment
from compose.config.config import V1
from compose.config.config import V2_0
from compose.config.config import V2_1
from compose.config.environment import Environment
from compose.config.errors import ConfigurationError
from compose.config.errors import VERSION_EXPLANATION
@ -155,6 +156,8 @@ class ConfigTest(unittest.TestCase):
for version in ['2', '2.0']:
cfg = config.load(build_config_details({'version': version}))
assert cfg.version == V2_0
cfg = config.load(build_config_details({'version': '2.1'}))
assert cfg.version == V2_1
def test_v1_file_version(self):
cfg = config.load(build_config_details({'web': {'image': 'busybox'}}))
@ -182,7 +185,7 @@ class ConfigTest(unittest.TestCase):
with pytest.raises(ConfigurationError) as excinfo:
config.load(
build_config_details(
{'version': '2.1'},
{'version': '2.18'},
filename='filename.yml',
)
)
@ -344,6 +347,35 @@ class ConfigTest(unittest.TestCase):
}, 'working_dir', 'filename.yml')
)
def test_load_config_link_local_ips_network(self):
base_file = config.ConfigFile(
'base.yaml',
{
'version': '2.1',
'services': {
'web': {
'image': 'example/web',
'networks': {
'foobar': {
'aliases': ['foo', 'bar'],
'link_local_ips': ['169.254.8.8']
}
}
}
},
'networks': {'foobar': {}}
}
)
details = config.ConfigDetails('.', [base_file])
web_service = config.load(details).services[0]
assert web_service['networks'] == {
'foobar': {
'aliases': ['foo', 'bar'],
'link_local_ips': ['169.254.8.8']
}
}
def test_load_config_invalid_service_names(self):
for invalid_name in ['?not?allowed', ' ', '', '!', '/', '\xe2']:
with pytest.raises(ConfigurationError) as exc: