Fixed binds and volumes. Now recognizes bound vs unbound as well as named volumes.
This commit is contained in:
parent
abbddbde49
commit
9dd95efe76
1 changed files with 99 additions and 42 deletions
|
@ -626,6 +626,8 @@ ansible_docker_container:
|
|||
}'
|
||||
'''
|
||||
|
||||
import re
|
||||
|
||||
from ansible.module_utils.docker_common import *
|
||||
|
||||
try:
|
||||
|
@ -643,6 +645,7 @@ REQUIRES_CONVERSION_TO_BYTES = [
|
|||
'shm_size'
|
||||
]
|
||||
|
||||
VOLUME_PERMISSIONS = ('rw', 'ro', 'z', 'Z')
|
||||
|
||||
class TaskParameters(DockerBaseClass):
|
||||
'''
|
||||
|
@ -739,14 +742,16 @@ class TaskParameters(DockerBaseClass):
|
|||
if self.volumes:
|
||||
self.volumes = self._expand_host_paths()
|
||||
|
||||
self.log("volumes:")
|
||||
self.log(self.volumes, pretty_print=True)
|
||||
|
||||
self.env = self._get_environment()
|
||||
self.ulimits = self._parse_ulimits()
|
||||
self.log_config = self._parse_log_config()
|
||||
self.exp_links = None
|
||||
self._parse_volumes()
|
||||
self.volume_binds = self._get_volume_binds(self.volumes)
|
||||
|
||||
self.log("volumes:")
|
||||
self.log(self.volumes, pretty_print=True)
|
||||
self.log("volume binds:")
|
||||
self.log(self.volume_binds, pretty_print=True)
|
||||
|
||||
if self.networks:
|
||||
for network in self.networks:
|
||||
|
@ -824,24 +829,37 @@ class TaskParameters(DockerBaseClass):
|
|||
if ':' in vol:
|
||||
if len(vol.split(':')) == 3:
|
||||
host, container, mode = vol.split(':')
|
||||
if re.match(r'[\.~]', host):
|
||||
host = os.path.abspath(host)
|
||||
new_vols.append("%s:%s:%s" % (host, container, mode))
|
||||
else:
|
||||
host, container = vol.split(':')
|
||||
host = os.path.abspath(host)
|
||||
new_vols.append("%s:%s:rw" % (host, container))
|
||||
else:
|
||||
continue
|
||||
elif len(vol.split(':')) == 2:
|
||||
parts = vol.split(':')
|
||||
if parts[1] not in VOLUME_PERMISSIONS and re.match(r'[\.~]', parts[0]):
|
||||
host = os.path.abspath(parts[0])
|
||||
new_vols.append("%s:%s:rw" % (host, parts[1]))
|
||||
continue
|
||||
new_vols.append(vol)
|
||||
return new_vols
|
||||
|
||||
def _get_mounts(self):
|
||||
'''
|
||||
Return a list of container mounts.
|
||||
:return:
|
||||
'''
|
||||
result = []
|
||||
if self.volumes:
|
||||
for vol in self.volumes:
|
||||
if ':' in vol:
|
||||
if len(vol.split(':')) == 3:
|
||||
host, container, _ = vol.split(':')
|
||||
result.append(host)
|
||||
else:
|
||||
result.append(container)
|
||||
continue
|
||||
if len(vol.split(':')) == 2:
|
||||
parts = vol.split(':')
|
||||
if parts[1] not in VOLUME_PERMISSIONS:
|
||||
result.append(parts[1])
|
||||
continue
|
||||
result.append(vol)
|
||||
self.log("mounts:")
|
||||
self.log(result, pretty_print=True)
|
||||
|
@ -923,24 +941,30 @@ class TaskParameters(DockerBaseClass):
|
|||
binds[container_port] = bind
|
||||
return binds
|
||||
|
||||
def _parse_volumes(self):
|
||||
@staticmethod
|
||||
def _get_volume_binds(volumes):
|
||||
'''
|
||||
Convert volumes parameter to host_config bind format.
|
||||
https://docker-py.readthedocs.org/en/latest/volumes/
|
||||
:return: array of binds
|
||||
Extract host bindings, if any, from list of volume mapping strings.
|
||||
|
||||
:return: dictionary of bind mappings
|
||||
'''
|
||||
if self.volumes:
|
||||
for vol in self.volumes:
|
||||
result = dict()
|
||||
if volumes:
|
||||
for vol in volumes:
|
||||
host = None
|
||||
if ':' in vol:
|
||||
if len(vol.split(':')) == 3:
|
||||
host, container, mode = vol.split(':')
|
||||
else:
|
||||
if len(vol.split(':')) == 2:
|
||||
parts = vol.split(':')
|
||||
if parts[1] not in VOLUME_PERMISSIONS:
|
||||
host, container, mode = (vol.split(':') + ['rw'])
|
||||
self.volume_binds[host] = dict(
|
||||
if host is not None:
|
||||
result[host] = dict(
|
||||
bind=container,
|
||||
mode=mode
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
def _parse_exposed_ports(self):
|
||||
'''
|
||||
|
@ -1091,6 +1115,7 @@ class Container(DockerBaseClass):
|
|||
self.parameters.expected_ports = self._get_expected_ports()
|
||||
self.parameters.expected_exposed = self._get_expected_exposed(image)
|
||||
self.parameters.expected_volumes = self._get_expected_volumes(image)
|
||||
self.parameters.expected_binds = self._get_expected_binds(image)
|
||||
self.parameters.expected_ulimits = self._get_expected_ulimits(self.parameters.ulimits)
|
||||
self.parameters.expected_etc_hosts = self._convert_simple_dict_to_list('etc_hosts')
|
||||
self.parameters.expected_env = self._get_expected_env(image)
|
||||
|
@ -1154,7 +1179,8 @@ class Container(DockerBaseClass):
|
|||
tty=config.get('Tty'),
|
||||
expected_ulimits=host_config.get('Ulimits'),
|
||||
uts=host_config.get('UTSMode'),
|
||||
expected_volumes=host_config['Binds'],
|
||||
expected_volumes=config.get('Volumes'),
|
||||
expected_binds=host_config.get('Binds'),
|
||||
volumes_from=host_config.get('VolumesFrom'),
|
||||
volume_driver=host_config.get('VolumeDriver')
|
||||
)
|
||||
|
@ -1382,26 +1408,30 @@ class Container(DockerBaseClass):
|
|||
exp_links.append("/%s:%s/%s" % (link, ('/' + self.parameters.name), alias))
|
||||
return exp_links
|
||||
|
||||
def _get_expected_volumes(self, image):
|
||||
self.log('_get_expected_volumes')
|
||||
def _get_expected_binds(self, image):
|
||||
self.log('_get_expected_binds')
|
||||
image_vols = []
|
||||
if image:
|
||||
image_vols = self._get_volumes_from_binds(image['ContainerConfig'].get('Volumes'))
|
||||
image_vols = self._get_image_binds(image['ContainerConfig'].get('Volumes'))
|
||||
param_vols = []
|
||||
if self.parameters.volumes:
|
||||
for vol in self.parameters.volumes:
|
||||
host = None
|
||||
if ':' in vol:
|
||||
if len(vol.split(':')) == 3:
|
||||
host, container, mode = vol.split(':')
|
||||
else:
|
||||
if len(vol.split(':')) == 2:
|
||||
parts = vol.split(':')
|
||||
if parts[1] not in VOLUME_PERMISSIONS:
|
||||
host, container, mode = vol.split(':') + ['rw']
|
||||
if host:
|
||||
param_vols.append("%s:%s:%s" % (host, container, mode))
|
||||
else:
|
||||
param_vols.append(vol)
|
||||
# flip to container first
|
||||
return list(set(image_vols + param_vols))
|
||||
result = list(set(image_vols + param_vols))
|
||||
self.log("expected_binds:")
|
||||
self.log(result, pretty_print=True)
|
||||
return result
|
||||
|
||||
def _get_volumes_from_binds(self, volumes):
|
||||
def _get_image_binds(self, volumes):
|
||||
'''
|
||||
Convert array of binds to array of strings with format host_path:container_path:mode
|
||||
|
||||
|
@ -1410,13 +1440,14 @@ class Container(DockerBaseClass):
|
|||
'''
|
||||
results = []
|
||||
if isinstance(volumes, dict):
|
||||
results += self._get_volume_from_dict(volumes)
|
||||
results += self._get_bind_from_dict(volumes)
|
||||
elif isinstance(volumes, list):
|
||||
for vol in volumes:
|
||||
results += self._get_volume_from_dict(vol)
|
||||
results += self._get_bind_from_dict(vol)
|
||||
return results
|
||||
|
||||
def _get_volume_from_dict(self, volume_dict):
|
||||
@staticmethod
|
||||
def _get_bind_from_dict(volume_dict):
|
||||
results = []
|
||||
if volume_dict:
|
||||
for host_path, config in volume_dict.items():
|
||||
|
@ -1426,6 +1457,32 @@ class Container(DockerBaseClass):
|
|||
results.append("%s:%s:%s" % (host_path, container_path, mode))
|
||||
return results
|
||||
|
||||
def _get_expected_volumes(self, image):
|
||||
self.log('_get_expected_volumes')
|
||||
expected_vols = dict()
|
||||
if image and image['ContainerConfig'].get('Volumes'):
|
||||
expected_vols.upate(image['ContainerConfig'].get('Volumes'))
|
||||
|
||||
if self.parameters.volumes:
|
||||
for vol in self.parameters.volumes:
|
||||
container = None
|
||||
if ':' in vol:
|
||||
if len(vol.split(':')) == 3:
|
||||
host, container, mode = vol.split(':')
|
||||
if len(vol.split(':')) == 2:
|
||||
parts = vol.split(':')
|
||||
if parts[1] not in VOLUME_PERMISSIONS:
|
||||
host, container, mode = vol.split(':') + ['rw']
|
||||
new_vol = dict()
|
||||
if container:
|
||||
new_vol[container] = dict()
|
||||
else:
|
||||
new_vol[vol] = dict()
|
||||
expected_vols.update(new_vol)
|
||||
self.log("expected_volumes:")
|
||||
self.log(expected_vols, pretty_print=True)
|
||||
return expected_vols
|
||||
|
||||
def _get_expected_env(self, image):
|
||||
self.log('_get_expected_env')
|
||||
expected_env = dict()
|
||||
|
@ -1535,7 +1592,7 @@ class ContainerManager(DockerBaseClass):
|
|||
if state == 'started':
|
||||
container = self.container_start(container.Id)
|
||||
self.facts = container.raw
|
||||
return True
|
||||
return
|
||||
|
||||
# Existing container
|
||||
self.log(container.raw, pretty_print=True)
|
||||
|
|
Loading…
Reference in a new issue