summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2020-05-08 17:32:04 +0000
committerGerrit Code Review <review@openstack.org>2020-05-08 17:32:04 +0000
commit0522f1bda6888880367f2c5fa716b7cc199df8cb (patch)
tree9fa6abfb49b4c7c932ab27a930f39fa8332778f8
parent0971847a50c317233733ab6dd921ae3b36f7793e (diff)
parentf9a1e1a9585dfd8b3f8136c8ccbfd154915b5b59 (diff)
downloadzuul-0522f1bda6888880367f2c5fa716b7cc199df8cb.tar.gz
Merge "Validate ansible extra packages"
-rw-r--r--tests/unit/test_executor.py24
-rw-r--r--tests/unit/test_lib_ansible.py33
-rw-r--r--zuul/lib/ansible.py61
3 files changed, 87 insertions, 31 deletions
diff --git a/tests/unit/test_executor.py b/tests/unit/test_executor.py
index ef28ad654..c0fbc5546 100644
--- a/tests/unit/test_executor.py
+++ b/tests/unit/test_executor.py
@@ -842,3 +842,27 @@ class TestExecutorStart(ZuulTestCase):
def test_executor_start(self):
self.assertFalse(os.path.exists(self.junk_dir))
+
+
+class TestExecutorExtraPackages(AnsibleZuulTestCase):
+ tenant_config_file = 'config/single-tenant/main.yaml'
+
+ test_package = 'pywinrm'
+
+ def setUp(self):
+ super(TestExecutorExtraPackages, self).setUp()
+ import subprocess
+ ansible_manager = self.executor_server.ansible_manager
+ for version in ansible_manager._supported_versions:
+ command = [ansible_manager.getAnsibleCommand(version, 'pip'),
+ 'uninstall', '-y', self.test_package]
+ subprocess.run(command)
+
+ @mock.patch('zuul.lib.ansible.ManagedAnsible.extra_packages',
+ new_callable=mock.PropertyMock)
+ def test_extra_packages(self, mock_extra_packages):
+ mock_extra_packages.return_value = [self.test_package]
+ ansible_manager = self.executor_server.ansible_manager
+ self.assertFalse(ansible_manager.validate())
+ ansible_manager.install()
+ self.assertTrue(ansible_manager.validate())
diff --git a/tests/unit/test_lib_ansible.py b/tests/unit/test_lib_ansible.py
index 2d35f0658..808719521 100644
--- a/tests/unit/test_lib_ansible.py
+++ b/tests/unit/test_lib_ansible.py
@@ -13,7 +13,6 @@
# under the License.
import collections
-import subprocess
from unittest import mock
from tests.base import BaseTestCase
@@ -23,8 +22,11 @@ from zuul.lib.ansible import AnsibleManager
class TestLibAnsibleManager(BaseTestCase):
@mock.patch('zuul.lib.ansible.AnsibleManager.load_ansible_config')
- @mock.patch('zuul.lib.ansible.AnsibleManager.getAnsibleCommand')
- def test_validate_remembers_failures(self, getAnsibleCommand, _):
+ @mock.patch('zuul.lib.ansible.AnsibleManager._validate_packages')
+ @mock.patch('zuul.lib.ansible.AnsibleManager._validate_ansible')
+ def test_validate_remembers_failures(self,
+ mock_validate_ansible,
+ mock_validate_packages, _):
okish = mock.Mock(
'subprocess.CompletedProcess',
@@ -33,17 +35,22 @@ class TestLibAnsibleManager(BaseTestCase):
am = AnsibleManager()
am._supported_versions = collections.OrderedDict([
- ('1.0', subprocess.CalledProcessError(1, 'fake failure')),
- ('2.8', okish),
+ ('1.0', False),
+ ('2.8', True),
])
- with mock.patch('subprocess.run') as ansible:
- ansible.side_effect = am._supported_versions.values()
- self.assertFalse(
- am.validate(),
- 'A valid ansible should not mask a previous failure')
+ mock_validate_packages.side_effect = am._supported_versions.values()
+ mock_validate_ansible.side_effect = am._supported_versions.values()
+ self.assertFalse(
+ am.validate(),
+ 'A valid ansible should not mask a previous failure')
+
self.assertEquals(
- [mock.call('1.0', 'ansible'),
- mock.call('2.8', 'ansible'),
+ [mock.call('1.0'),
+ mock.call('2.8')
],
- getAnsibleCommand.mock_calls)
+ mock_validate_ansible.mock_calls)
+
+ self.assertEquals(
+ [mock.call('2.8')],
+ mock_validate_packages.mock_calls)
diff --git a/zuul/lib/ansible.py b/zuul/lib/ansible.py
index f5eb7e0e8..df0ed0213 100644
--- a/zuul/lib/ansible.py
+++ b/zuul/lib/ansible.py
@@ -202,29 +202,54 @@ class AnsibleManager:
for future in concurrent.futures.as_completed(futures):
future.result()
+ def _validate_ansible(self, version):
+ result = True
+ try:
+ command = [
+ self.getAnsibleCommand(version, 'ansible'),
+ '--version',
+ ]
+
+ ret = subprocess.run(command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ check=True)
+ self.log.info('Ansible version %s information: \n%s',
+ version, ret.stdout.decode())
+ except subprocess.CalledProcessError:
+ result = False
+ self.log.exception("Ansible version %s not working" % version)
+ except Exception:
+ result = False
+ self.log.exception(
+ 'Ansible version %s not installed' % version)
+ return result
+
+ def _validate_packages(self, version):
+ result = True
+ try:
+ extra_packages = self._getAnsible(version).extra_packages
+ python_package_check = \
+ "import pkg_resources; pkg_resources.require({})".format(
+ repr(extra_packages))
+
+ command = [self.getAnsibleCommand(version, 'python'),
+ '-c', python_package_check]
+ subprocess.run(command, check=True)
+ except Exception:
+ result = False
+ self.log.exception(
+ 'Ansible version %s installation is missing packages' %
+ version)
+ return result
+
def validate(self):
result = True
for version in self._supported_versions:
- try:
- command = [
- self.getAnsibleCommand(version, 'ansible'),
- '--version',
- ]
-
- ret = subprocess.run(command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- check=True)
- self.log.info('Ansible version %s information: \n%s',
- version, ret.stdout.decode())
- except subprocess.CalledProcessError:
+ if not self._validate_ansible(version):
result = False
- self.log.exception("Ansible version %s not working" % version)
- except Exception:
+ elif not self._validate_packages(version):
result = False
- self.log.exception(
- 'Ansible version %s not installed' % version)
-
return result
def _getAnsible(self, version):