From 11a111bbe976725b43dce09bd423d1601b208941 Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Fri, 7 Apr 2023 20:08:09 +0200 Subject: [PATCH] stop using requests --- plugins/module_utils/_apypie.py | 3 +- plugins/module_utils/foreman_helper.py | 56 ++++++++++++++++++++++++++ tests/vcr_python_wrapper.py | 2 +- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/plugins/module_utils/_apypie.py b/plugins/module_utils/_apypie.py index 8052d1a85d..4b639e20f8 100644 --- a/plugins/module_utils/_apypie.py +++ b/plugins/module_utils/_apypie.py @@ -282,6 +282,7 @@ class Api(object): :param apidoc_cache_dir: where to cache the JSON description of the API. Defaults to `apidoc_cache_base_dir/`. :param apidoc_cache_name: name of the cache file. If there is cache in the `apidoc_cache_dir`, it is used. Defaults to `default`. :param verify_ssl: should the SSL certificate be verified. Defaults to `True`. + :param session: a `requests.Session` compatible object. Defaults to `requests.Session()`. Usage:: @@ -306,7 +307,7 @@ def __init__(self, **kwargs): self.apidoc_cache_dir = kwargs.get('apidoc_cache_dir', apidoc_cache_dir_default) self.apidoc_cache_name = kwargs.get('apidoc_cache_name', self._find_cache_name()) - self._session = requests.Session() + self._session = kwargs.get('session') or requests.Session() self._session.verify = kwargs.get('verify_ssl', True) self._session.headers['Accept'] = 'application/json;version={}'.format(self.api_version) diff --git a/plugins/module_utils/foreman_helper.py b/plugins/module_utils/foreman_helper.py index b91e1630bb..e3e9ad8536 100644 --- a/plugins/module_utils/foreman_helper.py +++ b/plugins/module_utils/foreman_helper.py @@ -24,6 +24,7 @@ from ansible.module_utils.basic import AnsibleModule, missing_required_lib, env_fallback from ansible.module_utils._text import to_bytes, to_native from ansible.module_utils import six +from ansible.module_utils.urls import Request try: from ansible_collections.theforeman.foreman.plugins.module_utils._version import LooseVersion @@ -89,6 +90,60 @@ class NoEntity(object): pass +def wrap_httpresponse_requests(resp): + def raise_for_status(): + http_error_msg = "" + if resp.status > 400: + http_error_msg = "you failed" + if http_error_msg: + raise Exception(http_error_msg) + + def fake_json(): + try: + return json.loads(resp.read()) + except Exception: + return None + + resp.raise_for_status = raise_for_status + resp.json = fake_json + resp.status_code = resp.status + return resp + + +class RequestSession(Request): + @property + def auth(self): + return (self.url_username, self.url_password) + + @auth.setter + def auth(self, value): + self.url_username, self.url_password = value + self.force_basic_auth = True + + @property + def verify(self): + return self.validate_certs + + @verify.setter + def verify(self, value): + self.validate_certs = value + + def request(self, http_method, full_path, **kwargs): + validate_certs = kwargs.pop('verify', None) + params = kwargs.pop('params', None) + if params: + full_path += '?' + six.moves.urllib.parse.urlencode(params) + headers = kwargs.pop('headers', None) + data = kwargs.pop('data', None) + if 'json' in kwargs: + # it can be `json=None`… + data = json.dumps(kwargs.pop('json')) + if headers is None: + headers = {} + headers['Content-Type'] = 'application/json' + return wrap_httpresponse_requests(self.open(http_method, full_path, validate_certs=validate_certs, data=data, headers=headers, **kwargs)) + + def _exception2fail_json(msg='Generic failure: {0}'): """ Decorator to convert Python exceptions into Ansible errors that can be reported to the user. @@ -596,6 +651,7 @@ def connect(self): password=to_bytes(self._foremanapi_password), api_version=2, verify_ssl=self._foremanapi_validate_certs, + session=RequestSession(), ) _status = self.status() diff --git a/tests/vcr_python_wrapper.py b/tests/vcr_python_wrapper.py index 19dc02362f..e7f1c96112 100755 --- a/tests/vcr_python_wrapper.py +++ b/tests/vcr_python_wrapper.py @@ -42,7 +42,7 @@ def body_json_l2_matcher(r1, r2): for i, v in enumerate(body1): assert body1[i] == body2[i], "body contents at position {} dont't match: '{}' vs '{}'".format(i, body1[i], body2[i]) else: - assert r1.body == r2.body, "{} != {}".format(r1.body, r2.body) + assert r1.body == r2.body, "{} != {} ({}, {})".format(r1.body, r2.body, r1.headers, r2.headers) def _query_without_search_matcher(r1, r2, path):