diff --git a/README.md b/README.md index 2b4f34aa5f..f77d95cc6f 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,23 @@ export OPENSHIFT_PYTHON_WRAPPER_LOG_LEVEL= # can be: "DEBUG", "INFO", export OPENSHIFT_PYTHON_WRAPPER_HASH_LOG_DATA="false" ``` +## Proxy Enablement + +This configuration allows the client to route traffic through a specified proxy server. +It can be enabled via the environment variable `OPENSHIFT_PYTHON_WRAPPER_CLIENT_USE_PROXY`. + +To enable proxy configuration for the client: + +1. Set the environment variable `OPENSHIFT_PYTHON_WRAPPER_CLIENT_USE_PROXY=` + +2. Define either `HTTPS_PROXY` or `HTTP_PROXY` environment variable with your proxy URL: +```bash +export HTTPS_PROXY="http://proxy.example.com:8080" +# or +export HTTP_PROXY="http://proxy.example.com:8080" +``` +If neither variable is set when proxy is enabled, a `ValueError` will be raised. + ## Code check We use pre-commit for code check. diff --git a/ocp_resources/resource.py b/ocp_resources/resource.py index f6b45a93d3..c744161b15 100644 --- a/ocp_resources/resource.py +++ b/ocp_resources/resource.py @@ -76,7 +76,10 @@ def _get_api_version(dyn_client: DynamicClient, api_group: str, kind: str) -> st def get_client( - config_file: str = "", config_dict: dict[str, Any] | None = None, context: str = "", **kwargs: Any + config_file: str = "", + config_dict: dict[str, Any] | None = None, + context: str = "", + **kwargs: Any, ) -> DynamicClient: """ Get a kubernetes client. @@ -104,6 +107,7 @@ def get_client( config_dict=config_dict, context=context or None, **kwargs ) ) + client_configuration = kwargs.get("client_configuration", kubernetes.client.Configuration()) try: # Ref: https://github.com/kubernetes-client/python/blob/v26.1.0/kubernetes/base/config/__init__.py LOGGER.info("Trying to get client via new_client_from_config") @@ -112,15 +116,34 @@ def get_client( # If `KUBECONFIG` environment variable is set via code, the `KUBE_CONFIG_DEFAULT_LOCATION` will be None since # is populated during import which comes before setting the variable in code. config_file = config_file or os.environ.get("KUBECONFIG", "~/.kube/config") + + if os.environ.get("OPENSHIFT_PYTHON_WRAPPER_CLIENT_USE_PROXY"): + proxy = os.environ.get("HTTPS_PROXY") or os.environ.get("HTTP_PROXY") + if not proxy: + raise ValueError( + "Proxy configuration is enabled but neither HTTPS_PROXY nor HTTP_PROXY environment variables are set." + ) + if client_configuration.proxy and client_configuration.proxy != proxy: + raise ValueError( + f"Conflicting proxy settings: client_configuration.proxy={client_configuration.proxy}, " + f"but the environment variable 'OPENSHIFT_PYTHON_WRAPPER_CLIENT_USE_PROXY' defines proxy as {proxy}." + ) + client_configuration.proxy = proxy + return kubernetes.dynamic.DynamicClient( - client=kubernetes.config.new_client_from_config(config_file=config_file, context=context or None, **kwargs) + client=kubernetes.config.new_client_from_config( + config_file=config_file, + client_configuration=client_configuration, + context=context or None, + **kwargs, + ) ) except MaxRetryError: # Ref: https://github.com/kubernetes-client/python/blob/v26.1.0/kubernetes/base/config/incluster_config.py LOGGER.info("Trying to get client via incluster_config") return kubernetes.dynamic.DynamicClient( client=kubernetes.config.incluster_config.load_incluster_config( - client_configuration=kwargs.get("client_configuration"), + client_configuration=client_configuration, try_refresh_token=kwargs.get("try_refresh_token", True), ) ) diff --git a/tests/test_resources.py b/tests/test_resources.py index 7f7487cdb5..403f76e81a 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -1,5 +1,6 @@ import pytest import yaml +import kubernetes from testcontainers.k3s import K3SContainer from ocp_resources.exceptions import ResourceTeardownError @@ -103,3 +104,26 @@ def test_resource_context_manager_exit(self, client): with pytest.raises(ResourceTeardownError): with TestSecretExit(name="test-context-manager-exit", namespace="default", client=client): pass + + def test_proxy_enabled_but_no_proxy_set(self, monkeypatch): + monkeypatch.setenv(name="OPENSHIFT_PYTHON_WRAPPER_CLIENT_USE_PROXY", value="1") + + with pytest.raises( + ValueError, + match="Proxy configuration is enabled but neither HTTPS_PROXY nor HTTP_PROXY environment variables are set.", + ): + get_client() + + def test_proxy_conflict_raises_value_error(self, monkeypatch): + monkeypatch.setenv(name="OPENSHIFT_PYTHON_WRAPPER_CLIENT_USE_PROXY", value="1") + monkeypatch.setenv(name="HTTPS_PROXY", value="http://env-proxy.com") + + client_configuration = kubernetes.client.Configuration() + client_configuration.proxy = "http://not-env-proxy.com" + + with pytest.raises( + ValueError, + match="Conflicting proxy settings: client_configuration.proxy=http://not-env-proxy.com, " + "but the environment variable 'OPENSHIFT_PYTHON_WRAPPER_CLIENT_USE_PROXY' defines proxy as http://env-proxy.com.", + ): + get_client(client_configuration=client_configuration)