fix(local-dev): Extend lakekeeper setup for windows - #7141
Conversation
Automated Reviewer SuggestionsBased on the
|
Backport auto-label reportThis
|
|
@Yicong-Huang would appreciate your review here. |
217ec77 to
4dafc4b
Compare
Yicong-Huang
left a comment
There was a problem hiding this comment.
🔴 1 must-fix · 1 advisory · 1 polish — align the Windows IP probe with the darwin/linux filtering contract; the rest is minor.
Design & architecture (1)
bin/local-dev/main.sh:471— Windows probe takes the firstipconfigIPv4 with no default-route preference or virtual-adapter filtering; on a Docker Desktop host it can pick a container-unreachable vEthernet/Hyper-V/APIPA address (must-fix, see inline)
Correctness (1)
bin/local-dev/main.sh:546-552— the FATAL diagnostic in_require_host_lan_ipstill reports "the macOS and Linux probes" on Windows, where theipconfigprobe is what actually ran; extend itsuname -sswitch with a Windows case (advisory)
Polish: 1 quick touch-up (see inline comments).
4dafc4b to
3e6a9c5
Compare
|
Hi @Yicong-Huang, I have revisited this. I took a different approach using the In the route table, we ensure that we obtain the correct gateway index ( |
Yicong-Huang
left a comment
There was a problem hiding this comment.
🔴 2 resolved · 1 open · 8 new (8 new = 5 newly introduced · 3 late catches)
The netsh rewrite is the right move and closes most of the distance to the linux probe. Two of its three parsing steps still misbehave.
Design & architecture (3)
main.sh:481— the virtual-adapter regex is tested against the gateway IP column, so it can never fire; a full-tunnel VPN's default route wins (must-fix, see inline)main.sh:469— no unit test, though the sibling linux probe ships 8 fake-ipcases in the same suite (must-fix, see inline)main.sh:500— no step-2 fallback scan unlike both peers, and the block comment above now misdescribes the probe beneath it (advisory, see inline)
Correctness (2)
main.sh:492— the address awk has noexit, so a second IPv4 puts a newline insideSTORAGE_S3_ENDPOINT— #7138's parse error verbatim (must-fix, see inline)main.sh:575— the FATAL diagnostic still names "the macOS and Linux probes" on Windows (advisory, from the previous review — still open)
Conventions (2)
- Retitle →
feat(local-dev): detect the host LAN IP on Windows— Windows support never existed, so AGENTS.md and the siblingfeat(local-dev): support Linux(#7077) both sayfeat; no lakekeeper setup is touched (must-fix) - Description: bullet 1 still credits
ipconfig, which this round's netsh rewrite replaced; the generative-AI answer also reads as both "No" and an admission (advisory)
Polish: 2 quick touch-ups (see inline comments).
Verification trace
Both parsing findings were reproduced against real-shaped netsh output rather than reasoned from the code. Route parse: a single physical default route returns Idx 14, correctly; two default routes (10.8.0.1 via Idx 22, 192.168.1.1 via Idx 14) return 22, because the field virt_excl tests holds an IP that the regex cannot match. Address parse: an adapter with two IP Address: lines yields both addresses joined by a newline. It survives the -n / 127.* / 169.254.* guards and produces STORAGE_S3_ENDPOINT=http://192.168.1.100<newline>192.168.1.101:9000.
| # Both platform probes follow the same two steps: the interface backing the | ||
| # default route first (most reliable on a laptop that may have wifi + | ||
| # thunderbolt + tailscale all active), then a scan as a fallback. | ||
| _detect_host_lan_ip_windows() { |
There was a problem hiding this comment.
This probe needs the test its sibling got. Test 29 (bin/local-dev/tests/test_local_dev_sh.sh:600-690) extracts _detect_host_lan_ip_linux with awk and drives it against a fake ip on PATH — 8 cases, one being "default route over a bridge/VPN is skipped, not trusted".
It stubs the tool, so it runs anywhere. A fake netsh echoing canned show route / show addresses output would cover this function on the existing ubuntu and macos build / infra jobs. Both other findings here are cases such a test pins directly.
| return 0 | ||
| fi | ||
| fi | ||
| return 1 |
There was a problem hiding this comment.
No step-2 fallback here, unlike both peers: darwin scans en0-en10 (main.sh:510-513), linux scans every global IPv4 (main.sh:536-549). A Windows host with no default route, or with netsh output this awk can't parse, hard-exits at main.sh:583 instead of finding what a scan would.
Either way main.sh:466-468 needs a rewrite — it promises "the same two steps ... then a scan as a fallback" and now sits directly above a one-step probe. Adding the scan is the better fix: it makes that comment true again.
3e6a9c5 to
ccffb5e
Compare
ccffb5e to
ed83ea0
Compare
Yicong-Huang
left a comment
There was a problem hiding this comment.
🔴 4 resolved · 5 open · 5 new (5 new = 4 newly introduced · 1 late catch)
Round 2's two parsing bugs are genuinely gone. What's left is the token list itself: it under-excludes the VPN adapters it was written for, and over-excludes a physical one.
Design & architecture (3)
main.sh:469— still no test, though the linux sibling ships 8 fake-ipcases; I wrote the netsh equivalent and it caught both findings below (must-fix, thread still open)main.sh:503— no step-2 fallback scan unlike both peers, and the comment above still promises one (advisory, thread still open)main.sh:578— the FATAL diagnostic still names "the macOS and Linux probes" on Windows (advisory, from an earlier round)
Correctness (2)
main.sh:491— case-exact match, so the lowercase VPN tokens can never fire; a Tailscale default route wins (must-fix, see inline)main.sh:472—Localnow excludes the physical "Local Area Connection", so the probe hard-fails (must-fix, see inline)
Simplifications (1)
main.sh:477—-v excl=is dead now that the exclusion moved out of this awk (advisory, see inline)
Conventions (2)
- Retitle →
feat(local-dev): detect the host LAN IP on Windows— Windows support never existed, and no lakekeeper setup is touched; the merged sibling isfeat(local-dev): support Linux(must-fix) - Description: bullet 1 still credits
ipconfig, which netsh replaced two rounds ago; the generative-AI answer reads as both "No" and an admission (advisory)
Polish: 2 quick touch-ups (see inline comments).
Verification trace
Both findings were reproduced, not reasoned from the code: the function was extracted the way test 29 extracts its linux sibling, then driven against a fake netsh. Two default routes — Idx 22 Tailscale, Idx 14 Ethernet — returned the tailscale address. ZeroTier One [...] slipped through the same way; vEthernet (WSL) was correctly excluded. A single default route on Local Area Connection returned nothing, so _require_host_lan_ip hard-exits. Dropping Local and matching case-insensitively fixed both, and still accepted Ethernet, Wi-Fi, Ethernet 2 and Wireless Network Connection.
|
|
||
| # Skip if adapter name is empty or matches virtual/VPN exclusions | ||
| iface_name=$(echo "$iface_details" | awk -F'"' '/Configuration for interface/ {print $2}') | ||
| if [[ -z "$iface_name" ]] || echo "$iface_name" | grep -qE "$virt_excl"; then |
There was a problem hiding this comment.
This match is case-exact, but Windows adapter names are capitalized display names. Nine of the sixteen tokens (tailscale, zerotier, tap, tun, cni, flannel, cali, kube, wg) are lowercase Linux device names carried over from the peer, so they can never fire here. Reproduced against a fake netsh: with default routes via Idx 22 (Tailscale) and Idx 14 (Ethernet), the probe returns the tailscale address — the one address lakekeeper cannot route back to. ZeroTier One [...] slips through identically.
| if [[ -z "$iface_name" ]] || echo "$iface_name" | grep -qE "$virt_excl"; then | |
| if [[ -z "$iface_name" ]] || echo "$iface_name" | grep -qiE "$virt_excl"; then |
| _detect_host_lan_ip_windows() { | ||
| local iface_details="" local_ip="" | ||
|
|
||
| local virt_excl="vEthernet|WSL|Hyper-V|VirtualBox|Docker|Bridge|tap|tun|cni|flannel|cali|kube|Local|tailscale|zerotier|wg|McAfee" |
There was a problem hiding this comment.
Local was inert while the regex tested the gateway column; now that it tests adapter names it matches the physical "Local Area Connection". Reproduced: a single default route on that adapter makes the probe return 1, and with no fallback scan behind it main.sh:586 hard-exits.
| local virt_excl="vEthernet|WSL|Hyper-V|VirtualBox|Docker|Bridge|tap|tun|cni|flannel|cali|kube|Local|tailscale|zerotier|wg|McAfee" | |
| local virt_excl="vEthernet|WSL|Hyper-V|VirtualBox|Docker|Bridge|tap|tun|cni|flannel|cali|kube|tailscale|zerotier|wg|McAfee" |
| # associated with the 0.0.0.0/0 (default) route and trace the respective indices | ||
| local idx_list | ||
| idx_list=$(netsh interface ip show route 2>/dev/null | \ | ||
| awk -v excl="$virt_excl" '{ |
There was a problem hiding this comment.
The exclusion moved down to the adapter name, so this awk program never reads excl.
| awk -v excl="$virt_excl" '{ | |
| awk '{ |
| # default route first (most reliable on a laptop that may have wifi + | ||
| # thunderbolt + tailscale all active), then a scan as a fallback. | ||
| _detect_host_lan_ip_windows() { | ||
| local iface_details="" local_ip="" |
There was a problem hiding this comment.
iface_name and the idx loop variable land in the global scope. Both peers declare all of theirs — linux includes its idx at main.sh:522 — and the previous round of this function did too.
| local iface_details="" local_ip="" | |
| local iface_details="" local_ip="" iface_name="" idx="" |
| if [[ -z "$iface_name" ]] || echo "$iface_name" | grep -qE "$virt_excl"; then | ||
| continue | ||
| fi | ||
|
|
There was a problem hiding this comment.
Whitespace-only line.

What changes were proposed in this PR?
Added a dedicated helper function _detect_host_lan_ip_windows() to parse the primary non-loopback IPv4 address on Windows environments using ipconfig.
Using the routing table, determined the index of the default gateway interface, followed by finding the IP address of the host machine based on the index. Ensures Minio can be accessed as an endpoint from the host machine.
Ensured interface filtering that shares the default gateway of the host machine in the routing table.
Updated _detect_host_lan_ip() to recognize Windows kernel and shell environments (MINGW*, MSYS*, CYGWIN*, _NT) via uname -s and route them to _detect_host_lan_ip_windows().
Any related issues, documentation, discussions?
Fixes: #7138
IP resolution failures when running scripts on Windows host systems (e.g., Git Bash, MSYS2, or Cygwin).
Improves cross-platform parity between macOS (Darwin), Linux, and Windows for container/host networking setup.
How was this PR tested?
Verified manually. Attaching a screenshot.

Ran the
test_local_dev_sh.shscript to verify.Was this PR authored or co-authored using generative AI tooling?
No, AI usage reused the existing Darwin method to resolve it.