def test_Request_fallback(urlopen_mock, install_opener_mock, mocker): cookies = cookiejar.CookieJar() request = Request( headers={'foo': 'bar'}, use_proxy=False, force=True, timeout=100, validate_certs=False, url_username='******', url_password='******', http_agent='ansible-tests', force_basic_auth=True, follow_redirects='all', client_cert='/tmp/client.pem', client_key='/tmp/client.key', cookies=cookies, unix_socket='/foo/bar/baz.sock', ca_path='/foo/bar/baz.pem', ) fallback_mock = mocker.spy(request, '_fallback') r = request.open('GET', 'https://ansible.com') calls = [ call(None, False), # use_proxy call(None, True), # force call(None, 100), # timeout call(None, False), # validate_certs call(None, 'user'), # url_username call(None, 'passwd'), # url_password call(None, 'ansible-tests'), # http_agent call(None, True), # force_basic_auth call(None, 'all'), # follow_redirects call(None, '/tmp/client.pem'), # client_cert call(None, '/tmp/client.key'), # client_key call(None, cookies), # cookies call(None, '/foo/bar/baz.sock'), # unix_socket call(None, '/foo/bar/baz.pem'), # ca_path ] fallback_mock.assert_has_calls(calls) assert fallback_mock.call_count == 14 # All but headers use fallback args = urlopen_mock.call_args[0] assert args[1] is None # data, this is handled in the Request not urlopen assert args[2] == 100 # timeout req = args[0] assert req.headers == { 'Authorization': b'Basic dXNlcjpwYXNzd2Q=', 'Cache-control': 'no-cache', 'Foo': 'bar', 'User-agent': 'ansible-tests' } assert req.data is None assert req.get_method() == 'GET'
class iControlRestSession(object): """Represents a session that communicates with a BigIP. This acts as a loose wrapper around Ansible's ``Request`` class. We're doing this as interim work until we move to the httpapi connector. """ def __init__(self, headers=None, use_proxy=True, force=False, timeout=120, validate_certs=True, url_username=None, url_password=None, http_agent=None, force_basic_auth=False, follow_redirects='urllib2', client_cert=None, client_key=None, cookies=None): self.request = Request( headers=headers, use_proxy=use_proxy, force=force, timeout=timeout, validate_certs=validate_certs, url_username=url_username, url_password=url_password, http_agent=http_agent, force_basic_auth=force_basic_auth, follow_redirects=follow_redirects, client_cert=client_cert, client_key=client_key, cookies=cookies ) self.last_url = None def get_headers(self, result): try: return dict(result.getheaders()) except AttributeError: return result.headers def update_response(self, response, result): response.headers = self.get_headers(result) response._content = result.read() response.status = result.getcode() response.url = result.geturl() response.msg = "OK (%s bytes)" % response.headers.get('Content-Length', 'unknown') def send(self, method, url, **kwargs): response = Response() # Set the last_url called # # This is used by the object destructor to erase the token when the # ModuleManager exits and destroys the iControlRestSession object self.last_url = url body = None data = kwargs.pop('data', None) json = kwargs.pop('json', None) if not data and json is not None: self.request.headers['Content-Type'] = 'application/json' body = _json.dumps(json) if not isinstance(body, bytes): body = body.encode('utf-8') if data: body = data if body: kwargs['data'] = body try: result = self.request.open(method, url, **kwargs) except HTTPError as e: # Catch HTTPError delivered from Ansible # # The structure of this object, in Ansible 2.8 is # # HttpError { # args # characters_written # close # code # delete # errno # file # filename # filename2 # fp # getcode # geturl # hdrs # headers # info # msg # name # reason # strerror # url # with_traceback # } self.update_response(response, e) return response self.update_response(response, result) return response def delete(self, url, **kwargs): return self.send('DELETE', url, **kwargs) def get(self, url, **kwargs): return self.send('GET', url, **kwargs) def patch(self, url, data=None, **kwargs): return self.send('PATCH', url, data=data, **kwargs) def post(self, url, data=None, **kwargs): return self.send('POST', url, data=data, **kwargs) def put(self, url, data=None, **kwargs): return self.send('PUT', url, data=data, **kwargs) def __del__(self): if self.last_url is None: return token = self.request.headers.get('X-F5-Auth-Token', None) if not token: return try: p = generic_urlparse(urlparse(self.last_url)) uri = "https://{0}:{1}/mgmt/shared/authz/tokens/{2}".format( p['hostname'], p['port'], token ) self.delete(uri) except ValueError: pass