Skip to content

Enable Integration tests in Windows CI #3280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 11 additions & 20 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,10 @@ jobs:
- name: Enable WSL2
run: |
wsl --set-default-version 2
# Manually install the latest kernel from MSI
Invoke-WebRequest -Uri "https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi" -OutFile "wsl_update_x64.msi"
$pwd = (pwd).Path
Start-Process msiexec.exe -Wait -ArgumentList "/I $pwd\wsl_update_x64.msi /quiet"
wsl --shutdown
wsl --update
wsl --status
wsl --version
wsl --list --online
- name: Install WSL2 distro
timeout-minutes: 1
Expand All @@ -160,22 +158,15 @@ jobs:
run: go test -v ./...
- name: Make
run: make
# FIXME: Windows CI began to fail on Oct 21, 2024.
# Something seems to have changed between win22/20241006.1 and win22/20241015.1.
# https://github.com/lima-vm/lima/issues/2775
# - name: Smoke test
# # Make sure the path is set properly and then run limactl
# run: |
# $env:Path = 'C:\Program Files\Git\usr\bin;' + $env:Path
# Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $env:Path
# .\_output\bin\limactl.exe start template://experimental/wsl2
# # TODO: run the full integration tests
# - name: Debug
# if: always()
# run: type C:\Users\runneradmin\.lima\wsl2\ha.stdout.log
# - name: Debug
# if: always()
# run: type C:\Users\runneradmin\.lima\wsl2\ha.stderr.log
- name: Integration tests (WSL2, Windows host)
run: |
$env:Path = "$pwd\_output\bin;" + 'C:\Program Files\Git\usr\bin;' + $env:Path
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $env:Path
$env:MSYS2_ENV_CONV_EXCL='HOME_HOST;HOME_GUEST'
$env:HOME_HOST=$(cygpath.exe "$env:USERPROFILE")
$env:HOME_GUEST="/mnt$env:HOME_HOST"
$env:LIMACTL_CREATE_ARGS='--vm-type=wsl2 --mount-type=wsl2 --containerd=system'
bash.exe -c "./hack/test-templates.sh templates/experimental/wsl2.yaml"

qemu:
name: "Integration tests (QEMU, macOS host)"
Expand Down
2 changes: 1 addition & 1 deletion hack/common.inc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ if [[ ${BASH_VERSINFO:-0} -lt 4 ]]; then
exit 1
fi

: "${LIMA_HOME:=$HOME/.lima}"
: "${LIMA_HOME:=${HOME_HOST:-$HOME}/.lima}"
_IPERF3=iperf3
# iperf3-darwin does some magic on macOS to avoid "No route on host" on macOS 15
# https://github.com/lima-vm/socket_vmnet/issues/85
Expand Down
5 changes: 3 additions & 2 deletions hack/test-mount-home.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ if [ "$#" -ne 1 ]; then
fi

NAME="$1"
hometmp="$HOME/lima-test-tmp"
hometmp="${HOME_HOST:-$HOME}/lima-test-tmp"
hometmpguest="${HOME_GUEST:-$HOME}/lima-test-tmp"
INFO "Testing home access (\"$hometmp\")"
rm -rf "$hometmp"
mkdir -p "$hometmp"
defer "rm -rf \"$hometmp\""
echo "random-content-${RANDOM}" >"$hometmp/random"
expected="$(cat "$hometmp/random")"
got="$(limactl shell "$NAME" cat "$hometmp/random")"
got="$(limactl shell "$NAME" cat "$hometmpguest/random")"
INFO "$hometmp/random: expected=${expected}, got=${got}"
if [ "$got" != "$expected" ]; then
ERROR "Home directory is not shared?"
Expand Down
3 changes: 2 additions & 1 deletion hack/test-port-forwarding.pl
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@
sleep 5;

# Record current log size, so we can skip prior output
$ENV{LIMA_HOME} ||= "$ENV{HOME}/.lima";
$ENV{HOME_HOST} ||= "$ENV{HOME}";
$ENV{LIMA_HOME} ||= "$ENV{HOME_HOST}/.lima";
my $ha_log = "$ENV{LIMA_HOME}/$instance/ha.stderr.log";
my $ha_log_size = -s $ha_log or die;

Expand Down
107 changes: 76 additions & 31 deletions hack/test-templates.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/usr/bin/env bash
set -eu -o pipefail

# will prevent msys2 converting Linux path arguments into Windows paths before passing to limactl
export MSYS2_ARG_CONV_EXCL='*'
Copy link
Member

@AkihiroSuda AkihiroSuda Feb 26, 2025

Choose a reason for hiding this comment

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

Needs a comment line for explanation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Commented


scriptdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=common.inc.sh
source "${scriptdir}/common.inc.sh"
Expand All @@ -12,16 +15,27 @@ fi

FILE="$1"
NAME="$(basename -s .yaml "$FILE")"
OS_HOST="$(uname -o)"

# On Windows $HOME of the bash runner, %USERPROFILE% of the host machine and mpunting point in the guest machine
# are all different folders. This will handle path differences, when values are expilictly set.
HOME_HOST=${HOME_HOST:-$HOME}
HOME_GUEST=${HOME_GUEST:-$HOME}
FILE_HOST=$FILE
if [ "${OS_HOST}" = "Msys" ]; then
FILE_HOST="$(cygpath -w "$FILE")"
fi

INFO "Validating \"$FILE\""
limactl validate "$FILE"
INFO "Validating \"$FILE_HOST\""
limactl validate "$FILE_HOST"

# --cpus=1 is needed for running vz on GHA: https://github.com/lima-vm/lima/pull/1511#issuecomment-1574937888
LIMACTL_CREATE=(limactl --tty=false create --cpus=1 --memory=1)

CONTAINER_ENGINE="nerdctl"

declare -A CHECKS=(
["proxy-settings"]="1"
["systemd"]="1"
["systemd-strict"]="1"
["mount-home"]="1"
Expand Down Expand Up @@ -69,6 +83,13 @@ case "$NAME" in
"docker")
CONTAINER_ENGINE="docker"
;;
"wsl2")
# TODO https://github.com/lima-vm/lima/issues/3267
CHECKS["systemd"]=
# TODO https://github.com/lima-vm/lima/issues/3268
CHECKS["proxy-settings"]=
CHECKS["port-forwards"]=
;;
esac

if limactl ls -q | grep -q "$NAME"; then
Expand All @@ -80,7 +101,7 @@ fi
# TODO: skip downloading and converting the image here.
# Probably `limactl create` should have "dry run" mode that just generates `lima.yaml`.
# shellcheck disable=SC2086
"${LIMACTL_CREATE[@]}" ${LIMACTL_CREATE_ARGS} --set ".additionalDisks=null" --name="${NAME}-tmp" "$FILE"
"${LIMACTL_CREATE[@]}" ${LIMACTL_CREATE_ARGS} --set ".additionalDisks=null" --name="${NAME}-tmp" "$FILE_HOST"
case "$(yq '.networks[].lima' "${LIMA_HOME}/${NAME}-tmp/lima.yaml")" in
"shared")
CHECKS["vmnet"]=1
Expand All @@ -93,32 +114,38 @@ esac
limactl rm -f "${NAME}-tmp"

if [[ -n ${CHECKS["port-forwards"]} ]]; then
tmpconfig="$HOME/lima-config-tmp"
tmpconfig="$HOME_HOST/lima-config-tmp"
mkdir -p "${tmpconfig}"
defer "rm -rf \"$tmpconfig\""
tmpfile="${tmpconfig}/${NAME}.yaml"
cp "$FILE" "${tmpfile}"
FILE="${tmpfile}"
FILE_HOST=$FILE
if [ "${OS_HOST}" = "Msys" ]; then
FILE_HOST="$(cygpath -w "$FILE")"
fi

INFO "Setup port forwarding rules for testing in \"${FILE}\""
"${scriptdir}/test-port-forwarding.pl" "${FILE}"
limactl validate "$FILE"
INFO "Validating \"$FILE_HOST\""
limactl validate "$FILE_HOST"
fi

