docker_container: allow more mount modes for volumes (#46598)
* Being more strict about volume mount modes.
This commit is contained in:
parent
513be8923d
commit
77127d6768
3 changed files with 43 additions and 12 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- "docker_container - mount modes in ``volumes`` allow more values, similar to when using the ``docker`` executable."
|
|
@ -435,9 +435,13 @@ options:
|
||||||
description:
|
description:
|
||||||
- List of volumes to mount within the container.
|
- List of volumes to mount within the container.
|
||||||
- "Use docker CLI-style syntax: C(/host:/container[:mode])"
|
- "Use docker CLI-style syntax: C(/host:/container[:mode])"
|
||||||
- You can specify a read mode for the mount with either C(ro) or C(rw).
|
- "Mount modes can be a comma-separated list of various modes such as C(ro), C(rw), C(consistent),
|
||||||
|
C(delegated), C(cached), C(rprivate), C(private), C(rshared), C(shared), C(rslave), C(slave).
|
||||||
|
Note that docker might not support all modes and combinations of such modes."
|
||||||
- SELinux hosts can additionally use C(z) or C(Z) to use a shared or
|
- SELinux hosts can additionally use C(z) or C(Z) to use a shared or
|
||||||
private label for the volume.
|
private label for the volume.
|
||||||
|
- "Note that Ansible 2.7 and earlier only supported one mode, which had to be one of C(ro), C(rw),
|
||||||
|
C(z), and C(Z)."
|
||||||
volume_driver:
|
volume_driver:
|
||||||
description:
|
description:
|
||||||
- The container volume driver.
|
- The container volume driver.
|
||||||
|
@ -724,7 +728,12 @@ REQUIRES_CONVERSION_TO_BYTES = [
|
||||||
'shm_size'
|
'shm_size'
|
||||||
]
|
]
|
||||||
|
|
||||||
VOLUME_PERMISSIONS = ('rw', 'ro', 'z', 'Z')
|
|
||||||
|
def is_volume_permissions(input):
|
||||||
|
for part in input.split(','):
|
||||||
|
if part not in ('rw', 'ro', 'z', 'Z', 'consistent', 'delegated', 'cached', 'rprivate', 'private', 'rshared', 'shared', 'rslave', 'slave'):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class TaskParameters(DockerBaseClass):
|
class TaskParameters(DockerBaseClass):
|
||||||
|
@ -964,13 +973,15 @@ class TaskParameters(DockerBaseClass):
|
||||||
if ':' in vol:
|
if ':' in vol:
|
||||||
if len(vol.split(':')) == 3:
|
if len(vol.split(':')) == 3:
|
||||||
host, container, mode = vol.split(':')
|
host, container, mode = vol.split(':')
|
||||||
|
if not is_volume_permissions(mode):
|
||||||
|
self.fail('Found invalid volumes mode: {0}'.format(mode))
|
||||||
if re.match(r'[.~]', host):
|
if re.match(r'[.~]', host):
|
||||||
host = os.path.abspath(os.path.expanduser(host))
|
host = os.path.abspath(os.path.expanduser(host))
|
||||||
new_vols.append("%s:%s:%s" % (host, container, mode))
|
new_vols.append("%s:%s:%s" % (host, container, mode))
|
||||||
continue
|
continue
|
||||||
elif len(vol.split(':')) == 2:
|
elif len(vol.split(':')) == 2:
|
||||||
parts = vol.split(':')
|
parts = vol.split(':')
|
||||||
if parts[1] not in VOLUME_PERMISSIONS and re.match(r'[.~]', parts[0]):
|
if not is_volume_permissions(parts[1]) and re.match(r'[.~]', parts[0]):
|
||||||
host = os.path.abspath(os.path.expanduser(parts[0]))
|
host = os.path.abspath(os.path.expanduser(parts[0]))
|
||||||
new_vols.append("%s:%s:rw" % (host, parts[1]))
|
new_vols.append("%s:%s:rw" % (host, parts[1]))
|
||||||
continue
|
continue
|
||||||
|
@ -992,7 +1003,7 @@ class TaskParameters(DockerBaseClass):
|
||||||
continue
|
continue
|
||||||
if len(vol.split(':')) == 2:
|
if len(vol.split(':')) == 2:
|
||||||
parts = vol.split(':')
|
parts = vol.split(':')
|
||||||
if parts[1] not in VOLUME_PERMISSIONS:
|
if not is_volume_permissions(parts[1]):
|
||||||
result.append(parts[1])
|
result.append(parts[1])
|
||||||
continue
|
continue
|
||||||
result.append(vol)
|
result.append(vol)
|
||||||
|
@ -1119,8 +1130,7 @@ class TaskParameters(DockerBaseClass):
|
||||||
binds[container_port] = bind
|
binds[container_port] = bind
|
||||||
return binds
|
return binds
|
||||||
|
|
||||||
@staticmethod
|
def _get_volume_binds(self, volumes):
|
||||||
def _get_volume_binds(volumes):
|
|
||||||
'''
|
'''
|
||||||
Extract host bindings, if any, from list of volume mapping strings.
|
Extract host bindings, if any, from list of volume mapping strings.
|
||||||
|
|
||||||
|
@ -1133,9 +1143,11 @@ class TaskParameters(DockerBaseClass):
|
||||||
if ':' in vol:
|
if ':' in vol:
|
||||||
if len(vol.split(':')) == 3:
|
if len(vol.split(':')) == 3:
|
||||||
host, container, mode = vol.split(':')
|
host, container, mode = vol.split(':')
|
||||||
|
if not is_volume_permissions(mode):
|
||||||
|
self.fail('Found invalid volumes mode: {0}'.format(mode))
|
||||||
if len(vol.split(':')) == 2:
|
if len(vol.split(':')) == 2:
|
||||||
parts = vol.split(':')
|
parts = vol.split(':')
|
||||||
if parts[1] not in VOLUME_PERMISSIONS:
|
if not is_volume_permissions(parts[1]):
|
||||||
host, container, mode = (vol.split(':') + ['rw'])
|
host, container, mode = (vol.split(':') + ['rw'])
|
||||||
if host is not None:
|
if host is not None:
|
||||||
result[host] = dict(
|
result[host] = dict(
|
||||||
|
@ -1747,9 +1759,11 @@ class Container(DockerBaseClass):
|
||||||
if ':' in vol:
|
if ':' in vol:
|
||||||
if len(vol.split(':')) == 3:
|
if len(vol.split(':')) == 3:
|
||||||
host, container, mode = vol.split(':')
|
host, container, mode = vol.split(':')
|
||||||
|
if not is_volume_permissions(mode):
|
||||||
|
self.fail('Found invalid volumes mode: {0}'.format(mode))
|
||||||
if len(vol.split(':')) == 2:
|
if len(vol.split(':')) == 2:
|
||||||
parts = vol.split(':')
|
parts = vol.split(':')
|
||||||
if parts[1] not in VOLUME_PERMISSIONS:
|
if not is_volume_permissions(parts[1]):
|
||||||
host, container, mode = vol.split(':') + ['rw']
|
host, container, mode = vol.split(':') + ['rw']
|
||||||
if host:
|
if host:
|
||||||
param_vols.append("%s:%s:%s" % (host, container, mode))
|
param_vols.append("%s:%s:%s" % (host, container, mode))
|
||||||
|
@ -1796,9 +1810,11 @@ class Container(DockerBaseClass):
|
||||||
if ':' in vol:
|
if ':' in vol:
|
||||||
if len(vol.split(':')) == 3:
|
if len(vol.split(':')) == 3:
|
||||||
host, container, mode = vol.split(':')
|
host, container, mode = vol.split(':')
|
||||||
|
if not is_volume_permissions(mode):
|
||||||
|
self.fail('Found invalid volumes mode: {0}'.format(mode))
|
||||||
if len(vol.split(':')) == 2:
|
if len(vol.split(':')) == 2:
|
||||||
parts = vol.split(':')
|
parts = vol.split(':')
|
||||||
if parts[1] not in VOLUME_PERMISSIONS:
|
if not is_volume_permissions(parts[1]):
|
||||||
host, container, mode = vol.split(':') + ['rw']
|
host, container, mode = vol.split(':') + ['rw']
|
||||||
new_vol = dict()
|
new_vol = dict()
|
||||||
if container:
|
if container:
|
||||||
|
|
|
@ -3109,7 +3109,7 @@
|
||||||
state: started
|
state: started
|
||||||
volumes:
|
volumes:
|
||||||
- "/tmp:/tmp"
|
- "/tmp:/tmp"
|
||||||
- "/:/whatever"
|
- "/:/whatever:rw,z"
|
||||||
register: volumes_1
|
register: volumes_1
|
||||||
|
|
||||||
- name: volumes (idempotency)
|
- name: volumes (idempotency)
|
||||||
|
@ -3119,7 +3119,7 @@
|
||||||
name: "{{ cname }}"
|
name: "{{ cname }}"
|
||||||
state: started
|
state: started
|
||||||
volumes:
|
volumes:
|
||||||
- "/:/whatever"
|
- "/:/whatever:rw,z"
|
||||||
- "/tmp:/tmp"
|
- "/tmp:/tmp"
|
||||||
register: volumes_2
|
register: volumes_2
|
||||||
|
|
||||||
|
@ -3141,10 +3141,22 @@
|
||||||
state: started
|
state: started
|
||||||
volumes:
|
volumes:
|
||||||
- "/tmp:/tmp"
|
- "/tmp:/tmp"
|
||||||
- "/tmp:/somewhereelse:ro"
|
- "/tmp:/somewhereelse:ro,Z"
|
||||||
stop_timeout: 1
|
stop_timeout: 1
|
||||||
register: volumes_4
|
register: volumes_4
|
||||||
|
|
||||||
|
- name: volumes (different modes)
|
||||||
|
docker_container:
|
||||||
|
image: alpine:3.8
|
||||||
|
command: '/bin/sh -c "sleep 10m"'
|
||||||
|
name: "{{ cname }}"
|
||||||
|
state: started
|
||||||
|
volumes:
|
||||||
|
- "/tmp:/tmp"
|
||||||
|
- "/tmp:/somewhereelse:ro"
|
||||||
|
stop_timeout: 1
|
||||||
|
register: volumes_5
|
||||||
|
|
||||||
- name: cleanup
|
- name: cleanup
|
||||||
docker_container:
|
docker_container:
|
||||||
name: "{{ cname }}"
|
name: "{{ cname }}"
|
||||||
|
@ -3157,6 +3169,7 @@
|
||||||
- volumes_2 is not changed
|
- volumes_2 is not changed
|
||||||
- volumes_3 is not changed
|
- volumes_3 is not changed
|
||||||
- volumes_4 is changed
|
- volumes_4 is changed
|
||||||
|
- volumes_5 is changed
|
||||||
|
|
||||||
####################################################################
|
####################################################################
|
||||||
## volumes_from ####################################################
|
## volumes_from ####################################################
|
||||||
|
|
Loading…
Reference in a new issue