Implement network_mode in v2

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
This commit is contained in:
Aanand Prasad 2016-01-25 12:45:30 +00:00
commit 2b7306967b
16 changed files with 405 additions and 87 deletions

View file

@ -496,8 +496,29 @@ class CLITestCase(DockerClientTestCase):
assert 'Service "web" uses an undefined network "foo"' in result.stderr
@v2_only()
def test_up_predefined_networks(self):
filename = 'predefined-networks.yml'
def test_up_with_bridge_network_plus_default(self):
filename = 'bridge.yml'
self.base_dir = 'tests/fixtures/networks'
self._project = get_project(self.base_dir, [filename])
self.dispatch(['-f', filename, 'up', '-d'], None)
container = self.project.containers()[0]
assert sorted(list(container.get('NetworkSettings.Networks'))) == sorted([
'bridge',
self.project.default_network.full_name,
])
@v2_only()
def test_up_with_network_mode(self):
c = self.client.create_container('busybox', 'top', name='composetest_network_mode_container')
self.addCleanup(self.client.remove_container, c, force=True)
self.client.start(c)
container_mode_source = 'container:{}'.format(c['Id'])
filename = 'network-mode.yml'
self.base_dir = 'tests/fixtures/networks'
self._project = get_project(self.base_dir, [filename])
@ -515,6 +536,16 @@ class CLITestCase(DockerClientTestCase):
assert list(container.get('NetworkSettings.Networks')) == [name]
assert container.get('HostConfig.NetworkMode') == name
service_mode_source = 'container:{}'.format(
self.project.get_service('bridge').containers()[0].id)
service_mode_container = self.project.get_service('service').containers()[0]
assert not service_mode_container.get('NetworkSettings.Networks')
assert service_mode_container.get('HostConfig.NetworkMode') == service_mode_source
container_mode_container = self.project.get_service('container').containers()[0]
assert not container_mode_container.get('NetworkSettings.Networks')
assert container_mode_container.get('HostConfig.NetworkMode') == container_mode_source
@v2_only()
def test_up_external_networks(self):
filename = 'external-networks.yml'

View file

@ -0,0 +1,12 @@
version: 2
services:
myweb:
build: '.'
extends:
service: web
command: top
web:
build: '.'
network_mode: "service:net"
net:
build: '.'

9
tests/fixtures/networks/bridge.yml vendored Normal file
View file

@ -0,0 +1,9 @@
version: 2
services:
web:
image: busybox
command: top
networks:
- bridge
- default

View file

@ -0,0 +1,27 @@
version: 2
services:
bridge:
image: busybox
command: top
network_mode: bridge
service:
image: busybox
command: top
network_mode: "service:bridge"
container:
image: busybox
command: top
network_mode: "container:composetest_network_mode_container"
host:
image: busybox
command: top
network_mode: host
none:
image: busybox
command: top
network_mode: none

View file

@ -1,17 +0,0 @@
version: 2
services:
bridge:
image: busybox
command: top
networks: ["bridge"]
host:
image: busybox
command: top
networks: ["host"]
none:
image: busybox
command: top
networks: []

View file