function diagnose() {
NAME="$1"
set -x +e
tail "$HOME/.lima/${NAME}"/*.log
tail "$HOME_HOST/.lima/${NAME}"/*.log
limactl shell "$NAME" systemctl --no-pager status
limactl shell "$NAME" systemctl --no-pager
mkdir -p failure-logs
cp -pf "$HOME/.lima/${NAME}"/*.log failure-logs/
cp -pf "$HOME_HOST/.lima/${NAME}"/*.log failure-logs/
limactl shell "$NAME" sudo cat /var/log/cloud-init-output.log | tee failure-logs/cloud-init-output.log
set +x -e
}

export ftp_proxy=http://localhost:2121

INFO "Creating \"$NAME\" from \"$FILE\""
INFO "Creating \"$NAME\" from \"$FILE_HOST\""
defer "limactl delete -f \"$NAME\""

if [[ -n ${CHECKS["disk"]} ]]; then
Expand All @@ -130,7 +157,7 @@ fi

set -x
# shellcheck disable=SC2086
"${LIMACTL_CREATE[@]}" ${LIMACTL_CREATE_ARGS} "$FILE"
"${LIMACTL_CREATE[@]}" ${LIMACTL_CREATE_ARGS} "$FILE_HOST"
set +x

if [[ -n ${CHECKS["mount-path-with-spaces"]} ]]; then
Expand All @@ -152,7 +179,7 @@ limactl shell "$NAME" cat /etc/os-release
set +x

INFO "Testing that host home is not wiped out"
[ -e "$HOME/.lima" ]
[ -e "$HOME_HOST/.lima" ]

if [[ -n ${CHECKS["mount-path-with-spaces"]} ]]; then
INFO 'Testing that "/tmp/lima test dir with spaces" is not wiped out'
Expand All @@ -179,23 +206,26 @@ if [[ -n ${CHECKS["set-user"]} ]]; then
limactl shell "$NAME" grep "^john:x:4711:4711:John Doe:/home/john-john" /etc/passwd
fi

INFO "Testing proxy settings are imported"
got=$(limactl shell "$NAME" env | grep FTP_PROXY)
# Expected: FTP_PROXY is set in addition to ftp_proxy, localhost is replaced
# by the gateway address, and the value is set immediately without a restart
gatewayIp=$(limactl shell "$NAME" ip route show 0.0.0.0/0 dev eth0 | cut -d\ -f3)
expected="FTP_PROXY=http://${gatewayIp}:2121"
INFO "FTP_PROXY: expected=${expected} got=${got}"
if [ "$got" != "$expected" ]; then
ERROR "proxy environment variable not set to correct value"
exit 1
if [[ -n ${CHECKS["proxy-settings"]} ]]; then
INFO "Testing proxy settings are imported"
got=$(limactl shell "$NAME" env | grep FTP_PROXY)
# Expected: FTP_PROXY is set in addition to ftp_proxy, localhost is replaced
# by the gateway address, and the value is set immediately without a restart
gatewayIp=$(limactl shell "$NAME" ip route show 0.0.0.0/0 dev eth0 | cut -d\ -f3)
expected="FTP_PROXY=http://${gatewayIp}:2121"
INFO "FTP_PROXY: expected=${expected} got=${got}"
if [ "$got" != "$expected" ]; then
ERROR "proxy environment variable not set to correct value"
exit 1
fi
fi

INFO "Testing limactl copy command"
tmpdir="$(mktemp -d "${TMPDIR:-/tmp}"/lima-test-templates.XXXXXX)"
defer "rm -rf \"$tmpdir\""
tmpfile="$tmpdir/lima-hostname"
rm -f "$tmpfile"
# TODO support Windows path https://github.com/lima-vm/lima/issues/3215
limactl cp "$NAME":/etc/hostname "$tmpfile"
expected="$(limactl shell "$NAME" cat /etc/hostname)"
got="$(cat "$tmpfile")"
Expand Down Expand Up @@ -234,32 +264,38 @@ nginx_image="ghcr.io/stargz-containers/nginx:1.19-alpine-org"
alpine_image="ghcr.io/containerd/alpine:3.14.0"

if [[ -n ${CHECKS["container-engine"]} ]]; then
sudo=""
# Currently WSL2 machines only support privileged engine. This requirement might be lifted in the future.
if [[ "$(limactl ls --json "${NAME}" | jq -r .vmType)" == "wsl2" ]]; then
sudo="sudo"
Copy link
Member

Choose a reason for hiding this comment

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

Needs a comment to explain the reason

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added

fi
INFO "Run a nginx container with port forwarding 127.0.0.1:8080"
set -x
if ! limactl shell "$NAME" $CONTAINER_ENGINE info; then
limactl shell "$NAME" sudo cat /var/log/cloud-init-output.log
if ! limactl shell "$NAME" $sudo $CONTAINER_ENGINE info; then
limactl shell "$NAME" cat /var/log/cloud-init-output.log
ERROR "\"${CONTAINER_ENGINE} info\" failed"
exit 1
fi
limactl shell "$NAME" $CONTAINER_ENGINE pull --quiet ${nginx_image}
limactl shell "$NAME" $CONTAINER_ENGINE run -d --name nginx -p 127.0.0.1:8080:80 ${nginx_image}
limactl shell "$NAME" $sudo $CONTAINER_ENGINE pull --quiet ${nginx_image}
limactl shell "$NAME" $sudo $CONTAINER_ENGINE run -d --name nginx -p 127.0.0.1:8080:80 ${nginx_image}

timeout 3m bash -euxc "until curl -f --retry 30 --retry-connrefused http://127.0.0.1:8080; do sleep 3; done"

limactl shell "$NAME" $CONTAINER_ENGINE rm -f nginx
limactl shell "$NAME" $sudo $CONTAINER_ENGINE rm -f nginx
set +x
if [[ -n ${CHECKS["mount-home"]} ]]; then
hometmp="$HOME/lima-container-engine-test-tmp"
hometmp="$HOME_HOST/lima-container-engine-test-tmp"
hometmpguest="$HOME_GUEST/lima-container-engine-test-tmp"
# test for https://github.com/lima-vm/lima/issues/187
INFO "Testing home bind mount (\"$hometmp\")"
rm -rf "$hometmp"
mkdir -p "$hometmp"
defer "rm -rf \"$hometmp\""
set -x
limactl shell "$NAME" $CONTAINER_ENGINE pull --quiet ${alpine_image}
limactl shell "$NAME" $sudo $CONTAINER_ENGINE pull --quiet ${alpine_image}
echo "random-content-${RANDOM}" >"$hometmp/random"
expected="$(cat "$hometmp/random")"
got="$(limactl shell "$NAME" $CONTAINER_ENGINE run --rm -v "$hometmp/random":/mnt/foo ${alpine_image} cat /mnt/foo)"
got="$(limactl shell "$NAME" $sudo $CONTAINER_ENGINE run --rm -v "$hometmpguest/random":/mnt/foo ${alpine_image} cat /mnt/foo)"
INFO "$hometmp/random: expected=${expected}, got=${got}"
if [ "$got" != "$expected" ]; then
ERROR "Home directory is not shared?"
Expand All @@ -284,6 +320,9 @@ if [[ -n ${CHECKS["port-forwards"]} ]]; then
if [ "${NAME}" = "opensuse" ]; then
limactl shell "$NAME" sudo zypper in -y netcat-openbsd
fi
if limactl shell "$NAME" command -v dnf; then
limactl shell "$NAME" sudo dnf install -y nc
fi
"${scriptdir}/test-port-forwarding.pl" "${NAME}"

if [[ -n ${CHECKS["container-engine"]} || ${NAME} == "alpine"* ]]; then
Expand All @@ -306,6 +345,10 @@ if [[ -n ${CHECKS["port-forwards"]} ]]; then
rm nerdctl-full.tgz
sudo="sudo"
fi
# Currently WSL2 machines only support privileged engine. This requirement might be lifted in the future.
if [[ "$(limactl ls --json "${NAME}" | jq -r .vmType)" == "wsl2" ]]; then
sudo="sudo"
fi
limactl shell "$NAME" $sudo $CONTAINER_ENGINE info
limactl shell "$NAME" $sudo $CONTAINER_ENGINE pull --quiet ${nginx_image}

Expand Down Expand Up @@ -360,7 +403,8 @@ if [[ -n ${CHECKS["restart"]} ]]; then
fi

INFO "Stopping \"$NAME\""
limactl stop "$NAME"
# TODO https://github.com/lima-vm/lima/issues/3221
limactl stop "$NAME" || [ "${OS_HOST}" = "Msys" ]
sleep 3

if [[ -n ${CHECKS["disk"]} ]]; then
Expand Down Expand Up @@ -406,7 +450,7 @@ fi
if [[ -n ${CHECKS["user-v2"]} ]]; then
INFO "Testing user-v2 network"
secondvm="$NAME-1"
"${LIMACTL_CREATE[@]}" --set ".additionalDisks=null" "$FILE" --name "$secondvm"
"${LIMACTL_CREATE[@]}" --set ".additionalDisks=null" "$FILE_HOST" --name "$secondvm"
if ! limactl start "$secondvm"; then
ERROR "Failed to start \"$secondvm\""
diagnose "$secondvm"
Expand Down Expand Up @@ -474,7 +518,8 @@ if [[ $NAME == "fedora" && "$(limactl ls --json "$NAME" | jq -r .vmType)" == "vz
fi

INFO "Stopping \"$NAME\""
limactl stop "$NAME"
# TODO https://github.com/lima-vm/lima/issues/3221
limactl stop "$NAME" || [ "${OS_HOST}" = "Msys" ]
sleep 3

INFO "Deleting \"$NAME\""
Expand Down
3 changes: 3 additions & 0 deletions pkg/osutil/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,16 @@ func LimaUser(limaVersion string, warn bool) *user.User {
home, err := call([]string{"cygpath", limaUser.HomeDir})
if err != nil {
logrus.Debug(err)
} else {
home += ".linux"
}
if home == "" {
drive := filepath.VolumeName(limaUser.HomeDir)
home = filepath.ToSlash(limaUser.HomeDir)
// replace C: with /c
prefix := strings.ToLower(fmt.Sprintf("/%c", drive[0]))
home = strings.Replace(home, drive, prefix, 1)
home += ".linux"
}
if !regexPath.MatchString(limaUser.HomeDir) {
warning := fmt.Sprintf("local home %q is not a valid Linux path (must match %q); using %q home instead",
Expand Down
Loading