Merge "Check if volume paths exist before executing Docker." into stable/queens

This commit is contained in:
Zuul 2019-08-13 14:59:27 +00:00 committed by Gerrit Code Review
commit 5004a33433
3 changed files with 81 additions and 5 deletions

View File

@ -126,8 +126,8 @@ def debug(config_id, container_name, action, config, managed_by, labels=None,
'--name',
r.unique_container_name(container_name)
]
builder.docker_run_args(cmd, container_name)
return r.execute_interactive(cmd)
if builder.docker_run_args(cmd, container_name):
return r.execute_interactive(cmd)
elif action == 'dump-yaml':
print(yaml.safe_dump(config, default_flow_style=False))
elif action == 'dump-json':

View File

@ -13,6 +13,7 @@
import json
import logging
import os
import tenacity
import yaml
@ -60,10 +61,15 @@ class ComposeV1Builder(object):
self.runner.unique_container_name(container)
]
self.label_arguments(cmd, container)
self.docker_run_args(cmd, container)
validations_passed = self.docker_run_args(cmd, container)
elif action == 'exec':
cmd = [self.runner.docker_cmd, 'exec']
self.docker_exec_args(cmd, container)
validations_passed = self.docker_exec_args(cmd, container)
if not validations_passed:
LOG.debug('Validations failed. Skipping container: %s' %
container)
continue
(cmd_stdout, cmd_stderr, returncode) = self.runner.execute(cmd)
if cmd_stdout:
@ -132,6 +138,12 @@ class ComposeV1Builder(object):
])
def docker_run_args(self, cmd, container):
"""Prepare the run command args, from the container configuration.
:param cmd: The list of command options to be modified
:param container: A dict with container configurations
:returns: True if configuration is valid, otherwise False
"""
cconfig = self.config[container]
if cconfig.get('detach', True):
cmd.append('--detach=true')
@ -192,7 +204,29 @@ class ComposeV1Builder(object):
cmd.append(cconfig.get('image', ''))
cmd.extend(self.command_argument(cconfig.get('command')))
# NOTE(xek): If the file to be mounted doesn't exist, Docker version
# 1.13.1 creates a directory in it's place. This behavior is different
# then Podman, which throws an error. We want to replicate the Podman
# behavior. Creating directories in place of files creates errors which
# are very difficult to diagnose.
for volume in cconfig.get('volumes', []):
host_path = volume.split(':', 1)[0]
if host_path and not os.path.exists(host_path):
LOG.error("Error running %s.\n" % cmd)
LOG.error('stderr: Error: error checking path "%s":'
' stat %s: no such file or directory\n' % (
host_path, host_path))
return False
return True
def docker_exec_args(self, cmd, container):
"""Prepare the exec command args, from the container configuration.
:param cmd: The list of command options to be modified
:param container: A dict with container configurations
:returns: True if configuration is valid, otherwise False
"""
cconfig = self.config[container]
if 'privileged' in cconfig:
cmd.append('--privileged=%s' % str(cconfig['privileged']).lower())
@ -206,6 +240,8 @@ class ComposeV1Builder(object):
command[0], self.config_id)
cmd.extend(command)
return True
def pull_missing_images(self, stdout, stderr):
images = set()
for container in self.config:

View File

@ -450,7 +450,47 @@ three-12345678 three''', '', 0),
cmd
)
def test_docker_run_args_lists(self):
@mock.patch('os.path.exists')
def test_docker_run_args_validation_true(self, path_exists):
path_exists.return_value = True
config = {
'one': {
'image': 'foo',
'volumes': ['/foo:/foo:rw', '/bar:/bar:ro'],
}
}
builder = compose1.ComposeV1Builder('foo', config, None)
cmd = ['docker']
self.assertTrue(builder.docker_run_args(cmd, 'one'))
self.assertEqual(
['docker', '--detach=true',
'--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', 'foo'],
cmd
)
@mock.patch('os.path.exists')
def test_docker_run_args_validation_false(self, path_exists):
path_exists.return_value = False
config = {
'one': {
'image': 'foo',
'volumes': ['/foo:/foo:rw', '/bar:/bar:ro'],
}
}
builder = compose1.ComposeV1Builder('foo', config, None)
cmd = ['docker']
self.assertFalse(builder.docker_run_args(cmd, 'one'))
self.assertEqual(
['docker', '--detach=true',
'--volume=/foo:/foo:rw', '--volume=/bar:/bar:ro', 'foo'],
cmd
)
@mock.patch('os.path.exists')
def test_docker_run_args_lists(self, path_exists):
path_exists.return_value = True
config = {
'one': {
'image': 'centos:7',