Fix docker connection plugin version tests and py2.6 compat (#16841)
* Rm py2.7+ code in docker connection plugin The docker connection plugin was using subprocess.check_output which only exists in python 2.7 and later. Connection plugins need to support python2.6 so this replaces it with Popen/communicate() * Handle docker ver errors in docker connection Add unit tests for DockerConnection Fixes #16971
This commit is contained in:
parent
7ce4165671
commit
a4785c2691
2 changed files with 55 additions and 19 deletions
|
@ -104,28 +104,43 @@ class Connection(ConnectionBase):
|
||||||
def _sanitize_version(version):
|
def _sanitize_version(version):
|
||||||
return re.sub('[^0-9a-zA-Z\.]', '', version)
|
return re.sub('[^0-9a-zA-Z\.]', '', version)
|
||||||
|
|
||||||
|
def _old_docker_version(self):
|
||||||
|
cmd_args = []
|
||||||
|
if self._play_context.docker_extra_args:
|
||||||
|
cmd_args += self._play_context.docker_extra_args.split(' ')
|
||||||
|
|
||||||
|
old_version_subcommand = ['version']
|
||||||
|
|
||||||
|
old_docker_cmd = [self.docker_cmd] + cmd_args + old_version_subcommand
|
||||||
|
p = subprocess.Popen(old_docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
cmd_output, err = p.communicate()
|
||||||
|
|
||||||
|
return old_docker_cmd, cmd_output, err, p.returncode
|
||||||
|
|
||||||
|
def _new_docker_version(self):
|
||||||
|
# no result yet, must be newer Docker version
|
||||||
|
cmd_args = []
|
||||||
|
if self._play_context.docker_extra_args:
|
||||||
|
cmd_args += self._play_context.docker_extra_args.split(' ')
|
||||||
|
|
||||||
|
new_version_subcommand = ['version', '--format', "'{{.Server.Version}}'"]
|
||||||
|
|
||||||
|
new_docker_cmd = [self.docker_cmd] + cmd_args + new_version_subcommand
|
||||||
|
p = subprocess.Popen(new_docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
cmd_output, err = p.communicate()
|
||||||
|
return new_docker_cmd, cmd_output, err, p.returncode
|
||||||
|
|
||||||
def _get_docker_version(self):
|
def _get_docker_version(self):
|
||||||
|
|
||||||
cmd = [self.docker_cmd]
|
cmd, cmd_output, err, returncode = self._old_docker_version()
|
||||||
|
if returncode == 0:
|
||||||
|
for line in cmd_output.split('\n'):
|
||||||
|
if line.startswith('Server version:'): # old docker versions
|
||||||
|
return self._sanitize_version(line.split()[2])
|
||||||
|
|
||||||
if self._play_context.docker_extra_args:
|
cmd, cmd_output, err, returncode = self._new_docker_version()
|
||||||
cmd += self._play_context.docker_extra_args.split(' ')
|
if returncode:
|
||||||
|
raise AnsibleError('Docker version check (%s) failed: %s' % (cmd, err))
|
||||||
cmd += ['version']
|
|
||||||
|
|
||||||
cmd_output = subprocess.check_output(cmd)
|
|
||||||
|
|
||||||
for line in cmd_output.split('\n'):
|
|
||||||
if line.startswith('Server version:'): # old docker versions
|
|
||||||
return self._sanitize_version(line.split()[2])
|
|
||||||
|
|
||||||
# no result yet, must be newer Docker version
|
|
||||||
new_docker_cmd = [
|
|
||||||
self.docker_cmd,
|
|
||||||
'version', '--format', "'{{.Server.Version}}'"
|
|
||||||
]
|
|
||||||
|
|
||||||
cmd_output = subprocess.check_output(new_docker_cmd)
|
|
||||||
|
|
||||||
return self._sanitize_version(cmd_output)
|
return self._sanitize_version(cmd_output)
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,10 @@ __metaclass__ = type
|
||||||
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
from ansible.compat.tests import unittest
|
from ansible.compat.tests import unittest
|
||||||
|
from ansible.errors import AnsibleError
|
||||||
from ansible.playbook.play_context import PlayContext
|
from ansible.playbook.play_context import PlayContext
|
||||||
|
|
||||||
from ansible.plugins.connection import ConnectionBase
|
from ansible.plugins.connection import ConnectionBase
|
||||||
|
@ -34,8 +37,10 @@ from ansible.plugins.connection.lxc import Connection as LxcConnection
|
||||||
from ansible.plugins.connection.local import Connection as LocalConnection
|
from ansible.plugins.connection.local import Connection as LocalConnection
|
||||||
from ansible.plugins.connection.paramiko_ssh import Connection as ParamikoConnection
|
from ansible.plugins.connection.paramiko_ssh import Connection as ParamikoConnection
|
||||||
from ansible.plugins.connection.ssh import Connection as SSHConnection
|
from ansible.plugins.connection.ssh import Connection as SSHConnection
|
||||||
|
from ansible.plugins.connection.docker import Connection as DockerConnection
|
||||||
#from ansible.plugins.connection.winrm import Connection as WinRmConnection
|
#from ansible.plugins.connection.winrm import Connection as WinRmConnection
|
||||||
|
|
||||||
|
|
||||||
class TestConnectionBaseClass(unittest.TestCase):
|
class TestConnectionBaseClass(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -102,5 +107,21 @@ class TestConnectionBaseClass(unittest.TestCase):
|
||||||
def test_ssh_connection_module(self):
|
def test_ssh_connection_module(self):
|
||||||
self.assertIsInstance(SSHConnection(self.play_context, self.in_stream), SSHConnection)
|
self.assertIsInstance(SSHConnection(self.play_context, self.in_stream), SSHConnection)
|
||||||
|
|
||||||
|
@mock.patch('ansible.plugins.connection.docker.Connection._old_docker_version', return_value=('false', 'garbage', '', 1))
|
||||||
|
@mock.patch('ansible.plugins.connection.docker.Connection._new_docker_version', return_value=('docker version', '1.2.3', '', 0))
|
||||||
|
def test_docker_connection_module_too_old(self, mock_new_docker_verison, mock_old_docker_version):
|
||||||
|
self.assertRaises(AnsibleError, DockerConnection, self.play_context, self.in_stream)
|
||||||
|
|
||||||
|
@mock.patch('ansible.plugins.connection.docker.Connection._old_docker_version', return_value=('false', 'garbage', '', 1))
|
||||||
|
@mock.patch('ansible.plugins.connection.docker.Connection._new_docker_version', return_value=('docker version', '1.3.4', '', 0))
|
||||||
|
def test_docker_connection_module(self, mock_new_docker_verison, mock_old_docker_version):
|
||||||
|
self.assertIsInstance(DockerConnection(self.play_context, self.in_stream), DockerConnection)
|
||||||
|
|
||||||
|
# old version and new version fail
|
||||||
|
@mock.patch('ansible.plugins.connection.docker.Connection._old_docker_version', return_value=('false', 'garbage', '', 1))
|
||||||
|
@mock.patch('ansible.plugins.connection.docker.Connection._new_docker_version', return_value=('false', 'garbage', '', 1))
|
||||||
|
def test_docker_connection_module_wrong_cmd(self, mock_new_docker_version, mock_old_docker_version):
|
||||||
|
self.assertRaises(AnsibleError, DockerConnection, self.play_context, self.in_stream)
|
||||||
|
|
||||||
# def test_winrm_connection_module(self):
|
# def test_winrm_connection_module(self):
|
||||||
# self.assertIsInstance(WinRmConnection(), WinRmConnection)
|
# self.assertIsInstance(WinRmConnection(), WinRmConnection)
|
||||||
|
|
Loading…
Reference in a new issue