From 0f0d33a9549798a27a1763b4cb48a0e52530cda3 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Thu, 7 Feb 2019 03:39:17 +1000 Subject: [PATCH] start getting modules to use shared import error code (#51787) --- lib/ansible/module_utils/basic.py | 9 ++++++--- lib/ansible/module_utils/influxdb.py | 12 ++++++++++-- lib/ansible/module_utils/k8s/common.py | 13 ++++++++++--- lib/ansible/module_utils/k8s/raw.py | 9 +++++++-- lib/ansible/module_utils/rabbitmq.py | 10 ++++++---- lib/ansible/modules/clustering/etcd3.py | 13 ++++++++----- .../modules/clustering/k8s/_kubernetes.py | 7 +++++-- lib/ansible/modules/clustering/znode.py | 7 +++++-- lib/ansible/modules/commands/expect.py | 7 +++++-- .../crypto/acme/acme_challenge_cert_helper.py | 7 +++++-- .../modules/crypto/certificate_complete_chain.py | 7 +++++-- lib/ansible/modules/crypto/get_certificate.py | 8 ++++++-- .../modules/crypto/openssl_certificate.py | 7 +++++-- lib/ansible/modules/crypto/openssl_csr.py | 11 ++++++++--- lib/ansible/modules/crypto/openssl_pkcs12.py | 7 +++++-- lib/ansible/modules/crypto/openssl_privatekey.py | 11 ++++++++--- lib/ansible/modules/crypto/openssl_publickey.py | 7 +++++-- .../database/aerospike/aerospike_migrations.py | 16 +++++++--------- lib/ansible/modules/database/misc/redis.py | 6 ++++-- .../database/mongodb/mongodb_parameter.py | 4 ++-- .../modules/database/mongodb/mongodb_shard.py | 4 ++-- .../modules/database/mongodb/mongodb_user.py | 4 ++-- lib/ansible/modules/database/mssql/mssql_db.py | 7 +++++-- .../modules/database/postgresql/postgresql_db.py | 6 ++++-- .../database/postgresql/postgresql_ext.py | 6 ++++-- .../database/postgresql/postgresql_idx.py | 6 ++++-- .../database/postgresql/postgresql_lang.py | 6 ++++-- .../database/postgresql/postgresql_privs.py | 6 ++++-- .../database/postgresql/postgresql_schema.py | 6 ++++-- .../database/postgresql/postgresql_user.py | 6 ++++-- .../database/vertica/vertica_configuration.py | 6 ++++-- .../modules/database/vertica/vertica_facts.py | 6 ++++-- .../modules/database/vertica/vertica_role.py | 6 ++++-- .../modules/database/vertica/vertica_schema.py | 6 ++++-- .../modules/database/vertica/vertica_user.py | 6 ++++-- lib/ansible/modules/files/archive.py | 8 +++++++- lib/ansible/modules/files/xml.py | 6 ++++-- .../messaging/rabbitmq/rabbitmq_binding.py | 8 +++++--- .../messaging/rabbitmq/rabbitmq_exchange.py | 7 +++++-- .../modules/messaging/rabbitmq/rabbitmq_queue.py | 7 +++++-- .../modules/monitoring/circonus_annotation.py | 6 ++++-- lib/ansible/modules/monitoring/datadog_event.py | 6 ++++-- .../modules/monitoring/datadog_monitor.py | 6 ++++-- lib/ansible/modules/monitoring/pingdom.py | 8 ++++++-- lib/ansible/modules/utilities/logic/wait_for.py | 8 +++++--- .../k8s/playbooks/older_openshift_fail.yml | 3 ++- 46 files changed, 230 insertions(+), 108 deletions(-) diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index 007cb32a33..0393a2abd5 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -727,10 +727,13 @@ def jsonify(data, **kwargs): raise UnicodeError('Invalid unicode encoding encountered') -def missing_required_lib(library): +def missing_required_lib(library, reason=None): hostname = platform.node() - return "Failed to import the required Python library (%s) on %s's Python %s. Please read module documentation " \ - "and install in the appropriate location." % (library, hostname, sys.executable) + msg = "Failed to import the required Python library (%s) on %s's Python %s." % (library, hostname, sys.executable) + if reason: + msg += " This is required %s." % reason + + return msg + " Please read module documentation and install in the appropriate location" class AnsibleFallbackNotFound(Exception): diff --git a/lib/ansible/module_utils/influxdb.py b/lib/ansible/module_utils/influxdb.py index da43604e8f..0cf71972f6 100644 --- a/lib/ansible/module_utils/influxdb.py +++ b/lib/ansible/module_utils/influxdb.py @@ -5,18 +5,26 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type +import traceback + +from ansible.module_utils.basic import missing_required_lib + +REQUESTS_IMP_ERR = None try: import requests.exceptions HAS_REQUESTS = True except ImportError: + REQUESTS_IMP_ERR = traceback.format_exc() HAS_REQUESTS = False +INFLUXDB_IMP_ERR = None try: from influxdb import InfluxDBClient from influxdb import __version__ as influxdb_version from influxdb import exceptions HAS_INFLUXDB = True except ImportError: + INFLUXDB_IMP_ERR = traceback.format_exc() HAS_INFLUXDB = False @@ -33,10 +41,10 @@ class InfluxDb(): def check_lib(self): if not HAS_REQUESTS: - self.module.fail_json(msg='This module requires "requests" module.') + self.module.fail_json(msg=missing_required_lib('requests'), exception=REQUESTS_IMP_ERR) if not HAS_INFLUXDB: - self.module.fail_json(msg='This module requires influxdb python package.') + self.module.fail_json(msg=missing_required_lib('influxdb'), exception=INFLUXDB_IMP_ERR) @staticmethod def influxdb_argument_spec(): diff --git a/lib/ansible/module_utils/k8s/common.py b/lib/ansible/module_utils/k8s/common.py index a83885b890..a4d57e1628 100644 --- a/lib/ansible/module_utils/k8s/common.py +++ b/lib/ansible/module_utils/k8s/common.py @@ -20,12 +20,15 @@ from __future__ import absolute_import, division, print_function import copy import json import os +import traceback -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.common.dict_transformations import recursive_diff from ansible.module_utils.six import iteritems, string_types +from ansible.module_utils._text import to_native +K8S_IMP_ERR = None try: import kubernetes import openshift @@ -36,11 +39,14 @@ try: except ImportError as e: HAS_K8S_MODULE_HELPER = False k8s_import_exception = e + K8S_IMP_ERR = traceback.format_exc() +YAML_IMP_ERR = None try: import yaml HAS_YAML = True except ImportError: + YAML_IMP_ERR = traceback.format_exc() HAS_YAML = False try: @@ -244,11 +250,12 @@ class KubernetesAnsibleModule(AnsibleModule, K8sAnsibleMixin): AnsibleModule.__init__(self, *args, **kwargs) if not HAS_K8S_MODULE_HELPER: - self.fail_json(msg="This module requires the OpenShift Python client. Try `pip install openshift`", error=str(k8s_import_exception)) + self.fail_json(msg=missing_required_lib('openshift'), exception=K8S_IMP_ERR, + error=to_native(k8s_import_exception)) self.openshift_version = openshift.__version__ if not HAS_YAML: - self.fail_json(msg="This module requires PyYAML. Try `pip install PyYAML`") + self.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR) def execute_module(self): raise NotImplementedError() diff --git a/lib/ansible/module_utils/k8s/raw.py b/lib/ansible/module_utils/k8s/raw.py index d772687d53..58909c9294 100644 --- a/lib/ansible/module_utils/k8s/raw.py +++ b/lib/ansible/module_utils/k8s/raw.py @@ -23,7 +23,9 @@ from datetime import datetime from distutils.version import LooseVersion import time import sys +import traceback +from ansible.module_utils.basic import missing_required_lib from ansible.module_utils.k8s.common import AUTH_ARG_SPEC, COMMON_ARG_SPEC from ansible.module_utils.six import string_types from ansible.module_utils.k8s.common import KubernetesAnsibleModule @@ -45,10 +47,12 @@ try: except ImportError: HAS_KUBERNETES_VALIDATE = False +K8S_CONFIG_HASH_IMP_ERR = None try: from openshift.helper.hashes import generate_hash HAS_K8S_CONFIG_HASH = True except ImportError: + K8S_CONFIG_HASH_IMP_ERR = traceback.format_exc() HAS_K8S_CONFIG_HASH = False @@ -97,10 +101,11 @@ class KubernetesRawModule(KubernetesAnsibleModule): self.append_hash = self.params.get('append_hash') if self.append_hash: if not HAS_K8S_CONFIG_HASH: - self.fail_json(msg="openshift >= 0.7.2 is required for append_hash") + self.fail_json(msg=missing_required_lib("openshift >= 0.7.2", reason="for append_hash"), + exception=K8S_CONFIG_HASH_IMP_ERR) if self.params['merge_type']: if LooseVersion(self.openshift_version) < LooseVersion("0.6.2"): - self.fail_json(msg="openshift >= 0.6.2 is required for merge_type") + self.fail_json(msg=missing_required_lib("openshift >= 0.6.2", reason="for merge_type")) if resource_definition: if isinstance(resource_definition, string_types): try: diff --git a/lib/ansible/module_utils/rabbitmq.py b/lib/ansible/module_utils/rabbitmq.py index d99f9bece2..3a58716515 100644 --- a/lib/ansible/module_utils/rabbitmq.py +++ b/lib/ansible/module_utils/rabbitmq.py @@ -8,18 +8,20 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -from ansible.module_utils._text import to_native, to_text -from ansible.module_utils.basic import env_fallback +from ansible.module_utils._text import to_native +from ansible.module_utils.basic import missing_required_lib from mimetypes import MimeTypes -import json import os +import traceback +PIKA_IMP_ERR = None try: import pika from pika import spec HAS_PIKA = True except ImportError: + PIKA_IMP_ERR = traceback.format_exc() HAS_PIKA = False @@ -61,7 +63,7 @@ class RabbitClient(): def check_required_library(self): if not HAS_PIKA: - self.module.fail_json(msg="Unable to find 'pika' Python library which is required.") + self.module.fail_json(msg=missing_required_lib("pika"), exception=PIKA_IMP_ERR) def check_host_params(self): # Fail if url is specified and other conflicting parameters have been specified diff --git a/lib/ansible/modules/clustering/etcd3.py b/lib/ansible/modules/clustering/etcd3.py index a9e84b062a..5ffaee152c 100644 --- a/lib/ansible/modules/clustering/etcd3.py +++ b/lib/ansible/modules/clustering/etcd3.py @@ -72,13 +72,16 @@ old_value: import traceback -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native + + try: import etcd3 - etcd_found = True + HAS_ETCD = True except ImportError: - etcd_found = False + ETCD_IMP_ERR = traceback.format_exc() + HAS_ETCD = False def run_module(): @@ -112,8 +115,8 @@ def run_module(): result['key'] = module.params.get('key') - if not etcd_found: - module.fail_json(msg="the python etcd3 module is required") + if not HAS_ETCD: + module.fail_json(msg=missing_required_lib('etcd3'), exception=ETCD_IMP_ERR) allowed_keys = ['host', 'port', 'ca_cert', 'cert_key', 'cert_cert', 'timeout', 'user', 'password'] diff --git a/lib/ansible/modules/clustering/k8s/_kubernetes.py b/lib/ansible/modules/clustering/k8s/_kubernetes.py index 2d9c4c0af2..34ceb6c513 100644 --- a/lib/ansible/modules/clustering/k8s/_kubernetes.py +++ b/lib/ansible/modules/clustering/k8s/_kubernetes.py @@ -153,14 +153,17 @@ api_response: import base64 import json +import traceback +YAML_IMP_ERR = None try: import yaml HAS_LIB_YAML = True except ImportError: + YAML_IMP_ERR = traceback.format_exc() HAS_LIB_YAML = False -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.urls import fetch_url @@ -353,7 +356,7 @@ def main(): ) if not HAS_LIB_YAML: - module.fail_json(msg="missing python library: yaml") + module.fail_json(msg=missing_required_lib('PyYAML'), exception=YAML_IMP_ERR) decode_cert_data(module) diff --git a/lib/ansible/modules/clustering/znode.py b/lib/ansible/modules/clustering/znode.py index 1824c5b2b9..446e9c8a9e 100644 --- a/lib/ansible/modules/clustering/znode.py +++ b/lib/ansible/modules/clustering/znode.py @@ -95,15 +95,18 @@ EXAMPLES = """ """ import time +import traceback +KAZOO_IMP_ERR = None try: from kazoo.client import KazooClient from kazoo.handlers.threading import KazooTimeoutError KAZOO_INSTALLED = True except ImportError: + KAZOO_IMP_ERR = traceback.format_exc() KAZOO_INSTALLED = False -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_bytes @@ -122,7 +125,7 @@ def main(): ) if not KAZOO_INSTALLED: - module.fail_json(msg='kazoo >= 2.1 is required to use this module. Use pip to install it.') + module.fail_json(msg=missing_required_lib('kazoo >= 2.1'), exception=KAZOO_IMP_ERR) check = check_params(module.params) if not check['success']: diff --git a/lib/ansible/modules/commands/expect.py b/lib/ansible/modules/commands/expect.py index bd6908e469..a807c7db38 100644 --- a/lib/ansible/modules/commands/expect.py +++ b/lib/ansible/modules/commands/expect.py @@ -98,13 +98,15 @@ import datetime import os import traceback +PEXPECT_IMP_ERR = None try: import pexpect HAS_PEXPECT = True except ImportError: + PEXPECT_IMP_ERR = traceback.format_exc() HAS_PEXPECT = False -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native, to_text @@ -137,7 +139,8 @@ def main(): ) if not HAS_PEXPECT: - module.fail_json(msg='The pexpect python module is required') + module.fail_json(msg=missing_required_lib("pexpect"), + exception=PEXPECT_IMP_ERR) chdir = module.params['chdir'] args = module.params['command'] diff --git a/lib/ansible/modules/crypto/acme/acme_challenge_cert_helper.py b/lib/ansible/modules/crypto/acme/acme_challenge_cert_helper.py index e249f6fc2e..6bdce424ef 100644 --- a/lib/ansible/modules/crypto/acme/acme_challenge_cert_helper.py +++ b/lib/ansible/modules/crypto/acme/acme_challenge_cert_helper.py @@ -125,13 +125,15 @@ from ansible.module_utils.acme import ( read_file, ) -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_bytes, to_text import base64 import datetime import sys +import traceback +CRYPTOGRAPHY_IMP_ERR = None try: import cryptography import cryptography.hazmat.backends @@ -147,6 +149,7 @@ try: HAS_CRYPTOGRAPHY = (LooseVersion(cryptography.__version__) >= LooseVersion('1.3')) _cryptography_backend = cryptography.hazmat.backends.default_backend() except ImportError as e: + CRYPTOGRAPHY_IMP_ERR = traceback.format_exc() HAS_CRYPTOGRAPHY = False @@ -179,7 +182,7 @@ def main(): ), ) if not HAS_CRYPTOGRAPHY: - module.fail_json(msg='cryptography >= 1.3 is required for this module.') + module.fail_json(msg=missing_required_lib('cryptography >= 1.3'), exception=CRYPTOGRAPHY_IMP_ERR) try: # Get parameters diff --git a/lib/ansible/modules/crypto/certificate_complete_chain.py b/lib/ansible/modules/crypto/certificate_complete_chain.py index c0855339f7..7759d767f0 100644 --- a/lib/ansible/modules/crypto/certificate_complete_chain.py +++ b/lib/ansible/modules/crypto/certificate_complete_chain.py @@ -121,10 +121,12 @@ complete_chain: ''' import os +import traceback -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_bytes +CRYPTOGRAPHY_IMP_ERR = None try: import cryptography import cryptography.hazmat.backends @@ -140,6 +142,7 @@ try: HAS_CRYPTOGRAPHY = (LooseVersion(cryptography.__version__) >= LooseVersion('1.5')) _cryptography_backend = cryptography.hazmat.backends.default_backend() except ImportError as e: + CRYPTOGRAPHY_IMP_ERR = traceback.format_exc() HAS_CRYPTOGRAPHY = False @@ -289,7 +292,7 @@ def main(): ) if not HAS_CRYPTOGRAPHY: - module.fail_json(msg='cryptography >= 1.5 is required for this module.') + module.fail_json(msg=missing_required_lib('cryptography >= 1.5'), exception=CRYPTOGRAPHY_IMP_ERR) # Load chain chain = parse_PEM_list(module, module.params['input_chain'], source='input chain') diff --git a/lib/ansible/modules/crypto/get_certificate.py b/lib/ansible/modules/crypto/get_certificate.py index 61ff9cb455..c59a3d40ff 100644 --- a/lib/ansible/modules/crypto/get_certificate.py +++ b/lib/ansible/modules/crypto/get_certificate.py @@ -107,15 +107,19 @@ EXAMPLES = ''' register: cert ''' -from ansible.module_utils.basic import AnsibleModule +import traceback + +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from os.path import isfile from ssl import get_server_certificate from socket import setdefaulttimeout +PYOPENSSL_IMP_ERR = None try: from OpenSSL import crypto except ImportError: + PYOPENSSL_IMP_ERR = traceback.format_exc() pyopenssl_found = False else: pyopenssl_found = True @@ -141,7 +145,7 @@ def main(): ) if not pyopenssl_found: - module.fail_json(msg='the python pyOpenSSL module is required') + module.fail_json(msg=missing_required_lib('pyOpenSSL'), exception=PYOPENSSL_IMP_ERR) if timeout: setdefaulttimeout(timeout) diff --git a/lib/ansible/modules/crypto/openssl_certificate.py b/lib/ansible/modules/crypto/openssl_certificate.py index e4c930749f..2f1e72aca1 100644 --- a/lib/ansible/modules/crypto/openssl_certificate.py +++ b/lib/ansible/modules/crypto/openssl_certificate.py @@ -418,15 +418,18 @@ filename: from random import randint import datetime import os +import traceback from ansible.module_utils import crypto as crypto_utils -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native, to_bytes +PYOPENSSL_IMP_ERR = None try: import OpenSSL from OpenSSL import crypto except ImportError: + PYOPENSSL_IMP_ERR = traceback.format_exc() pyopenssl_found = False else: pyopenssl_found = True @@ -1052,7 +1055,7 @@ def main(): ) if not pyopenssl_found: - module.fail_json(msg='The python pyOpenSSL library is required') + module.fail_json(msg=missing_required_lib('pyOpenSSL'), exception=PYOPENSSL_IMP_ERR) if module.params['provider'] in ['selfsigned', 'ownca', 'assertonly']: try: getattr(crypto.X509Req, 'get_extensions') diff --git a/lib/ansible/modules/crypto/openssl_csr.py b/lib/ansible/modules/crypto/openssl_csr.py index f3a400badb..1ed86269ea 100644 --- a/lib/ansible/modules/crypto/openssl_csr.py +++ b/lib/ansible/modules/crypto/openssl_csr.py @@ -319,20 +319,23 @@ ocsp_must_staple: import abc import os +import traceback from distutils.version import LooseVersion from ansible.module_utils import crypto as crypto_utils -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native, to_bytes, to_text MINIMAL_PYOPENSSL_VERSION = '0.15' MINIMAL_CRYPTOGRAPHY_VERSION = '1.3' +PYOPENSSL_IMP_ERR = None try: import OpenSSL from OpenSSL import crypto PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__) except ImportError: + PYOPENSSL_IMP_ERR = traceback.format_exc() PYOPENSSL_FOUND = False else: PYOPENSSL_FOUND = True @@ -345,6 +348,7 @@ else: OPENSSL_MUST_STAPLE_NAME = b"1.3.6.1.5.5.7.1.24" OPENSSL_MUST_STAPLE_VALUE = b"DER:30:03:02:01:05" +CRYPTOGRAPHY_IMP_ERR = None try: import cryptography import cryptography.x509 @@ -355,6 +359,7 @@ try: import cryptography.hazmat.primitives.hashes CRYPTOGRAPHY_VERSION = LooseVersion(cryptography.__version__) except ImportError: + CRYPTOGRAPHY_IMP_ERR = traceback.format_exc() CRYPTOGRAPHY_FOUND = False else: CRYPTOGRAPHY_FOUND = True @@ -995,7 +1000,7 @@ def main(): MINIMAL_PYOPENSSL_VERSION)) if backend == 'pyopenssl': if not PYOPENSSL_FOUND: - module.fail_json(msg='The Python pyOpenSSL library is required') + module.fail_json(msg=missing_required_lib('pyOpenSSL'), exception=PYOPENSSL_IMP_ERR) try: getattr(crypto.X509Req, 'get_extensions') except AttributeError: @@ -1003,7 +1008,7 @@ def main(): csr = CertificateSigningRequestPyOpenSSL(module) elif backend == 'cryptography': if not CRYPTOGRAPHY_FOUND: - module.fail_json(msg='The Python cryptography library is required') + module.fail_json(msg=missing_required_lib('cryptography'), exception=CRYPTOGRAPHY_IMP_ERR) csr = CertificateSigningRequestCryptography(module) if module.params['state'] == 'present': diff --git a/lib/ansible/modules/crypto/openssl_pkcs12.py b/lib/ansible/modules/crypto/openssl_pkcs12.py index 1f92134684..d8cf55f09f 100644 --- a/lib/ansible/modules/crypto/openssl_pkcs12.py +++ b/lib/ansible/modules/crypto/openssl_pkcs12.py @@ -140,15 +140,18 @@ privatekey: import stat import os +import traceback +PYOPENSSL_IMP_ERR = None try: from OpenSSL import crypto except ImportError: + PYOPENSSL_IMP_ERR = traceback.format_exc() pyopenssl_found = False else: pyopenssl_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils import crypto as crypto_utils from ansible.module_utils._text import to_bytes, to_native @@ -311,7 +314,7 @@ def main(): ) if not pyopenssl_found: - module.fail_json(msg='The python pyOpenSSL library is required') + module.fail_json(msg=missing_required_lib('pyOpenSSL'), exception=PYOPENSSL_IMP_ERR) base_dir = os.path.dirname(module.params['path']) or '.' if not os.path.isdir(base_dir): diff --git a/lib/ansible/modules/crypto/openssl_privatekey.py b/lib/ansible/modules/crypto/openssl_privatekey.py index 6df58c0020..09fd66dad6 100644 --- a/lib/ansible/modules/crypto/openssl_privatekey.py +++ b/lib/ansible/modules/crypto/openssl_privatekey.py @@ -198,14 +198,18 @@ from distutils.version import LooseVersion MINIMAL_PYOPENSSL_VERSION = '0.6' MINIMAL_CRYPTOGRAPHY_VERSION = '1.2.3' +PYOPENSSL_IMP_ERR = None try: import OpenSSL from OpenSSL import crypto PYOPENSSL_VERSION = LooseVersion(OpenSSL.__version__) except ImportError: + PYOPENSSL_IMP_ERR = traceback.format_exc() PYOPENSSL_FOUND = False else: PYOPENSSL_FOUND = True + +CRYPTOGRAPHY_IMP_ERR = None try: import cryptography import cryptography.exceptions @@ -217,6 +221,7 @@ try: import cryptography.hazmat.primitives.asymmetric.utils CRYPTOGRAPHY_VERSION = LooseVersion(cryptography.__version__) except ImportError: + CRYPTOGRAPHY_IMP_ERR = traceback.format_exc() CRYPTOGRAPHY_FOUND = False else: CRYPTOGRAPHY_FOUND = True @@ -233,7 +238,7 @@ else: from ansible.module_utils import crypto as crypto_utils from ansible.module_utils._text import to_native, to_bytes -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.six import string_types @@ -617,11 +622,11 @@ def main(): MINIMAL_PYOPENSSL_VERSION)) if backend == 'pyopenssl': if not PYOPENSSL_FOUND: - module.fail_json(msg='The Python pyOpenSSL library is required') + module.fail_json(msg=missing_required_lib('pyOpenSSL'), exception=PYOPENSSL_IMP_ERR) private_key = PrivateKeyPyOpenSSL(module) elif backend == 'cryptography': if not CRYPTOGRAPHY_FOUND: - module.fail_json(msg='The Python cryptography library is required') + module.fail_json(msg=missing_required_lib('cryptography'), exception=CRYPTOGRAPHY_IMP_ERR) private_key = PrivateKeyCryptography(module) if private_key.state == 'present': diff --git a/lib/ansible/modules/crypto/openssl_publickey.py b/lib/ansible/modules/crypto/openssl_publickey.py index bfc3ade425..f049e3d39a 100644 --- a/lib/ansible/modules/crypto/openssl_publickey.py +++ b/lib/ansible/modules/crypto/openssl_publickey.py @@ -125,19 +125,22 @@ fingerprint: import hashlib import os +import traceback +PYOPENSSL_IMP_ERR = None try: from OpenSSL import crypto from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization as crypto_serialization except ImportError: + PYOPENSSL_IMP_ERR = traceback.format_exc() pyopenssl_found = False else: pyopenssl_found = True from ansible.module_utils import crypto as crypto_utils from ansible.module_utils._text import to_native -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib class PublicKeyError(crypto_utils.OpenSSLObjectError): @@ -269,7 +272,7 @@ def main(): ) if not pyopenssl_found: - module.fail_json(msg='the python pyOpenSSL module is required') + module.fail_json(msg=missing_required_lib('pyOpenSSL'), exception=PYOPENSSL_IMP_ERR) base_dir = os.path.dirname(module.params['path']) or '.' if not os.path.isdir(base_dir): diff --git a/lib/ansible/modules/database/aerospike/aerospike_migrations.py b/lib/ansible/modules/database/aerospike/aerospike_migrations.py index 82d8e2493c..1cff28411b 100644 --- a/lib/ansible/modules/database/aerospike/aerospike_migrations.py +++ b/lib/ansible/modules/database/aerospike/aerospike_migrations.py @@ -169,15 +169,18 @@ RETURN = ''' # Returns only a success/failure result. Changed is always false. ''' -from ansible.module_utils.basic import AnsibleModule +import traceback +from ansible.module_utils.basic import AnsibleModule, missing_required_lib + +LIB_FOUND_ERR = None try: import aerospike from time import sleep import re except ImportError as ie: LIB_FOUND = False - LIB_FOUND_ERR = ie + LIB_FOUND_ERR = traceback.format_exc() else: LIB_FOUND = True @@ -210,13 +213,8 @@ def run_module(): supports_check_mode=True ) if not LIB_FOUND: - module.fail_json( - msg="A required module was not found. This playbook" + - " requires the 'aerospike' 'time' and 're' modules. " + - "Please run 'pip install aerospike'. The other modules" + - " should be included in a basic python install." + - " OS Error: {0}".format(LIB_FOUND_ERR) - ) + module.fail_json(msg=missing_required_lib('aerospike'), + exception=LIB_FOUND_ERR) try: if module.check_mode: diff --git a/lib/ansible/modules/database/misc/redis.py b/lib/ansible/modules/database/misc/redis.py index bbeed27d77..0a27c4e1b1 100644 --- a/lib/ansible/modules/database/misc/redis.py +++ b/lib/ansible/modules/database/misc/redis.py @@ -117,14 +117,16 @@ EXAMPLES = ''' import traceback +REDIS_IMP_ERR = None try: import redis except ImportError: + REDIS_IMP_ERR = traceback.format_exc() redis_found = False else: redis_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native @@ -174,7 +176,7 @@ def main(): ) if not redis_found: - module.fail_json(msg="python redis module is required") + module.fail_json(msg=missing_required_lib('redis'), exception=REDIS_IMP_ERR) login_password = module.params['login_password'] login_host = module.params['login_host'] diff --git a/lib/ansible/modules/database/mongodb/mongodb_parameter.py b/lib/ansible/modules/database/mongodb/mongodb_parameter.py index 870fb954cb..468250ec6b 100644 --- a/lib/ansible/modules/database/mongodb/mongodb_parameter.py +++ b/lib/ansible/modules/database/mongodb/mongodb_parameter.py @@ -110,7 +110,7 @@ except ImportError: else: pymongo_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.six.moves import configparser from ansible.module_utils._text import to_native @@ -156,7 +156,7 @@ def main(): ) if not pymongo_found: - module.fail_json(msg='the python pymongo module is required') + module.fail_json(msg=missing_required_lib('pymongo')) login_user = module.params['login_user'] login_password = module.params['login_password'] diff --git a/lib/ansible/modules/database/mongodb/mongodb_shard.py b/lib/ansible/modules/database/mongodb/mongodb_shard.py index 081887e926..fd49b5c86e 100644 --- a/lib/ansible/modules/database/mongodb/mongodb_shard.py +++ b/lib/ansible/modules/database/mongodb/mongodb_shard.py @@ -140,7 +140,7 @@ except ImportError: else: pymongo_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.six import binary_type, text_type from ansible.module_utils.six.moves import configparser from ansible.module_utils._text import to_native @@ -243,7 +243,7 @@ def main(): supports_check_mode=True) if not pymongo_found: - module.fail_json(msg='the python pymongo module is required') + module.fail_json(msg=missing_required_lib('pymongo')) login_user = module.params['login_user'] login_password = module.params['login_password'] diff --git a/lib/ansible/modules/database/mongodb/mongodb_user.py b/lib/ansible/modules/database/mongodb/mongodb_user.py index f5634e9813..e821ef98d8 100644 --- a/lib/ansible/modules/database/mongodb/mongodb_user.py +++ b/lib/ansible/modules/database/mongodb/mongodb_user.py @@ -194,7 +194,7 @@ except ImportError: else: pymongo_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.six import binary_type, text_type from ansible.module_utils.six.moves import configparser from ansible.module_utils._text import to_native @@ -350,7 +350,7 @@ def main(): ) if not pymongo_found: - module.fail_json(msg='the python pymongo module is required') + module.fail_json(msg=missing_required_lib('pymongo')) login_user = module.params['login_user'] login_password = module.params['login_password'] diff --git a/lib/ansible/modules/database/mssql/mssql_db.py b/lib/ansible/modules/database/mssql/mssql_db.py index f9d0994064..fa84d79b57 100644 --- a/lib/ansible/modules/database/mssql/mssql_db.py +++ b/lib/ansible/modules/database/mssql/mssql_db.py @@ -86,15 +86,18 @@ RETURN = ''' ''' import os +import traceback +PYMSSQL_IMP_ERR = None try: import pymssql except ImportError: + PYMSSQL_IMP_ERR = traceback.format_exc() mssql_found = False else: mssql_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib def db_exists(conn, cursor, db): @@ -155,7 +158,7 @@ def main(): ) if not mssql_found: - module.fail_json(msg="pymssql python module is required") + module.fail_json(msg=missing_required_lib('pymssql'), exception=PYMSSQL_IMP_ERR) db = module.params['name'] state = module.params['state'] diff --git a/lib/ansible/modules/database/postgresql/postgresql_db.py b/lib/ansible/modules/database/postgresql/postgresql_db.py index 796fdfade5..a2d78ed527 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_db.py +++ b/lib/ansible/modules/database/postgresql/postgresql_db.py @@ -115,16 +115,18 @@ import pipes import subprocess import traceback +PSYCOPG2_IMP_ERR = None try: import psycopg2 import psycopg2.extras except ImportError: + PSYCOPG2_IMP_ERR = traceback.format_exc() HAS_PSYCOPG2 = False else: HAS_PSYCOPG2 = True import ansible.module_utils.postgres as pgutils -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.database import SQLParseError, pg_quote_identifier from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_native @@ -384,7 +386,7 @@ def main(): ) if not HAS_PSYCOPG2: - module.fail_json(msg="the python psycopg2 module is required") + module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) db = module.params["db"] owner = module.params["owner"] diff --git a/lib/ansible/modules/database/postgresql/postgresql_ext.py b/lib/ansible/modules/database/postgresql/postgresql_ext.py index c1cd258631..f5b37560f3 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_ext.py +++ b/lib/ansible/modules/database/postgresql/postgresql_ext.py @@ -110,15 +110,17 @@ EXAMPLES = ''' ''' import traceback +PSYCOPG2_IMP_ERR = None try: import psycopg2 import psycopg2.extras except ImportError: + PSYCOPG2_IMP_ERR = traceback.format_exc() postgresqldb_found = False else: postgresqldb_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_native from ansible.module_utils.database import pg_quote_identifier @@ -188,7 +190,7 @@ def main(): ) if not postgresqldb_found: - module.fail_json(msg="the python psycopg2 module is required") + module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) db = module.params["db"] ext = module.params["ext"] diff --git a/lib/ansible/modules/database/postgresql/postgresql_idx.py b/lib/ansible/modules/database/postgresql/postgresql_idx.py index 20807bfa1a..92cd971791 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_idx.py +++ b/lib/ansible/modules/database/postgresql/postgresql_idx.py @@ -155,16 +155,18 @@ RETURN = ''' # ''' import traceback +PSYCOPG2_IMP_ERR = None try: import psycopg2 import psycopg2.extras except ImportError: + PSYCOPG2_IMP_ERR = traceback.format_exc() postgresqldb_found = False else: postgresqldb_found = True import ansible.module_utils.postgres as pgutils -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.database import SQLParseError from ansible.module_utils._text import to_native from ansible.module_utils.six import iteritems @@ -320,7 +322,7 @@ def main(): "make sense to pass an index type" % idxname) if not postgresqldb_found: - module.fail_json(msg="the python psycopg2 module is required") + module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) # To use defaults values, keyword arguments must be absent, so # check which values are empty and don't include in the **kw diff --git a/lib/ansible/modules/database/postgresql/postgresql_lang.py b/lib/ansible/modules/database/postgresql/postgresql_lang.py index 1dcf861943..aa4f29b799 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_lang.py +++ b/lib/ansible/modules/database/postgresql/postgresql_lang.py @@ -158,14 +158,16 @@ EXAMPLES = ''' ''' import traceback +PSYCOPG2_IMP_ERR = None try: import psycopg2 except ImportError: + PSYCOPG2_IMP_ERR = traceback.format_exc() postgresqldb_found = False else: postgresqldb_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_native from ansible.module_utils.database import pg_quote_identifier @@ -252,7 +254,7 @@ def main(): session_role = module.params["session_role"] if not postgresqldb_found: - module.fail_json(msg="the python psycopg2 module is required") + module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) # To use defaults values, keyword arguments must be absent, so # check which values are empty and don't include in the **kw diff --git a/lib/ansible/modules/database/postgresql/postgresql_privs.py b/lib/ansible/modules/database/postgresql/postgresql_privs.py index 5dac25a35f..ba1f1585ba 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_privs.py +++ b/lib/ansible/modules/database/postgresql/postgresql_privs.py @@ -269,14 +269,16 @@ EXAMPLES = """ import traceback +PSYCOPG2_IMP_ERR = None try: import psycopg2 import psycopg2.extensions except ImportError: + PSYCOPG2_IMP_ERR = traceback.format_exc() psycopg2 = None # import module snippets -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.database import pg_quote_identifier from ansible.module_utils._text import to_native @@ -715,7 +717,7 @@ def main(): # Connect to Database if not psycopg2: - module.fail_json(msg='Python module "psycopg2" must be installed.') + module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) try: conn = Connection(p) except psycopg2.Error as e: diff --git a/lib/ansible/modules/database/postgresql/postgresql_schema.py b/lib/ansible/modules/database/postgresql/postgresql_schema.py index 0cb6f7c4c9..0964ca2417 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_schema.py +++ b/lib/ansible/modules/database/postgresql/postgresql_schema.py @@ -119,15 +119,17 @@ schema: import traceback +PSYCOPG2_IMP_ERR = None try: import psycopg2 import psycopg2.extras except ImportError: + PSYCOPG2_IMP_ERR = traceback.format_exc() postgresqldb_found = False else: postgresqldb_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.database import SQLParseError, pg_quote_identifier from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_native @@ -229,7 +231,7 @@ def main(): ) if not postgresqldb_found: - module.fail_json(msg="the python psycopg2 module is required") + module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) schema = module.params["schema"] owner = module.params["owner"] diff --git a/lib/ansible/modules/database/postgresql/postgresql_user.py b/lib/ansible/modules/database/postgresql/postgresql_user.py index 2ebecd73a0..d2bcc5ed43 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_user.py +++ b/lib/ansible/modules/database/postgresql/postgresql_user.py @@ -223,16 +223,18 @@ import re import traceback from hashlib import md5 +PSYCOPG2_IMP_ERR = None try: import psycopg2 import psycopg2.extras except ImportError: + PSYCOPG2_IMP_ERR = traceback.format_exc() postgresqldb_found = False else: postgresqldb_found = True import ansible.module_utils.postgres as pgutils -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.database import pg_quote_identifier, SQLParseError from ansible.module_utils._text import to_bytes, to_native from ansible.module_utils.six import iteritems @@ -785,7 +787,7 @@ def main(): conn_limit = module.params["conn_limit"] if not postgresqldb_found: - module.fail_json(msg="the python psycopg2 module is required") + module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) # To use defaults values, keyword arguments must be absent, so # check which values are empty and don't include in the **kw diff --git a/lib/ansible/modules/database/vertica/vertica_configuration.py b/lib/ansible/modules/database/vertica/vertica_configuration.py index e71e1bb5cb..1e4958b6d3 100644 --- a/lib/ansible/modules/database/vertica/vertica_configuration.py +++ b/lib/ansible/modules/database/vertica/vertica_configuration.py @@ -66,14 +66,16 @@ EXAMPLES = """ """ import traceback +PYODBC_IMP_ERR = None try: import pyodbc except ImportError: + PYODBC_IMP_ERR = traceback.format_exc() pyodbc_found = False else: pyodbc_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native @@ -141,7 +143,7 @@ def main(): ), supports_check_mode=True) if not pyodbc_found: - module.fail_json(msg="The python pyodbc module is required.") + module.fail_json(msg=missing_required_lib('pyodbc'), exception=PYODBC_IMP_ERR) parameter_name = module.params['parameter'] current_value = module.params['value'] diff --git a/lib/ansible/modules/database/vertica/vertica_facts.py b/lib/ansible/modules/database/vertica/vertica_facts.py index f1d766cc35..6f18e76421 100644 --- a/lib/ansible/modules/database/vertica/vertica_facts.py +++ b/lib/ansible/modules/database/vertica/vertica_facts.py @@ -58,14 +58,16 @@ EXAMPLES = """ """ import traceback +PYODBC_IMP_ERR = None try: import pyodbc except ImportError: + PYODBC_IMP_ERR = traceback.format_exc() pyodbc_found = False else: pyodbc_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native @@ -227,7 +229,7 @@ def main(): ), supports_check_mode=True) if not pyodbc_found: - module.fail_json(msg="The python pyodbc module is required.") + module.fail_json(msg=missing_required_lib('pyodbc'), exception=PYODBC_IMP_ERR) db = '' if module.params['db']: diff --git a/lib/ansible/modules/database/vertica/vertica_role.py b/lib/ansible/modules/database/vertica/vertica_role.py index 09433cb028..ec419a0ebd 100644 --- a/lib/ansible/modules/database/vertica/vertica_role.py +++ b/lib/ansible/modules/database/vertica/vertica_role.py @@ -74,14 +74,16 @@ EXAMPLES = """ """ import traceback +PYODBC_IMP_ERR = None try: import pyodbc except ImportError: + PYODBC_IMP_ERR = traceback.format_exc() pyodbc_found = False else: pyodbc_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native @@ -180,7 +182,7 @@ def main(): ), supports_check_mode=True) if not pyodbc_found: - module.fail_json(msg="The python pyodbc module is required.") + module.fail_json(msg=missing_required_lib('pyodbc'), exception=PYODBC_IMP_ERR) role = module.params['role'] assigned_roles = [] diff --git a/lib/ansible/modules/database/vertica/vertica_schema.py b/lib/ansible/modules/database/vertica/vertica_schema.py index a5579800aa..3465c4d95c 100644 --- a/lib/ansible/modules/database/vertica/vertica_schema.py +++ b/lib/ansible/modules/database/vertica/vertica_schema.py @@ -94,14 +94,16 @@ EXAMPLES = """ """ import traceback +PYODBC_IMP_ERR = None try: import pyodbc except ImportError: + PYODBC_IMP_ERR = traceback.format_exc() pyodbc_found = False else: pyodbc_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native @@ -246,7 +248,7 @@ def main(): ), supports_check_mode=True) if not pyodbc_found: - module.fail_json(msg="The python pyodbc module is required.") + module.fail_json(msg=missing_required_lib('pyodbc'), exception=PYODBC_IMP_ERR) schema = module.params['schema'] usage_roles = [] diff --git a/lib/ansible/modules/database/vertica/vertica_user.py b/lib/ansible/modules/database/vertica/vertica_user.py index 48985d7957..53202537ce 100644 --- a/lib/ansible/modules/database/vertica/vertica_user.py +++ b/lib/ansible/modules/database/vertica/vertica_user.py @@ -102,14 +102,16 @@ EXAMPLES = """ """ import traceback +PYODBC_IMP_ERR = None try: import pyodbc except ImportError: + PYODBC_IMP_ERR = traceback.format_exc() pyodbc_found = False else: pyodbc_found = True -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native @@ -301,7 +303,7 @@ def main(): ), supports_check_mode=True) if not pyodbc_found: - module.fail_json(msg="The python pyodbc module is required.") + module.fail_json(msg=missing_required_lib('pyodbc'), exception=PYODBC_IMP_ERR) user = module.params['user'] profile = module.params['profile'] diff --git a/lib/ansible/modules/files/archive.py b/lib/ansible/modules/files/archive.py index 1ca3612b9f..5e74464ed9 100644 --- a/lib/ansible/modules/files/archive.py +++ b/lib/ansible/modules/files/archive.py @@ -151,21 +151,25 @@ import tarfile import zipfile from traceback import format_exc -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native from ansible.module_utils.six import PY3 + +LZMA_IMP_ERR = None if PY3: try: import lzma HAS_LZMA = True except ImportError: + LZMA_IMP_ERR = format_exc() HAS_LZMA = False else: try: from backports import lzma HAS_LZMA = True except ImportError: + LZMA_IMP_ERR = format_exc() HAS_LZMA = False @@ -202,6 +206,8 @@ def main(): # Fail early if not HAS_LZMA and format == 'xz': + module.fail_json(msg=missing_required_lib("lzma or backports.lzma", reason="when using xz format"), + exception=LZMA_IMP_ERR) module.fail_json(msg="lzma or backports.lzma is required when using xz format.") for path in paths: diff --git a/lib/ansible/modules/files/xml.py b/lib/ansible/modules/files/xml.py index 66a52e2917..c547cec153 100644 --- a/lib/ansible/modules/files/xml.py +++ b/lib/ansible/modules/files/xml.py @@ -335,13 +335,15 @@ import traceback from distutils.version import LooseVersion from io import BytesIO +LXML_IMP_ERR = None try: from lxml import etree, objectify HAS_LXML = True except ImportError: + LXML_IMP_ERR = traceback.format_exc() HAS_LXML = False -from ansible.module_utils.basic import AnsibleModule, json_dict_bytes_to_unicode +from ansible.module_utils.basic import AnsibleModule, json_dict_bytes_to_unicode, missing_required_lib from ansible.module_utils.six import iteritems, string_types from ansible.module_utils._text import to_bytes, to_native from ansible.module_utils.common._collections_compat import MutableMapping @@ -876,7 +878,7 @@ def main(): # Check if we have lxml 2.3.0 or newer installed if not HAS_LXML: - module.fail_json(msg='The xml ansible module requires the lxml python library installed on the managed machine') + module.fail_json(msg=missing_required_lib("lxml"), exception=LXML_IMP_ERR) elif LooseVersion('.'.join(to_native(f) for f in etree.LXML_VERSION)) < LooseVersion('2.3.0'): module.fail_json(msg='The xml ansible module requires lxml 2.3.0 or newer installed on the managed machine') elif LooseVersion('.'.join(to_native(f) for f in etree.LXML_VERSION)) < LooseVersion('3.0.0'): diff --git a/lib/ansible/modules/messaging/rabbitmq/rabbitmq_binding.py b/lib/ansible/modules/messaging/rabbitmq/rabbitmq_binding.py index 87c56bf210..7b0138dfcf 100644 --- a/lib/ansible/modules/messaging/rabbitmq/rabbitmq_binding.py +++ b/lib/ansible/modules/messaging/rabbitmq/rabbitmq_binding.py @@ -75,16 +75,18 @@ EXAMPLES = ''' ''' import json +import traceback +REQUESTS_IMP_ERR = None try: import requests - HAS_REQUESTS = True except ImportError: + REQUESTS_IMP_ERR = traceback.format_exc() HAS_REQUESTS = False from ansible.module_utils.six.moves.urllib import parse as urllib_parse -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.rabbitmq import rabbitmq_argument_spec @@ -286,7 +288,7 @@ def main(): module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) if not HAS_REQUESTS: - module.fail_json(msg="requests library is required for this module. To install, use `pip install requests`") + module.fail_json(msg=missing_required_lib("requests"), exception=REQUESTS_IMP_ERR) RabbitMqBinding(module).run() diff --git a/lib/ansible/modules/messaging/rabbitmq/rabbitmq_exchange.py b/lib/ansible/modules/messaging/rabbitmq/rabbitmq_exchange.py index 65977a93f9..d65fce9382 100644 --- a/lib/ansible/modules/messaging/rabbitmq/rabbitmq_exchange.py +++ b/lib/ansible/modules/messaging/rabbitmq/rabbitmq_exchange.py @@ -81,14 +81,17 @@ EXAMPLES = ''' ''' import json +import traceback +REQUESTS_IMP_ERR = None try: import requests HAS_REQUESTS = True except ImportError: + REQUESTS_IMP_ERR = traceback.format_exc() HAS_REQUESTS = False -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.six.moves.urllib import parse as urllib_parse from ansible.module_utils.rabbitmq import rabbitmq_argument_spec @@ -118,7 +121,7 @@ def main(): ) if not HAS_REQUESTS: - module.fail_json(msg="requests library is required for this module. To install, use `pip install requests`") + module.fail_json(msg=missing_required_lib("requests"), exception=REQUESTS_IMP_ERR) result = dict(changed=False, name=module.params['name']) diff --git a/lib/ansible/modules/messaging/rabbitmq/rabbitmq_queue.py b/lib/ansible/modules/messaging/rabbitmq/rabbitmq_queue.py index 812a59767a..1086fc1e39 100644 --- a/lib/ansible/modules/messaging/rabbitmq/rabbitmq_queue.py +++ b/lib/ansible/modules/messaging/rabbitmq/rabbitmq_queue.py @@ -91,14 +91,17 @@ EXAMPLES = ''' ''' import json +import traceback +REQUESTS_IMP_ERR = None try: import requests HAS_REQUESTS = True except ImportError: + REQUESTS_IMP_ERR = traceback.format_exc() HAS_REQUESTS = False -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.six.moves.urllib import parse as urllib_parse from ansible.module_utils.rabbitmq import rabbitmq_argument_spec @@ -132,7 +135,7 @@ def main(): ) if not HAS_REQUESTS: - module.fail_json(msg="requests library is required for this module. To install, use `pip install requests`") + module.fail_json(msg=missing_required_lib("requests"), exception=REQUESTS_IMP_ERR) result = dict(changed=False, name=module.params['name']) diff --git a/lib/ansible/modules/monitoring/circonus_annotation.py b/lib/ansible/modules/monitoring/circonus_annotation.py index 0447e853f0..713e3fa436 100644 --- a/lib/ansible/modules/monitoring/circonus_annotation.py +++ b/lib/ansible/modules/monitoring/circonus_annotation.py @@ -142,13 +142,15 @@ import time import traceback from distutils.version import LooseVersion +REQUESTS_IMP_ERR = None try: import requests HAS_REQUESTS = True except ImportError: + REQUESTS_IMP_ERR = traceback.format_exc() HAS_REQUESTS = False -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.six import PY3 from ansible.module_utils._text import to_native @@ -156,7 +158,7 @@ from ansible.module_utils._text import to_native def check_requests_dep(module): """Check if an adequate requests version is available""" if not HAS_REQUESTS: - module.fail_json(msg='requests is required for this module') + module.fail_json(msg=missing_required_lib('requests'), exception=REQUESTS_IMP_ERR) else: required_version = '2.0.0' if PY3 else '1.0.0' if LooseVersion(requests.__version__) < LooseVersion(required_version): diff --git a/lib/ansible/modules/monitoring/datadog_event.py b/lib/ansible/modules/monitoring/datadog_event.py index 0f42b567d1..d8ba115bc2 100644 --- a/lib/ansible/modules/monitoring/datadog_event.py +++ b/lib/ansible/modules/monitoring/datadog_event.py @@ -93,13 +93,15 @@ import platform import traceback # Import Datadog +DATADOG_IMP_ERR = None try: from datadog import initialize, api HAS_DATADOG = True except Exception: + DATADOG_IMP_ERR = traceback.format_exc() HAS_DATADOG = False -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native @@ -127,7 +129,7 @@ def main(): # Prepare Datadog if not HAS_DATADOG: - module.fail_json(msg='datadogpy required for this module') + module.fail_json(msg=missing_required_lib('datadogpy'), exception=DATADOG_IMP_ERR) options = { 'api_key': module.params['api_key'], diff --git a/lib/ansible/modules/monitoring/datadog_monitor.py b/lib/ansible/modules/monitoring/datadog_monitor.py index 9937269ba7..a09f674006 100644 --- a/lib/ansible/modules/monitoring/datadog_monitor.py +++ b/lib/ansible/modules/monitoring/datadog_monitor.py @@ -141,13 +141,15 @@ EXAMPLES = ''' import traceback # Import Datadog +DATADOG_IMP_ERR = None try: from datadog import initialize, api HAS_DATADOG = True except Exception: + DATADOG_IMP_ERR = traceback.format_exc() HAS_DATADOG = False -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils._text import to_native @@ -180,7 +182,7 @@ def main(): # Prepare Datadog if not HAS_DATADOG: - module.fail_json(msg='datadogpy required for this module') + module.fail_json(msg=missing_required_lib('datadogpy'), exception=DATADOG_IMP_ERR) options = { 'api_key': module.params['api_key'], diff --git a/lib/ansible/modules/monitoring/pingdom.py b/lib/ansible/modules/monitoring/pingdom.py index 9d8ef6eb8d..a9025604f5 100644 --- a/lib/ansible/modules/monitoring/pingdom.py +++ b/lib/ansible/modules/monitoring/pingdom.py @@ -68,13 +68,17 @@ EXAMPLES = ''' state: running ''' +import traceback + +PINGDOM_IMP_ERR = None try: import pingdom HAS_PINGDOM = True except Exception: + PINGDOM_IMP_ERR = traceback.format_exc() HAS_PINGDOM = False -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, missing_required_lib def pause(checkid, uid, passwd, key): @@ -114,7 +118,7 @@ def main(): ) if not HAS_PINGDOM: - module.fail_json(msg="Missing required pingdom module (check docs)") + module.fail_json(msg=missing_required_lib("pingdom"), exception=PINGDOM_IMP_ERR) checkid = module.params['checkid'] state = module.params['state'] diff --git a/lib/ansible/modules/utilities/logic/wait_for.py b/lib/ansible/modules/utilities/logic/wait_for.py index 7c19f876b7..bd8ee13cb3 100644 --- a/lib/ansible/modules/utilities/logic/wait_for.py +++ b/lib/ansible/modules/utilities/logic/wait_for.py @@ -214,18 +214,20 @@ import select import socket import sys import time +import traceback -from ansible.module_utils.basic import AnsibleModule, load_platform_subclass +from ansible.module_utils.basic import AnsibleModule, load_platform_subclass, missing_required_lib from ansible.module_utils._text import to_native HAS_PSUTIL = False +PSUTIL_IMP_ERR = None try: import psutil HAS_PSUTIL = True # just because we can import it on Linux doesn't mean we will use it except ImportError: - pass + PSUTIL_IMP_ERR = traceback.format_exc() class TCPConnectionInfo(object): @@ -261,7 +263,7 @@ class TCPConnectionInfo(object): self.port = int(self.module.params['port']) self.exclude_ips = self._get_exclude_ips() if not HAS_PSUTIL: - module.fail_json(msg="psutil module required for wait_for") + module.fail_json(msg=missing_required_lib('psutil'), exception=PSUTIL_IMP_ERR) def _get_exclude_ips(self): exclude_hosts = self.module.params['exclude_hosts'] diff --git a/test/integration/targets/k8s/playbooks/older_openshift_fail.yml b/test/integration/targets/k8s/playbooks/older_openshift_fail.yml index e9e2d2da67..824242c928 100644 --- a/test/integration/targets/k8s/playbooks/older_openshift_fail.yml +++ b/test/integration/targets/k8s/playbooks/older_openshift_fail.yml @@ -31,7 +31,8 @@ assert: that: - k8s_append_hash is failed - - "k8s_append_hash.msg == 'openshift >= 0.7.2 is required for append_hash'" + - "'Failed to import the required Python library (openshift >= 0.7.2)' in k8s_append_hash.msg" + - "'. This is required for append_hash.' in k8s_append_hash.msg" # merge_type - include_role: