Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite3b373f

Browse files
committed
Added proxy variable to read values from environment
What type of PR is this?/kind bugWhat this PR does / why we need it:This PRs will read environment variables assigned for proxy and no_proxy.Update ws_client_test.pyUpdate configuration.pyWhat type of PR is this?/kind bugWhat this PR does / why we need it:This PRs will read environment variables assigned for proxy and no_proxy.Update configuration.pyAdd debug logging doc and exampleadd .readthedocs.yaml config fileAddedAdded insert_proxy_config.sh to edit configuration.py in clientRevert "Added insert_proxy_config.sh to edit configuration.py in client"This reverts commitb295c2d.To avoid condition self.no_proxy is already present
1 parent230925f commite3b373f

File tree

7 files changed

+352
-21
lines changed

7 files changed

+352
-21
lines changed

‎.readthedocs.yaml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Read the Docs configuration file for Sphinx projects
2+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3+
4+
# Required
5+
version:2
6+
7+
# Set the OS, Python version and other tools you might need
8+
build:
9+
os:ubuntu-22.04
10+
tools:
11+
python:"3.12"
12+
# You can also specify other tool versions:
13+
# nodejs: "20"
14+
# rust: "1.70"
15+
# golang: "1.20"
16+
17+
# Build documentation in the "docs/" directory with Sphinx
18+
sphinx:
19+
configuration:doc/source/conf.py
20+
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
21+
# builder: "dirhtml"
22+
# Fail on all warnings to avoid broken references
23+
# fail_on_warning: true
24+
25+
# Optionally build your docs in additional formats such as PDF and ePub
26+
# formats:
27+
# - pdf
28+
# - epub
29+
30+
# Optional but recommended, declare the Python requirements required
31+
# to build your documentation
32+
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
33+
python:
34+
install:
35+
-requirements:doc/requirements-docs.txt
36+
-requirements:test-requirements.txt
37+
38+
39+
# git clone --depth 1 https://github.com/kubernetes-client/python .
40+
# git fetch origin --force --prune --prune-tags --depth 50 refs/heads/master:refs/remotes/origin/master
41+
# git checkout --force origin/master
42+
# git clean -d -f -f
43+
# python3.7 -mvirtualenv $READTHEDOCS_VIRTUALENV_PATH
44+
# python -m pip install --upgrade --no-cache-dir pip setuptools
45+
# python -m pip install --upgrade --no-cache-dir pillow mock==1.0.1 alabaster>=0.7,<0.8,!=0.7.5 commonmark==0.9.1 recommonmark==0.5.0 sphinx<2 sphinx-rtd-theme<0.5 readthedocs-sphinx-ext<2.3 jinja2<3.1.0
46+
47+
# cat doc/source/conf.py
48+
# python -m sphinx -T -E -b html -d _build/doctrees -D language=en . $READTHEDOCS_OUTPUT/html
49+
# python -m sphinx -T -E -b readthedocssinglehtmllocalmedia -d _build/doctrees -D language=en . $READTHEDOCS_OUTPUT/htmlzip
50+
# python -m sphinx -T -E -b latex -d _build/doctrees -D language=en . $READTHEDOCS_OUTPUT/pdf
51+
# cat latexmkrc
52+
# latexmk -r latexmkrc -pdf -f -dvi- -ps- -jobname=kubernetes -interaction=nonstopmode
53+
# python -m sphinx -T -E -b epub -d _build/doctrees -D language=en . $READTHEDOCS_OUTPUT/epub

‎devel/debug_logging.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#Enabling Debug Logging in Kubernetes Python Client
2+
3+
This document describes how to enable debug logging, view logged information, and provides examples for creating, patching, and deleting Kubernetes resources.
4+
5+
##1. Why Enable Debug Logging?
6+
7+
Debug logging is useful for troubleshooting as it shows details like HTTP request and response headers and bodies. These details can help identify issues during interactions with the Kubernetes API server.
8+
9+
---
10+
11+
##2. Enabling Debug Logging
12+
13+
To enable debug logging in the Kubernetes Python client, follow these steps:
14+
15+
1.**Modify the Configuration Object:**
16+
Enable debug mode by setting the`debug` attribute of the`client.Configuration` object to`True`.
17+
18+
2.**Example Code to Enable Debug Logging:**
19+
Below is an example showing how to enable debug logging:
20+
```python
21+
from kubernetesimport client, config
22+
23+
# Load kube config
24+
config.load_kube_config()
25+
26+
# Enable debug logging
27+
c= client.Configuration()
28+
c.debug=True
29+
30+
# Pass the updated configuration to the API client
31+
api_client= client.ApiClient(configuration=c)
32+
33+
# Use the API client with debug logging enabled
34+
apps_v1= client.AppsV1Api(api_client=api_client)

‎examples/enable_debug_logging.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Copyright 2025 The Kubernetes Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# You may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# This example demonstrates how to enable debug logging in the Kubernetes
10+
# Python client and how it can be used for troubleshooting requests/responses.
11+
12+
fromkubernetesimportclient,config
13+
14+
15+
defmain():
16+
# Load kubeconfig from default location
17+
config.load_kube_config()
18+
19+
# Enable debug logging
20+
configuration=client.Configuration()
21+
configuration.debug=True
22+
api_client=client.ApiClient(configuration=configuration)
23+
24+
# Use AppsV1Api with debug logging enabled
25+
apps_v1=client.AppsV1Api(api_client=api_client)
26+
27+
# Example: Create a dummy deployment (adjust namespace as needed)
28+
deployment=client.V1Deployment(
29+
api_version="apps/v1",
30+
kind="Deployment",
31+
metadata=client.V1ObjectMeta(name="debug-example"),
32+
spec=client.V1DeploymentSpec(
33+
replicas=1,
34+
selector={"matchLabels": {"app":"debug"}},
35+
template=client.V1PodTemplateSpec(
36+
metadata=client.V1ObjectMeta(labels={"app":"debug"}),
37+
spec=client.V1PodSpec(
38+
containers=[
39+
client.V1Container(
40+
name="busybox",
41+
image="busybox",
42+
command=["sh","-c","echo Hello, Kubernetes! && sleep 3600"]
43+
)
44+
]
45+
),
46+
),
47+
),
48+
)
49+
50+
# Create the deployment
51+
try:
52+
print("[INFO] Creating deployment...")
53+
apps_v1.create_namespaced_deployment(
54+
namespace="default",body=deployment
55+
)
56+
exceptclient.exceptions.ApiExceptionase:
57+
print("[ERROR] Exception occurred:",e)
58+
59+
60+
if__name__=="__main__":
61+
main()

‎kubernetes/base/stream/ws_client_test.py

Lines changed: 118 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,70 @@
1717
from .ws_clientimportget_websocket_url
1818
from .ws_clientimportwebsocket_proxycare
1919
fromkubernetes.client.configurationimportConfiguration
20+
importos
21+
importsocket
22+
importthreading
23+
importpytest
24+
fromkubernetesimportstream,client,config
2025

2126
try:
2227
importurllib3
2328
urllib3.disable_warnings()
2429
exceptImportError:
2530
pass
31+
@pytest.fixture(autouse=True)
32+
defdummy_kubeconfig(tmp_path,monkeypatch):
33+
# Creating a kubeconfig
34+
content="""
35+
apiVersion: v1
36+
kind: Config
37+
clusters:
38+
- name: default
39+
cluster:
40+
server: http://127.0.0.1:8888
41+
contexts:
42+
- name: default
43+
context:
44+
cluster: default
45+
user: default
46+
users:
47+
- name: default
48+
user: {}
49+
current-context: default
50+
"""
51+
cfg_file=tmp_path/"kubeconfig"
52+
cfg_file.write_text(content)
53+
monkeypatch.setenv("KUBECONFIG",str(cfg_file))
2654

27-
defdictval(dict,key,default=None):
28-
try:
29-
val=dict[key]
30-
exceptKeyError:
31-
val=default
32-
returnval
55+
56+
defdictval(dict_obj,key,default=None):
57+
58+
returndict_obj.get(key,default)
59+
60+
classDummyProxy(threading.Thread):
61+
"""
62+
A minimal HTTP proxy that flags any CONNECT request and returns 200 OK.
63+
Listens on 127.0.0.1:8888 by default.
64+
"""
65+
def__init__(self,host='127.0.0.1',port=8888):
66+
super().__init__(daemon=True)
67+
self.host=host
68+
self.port=port
69+
self.received_connect=False
70+
self._server_sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
71+
self._server_sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
72+
self._server_sock.bind((self.host,self.port))
73+
self._server_sock.listen(1)
74+
75+
defrun(self):
76+
conn,_=self._server_sock.accept()
77+
try:
78+
data=conn.recv(1024).decode('utf-8',errors='ignore')
79+
ifdata.startswith('CONNECT '):
80+
self.received_connect=True
81+
conn.sendall(b"HTTP/1.1 200 Connection established\r\n\r\n")
82+
finally:
83+
conn.close()
3384

3485
classWSClientTest(unittest.TestCase):
3586

@@ -56,21 +107,68 @@ def test_websocket_proxycare(self):
56107
('http://proxy.example.com:8080/','user:pass','.example.com','proxy.example.com',8080, ('user','pass'), ['.example.com']),
57108
('http://proxy.example.com:8080/','user:pass','localhost,.local,.example.com','proxy.example.com',8080, ('user','pass'), ['localhost','.local','.example.com']),
58109
]:
59-
#setup input
60-
config=Configuration()
61-
ifproxyisnotNone:
62-
setattr(config,'proxy',proxy)
63-
ifidpassisnotNone:
64-
setattr(config,'proxy_headers',urllib3.util.make_headers(proxy_basic_auth=idpass))
110+
# input setup
111+
cfg=Configuration()
112+
ifproxy:
113+
cfg.proxy=proxy
114+
ifidpass:
115+
cfg.proxy_headers=urllib3.util.make_headers(proxy_basic_auth=idpass)
65116
ifno_proxyisnotNone:
66-
setattr(config,'no_proxy',no_proxy)
67-
# setup done
68-
# test starts
69-
connect_opt=websocket_proxycare( {},config,None,None)
70-
self.assertEqual(dictval(connect_opt,'http_proxy_host'),expect_host)
71-
self.assertEqual(dictval(connect_opt,'http_proxy_port'),expect_port)
72-
self.assertEqual(dictval(connect_opt,'http_proxy_auth'),expect_auth)
73-
self.assertEqual(dictval(connect_opt,'http_no_proxy'),expect_noproxy)
117+
cfg.no_proxy=no_proxy
118+
119+
120+
connect_opts=websocket_proxycare({},cfg,None,None)
121+
assertdictval(connect_opts,'http_proxy_host')==expect_host
122+
assertdictval(connect_opts,'http_proxy_port')==expect_port
123+
assertdictval(connect_opts,'http_proxy_auth')==expect_auth
124+
assertdictval(connect_opts,'http_no_proxy')==expect_noproxy
125+
126+
@pytest.fixture(scope="module")
127+
defdummy_proxy():
128+
#Dummy Proxy
129+
proxy=DummyProxy(port=8888)
130+
proxy.start()
131+
yieldproxy
132+
133+
@pytest.fixture(autouse=True)
134+
defclear_proxy_env(monkeypatch):
135+
forvarin ("HTTP_PROXY","http_proxy","HTTPS_PROXY","https_proxy","NO_PROXY","no_proxy"):
136+
monkeypatch.delenv(var,raising=False)
137+
138+
defapply_proxy_to_conf():
139+
#apply HTTPS_PROXY env var and set it as global.
140+
cfg=client.Configuration.get_default_copy()
141+
cfg.proxy=os.getenv("HTTPS_PROXY")
142+
cfg.no_proxy=os.getenv("NO_PROXY","")
143+
client.Configuration.set_default(cfg)
144+
145+
deftest_rest_call_ignores_env(dummy_proxy,monkeypatch):
146+
# HTTPS_PROXY to dummy proxy
147+
monkeypatch.setenv("HTTPS_PROXY","http://127.0.0.1:8888")
148+
# Avoid real HTTP request
149+
monkeypatch.setattr(client.CoreV1Api,"list_namespace",lambdaself,*_args,**_kwargs:None)
150+
# Load config using kubeconfig
151+
config.load_kube_config(config_file=os.environ["KUBECONFIG"])
152+
apply_proxy_to_conf()
153+
# HTTPS_PROXY to dummy proxy
154+
monkeypatch.setenv("HTTPS_PROXY","http://127.0.0.1:8888")
155+
config.load_kube_config(config_file=os.environ["KUBECONFIG"])
156+
apply_proxy_to_conf()
157+
v1=client.CoreV1Api()
158+
v1.list_namespace(_preload_content=False)
159+
assertnotdummy_proxy.received_connect,"REST path should ignore HTTPS_PROXY"
160+
161+
deftest_websocket_call_honors_env(dummy_proxy,monkeypatch):
162+
# set HTTPS_PROXY again
163+
monkeypatch.setenv("HTTPS_PROXY","http://127.0.0.1:8888")
164+
# Load kubeconfig
165+
config.load_kube_config(config_file=os.environ["KUBECONFIG"])
166+
apply_proxy_to_conf()
167+
opts=websocket_proxycare({},client.Configuration.get_default_copy(),None,None)
168+
assertopts.get('http_proxy_host')=='127.0.0.1'
169+
assertopts.get('http_proxy_port')==8888
170+
# Optionally verify no_proxy parsing
171+
assertopts.get('http_no_proxy')isNone
74172

75173
if__name__=='__main__':
76174
unittest.main()

‎kubernetes/client/configuration.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
importmultiprocessing
1818
importsys
1919
importurllib3
20+
importos
2021

2122
importsix
2223
fromsix.movesimporthttp_clientashttplib
@@ -158,9 +159,15 @@ def __init__(self, host="http://localhost",
158159
"""
159160

160161
self.proxy=None
162+
if(os.getenv("HTTPS_PROXY")):self.proxy=os.getenv("HTTPS_PROXY")
163+
if(os.getenv("https_proxy")):self.proxy=os.getenv("https_proxy")
164+
if(os.getenv("HTTP_PROXY")):self.proxy=os.getenv("HTTP_PROXY")
165+
if(os.getenv("http_proxy")):self.proxy=os.getenv("http_proxy")
161166
"""Proxy URL
162167
"""
163168
self.no_proxy=None
169+
if(os.getenv("NO_PROXY")):self.no_proxy=os.getenv("NO_PROXY")
170+
if(os.getenv("no_proxy")):self.no_proxy=os.getenv("no_proxy")
164171
"""bypass proxy for host in the no_proxy list.
165172
"""
166173
self.proxy_headers=None

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp