|
@@ -1,6 +1,7 @@
|
|
|
from __future__ import absolute_import
|
|
|
from __future__ import unicode_literals
|
|
|
|
|
|
+import os.path
|
|
|
import random
|
|
|
|
|
|
import py
|
|
@@ -8,12 +9,14 @@ import pytest
|
|
|
from docker.errors import NotFound
|
|
|
|
|
|
from .. import mock
|
|
|
-from ..helpers import build_config
|
|
|
+from ..helpers import build_config as load_config
|
|
|
from .testcases import DockerClientTestCase
|
|
|
from compose.config import config
|
|
|
from compose.config import ConfigurationError
|
|
|
+from compose.config import types
|
|
|
from compose.config.config import V2_0
|
|
|
from compose.config.config import V2_1
|
|
|
+from compose.config.config import V3_1
|
|
|
from compose.config.types import VolumeFromSpec
|
|
|
from compose.config.types import VolumeSpec
|
|
|
from compose.const import LABEL_PROJECT
|
|
@@ -26,6 +29,16 @@ 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
|
|
|
+from tests.integration.testcases import v3_only
|
|
|
+
|
|
|
+
|
|
|
+def build_config(**kwargs):
|
|
|
+ return config.Config(
|
|
|
+ version=kwargs.get('version'),
|
|
|
+ services=kwargs.get('services'),
|
|
|
+ volumes=kwargs.get('volumes'),
|
|
|
+ networks=kwargs.get('networks'),
|
|
|
+ secrets=kwargs.get('secrets'))
|
|
|
|
|
|
|
|
|
class ProjectTest(DockerClientTestCase):
|
|
@@ -70,7 +83,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
def test_volumes_from_service(self):
|
|
|
project = Project.from_config(
|
|
|
name='composetest',
|
|
|
- config_data=build_config({
|
|
|
+ config_data=load_config({
|
|
|
'data': {
|
|
|
'image': 'busybox:latest',
|
|
|
'volumes': ['/var/data'],
|
|
@@ -96,7 +109,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
)
|
|
|
project = Project.from_config(
|
|
|
name='composetest',
|
|
|
- config_data=build_config({
|
|
|
+ config_data=load_config({
|
|
|
'db': {
|
|
|
'image': 'busybox:latest',
|
|
|
'volumes_from': ['composetest_data_container'],
|
|
@@ -112,7 +125,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
project = Project.from_config(
|
|
|
name='composetest',
|
|
|
client=self.client,
|
|
|
- config_data=build_config({
|
|
|
+ config_data=load_config({
|
|
|
'version': V2_0,
|
|
|
'services': {
|
|
|
'net': {
|
|
@@ -139,7 +152,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
def get_project():
|
|
|
return Project.from_config(
|
|
|
name='composetest',
|
|
|
- config_data=build_config({
|
|
|
+ config_data=load_config({
|
|
|
'version': V2_0,
|
|
|
'services': {
|
|
|
'web': {
|
|
@@ -174,7 +187,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
def test_net_from_service_v1(self):
|
|
|
project = Project.from_config(
|
|
|
name='composetest',
|
|
|
- config_data=build_config({
|
|
|
+ config_data=load_config({
|
|
|
'net': {
|
|
|
'image': 'busybox:latest',
|
|
|
'command': ["top"]
|
|
@@ -198,7 +211,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
def get_project():
|
|
|
return Project.from_config(
|
|
|
name='composetest',
|
|
|
- config_data=build_config({
|
|
|
+ config_data=load_config({
|
|
|
'web': {
|
|
|
'image': 'busybox:latest',
|
|
|
'net': 'container:composetest_net_container'
|
|
@@ -469,7 +482,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
def test_project_up_starts_depends(self):
|
|
|
project = Project.from_config(
|
|
|
name='composetest',
|
|
|
- config_data=build_config({
|
|
|
+ config_data=load_config({
|
|
|
'console': {
|
|
|
'image': 'busybox:latest',
|
|
|
'command': ["top"],
|
|
@@ -504,7 +517,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
def test_project_up_with_no_deps(self):
|
|
|
project = Project.from_config(
|
|
|
name='composetest',
|
|
|
- config_data=build_config({
|
|
|
+ config_data=load_config({
|
|
|
'console': {
|
|
|
'image': 'busybox:latest',
|
|
|
'command': ["top"],
|
|
@@ -564,7 +577,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
|
|
|
@v2_only()
|
|
|
def test_project_up_networks(self):
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -576,7 +589,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
'baz': {'aliases': ['extra']},
|
|
|
},
|
|
|
}],
|
|
|
- volumes={},
|
|
|
networks={
|
|
|
'foo': {'driver': 'bridge'},
|
|
|
'bar': {'driver': None},
|
|
@@ -610,14 +622,13 @@ class ProjectTest(DockerClientTestCase):
|
|
|
|
|
|
@v2_only()
|
|
|
def test_up_with_ipam_config(self):
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
|
'image': 'busybox:latest',
|
|
|
'networks': {'front': None},
|
|
|
}],
|
|
|
- volumes={},
|
|
|
networks={
|
|
|
'front': {
|
|
|
'driver': 'bridge',
|
|
@@ -671,7 +682,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
|
|
|
@v2_only()
|
|
|
def test_up_with_network_static_addresses(self):
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -684,7 +695,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
}
|
|
|
},
|
|
|
}],
|
|
|
- volumes={},
|
|
|
networks={
|
|
|
'static_test': {
|
|
|
'driver': 'bridge',
|
|
@@ -726,7 +736,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
@v2_1_only()
|
|
|
def test_up_with_enable_ipv6(self):
|
|
|
self.require_api_version('1.23')
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -738,7 +748,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
}
|
|
|
},
|
|
|
}],
|
|
|
- volumes={},
|
|
|
networks={
|
|
|
'static_test': {
|
|
|
'driver': 'bridge',
|
|
@@ -770,7 +779,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
|
|
|
@v2_only()
|
|
|
def test_up_with_network_static_addresses_missing_subnet(self):
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -782,7 +791,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
}
|
|
|
},
|
|
|
}],
|
|
|
- volumes={},
|
|
|
networks={
|
|
|
'static_test': {
|
|
|
'driver': 'bridge',
|
|
@@ -807,7 +815,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
|
|
|
@v2_1_only()
|
|
|
def test_up_with_network_link_local_ips(self):
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_1,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -818,7 +826,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
}
|
|
|
}
|
|
|
}],
|
|
|
- volumes={},
|
|
|
networks={
|
|
|
'linklocaltest': {'driver': 'bridge'}
|
|
|
}
|
|
@@ -844,15 +851,13 @@ class ProjectTest(DockerClientTestCase):
|
|
|
@v2_1_only()
|
|
|
def test_up_with_isolation(self):
|
|
|
self.require_api_version('1.24')
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_1,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
|
'image': 'busybox:latest',
|
|
|
'isolation': 'default'
|
|
|
}],
|
|
|
- volumes={},
|
|
|
- networks={}
|
|
|
)
|
|
|
project = Project.from_config(
|
|
|
client=self.client,
|
|
@@ -866,15 +871,13 @@ class ProjectTest(DockerClientTestCase):
|
|
|
@v2_1_only()
|
|
|
def test_up_with_invalid_isolation(self):
|
|
|
self.require_api_version('1.24')
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_1,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
|
'image': 'busybox:latest',
|
|
|
'isolation': 'foobar'
|
|
|
}],
|
|
|
- volumes={},
|
|
|
- networks={}
|
|
|
)
|
|
|
project = Project.from_config(
|
|
|
client=self.client,
|
|
@@ -887,14 +890,13 @@ class ProjectTest(DockerClientTestCase):
|
|
|
@v2_only()
|
|
|
def test_project_up_with_network_internal(self):
|
|
|
self.require_api_version('1.23')
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
|
'image': 'busybox:latest',
|
|
|
'networks': {'internal': None},
|
|
|
}],
|
|
|
- volumes={},
|
|
|
networks={
|
|
|
'internal': {'driver': 'bridge', 'internal': True},
|
|
|
},
|
|
@@ -917,14 +919,13 @@ class ProjectTest(DockerClientTestCase):
|
|
|
|
|
|
network_name = 'network_with_label'
|
|
|
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
|
'image': 'busybox:latest',
|
|
|
'networks': {network_name: None}
|
|
|
}],
|
|
|
- volumes={},
|
|
|
networks={
|
|
|
network_name: {'labels': {'label_key': 'label_val'}}
|
|
|
}
|
|
@@ -951,7 +952,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
def test_project_up_volumes(self):
|
|
|
vol_name = '{0:x}'.format(random.getrandbits(32))
|
|
|
full_vol_name = 'composetest_{0}'.format(vol_name)
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -959,7 +960,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
'command': 'top'
|
|
|
}],
|
|
|
volumes={vol_name: {'driver': 'local'}},
|
|
|
- networks={},
|
|
|
)
|
|
|
|
|
|
project = Project.from_config(
|
|
@@ -979,7 +979,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
|
|
|
volume_name = 'volume_with_label'
|
|
|
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -993,7 +993,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
- networks={},
|
|
|
)
|
|
|
|
|
|
project = Project.from_config(
|
|
@@ -1106,7 +1105,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
def test_initialize_volumes(self):
|
|
|
vol_name = '{0:x}'.format(random.getrandbits(32))
|
|
|
full_vol_name = 'composetest_{0}'.format(vol_name)
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -1114,7 +1113,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
'command': 'top'
|
|
|
}],
|
|
|
volumes={vol_name: {}},
|
|
|
- networks={},
|
|
|
)
|
|
|
|
|
|
project = Project.from_config(
|
|
@@ -1124,14 +1122,14 @@ class ProjectTest(DockerClientTestCase):
|
|
|
project.volumes.initialize()
|
|
|
|
|
|
volume_data = self.client.inspect_volume(full_vol_name)
|
|
|
- self.assertEqual(volume_data['Name'], full_vol_name)
|
|
|
- self.assertEqual(volume_data['Driver'], 'local')
|
|
|
+ assert volume_data['Name'] == full_vol_name
|
|
|
+ assert volume_data['Driver'] == 'local'
|
|
|
|
|
|
@v2_only()
|
|
|
def test_project_up_implicit_volume_driver(self):
|
|
|
vol_name = '{0:x}'.format(random.getrandbits(32))
|
|
|
full_vol_name = 'composetest_{0}'.format(vol_name)
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -1139,7 +1137,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
'command': 'top'
|
|
|
}],
|
|
|
volumes={vol_name: {}},
|
|
|
- networks={},
|
|
|
)
|
|
|
|
|
|
project = Project.from_config(
|
|
@@ -1152,11 +1149,45 @@ class ProjectTest(DockerClientTestCase):
|
|
|
self.assertEqual(volume_data['Name'], full_vol_name)
|
|
|
self.assertEqual(volume_data['Driver'], 'local')
|
|
|
|
|
|
+ @v3_only()
|
|
|
+ def test_project_up_with_secrets(self):
|
|
|
+ config_data = build_config(
|
|
|
+ version=V3_1,
|
|
|
+ services=[{
|
|
|
+ 'name': 'web',
|
|
|
+ 'image': 'busybox:latest',
|
|
|
+ 'command': 'cat /run/secrets/special',
|
|
|
+ 'secrets': [
|
|
|
+ types.ServiceSecret.parse({'source': 'super', 'target': 'special'}),
|
|
|
+ ],
|
|
|
+ }],
|
|
|
+ secrets={
|
|
|
+ 'super': {
|
|
|
+ 'file': os.path.abspath('tests/fixtures/secrets/default'),
|
|
|
+ },
|
|
|
+ },
|
|
|
+ )
|
|
|
+
|
|
|
+ project = Project.from_config(
|
|
|
+ client=self.client,
|
|
|
+ name='composetest',
|
|
|
+ config_data=config_data,
|
|
|
+ )
|
|
|
+ project.up()
|
|
|
+ project.stop()
|
|
|
+
|
|
|
+ containers = project.containers(stopped=True)
|
|
|
+ assert len(containers) == 1
|
|
|
+ container, = containers
|
|
|
+
|
|
|
+ output = container.logs()
|
|
|
+ assert output == "This is the secret\n"
|
|
|
+
|
|
|
@v2_only()
|
|
|
def test_initialize_volumes_invalid_volume_driver(self):
|
|
|
vol_name = '{0:x}'.format(random.getrandbits(32))
|
|
|
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -1164,7 +1195,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
'command': 'top'
|
|
|
}],
|
|
|
volumes={vol_name: {'driver': 'foobar'}},
|
|
|
- networks={},
|
|
|
)
|
|
|
|
|
|
project = Project.from_config(
|
|
@@ -1179,7 +1209,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
vol_name = '{0:x}'.format(random.getrandbits(32))
|
|
|
full_vol_name = 'composetest_{0}'.format(vol_name)
|
|
|
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -1187,7 +1217,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
'command': 'top'
|
|
|
}],
|
|
|
volumes={vol_name: {'driver': 'local'}},
|
|
|
- networks={},
|
|
|
)
|
|
|
project = Project.from_config(
|
|
|
name='composetest',
|
|
@@ -1218,7 +1247,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
vol_name = '{0:x}'.format(random.getrandbits(32))
|
|
|
full_vol_name = 'composetest_{0}'.format(vol_name)
|
|
|
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -1226,7 +1255,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
'command': 'top'
|
|
|
}],
|
|
|
volumes={vol_name: {'driver': 'local'}},
|
|
|
- networks={},
|
|
|
)
|
|
|
project = Project.from_config(
|
|
|
name='composetest',
|
|
@@ -1257,7 +1285,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
vol_name = 'composetest_{0:x}'.format(random.getrandbits(32))
|
|
|
full_vol_name = 'composetest_{0}'.format(vol_name)
|
|
|
self.client.create_volume(vol_name)
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -1267,7 +1295,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
volumes={
|
|
|
vol_name: {'external': True, 'external_name': vol_name}
|
|
|
},
|
|
|
- networks=None,
|
|
|
)
|
|
|
project = Project.from_config(
|
|
|
name='composetest',
|
|
@@ -1282,7 +1309,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
def test_initialize_volumes_inexistent_external_volume(self):
|
|
|
vol_name = '{0:x}'.format(random.getrandbits(32))
|
|
|
|
|
|
- config_data = config.Config(
|
|
|
+ config_data = build_config(
|
|
|
version=V2_0,
|
|
|
services=[{
|
|
|
'name': 'web',
|
|
@@ -1292,7 +1319,6 @@ class ProjectTest(DockerClientTestCase):
|
|
|
volumes={
|
|
|
vol_name: {'external': True, 'external_name': vol_name}
|
|
|
},
|
|
|
- networks=None,
|
|
|
)
|
|
|
project = Project.from_config(
|
|
|
name='composetest',
|
|
@@ -1349,7 +1375,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- config_data = build_config(config_dict)
|
|
|
+ config_data = load_config(config_dict)
|
|
|
project = Project.from_config(
|
|
|
name='composetest', config_data=config_data, client=self.client
|
|
|
)
|
|
@@ -1357,7 +1383,7 @@ class ProjectTest(DockerClientTestCase):
|
|
|
config_dict['service2'] = config_dict['service1']
|
|
|
del config_dict['service1']
|
|
|
|
|
|
- config_data = build_config(config_dict)
|
|
|
+ config_data = load_config(config_dict)
|
|
|
project = Project.from_config(
|
|
|
name='composetest', config_data=config_data, client=self.client
|
|
|
)
|