Skip to content

Commit df7f023

Browse files
windows: add shim modules, windows dev guide & setup script (issues kubernetes-client#2427 kubernetes-client#2428)
1 parent ab318a5 commit df7f023

File tree

7 files changed

+168
-5
lines changed

7 files changed

+168
-5
lines changed

WINDOWS_DEVELOPMENT.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Windows Development Guide
2+
3+
This repository historically used Unix symbolic links inside the `kubernetes` package (e.g. `kubernetes/config` -> `kubernetes/base/config`). Windows clones without Developer Mode or elevated privileges could not create these links, breaking imports.
4+
5+
## What Changed
6+
7+
Shim Python modules replaced symlink placeholders (`config`, `dynamic`, `watch`, `stream`, `leaderelection`). They re-export from `kubernetes.base.*` so public APIs remain the same and no filesystem symlink is required.
8+
9+
## Getting Started
10+
11+
1. Ensure Python 3.9+ is installed and on PATH.
12+
2. (Optional) Create virtual environment:
13+
14+
```powershell
15+
py -3 -m venv .venv
16+
.\.venv\Scripts\Activate.ps1
17+
```
18+
19+
3. Install requirements:
20+
21+
```powershell
22+
pip install -r requirements.txt -r test-requirements.txt
23+
```
24+
25+
4. Run a quick import smoke test:
26+
27+
```powershell
28+
python - <<'PY'
29+
from kubernetes import config, watch, dynamic, stream, leaderelection
30+
print('Imported packages OK')
31+
PY
32+
```
33+
34+
## Running Tests on Windows
35+
36+
`tox` can run most tests; some network / streaming tests are flaky under Windows due to timing. Recommended:
37+
38+
```powershell
39+
pip install tox
40+
tox -e py
41+
```
42+
43+
If you see intermittent websocket or watch hangs, re-run that specific test module with pytest's `-k` to isolate.
44+
45+
## Permission Semantics
46+
47+
Windows has different file permission behavior than POSIX; tests expecting strict mode bits may fail. Adjust or skip such tests with `pytest.mark.skipif(sys.platform.startswith('win'), ...)` when encountered (none required yet after shims).
48+
49+
## Streaming / WebSocket Notes
50+
51+
If exec/port-forward tests hang:
52+
53+
- Ensure firewall allows local loopback connections.
54+
- Set `PYTHONUNBUFFERED=1` to improve real-time logs.
55+
56+
## Troubleshooting
57+
58+
| Symptom | Fix |
59+
| ------- | --- |
60+
| `ModuleNotFoundError` for subpackages | Ensure shim files exist and you installed the package in editable mode `pip install -e .` |
61+
| Watch stream stalls | Use smaller `timeout_seconds` and retry; Windows networking latency differs |
62+
| PermissionError deleting temp files | Close file handles; Windows locks open files |
63+
64+
## Regenerating Client (Optional)
65+
66+
Regeneration scripts in `scripts/` assume a Unix-like environment. Use WSL2 or a Linux container when running `update-client.sh`.
67+
68+
## Contributing Windows Fixes
69+
70+
1. Create branch
71+
2. Add / adjust tests using `sys.platform` guards
72+
3. Run `ruff` or `flake8` (if adopted) and `tox`
73+
4. Open PR referencing related issue (e.g. #2427 #2428)
74+
75+
---
76+
77+
Maintainers: Please keep this doc updated as additional Windows-specific adjustments are made.

kubernetes/config

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
1-
base/config
1+
"""Windows-friendly shim: exposes symbols from kubernetes.base.config.
2+
3+
Previously this path used a symlink to base/config which is not portable on
4+
Windows (especially in workspaces lacking Developer Mode or proper
5+
permissions). Converting to a simple Python re-export preserves public API
6+
without requiring filesystem symlinks.
7+
"""
8+
9+
from kubernetes.base.config import * # noqa: F401,F403

kubernetes/dynamic

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1-
base/dynamic
1+
"""Windows-friendly shim for kubernetes.base.dynamic.
2+
3+
Replaces symlink with explicit import to maintain cross-platform behavior.
4+
"""
5+
6+
from kubernetes.base.dynamic import * # noqa: F401,F403

kubernetes/leaderelection

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
base/leaderelection
1+
"""Windows-friendly shim for kubernetes.base.leaderelection."""
2+
3+
from kubernetes.base.leaderelection import * # noqa: F401,F403

kubernetes/stream

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
base/stream
1+
"""Windows-friendly shim for kubernetes.base.stream."""
2+
3+
from kubernetes.base.stream import * # noqa: F401,F403

kubernetes/watch

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
base/watch
1+
"""Windows-friendly shim for kubernetes.base.watch."""
2+
3+
from kubernetes.base.watch import * # noqa: F401,F403
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<#
2+
.SYNOPSIS
3+
Bootstrap Windows development environment for Kubernetes Python client.
4+
5+
.DESCRIPTION
6+
Creates virtual environment (if missing), installs dependencies, and ensures
7+
shim modules (config/dynamic/watch/stream/leaderelection) contain re-export
8+
code replacing symlinks for Windows portability.
9+
10+
#>
11+
param(
12+
[string]$Python = "py",
13+
[string]$Venv = ".venv"
14+
)
15+
16+
$ErrorActionPreference = 'Stop'
17+
18+
function Write-Step($m){ Write-Host "[setup] $m" -ForegroundColor Cyan }
19+
20+
Write-Step "Python version"
21+
& $Python -3 -c "import sys; print(sys.version)" | Write-Host
22+
23+
if(!(Test-Path $Venv)){
24+
Write-Step "Creating venv $Venv"
25+
& $Python -3 -m venv $Venv
26+
}
27+
Write-Step "Activating venv"
28+
$activate = Join-Path $Venv 'Scripts/Activate.ps1'
29+
. $activate
30+
31+
Write-Step "Upgrading pip"
32+
python -m pip install --upgrade pip > $null
33+
34+
Write-Step "Installing requirements"
35+
if(Test-Path requirements.txt){ pip install -r requirements.txt }
36+
if(Test-Path test-requirements.txt){ pip install -r test-requirements.txt }
37+
38+
$shimMap = @{
39+
'kubernetes/config' = 'from kubernetes.base.config import * # noqa: F401,F403';
40+
'kubernetes/dynamic' = 'from kubernetes.base.dynamic import * # noqa: F401,F403';
41+
'kubernetes/watch' = 'from kubernetes.base.watch import * # noqa: F401,F403';
42+
'kubernetes/stream' = 'from kubernetes.base.stream import * # noqa: F401,F403';
43+
'kubernetes/leaderelection' = 'from kubernetes.base.leaderelection import * # noqa: F401,F403'
44+
}
45+
46+
foreach($path in $shimMap.Keys){
47+
if(Test-Path $path){
48+
$item = Get-Item $path
49+
if($item.PSIsContainer){ continue }
50+
$content = Get-Content $path -Raw
51+
if($content -notmatch 'kubernetes.base'){
52+
Write-Step "Updating shim $path"
53+
"""Windows shim auto-generated`n$($shimMap[$path])""" | Out-File -FilePath $path -Encoding UTF8
54+
}
55+
} else {
56+
Write-Step "Creating shim file $path"
57+
"""Windows shim auto-generated`n$($shimMap[$path])""" | Out-File -FilePath $path -Encoding UTF8
58+
}
59+
}
60+
61+
Write-Step "Smoke import"
62+
python - <<'PY'
63+
from kubernetes import config, dynamic, watch, stream, leaderelection
64+
print('Shim import success')
65+
PY
66+
67+
Write-Step "Done"

0 commit comments

Comments
 (0)