-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #276 from gurock/feat/add-http-proxy
Add http proxy support
- Loading branch information
Showing
10 changed files
with
309 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import pytest | ||
from trcli.constants import FAULT_MAPPING | ||
from trcli.cli import Environment | ||
from requests.exceptions import ProxyError | ||
from trcli.api.api_client import APIClient | ||
from tests.helpers.api_client_helpers import ( | ||
TEST_RAIL_URL, | ||
create_url, | ||
check_response, | ||
check_calls_count, | ||
) | ||
from tests.test_data.proxy_test_data import FAKE_PROJECT_DATA, FAKE_PROXY, FAKE_PROXY_USER, PROXY_ERROR_MESSAGE | ||
|
||
|
||
@pytest.fixture(scope="class") | ||
def api_resources_maker(): | ||
def _make_api_resources(retries=3, environment=None, timeout=30, proxy=None, proxy_user=None, noproxy=None): | ||
if environment is None: | ||
environment = Environment() | ||
environment.verbose = False | ||
api_client = APIClient( | ||
host_name=TEST_RAIL_URL, | ||
verbose_logging_function=environment.vlog, | ||
logging_function=environment.log, | ||
retries=retries, | ||
timeout=timeout, | ||
proxy=proxy, | ||
proxy_user=proxy_user, | ||
noproxy=noproxy, # For bypassing proxy when using --noproxy | ||
) | ||
return api_client | ||
|
||
return _make_api_resources | ||
|
||
|
||
@pytest.fixture(scope="class") | ||
def api_resources(api_resources_maker): | ||
yield api_resources_maker() | ||
|
||
|
||
class TestAPIClientProxy: | ||
@pytest.mark.proxy | ||
def test_send_get_with_proxy(self, api_resources_maker, requests_mock): | ||
"""Test send_get works correctly with a proxy.""" | ||
requests_mock.get(create_url("get_projects"), status_code=200, json=FAKE_PROJECT_DATA) | ||
api_client = api_resources_maker(proxy=FAKE_PROXY) | ||
|
||
response = api_client.send_get("get_projects") | ||
|
||
check_calls_count(requests_mock) | ||
check_response(200, FAKE_PROJECT_DATA, "", response) | ||
|
||
@pytest.mark.proxy | ||
def test_send_post_with_proxy(self, api_resources_maker, requests_mock): | ||
"""Test send_post works correctly with a proxy.""" | ||
requests_mock.post(create_url("add_project"), status_code=201, json=FAKE_PROJECT_DATA) | ||
api_client = api_resources_maker(proxy=FAKE_PROXY) | ||
|
||
response = api_client.send_post("add_project", FAKE_PROJECT_DATA) | ||
|
||
check_calls_count(requests_mock) | ||
check_response(201, FAKE_PROJECT_DATA, "", response) | ||
|
||
@pytest.mark.proxy | ||
def test_send_get_with_proxy_authentication(self, api_resources_maker, requests_mock, mocker): | ||
"""Test proxy with authentication (proxy_user).""" | ||
requests_mock.get(create_url("get_projects"), status_code=200, json=FAKE_PROJECT_DATA) | ||
basic_auth_mock = mocker.patch("trcli.api.api_client.b64encode") | ||
|
||
api_client = api_resources_maker(proxy=FAKE_PROXY, proxy_user=FAKE_PROXY_USER) | ||
_ = api_client.send_get("get_projects") | ||
|
||
basic_auth_mock.assert_called_once_with(FAKE_PROXY_USER.encode('utf-8')) | ||
|
||
@pytest.mark.proxy | ||
def test_send_get_proxy_error(self, api_resources_maker, requests_mock): | ||
"""Test handling a proxy authentication failure.""" | ||
requests_mock.get(create_url("get_projects"), exc=ProxyError) | ||
|
||
api_client = api_resources_maker(proxy=FAKE_PROXY) | ||
|
||
response = api_client.send_get("get_projects") | ||
|
||
check_calls_count(requests_mock) | ||
check_response(-1, "", PROXY_ERROR_MESSAGE, response) | ||
|
||
@pytest.mark.proxy | ||
def test_send_get_no_proxy(self, api_resources_maker, requests_mock): | ||
"""Test API request without a proxy (no --proxy provided).""" | ||
requests_mock.get(create_url("get_projects"), status_code=200, json=FAKE_PROJECT_DATA) | ||
api_client = api_resources_maker() | ||
|
||
response = api_client.send_get("get_projects") | ||
|
||
check_calls_count(requests_mock) | ||
check_response(200, FAKE_PROJECT_DATA, "", response) | ||
|
||
@pytest.mark.proxy | ||
def test_send_get_bypass_proxy(self, api_resources_maker, requests_mock, mocker): | ||
"""Test that proxy is bypassed for certain hosts using --noproxy option.""" | ||
requests_mock.get(create_url("get_projects"), status_code=200, json=FAKE_PROJECT_DATA) | ||
proxy_bypass_mock = mocker.patch("trcli.api.api_client.APIClient._get_proxies_for_request", return_value=None) | ||
|
||
api_client = api_resources_maker(proxy=FAKE_PROXY, noproxy="127.0.0.1") | ||
_ = api_client.send_get("get_projects") | ||
|
||
proxy_bypass_mock.assert_called_once() | ||
|
||
@pytest.mark.proxy | ||
def test_send_get_with_invalid_proxy_user(self, api_resources_maker, requests_mock, mocker): | ||
"""Test handling invalid proxy authentication.""" | ||
requests_mock.get(create_url("get_projects"), exc=ProxyError) | ||
|
||
api_client = api_resources_maker(proxy=FAKE_PROXY, proxy_user="invalid_user:invalid_password") | ||
|
||
response = api_client.send_get("get_projects") | ||
|
||
check_calls_count(requests_mock) | ||
check_response(-1, "", PROXY_ERROR_MESSAGE, response) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from trcli.settings import DEFAULT_API_CALL_TIMEOUT | ||
|
||
FAKE_PROJECT_DATA = {"fake_project_data": "data"} | ||
INVALID_TEST_CASE_ERROR = {"error": "Invalid or unknown test case"} | ||
API_RATE_LIMIT_REACHED_ERROR = {"error": "API rate limit reached"} | ||
NO_PERMISSION_PROJECT_ERROR = { | ||
"error": "No permissions to add projects (requires admin rights)" | ||
} | ||
TIMEOUT_PARSE_ERROR = ( | ||
f"Warning. Could not convert provided 'timeout' to float. " | ||
f"Please make sure that timeout format is correct. Setting to default: " | ||
f"{DEFAULT_API_CALL_TIMEOUT}" | ||
) | ||
|
||
#proxy test data | ||
FAKE_PROXY = "http://127.0.0.1:8080" | ||
FAKE_PROXY_USER = "username:password" | ||
|
||
PROXY_ERROR_MESSAGE = ( | ||
f"Failed to connect to the proxy server. Please check the proxy settings and ensure the server is available." | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
__version__ = "1.9.7" | ||
__version__ = "1.9.8" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.