Skip to content

fix(local-dev): Extend lakekeeper setup for windows - #7141

Draft
Mrudhulraj wants to merge 1 commit into
apache:mainfrom
Mrudhulraj:fix/windows-setup
Draft

fix(local-dev): Extend lakekeeper setup for windows#7141
Mrudhulraj wants to merge 1 commit into
apache:mainfrom
Mrudhulraj:fix/windows-setup

Conversation

@Mrudhulraj

@Mrudhulraj Mrudhulraj commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

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.sh script to verify.
image

Was this PR authored or co-authored using generative AI tooling?

No, AI usage reused the existing Darwin method to resolve it.

@github-actions

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Contributors with relevant context: @Yicong-Huang
    You can notify them by mentioning @Yicong-Huang in a comment.

@Mrudhulraj Mrudhulraj changed the title Extend lakekeeper setup for windows fix(local-dev): Extend lakekeeper setup for windows Jul 30, 2026
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Backport auto-label report

This fix: PR was checked against each actively-supported release branch. release/* labels drive the post-merge backport, so add or remove one to change where this fix lands.

Release branch Analysis
⚠️ release/v1.2 Not labeled automatically — none of the files this PR modifies exist on this branch (bin/local-dev/main.sh). The fix may target code that isn't on this release, or the files were moved/renamed after the branch was cut. Please check and add release/v1.2 by hand if this fix should be backported here.

Auto-label run.

@Mrudhulraj

Copy link
Copy Markdown
Contributor Author

@Yicong-Huang would appreciate your review here.

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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 first ipconfig IPv4 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_ip still reports "the macOS and Linux probes" on Windows, where the ipconfig probe is what actually ran; extend its uname -s switch with a Windows case (advisory)

Polish: 1 quick touch-up (see inline comments).

Comment thread bin/local-dev/main.sh Outdated
Comment thread bin/local-dev/main.sh Outdated
@Mrudhulraj
Mrudhulraj marked this pull request as draft July 31, 2026 16:00
@Mrudhulraj
Mrudhulraj marked this pull request as ready for review August 11, 2026 23:01
@Mrudhulraj

Mrudhulraj commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Hi @Yicong-Huang,

I have revisited this. I took a different approach using the netsh tool, which closely resembles the Linux method by retrieving the index of the default gateway from the route table based on the gateway names.

In the route table, we ensure that we obtain the correct gateway index (idx). Following this, we use the idx to finally retrieve the IPv4 address.

Tested this out:
image

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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-ip cases 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 no exit, so a second IPv4 puts a newline inside STORAGE_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 sibling feat(local-dev): support Linux (#7077) both say feat; 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.

Comment thread bin/local-dev/main.sh Outdated
Comment thread bin/local-dev/main.sh Outdated
Comment thread bin/local-dev/main.sh
# 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() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread bin/local-dev/main.sh
return 0
fi
fi
return 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread bin/local-dev/main.sh Outdated
Comment thread bin/local-dev/main.sh Outdated

@Yicong-Huang Yicong-Huang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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-ip cases; 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:472Local now 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 is feat(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.

Comment thread bin/local-dev/main.sh

# 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
if [[ -z "$iface_name" ]] || echo "$iface_name" | grep -qE "$virt_excl"; then
if [[ -z "$iface_name" ]] || echo "$iface_name" | grep -qiE "$virt_excl"; then

Comment thread bin/local-dev/main.sh
_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"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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"

Comment thread bin/local-dev/main.sh
# 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" '{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exclusion moved down to the adapter name, so this awk program never reads excl.

Suggested change
awk -v excl="$virt_excl" '{
awk '{

Comment thread bin/local-dev/main.sh
# 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=""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
local iface_details="" local_ip=""
local iface_details="" local_ip="" iface_name="" idx=""

Comment thread bin/local-dev/main.sh
if [[ -z "$iface_name" ]] || echo "$iface_name" | grep -qE "$virt_excl"; then
continue
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace-only line.

Suggested change

@Mrudhulraj
Mrudhulraj marked this pull request as draft August 13, 2026 00:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Setup Failure: Lakekeeper-init container fails with parse error for Windows local setup.

2 participants