diff --git a/vhdbuilder/packer/test/linux-vhd-content-test.sh b/vhdbuilder/packer/test/linux-vhd-content-test.sh index 493ad55b0cf..77c3ba0978c 100644 --- a/vhdbuilder/packer/test/linux-vhd-content-test.sh +++ b/vhdbuilder/packer/test/linux-vhd-content-test.sh @@ -33,6 +33,35 @@ err() { echo "$1:Error: $2" >>/dev/stderr } +# assertPackageVersion verifies that the installed deb/rpm package version matches +# the expected full version string from components.json (including hotfix suffix). +# This catches drift between what the package manager installs and what components.json +# specifies at VHD build time rather than in e2e. +# shellcheck disable=SC2016 +assertPackageVersion() { + local test="$1" + local packageName="$2" + local expectedVersion="$3" + + local installedVersion="" + if command -v dpkg-query >/dev/null 2>&1 && dpkg-query -W -f='${Status}' "$packageName" 2>/dev/null | grep -q "install ok installed"; then + # dpkg versions may include an epoch prefix (e.g. "1:..."); strip it for comparison with components.json. + installedVersion=$(dpkg-query -W -f='${Version}' "$packageName" 2>/dev/null | sed 's/^[0-9]*://') + elif command -v rpm >/dev/null 2>&1 && rpm -q "$packageName" >/dev/null 2>&1; then + installedVersion=$(rpm -q --queryformat '%{VERSION}-%{RELEASE}' "$packageName" 2>/dev/null) + else + err "$test" "$packageName is not installed" + return 1 + fi + + echo "$test: checking if installed $packageName version '$installedVersion' matches expected '$expectedVersion'" + if [ "$installedVersion" != "$expectedVersion" ]; then + err "$test" "installed $packageName version '$installedVersion' does not match expected '$expectedVersion' from components.json" + return 1 + fi + return 0 +} + # Clone the repo and checkout the branch provided. # Simply clone with just the branch doesn't work for pull requests, but this technique works # with everything we've tested so far. @@ -278,10 +307,22 @@ testPackagesInstalled() { # We can simply execute the command to verify the package version. case "$name" in "kubernetes-cri-tools") - testCriCtl "$version" + testCriCtl "$version" "kubernetes-cri-tools" ;; "containerd") - testContainerd "$version" + # The deb/rpm package name for containerd varies by OS: + # Ubuntu / Mariner 2.0: moby-containerd + # Azure Linux 3.0+: containerd2 + local pkgName + case "$OS" in + "$AZURELINUX_OS_NAME") + pkgName="containerd2" + ;; + *) + pkgName="moby-containerd" + ;; + esac + testContainerd "$version" "$pkgName" ;; esac break @@ -1965,25 +2006,34 @@ testAKSNodeControllerService() { } testCriCtl() { - expectedVersion="${1}" + local expectedVersion="${1}" + local installedPackageName="${2}" local test="testCriCtl" echo "$test: Start" # If the version defined in components.json is , that means it will use whatever version is installed on the system. # Therefore, we will just skip the test. if [ "$expectedVersion" = "" ]; then - echo "$test: Skipping test for containerd version, as expected version is " + echo "$test: Skipping test for crictl version, as expected version is " return 0 fi - # the expectedVersion looks like this, "1.32.0-ubuntu24.04u3", need to extract the version number. - expectedVersion=$(echo $expectedVersion | cut -d'-' -f1) - # use command `crictl --version` to get the version - local crictl_version=$(crictl --version) + # Strict match: verify the full deb/rpm package version matches components.json + if [ -z "$installedPackageName" ]; then + err "$test" "installed package name was not provided" + return 1 + fi + assertPackageVersion "$test" "$installedPackageName" "$expectedVersion" || return 1 + + # Verify the binary reports the expected major.minor.patch version. + local expectedMajorMinorPatch + expectedMajorMinorPatch=$(echo "$expectedVersion" | cut -d'-' -f1) + local crictl_version + crictl_version=$(crictl --version) # the output of crictl_version looks like this "crictl version 1.32.0", need to extract the version number. crictl_version=$(echo $crictl_version | cut -d' ' -f3) - echo "$test: checking if crictl version is $expectedVersion" - if [ "$crictl_version" != "$expectedVersion" ]; then - err "$test: crictl version is not $expectedVersion, instead it is $crictl_version" + echo "$test: checking if crictl binary version is $expectedMajorMinorPatch" + if [ "$crictl_version" != "$expectedMajorMinorPatch" ]; then + err "$test" "crictl binary version is not $expectedMajorMinorPatch, instead it is $crictl_version" return 1 fi echo "$test: Test finished successfully." @@ -1991,7 +2041,8 @@ testCriCtl() { } testContainerd() { - expectedVersion="${1}" + local expectedVersion="${1}" + local installedPackageName="${2}" local test="testContainerd" echo "$test: Start" # If the version defined in components.json is , that means it will use whatever version is installed on the system. @@ -2000,19 +2051,26 @@ testContainerd() { echo "$test: Skipping test for containerd version, as expected version is " return 0 fi - # the expectedVersion looks like this, "1.6.24-0ubuntu1~24.04.1" or "2.0.0-6.azl3", we need to extract the major.minor.patch version only. - expectedVersion=$(echo $expectedVersion | cut -d'-' -f1) - # use command `containerd --version` to get the version - local containerd_version=$(containerd --version) - # the output of containerd_version looks like the followings. We need to extract the major.minor.patch version only. + + # Strict match: verify the full deb/rpm package version matches components.json + if [ -z "$installedPackageName" ]; then + err "$test" "installed package name was not provided" + return 1 + fi + assertPackageVersion "$test" "$installedPackageName" "$expectedVersion" || return 1 + + # Verify the containerd binary reports the expected major.minor.patch version. + local expectedMajorMinorPatch + expectedMajorMinorPatch=$(echo "$expectedVersion" | cut -d'-' -f1) + local containerd_version + containerd_version=$(containerd --version) # For containerd (v1): containerd github.com/containerd/containerd 1.6.26 # For containerd (v2): containerd github.com/containerd/containerd/v2 2.0.0 - containerd_version=$(echo $containerd_version | cut -d' ' -f3) - # The version could be in the format "1.6.24-11-ubuntu1~24.04.1" or "2.0.0-6.azl3" or just "2.0.0", we need to extract the major.minor.patch version only. - containerd_version=$(echo "$containerd_version" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+') - echo "$test: checking if containerd version is $expectedVersion" - if [ "$containerd_version" != "$expectedVersion" ]; then - err "$test: containerd version is not $expectedVersion, instead it is $containerd_version" + # Extract the semver from anywhere in the output (works for both v1 and v2). + containerd_version=$(echo "$containerd_version" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1) + echo "$test: checking if containerd binary version is $expectedMajorMinorPatch" + if [ "$containerd_version" != "$expectedMajorMinorPatch" ]; then + err "$test" "containerd binary version is not $expectedMajorMinorPatch, instead it is $containerd_version" return 1 fi echo "$test: Test finished successfully."