@ -4,10 +4,12 @@ from __future__ import unicode_literals
import random
import py
import pytest
from docker.errors import NotFound
from .testcases import DockerClientTestCase
from compose.config import config
from compose.config import ConfigurationError
from compose.config.types import VolumeFromSpec
from compose.config.types import VolumeSpec
from compose.const import LABEL_PROJECT
@ -104,7 +106,71 @@ class ProjectTest(DockerClientTestCase):
db = project.get_service('db')
self.assertEqual(db._get_volumes_from(), [data_container.id + ':rw'])
def test_net_from_service(self):
@v2_only()
def test_network_mode_from_service(self):
project = Project.from_config(
name='composetest',
client=self.client,
config_data=build_service_dicts({
'version': 2,
'services': {
'net': {
'image': 'busybox:latest',
'command': ["top"]
},
'web': {
'image': 'busybox:latest',
'network_mode': 'service:net',
'command': ["top"]
},
},
}),
)
project.up()
web = project.get_service('web')
net = project.get_service('net')
self.assertEqual(web.net.mode, 'container:' + net.containers()[0].id)
@v2_only()
def test_network_mode_from_container(self):
def get_project():
return Project.from_config(
name='composetest',
config_data=build_service_dicts({
'version': 2,
'services': {
'web': {
'image': 'busybox:latest',
'network_mode': 'container:composetest_net_container'
},
},
}),
client=self.client,
)
with pytest.raises(ConfigurationError) as excinfo:
get_project()
assert "container 'composetest_net_container' which does not exist" in excinfo.exconly()
net_container = Container.create(
self.client,
image='busybox:latest',
name='composetest_net_container',
command='top',
labels={LABEL_PROJECT: 'composetest'},
)
net_container.start()
project = get_project()
project.up()
web = project.get_service('web')
self.assertEqual(web.net.mode, 'container:' + net_container.id)
def test_net_from_service_v1(self):
project = Project.from_config(
name='composetest',
config_data=build_service_dicts({
@ -127,7 +193,24 @@ class ProjectTest(DockerClientTestCase):
net = project.get_service('net')
self.assertEqual(web.net.mode, 'container:' + net.containers()[0].id)
def test_net_from_container(self):
def test_net_from_container_v1(self):
def get_project():
return Project.from_config(
name='composetest',
config_data=build_service_dicts({
'web': {
'image': 'busybox:latest',
'net': 'container:composetest_net_container'
},
}),
client=self.client,
)
with pytest.raises(ConfigurationError) as excinfo:
get_project()
assert "container 'composetest_net_container' which does not exist" in excinfo.exconly()
net_container = Container.create(
self.client,
image='busybox:latest',
@ -137,17 +220,7 @@ class ProjectTest(DockerClientTestCase):
)
net_container.start()
project = Project.from_config(
name='composetest',
config_data=build_service_dicts({
'web': {
'image': 'busybox:latest',
'net': 'container:composetest_net_container'
},
}),
client=self.client,
)
project = get_project()
project.up()
web = project.get_service('web')

View file

@ -1015,6 +1015,126 @@ class ConfigTest(unittest.TestCase):
assert "Service 'one' depends on service 'three'" in exc.exconly()
class NetworkModeTest(unittest.TestCase):
def test_network_mode_standard(self):
config_data = config.load(build_config_details({
'version': 2,
'services': {
'web': {
'image': 'busybox',
'command': "top",
'network_mode': 'bridge',
},
},
}))
assert config_data.services[0]['network_mode'] == 'bridge'
def test_network_mode_standard_v1(self):
config_data = config.load(build_config_details({
'web': {
'image': 'busybox',
'command': "top",
'net': 'bridge',
},
}))
assert config_data.services[0]['network_mode'] == 'bridge'
assert 'net' not in config_data.services[0]
def test_network_mode_container(self):
config_data = config.load(build_config_details({
'version': 2,
'services': {
'web': {
'image': 'busybox',
'command': "top",
'network_mode': 'container:foo',
},
},
}))
assert config_data.services[0]['network_mode'] == 'container:foo'
def test_network_mode_container_v1(self):
config_data = config.load(build_config_details({
'web': {
'image': 'busybox',
'command': "top",
'net': 'container:foo',
},
}))
assert config_data.services[0]['network_mode'] == 'container:foo'
def test_network_mode_service(self):
config_data = config.load(build_config_details({
'version': 2,
'services': {
'web': {
'image': 'busybox',
'command': "top",
'network_mode': 'service:foo',
},
'foo': {
'image': 'busybox',
'command': "top",
},
},
}))
assert config_data.services[1]['network_mode'] == 'service:foo'
def test_network_mode_service_v1(self):
config_data = config.load(build_config_details({
'web': {
'image': 'busybox',
'command': "top",
'net': 'container:foo',
},
'foo': {
'image': 'busybox',
'command': "top",
},
}))
assert config_data.services[1]['network_mode'] == 'service:foo'
def test_network_mode_service_nonexistent(self):
with pytest.raises(ConfigurationError) as excinfo:
config.load(build_config_details({
'version': 2,
'services': {
'web': {
'image': 'busybox',
'command': "top",
'network_mode': 'service:foo',
},
},
}))
assert "service 'foo' which is undefined" in excinfo.exconly()
def test_network_mode_plus_networks_is_invalid(self):
with pytest.raises(ConfigurationError) as excinfo:
config.load(build_config_details({
'version': 2,
'services': {
'web': {
'image': 'busybox',
'command': "top",
'network_mode': 'bridge',
'networks': ['front'],
},
},
'networks': {
'front': None,
}
}))
assert "'network_mode' and 'networks' cannot be combined" in excinfo.exconly()
class PortsTest(unittest.TestCase):
INVALID_PORTS_TYPES = [
{"1": "8000"},
@ -1867,11 +1987,18 @@ class ExtendsTest(unittest.TestCase):
load_from_filename('tests/fixtures/extends/invalid-volumes.yml')
def test_invalid_net_in_extended_service(self):
expected_error_msg = "services with 'net: container' cannot be extended"
with pytest.raises(ConfigurationError) as excinfo:
load_from_filename('tests/fixtures/extends/invalid-net-v2.yml')
with self.assertRaisesRegexp(ConfigurationError, expected_error_msg):
assert 'network_mode: service' in excinfo.exconly()
assert 'cannot be extended' in excinfo.exconly()
with pytest.raises(ConfigurationError) as excinfo:
load_from_filename('tests/fixtures/extends/invalid-net.yml')
assert 'net: container' in excinfo.exconly()
assert 'cannot be extended' in excinfo.exconly()
@mock.patch.dict(os.environ)
def test_load_config_runs_interpolation_in_extended_service(self):
os.environ.update(HOSTNAME_VALUE="penguin")

View file

@ -100,7 +100,7 @@ class TestSortService(object):
},
{
'name': 'parent',
'net': 'container:child'
'network_mode': 'service:child'
},
{
'name': 'child'
@ -137,7 +137,7 @@ class TestSortService(object):
def test_sort_service_dicts_7(self):
services = [
{
'net': 'container:three',
'network_mode': 'service:three',
'name': 'four'
},
{

View file

@ -365,7 +365,7 @@ class ProjectTest(unittest.TestCase):
{
'name': 'test',
'image': 'busybox:latest',
'net': 'container:aaa'
'network_mode': 'container:aaa'
},
],
networks=None,
@ -398,7 +398,7 @@ class ProjectTest(unittest.TestCase):
{
'name': 'test',
'image': 'busybox:latest',
'net': 'container:aaa'
'network_mode': 'service:aaa'
},
],
networks=None,