Merge pull request #2390 from p172913/master
Changes made in configuration.py to accept environmental variables
This commit is contained in:
commit
51f4db5706
@ -17,19 +17,70 @@ import unittest
|
||||
from .ws_client import get_websocket_url
|
||||
from .ws_client import websocket_proxycare
|
||||
from kubernetes.client.configuration import Configuration
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
import pytest
|
||||
from kubernetes import stream, client, config
|
||||
|
||||
try:
|
||||
import urllib3
|
||||
urllib3.disable_warnings()
|
||||
except ImportError:
|
||||
pass
|
||||
@pytest.fixture(autouse=True)
|
||||
def dummy_kubeconfig(tmp_path, monkeypatch):
|
||||
# Creating a kubeconfig
|
||||
content = """
|
||||
apiVersion: v1
|
||||
kind: Config
|
||||
clusters:
|
||||
- name: default
|
||||
cluster:
|
||||
server: http://127.0.0.1:8888
|
||||
contexts:
|
||||
- name: default
|
||||
context:
|
||||
cluster: default
|
||||
user: default
|
||||
users:
|
||||
- name: default
|
||||
user: {}
|
||||
current-context: default
|
||||
"""
|
||||
cfg_file = tmp_path / "kubeconfig"
|
||||
cfg_file.write_text(content)
|
||||
monkeypatch.setenv("KUBECONFIG", str(cfg_file))
|
||||
|
||||
def dictval(dict, key, default=None):
|
||||
try:
|
||||
val = dict[key]
|
||||
except KeyError:
|
||||
val = default
|
||||
return val
|
||||
|
||||
def dictval(dict_obj, key, default=None):
|
||||
|
||||
return dict_obj.get(key, default)
|
||||
|
||||
class DummyProxy(threading.Thread):
|
||||
"""
|
||||
A minimal HTTP proxy that flags any CONNECT request and returns 200 OK.
|
||||
Listens on 127.0.0.1:8888 by default.
|
||||
"""
|
||||
def __init__(self, host='127.0.0.1', port=8888):
|
||||
super().__init__(daemon=True)
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.received_connect = False
|
||||
self._server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self._server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self._server_sock.bind((self.host, self.port))
|
||||
self._server_sock.listen(1)
|
||||
|
||||
def run(self):
|
||||
conn, _ = self._server_sock.accept()
|
||||
try:
|
||||
data = conn.recv(1024).decode('utf-8', errors='ignore')
|
||||
if data.startswith('CONNECT '):
|
||||
self.received_connect = True
|
||||
conn.sendall(b"HTTP/1.1 200 Connection established\r\n\r\n")
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
class WSClientTest(unittest.TestCase):
|
||||
|
||||
@ -56,21 +107,68 @@ class WSClientTest(unittest.TestCase):
|
||||
( 'http://proxy.example.com:8080/', 'user:pass', '.example.com', 'proxy.example.com', 8080, ('user','pass'), ['.example.com']),
|
||||
( 'http://proxy.example.com:8080/', 'user:pass', 'localhost,.local,.example.com', 'proxy.example.com', 8080, ('user','pass'), ['localhost','.local','.example.com']),
|
||||
]:
|
||||
# setup input
|
||||
config = Configuration()
|
||||
if proxy is not None:
|
||||
setattr(config, 'proxy', proxy)
|
||||
if idpass is not None:
|
||||
setattr(config, 'proxy_headers', urllib3.util.make_headers(proxy_basic_auth=idpass))
|
||||
# input setup
|
||||
cfg = Configuration()
|
||||
if proxy:
|
||||
cfg.proxy = proxy
|
||||
if idpass:
|
||||
cfg.proxy_headers = urllib3.util.make_headers(proxy_basic_auth=idpass)
|
||||
if no_proxy is not None:
|
||||
setattr(config, 'no_proxy', no_proxy)
|
||||
# setup done
|
||||
# test starts
|
||||
connect_opt = websocket_proxycare( {}, config, None, None)
|
||||
self.assertEqual( dictval(connect_opt,'http_proxy_host'), expect_host)
|
||||
self.assertEqual( dictval(connect_opt,'http_proxy_port'), expect_port)
|
||||
self.assertEqual( dictval(connect_opt,'http_proxy_auth'), expect_auth)
|
||||
self.assertEqual( dictval(connect_opt,'http_no_proxy'), expect_noproxy)
|
||||
cfg.no_proxy = no_proxy
|
||||
|
||||
|
||||
connect_opts = websocket_proxycare({}, cfg, None, None)
|
||||
assert dictval(connect_opts, 'http_proxy_host') == expect_host
|
||||
assert dictval(connect_opts, 'http_proxy_port') == expect_port
|
||||
assert dictval(connect_opts, 'http_proxy_auth') == expect_auth
|
||||
assert dictval(connect_opts, 'http_no_proxy') == expect_noproxy
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def dummy_proxy():
|
||||
#Dummy Proxy
|
||||
proxy = DummyProxy(port=8888)
|
||||
proxy.start()
|
||||
yield proxy
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def clear_proxy_env(monkeypatch):
|
||||
for var in ("HTTP_PROXY", "http_proxy", "HTTPS_PROXY", "https_proxy", "NO_PROXY", "no_proxy"):
|
||||
monkeypatch.delenv(var, raising=False)
|
||||
|
||||
def apply_proxy_to_conf():
|
||||
#apply HTTPS_PROXY env var and set it as global.
|
||||
cfg = client.Configuration.get_default_copy()
|
||||
cfg.proxy = os.getenv("HTTPS_PROXY")
|
||||
cfg.no_proxy = os.getenv("NO_PROXY", "")
|
||||
client.Configuration.set_default(cfg)
|
||||
|
||||
def test_rest_call_ignores_env(dummy_proxy, monkeypatch):
|
||||
# HTTPS_PROXY to dummy proxy
|
||||
monkeypatch.setenv("HTTPS_PROXY", "http://127.0.0.1:8888")
|
||||
# Avoid real HTTP request
|
||||
monkeypatch.setattr(client.CoreV1Api, "list_namespace", lambda self, *_args, **_kwargs: None)
|
||||
# Load config using kubeconfig
|
||||
config.load_kube_config(config_file=os.environ["KUBECONFIG"])
|
||||
apply_proxy_to_conf()
|
||||
# HTTPS_PROXY to dummy proxy
|
||||
monkeypatch.setenv("HTTPS_PROXY", "http://127.0.0.1:8888")
|
||||
config.load_kube_config(config_file=os.environ["KUBECONFIG"])
|
||||
apply_proxy_to_conf()
|
||||
v1 = client.CoreV1Api()
|
||||
v1.list_namespace(_preload_content=False)
|
||||
assert not dummy_proxy.received_connect, "REST path should ignore HTTPS_PROXY"
|
||||
|
||||
def test_websocket_call_honors_env(dummy_proxy, monkeypatch):
|
||||
# set HTTPS_PROXY again
|
||||
monkeypatch.setenv("HTTPS_PROXY", "http://127.0.0.1:8888")
|
||||
# Load kubeconfig
|
||||
config.load_kube_config(config_file=os.environ["KUBECONFIG"])
|
||||
apply_proxy_to_conf()
|
||||
opts = websocket_proxycare({}, client.Configuration.get_default_copy(), None, None)
|
||||
assert opts.get('http_proxy_host') == '127.0.0.1'
|
||||
assert opts.get('http_proxy_port') == 8888
|
||||
# Optionally verify no_proxy parsing
|
||||
assert opts.get('http_no_proxy') is None
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@ -17,6 +17,7 @@ import logging
|
||||
import multiprocessing
|
||||
import sys
|
||||
import urllib3
|
||||
import os
|
||||
|
||||
import six
|
||||
from six.moves import http_client as httplib
|
||||
@ -158,9 +159,15 @@ class Configuration(object):
|
||||
"""
|
||||
|
||||
self.proxy = None
|
||||
if(os.getenv("HTTPS_PROXY")):self.proxy=os.getenv("HTTPS_PROXY")
|
||||
if(os.getenv("https_proxy")):self.proxy=os.getenv("https_proxy")
|
||||
if(os.getenv("HTTP_PROXY")):self.proxy=os.getenv("HTTP_PROXY")
|
||||
if(os.getenv("http_proxy")):self.proxy=os.getenv("http_proxy")
|
||||
"""Proxy URL
|
||||
"""
|
||||
self.no_proxy = None
|
||||
if(os.getenv("NO_PROXY")):self.no_proxy=os.getenv("NO_PROXY")
|
||||
if(os.getenv("no_proxy")):self.no_proxy=os.getenv("no_proxy")
|
||||
"""bypass proxy for host in the no_proxy list.
|
||||
"""
|
||||
self.proxy_headers = None
|
||||
|
||||
77
scripts/insert_proxy_config.sh
Normal file
77
scripts/insert_proxy_config.sh
Normal file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bash
|
||||
# insert_proxy_config.sh - run this after openapi-generator release.sh
|
||||
CONFIG_PATH="../python_kubernetes/kubernetes/client"
|
||||
|
||||
# Compute the full file path
|
||||
CONFIG_FILE="$CONFIG_PATH/configuration.py"
|
||||
|
||||
# --- Normalize Windows-style backslashes to Unix forward slashes ---
|
||||
CONFIG_FILE="$(echo "$CONFIG_FILE" | sed 's|\\|/|g')"
|
||||
|
||||
# --- Ensure the target file exists and is writable ---
|
||||
if [ ! -f "$CONFIG_FILE" ] || [ ! -w "$CONFIG_FILE" ]; then
|
||||
echo "Error: $CONFIG_FILE does not exist or is not writable." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Step 1: Ensure 'import os' follows existing imports (idempotent) ---
|
||||
if ! grep -qE '^import os$' "$CONFIG_FILE"; then
|
||||
LAST_IMPORT=$(grep -nE '^(import |from )' "$CONFIG_FILE" | tail -n1 | cut -d: -f1)
|
||||
if [ -n "$LAST_IMPORT" ]; then
|
||||
sed -i "$((LAST_IMPORT+1))i import os" "$CONFIG_FILE"
|
||||
else
|
||||
if head -n1 "$CONFIG_FILE" | grep -q '^#!'; then
|
||||
sed -i '2i import os' "$CONFIG_FILE"
|
||||
else
|
||||
sed -i '1i import os' "$CONFIG_FILE"
|
||||
fi
|
||||
fi
|
||||
echo "Inserted 'import os' after existing imports in $CONFIG_FILE."
|
||||
else
|
||||
echo "'import os' already present; no changes made."
|
||||
fi
|
||||
|
||||
# --- Step 2: Insert proxy & no_proxy environment code ---
|
||||
if ! grep -q 'os.getenv("HTTPS_PROXY"' "$CONFIG_FILE"; then
|
||||
PROXY_LINE=$(grep -n "self.proxy = None" "$CONFIG_FILE" | cut -d: -f1)
|
||||
NO_PROXY_LINE=$(grep -n "^[[:space:]]*self\.no_proxy[[:space:]]*=[[:space:]]*None" "$CONFIG_FILE" | cut -d: -f1)
|
||||
|
||||
if [ -n "$PROXY_LINE" ]; then
|
||||
INDENT=$(sed -n "${PROXY_LINE}s/^\( *\).*/\1/p" "$CONFIG_FILE")
|
||||
|
||||
BLOCK=""
|
||||
|
||||
if [ -z "$NO_PROXY_LINE" ]; then
|
||||
# self.no_proxy = None is not present → insert full block after self.proxy = None
|
||||
BLOCK+="${INDENT}# Load proxy from environment variables (if set)\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"HTTPS_PROXY\"): self.proxy = os.getenv(\"HTTPS_PROXY\")\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"https_proxy\"): self.proxy = os.getenv(\"https_proxy\")\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"HTTP_PROXY\"): self.proxy = os.getenv(\"HTTP_PROXY\")\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"http_proxy\"): self.proxy = os.getenv(\"http_proxy\")\n"
|
||||
BLOCK+="${INDENT}self.no_proxy = None\n"
|
||||
BLOCK+="${INDENT}# Load no_proxy from environment variables (if set)\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"NO_PROXY\"): self.no_proxy = os.getenv(\"NO_PROXY\")\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"no_proxy\"): self.no_proxy = os.getenv(\"no_proxy\")"
|
||||
|
||||
sed -i "${PROXY_LINE}a $BLOCK" "$CONFIG_FILE"
|
||||
echo "Inserted full proxy + no_proxy block after 'self.proxy = None'."
|
||||
else
|
||||
# self.no_proxy = None exists → insert only env logic after that
|
||||
BLOCK+="${INDENT}# Load proxy from environment variables (if set)\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"HTTPS_PROXY\"): self.proxy = os.getenv(\"HTTPS_PROXY\")\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"https_proxy\"): self.proxy = os.getenv(\"https_proxy\")\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"HTTP_PROXY\"): self.proxy = os.getenv(\"HTTP_PROXY\")\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"http_proxy\"): self.proxy = os.getenv(\"http_proxy\")\n"
|
||||
BLOCK+="${INDENT}# Load no_proxy from environment variables (if set)\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"NO_PROXY\"): self.no_proxy = os.getenv(\"NO_PROXY\")\n"
|
||||
BLOCK+="${INDENT}if os.getenv(\"no_proxy\"): self.no_proxy = os.getenv(\"no_proxy\")"
|
||||
|
||||
sed -i "${NO_PROXY_LINE}a $BLOCK" "$CONFIG_FILE"
|
||||
echo "Inserted environment block after 'self.no_proxy = None'."
|
||||
fi
|
||||
else
|
||||
echo "Warning: 'self.proxy = None' not found in $CONFIG_FILE. No proxy code inserted."
|
||||
fi
|
||||
else
|
||||
echo "Proxy environment code already present; no changes made."
|
||||
fi
|
||||
@ -207,7 +207,8 @@ git diff-index --quiet --cached HEAD || git commit -am "update changelog"
|
||||
|
||||
# Re-generate the client
|
||||
scripts/update-client.sh
|
||||
|
||||
#edit comfiguration.py files
|
||||
scripts/insert_proxy_config.sh
|
||||
# Apply hotfixes
|
||||
rm -r kubernetes/test/
|
||||
git add .
|
||||
|
||||
Loading…
Reference in New Issue
Block a user