mirror of https://github.com/docker/compose.git
add support for creating volume and network with label definition
Signed-off-by: dbdd <wangtong2712@gmail.com>
This commit is contained in:
parent
9248298a4a
commit
bdcce13f4a
|
@ -361,6 +361,9 @@ def load_mapping(config_files, get_func, entity_type):
|
|||
config['driver_opts']
|
||||
)
|
||||
|
||||
if 'labels' in config:
|
||||
config['labels'] = parse_labels(config['labels'])
|
||||
|
||||
return mapping
|
||||
|
||||
|
||||
|
|
|
@ -246,7 +246,8 @@
|
|||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
@ -268,6 +269,7 @@
|
|||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
|
|
@ -15,7 +15,7 @@ log = logging.getLogger(__name__)
|
|||
|
||||
class Network(object):
|
||||
def __init__(self, client, project, name, driver=None, driver_opts=None,
|
||||
ipam=None, external_name=None, internal=False):
|
||||
ipam=None, external_name=None, internal=False, labels=None):
|
||||
self.client = client
|
||||
self.project = project
|
||||
self.name = name
|
||||
|
@ -24,6 +24,7 @@ class Network(object):
|
|||
self.ipam = create_ipam_config_from_dict(ipam)
|
||||
self.external_name = external_name
|
||||
self.internal = internal
|
||||
self.labels = labels
|
||||
|
||||
def ensure(self):
|
||||
if self.external_name:
|
||||
|
@ -70,6 +71,7 @@ class Network(object):
|
|||
options=self.driver_opts,
|
||||
ipam=self.ipam,
|
||||
internal=self.internal,
|
||||
labels=self.labels,
|
||||
)
|
||||
|
||||
def remove(self):
|
||||
|
@ -118,6 +120,7 @@ def build_networks(name, config_data, client):
|
|||
ipam=data.get('ipam'),
|
||||
external_name=data.get('external_name'),
|
||||
internal=data.get('internal'),
|
||||
labels=data.get('labels'),
|
||||
)
|
||||
for network_name, data in network_config.items()
|
||||
}
|
||||
|
|
|
@ -12,17 +12,18 @@ log = logging.getLogger(__name__)
|
|||
|
||||
class Volume(object):
|
||||
def __init__(self, client, project, name, driver=None, driver_opts=None,
|
||||
external_name=None):
|
||||
external_name=None, labels=None):
|
||||
self.client = client
|
||||
self.project = project
|
||||
self.name = name
|
||||
self.driver = driver
|
||||
self.driver_opts = driver_opts
|
||||
self.external_name = external_name
|
||||
self.labels = labels
|
||||
|
||||
def create(self):
|
||||
return self.client.create_volume(
|
||||
self.full_name, self.driver, self.driver_opts
|
||||
self.full_name, self.driver, self.driver_opts, labels=self.labels
|
||||
)
|
||||
|
||||
def remove(self):
|
||||
|
@ -68,7 +69,8 @@ class ProjectVolumes(object):
|
|||
name=vol_name,
|
||||
driver=data.get('driver'),
|
||||
driver_opts=data.get('driver_opts'),
|
||||
external_name=data.get('external_name')
|
||||
external_name=data.get('external_name'),
|
||||
labels=data.get('labels')
|
||||
)
|
||||
for vol_name, data in config_volumes.items()
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ from compose.project import OneOffFilter
|
|||
from tests.integration.testcases import DockerClientTestCase
|
||||
from tests.integration.testcases import get_links
|
||||
from tests.integration.testcases import pull_busybox
|
||||
from tests.integration.testcases import v2_1_only
|
||||
from tests.integration.testcases import v2_only
|
||||
|
||||
|
||||
|
@ -767,6 +768,46 @@ class CLITestCase(DockerClientTestCase):
|
|||
container = self.project.containers()[0]
|
||||
assert list(container.get('NetworkSettings.Networks')) == [network_name]
|
||||
|
||||
@v2_1_only()
|
||||
def test_up_with_network_labels(self):
|
||||
filename = 'network-label.yml'
|
||||
|
||||
self.base_dir = 'tests/fixtures/networks'
|
||||
self._project = get_project(self.base_dir, [filename])
|
||||
|
||||
self.dispatch(['-f', filename, 'up', '-d'], returncode=0)
|
||||
|
||||
network_with_label = '{}_network_with_label'.format(self.project.name)
|
||||
|
||||
networks = [
|
||||
n for n in self.client.networks()
|
||||
if n['Name'].startswith('{}_'.format(self.project.name))
|
||||
]
|
||||
|
||||
assert [n['Name'] for n in networks] == [network_with_label]
|
||||
|
||||
assert networks[0]['Labels'] == {'label_key': 'label_val'}
|
||||
|
||||
@v2_1_only()
|
||||
def test_up_with_volume_labels(self):
|
||||
filename = 'volume-label.yml'
|
||||
|
||||
self.base_dir = 'tests/fixtures/volumes'
|
||||
self._project = get_project(self.base_dir, [filename])
|
||||
|
||||
self.dispatch(['-f', filename, 'up', '-d'], returncode=0)
|
||||
|
||||
volume_with_label = '{}_volume_with_label'.format(self.project.name)
|
||||
|
||||
volumes = [
|
||||
v for v in self.client.volumes().get('Volumes', [])
|
||||
if v['Name'].startswith('{}_'.format(self.project.name))
|
||||
]
|
||||
|
||||
assert [v['Name'] for v in volumes] == [volume_with_label]
|
||||
|
||||
assert volumes[0]['Labels'] == {'label_key': 'label_val'}
|
||||
|
||||
@v2_only()
|
||||
def test_up_no_services(self):
|
||||
self.base_dir = 'tests/fixtures/no-services'
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
version: "2.1"
|
||||
|
||||
services:
|
||||
web:
|
||||
image: busybox
|
||||
command: top
|
||||
networks:
|
||||
- network_with_label
|
||||
|
||||
networks:
|
||||
network_with_label:
|
||||
labels:
|
||||
- "label_key=label_val"
|
|
@ -0,0 +1,13 @@
|
|||
version: "2.1"
|
||||
|
||||
services:
|
||||
web:
|
||||
image: busybox
|
||||
command: top
|
||||
volumes:
|
||||
- volume_with_label:/data
|
||||
|
||||
volumes:
|
||||
volume_with_label:
|
||||
labels:
|
||||
- "label_key=label_val"
|
|
@ -821,6 +821,42 @@ class ProjectTest(DockerClientTestCase):
|
|||
|
||||
assert network['Internal'] is True
|
||||
|
||||
@v2_1_only()
|
||||
def test_project_up_with_network_label(self):
|
||||
self.require_api_version('1.23')
|
||||
|
||||
network_name = 'network_with_label'
|
||||
|
||||
config_data = config.Config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': 'busybox:latest',
|
||||
'networks': {network_name: None}
|
||||
}],
|
||||
volumes={},
|
||||
networks={
|
||||
network_name: {'labels': {'label_key': 'label_val'}}
|
||||
}
|
||||
)
|
||||
|
||||
project = Project.from_config(
|
||||
client=self.client,
|
||||
name='composetest',
|
||||
config_data=config_data
|
||||
)
|
||||
|
||||
project.up()
|
||||
|
||||
networks = [
|
||||
n for n in self.client.networks()
|
||||
if n['Name'].startswith('composetest_')
|
||||
]
|
||||
|
||||
assert [n['Name'] for n in networks] == ['composetest_{}'.format(network_name)]
|
||||
|
||||
assert networks[0]['Labels'] == {'label_key': 'label_val'}
|
||||
|
||||
@v2_only()
|
||||
def test_project_up_volumes(self):
|
||||
vol_name = '{0:x}'.format(random.getrandbits(32))
|
||||
|
@ -847,6 +883,46 @@ class ProjectTest(DockerClientTestCase):
|
|||
self.assertEqual(volume_data['Name'], full_vol_name)
|
||||
self.assertEqual(volume_data['Driver'], 'local')
|
||||
|
||||
@v2_1_only()
|
||||
def test_project_up_with_volume_labels(self):
|
||||
self.require_api_version('1.23')
|
||||
|
||||
volume_name = 'volume_with_label'
|
||||
|
||||
config_data = config.Config(
|
||||
version=V2_0,
|
||||
services=[{
|
||||
'name': 'web',
|
||||
'image': 'busybox:latest',
|
||||
'volumes': [VolumeSpec.parse('{}:/data'.format(volume_name))]
|
||||
}],
|
||||
volumes={
|
||||
volume_name: {
|
||||
'labels': {
|
||||
'label_key': 'label_val'
|
||||
}
|
||||
}
|
||||
},
|
||||
networks={},
|
||||
)
|
||||
|
||||
project = Project.from_config(
|
||||
client=self.client,
|
||||
name='composetest',
|
||||
config_data=config_data,
|
||||
)
|
||||
|
||||
project.up()
|
||||
|
||||
volumes = [
|
||||
v for v in self.client.volumes().get('Volumes', [])
|
||||
if v['Name'].startswith('composetest_')
|
||||
]
|
||||
|
||||
assert [v['Name'] for v in volumes] == ['composetest_{}'.format(volume_name)]
|
||||
|
||||
assert volumes[0]['Labels'] == {'label_key': 'label_val'}
|
||||
|
||||
@v2_only()
|
||||
def test_project_up_logging_with_multiple_files(self):
|
||||
base_file = config.ConfigFile(
|
||||
|
|
|
@ -376,6 +376,59 @@ class ConfigTest(unittest.TestCase):
|
|||
}
|
||||
}
|
||||
|
||||
def test_load_config_volume_and_network_labels(self):
|
||||
base_file = config.ConfigFile(
|
||||
'base.yaml',
|
||||
{
|
||||
'version': '2.1',
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'example/web',
|
||||
},
|
||||
},
|
||||
'networks': {
|
||||
'with_label': {
|
||||
'labels': {
|
||||
'label_key': 'label_val'
|
||||
}
|
||||
}
|
||||
},
|
||||
'volumes': {
|
||||
'with_label': {
|
||||
'labels': {
|
||||
'label_key': 'label_val'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
details = config.ConfigDetails('.', [base_file])
|
||||
network_dict = config.load(details).networks
|
||||
volume_dict = config.load(details).volumes
|
||||
|
||||
self.assertEqual(
|
||||
network_dict,
|
||||
{
|
||||
'with_label': {
|
||||
'labels': {
|
||||
'label_key': 'label_val'
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
volume_dict,
|
||||
{
|
||||
'with_label': {
|
||||
'labels': {
|
||||
'label_key': 'label_val'
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
def test_load_config_invalid_service_names(self):
|
||||
for invalid_name in ['?not?allowed', ' ', '', '!', '/', '\xe2']:
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
|
|
Loading…
Reference in New Issue