fix: cni-plugins backward compatibility - continue#7881
Conversation
There was a problem hiding this comment.
Pull request overview
This PR enhances backward compatibility for CNI plugin component detection during VM provisioning by updating the installFixedCNI() function to check for both "containernetworking-plugins" and "cni-plugins" component names in components.json.
Context: AgentBaker uses a dual naming convention for CNI plugins components. Newer VHDs may have the component named "cni-plugins" in components.json, while older VHDs use "containernetworking-plugins" (installed via package managers like apt/dnf). The VHD build process in vhdbuilder/packer/install-dependencies.sh installs "containernetworking-plugins" as the actual package, but components.json also maintains a separate "cni-plugins" entry for backward compatibility purposes (as noted in the test file comment at line 236-238).
The Fix: This change ensures that provisioning scripts running on newer VHDs with "cni-plugins" entries won't incorrectly fall back to downloading a hardcoded CNI version (v1.4.1) when the component is already present under a different name. This prevents unnecessary downloads and potential version conflicts.
Changes:
- Updated jq query in
installFixedCNI()to check for either "containernetworking-plugins" OR "cni-plugins" component names
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| updatePackageVersions "${cniPackage}" "${os}" "${os_version}" "${OS_VARIANT}" | ||
|
|
||
| #should change to ne | ||
| # shellcheck disable=SC3010 | ||
| if [[ ${#PACKAGE_VERSIONS[@]} -gt 1 ]]; then | ||
| echo "WARNING: containerd package versions array has more than one element. Installing the last element in the array." | ||
| exit $ERR_CONTAINERD_VERSION_INVALID | ||
| fi | ||
| packageVersion=${PACKAGE_VERSIONS[0]} |
There was a problem hiding this comment.
Missing validation for empty PACKAGE_VERSIONS array or value. The code directly accesses PACKAGE_VERSIONS[0] without checking if the array is empty or contains the special value. Following the pattern in installContainerdWithComponentsJson (lines 77-80), this code should include a check like:
if [[ ${#PACKAGE_VERSIONS[@]} -eq 0 || ${PACKAGE_VERSIONS[0]} == "<SKIP>" ]]; then
echo "INFO: cni-plugins package versions array is either empty or the first element is <SKIP>. Skipping cni-plugins installation."
return 0
fi
Without this check, the script will fail with an unbound variable error or use an invalid version if the array is empty.
| os_version="${UBUNTU_RELEASE}" | ||
| if isMarinerOrAzureLinux "${OS}" && [ "${IS_KATA}" = "true" ]; then | ||
| os=${MARINER_KATA_OS_NAME} | ||
| fi |
There was a problem hiding this comment.
The logic in line 162-163 only handles the Kata case for setting os to MARINER_KATA_OS_NAME, but it doesn't handle the Azure Linux Kata case (AZURELINUX_KATA_OS_NAME). The containerd installation function (lines 62-67) checks both isMariner and isAzureLinux separately for Kata. This code should follow the same pattern:
if isMarinerOrAzureLinux "${OS}" && [ "${IS_KATA}" = "true" ]; then
os=${MARINER_KATA_OS_NAME}
fi
if isAzureLinux "${OS}" && [ "${IS_KATA}" = "true" ]; then
os=${AZURELINUX_KATA_OS_NAME}
fi
Note that isMarinerOrAzureLinux returns true for both Mariner and Azure Linux, so the current code sets os to MARINER_KATA_OS_NAME even when OS is Azure Linux, which is incorrect.
| fi | |
| fi | |
| if isAzureLinux "${OS}" && [ "${IS_KATA}" = "true" ]; then | |
| os=${AZURELINUX_KATA_OS_NAME} | |
| fi |
| fi | ||
| packageVersion=${PACKAGE_VERSIONS[0]} | ||
|
|
||
| # Is there a ${arch} variable I can use instead of the iff |
There was a problem hiding this comment.
Typo in comment: "iff" should be "if". The comment currently reads "Is there a ${arch} variable I can use instead of the iff" but should say "Is there a ${arch} variable I can use instead of the if".
| # Is there a ${arch} variable I can use instead of the iff | |
| # Is there a ${arch} variable I can use instead of the if |
| if [ -z "$UBUNTU_RELEASE" ]; then | ||
| os=${OS} | ||
| os_version="current" | ||
| fi | ||
| os_version="${UBUNTU_RELEASE}" |
There was a problem hiding this comment.
The os_version assignment logic has a bug. Line 161 unconditionally overwrites the os_version set in line 159. This means when UBUNTU_RELEASE is empty (non-Ubuntu systems), os_version will be set to an empty string instead of "current". The logic should match the pattern used in installContainerdWithComponentsJson (lines 53-59) where os_version is only set to UBUNTU_RELEASE when it's not empty. The corrected logic should be:
os=${UBUNTU_OS_NAME}
os_version="${UBUNTU_RELEASE}"
if [ -z "$UBUNTU_RELEASE" ]; then
os=${OS}
os_version="current"
fi
| if [ -z "$UBUNTU_RELEASE" ]; then | |
| os=${OS} | |
| os_version="current" | |
| fi | |
| os_version="${UBUNTU_RELEASE}" | |
| os_version="${UBUNTU_RELEASE}" | |
| if [ -z "$UBUNTU_RELEASE" ]; then | |
| os=${OS} | |
| os_version="current" | |
| fi |
| #should change to ne | ||
| # shellcheck disable=SC3010 | ||
| if [[ ${#PACKAGE_VERSIONS[@]} -gt 1 ]]; then | ||
| echo "WARNING: containerd package versions array has more than one element. Installing the last element in the array." |
There was a problem hiding this comment.
The error message refers to "containerd" but this code is installing CNI plugins. The message should say "CNI plugins package versions array has more than one element" instead of "containerd package versions array has more than one element".
| echo "WARNING: containerd package versions array has more than one element. Installing the last element in the array." | |
| echo "WARNING: CNI plugins package versions array has more than one element. Installing the last element in the array." |
| #always just use what is listed in components.json so we don't have to sync. | ||
| if [ -z "$(jq -r '.Packages[] | select(.name == "containernetworking-plugins") | .name' < $COMPONENTS_FILEPATH)" ]; then | ||
| cniPackage=$(jq ".Packages" "$COMPONENTS_FILEPATH" | jq ".[] | select(.name == \"cni-plugins\")") || exit $ERR_CNI_VERSION_INVALID | ||
|
|
||
| #CNI doesn't really care about this but wanted to reuse updatePackageVersions which requires it. | ||
| os=${UBUNTU_OS_NAME} | ||
| if [ -z "$UBUNTU_RELEASE" ]; then | ||
| os=${OS} | ||
| os_version="current" | ||
| fi | ||
| os_version="${UBUNTU_RELEASE}" | ||
| if isMarinerOrAzureLinux "${OS}" && [ "${IS_KATA}" = "true" ]; then | ||
| os=${MARINER_KATA_OS_NAME} | ||
| fi | ||
| updatePackageVersions "${cniPackage}" "${os}" "${os_version}" "${OS_VARIANT}" | ||
|
|
||
| #should change to ne | ||
| # shellcheck disable=SC3010 | ||
| if [[ ${#PACKAGE_VERSIONS[@]} -gt 1 ]]; then | ||
| echo "WARNING: containerd package versions array has more than one element. Installing the last element in the array." | ||
| exit $ERR_CONTAINERD_VERSION_INVALID | ||
| fi | ||
| packageVersion=${PACKAGE_VERSIONS[0]} | ||
|
|
||
| # Is there a ${arch} variable I can use instead of the iff | ||
| if [ "$(isARM64)" -eq 1 ]; then | ||
| CNI_DIR_TMP="cni-plugins-linux-arm64-v${packageVersion}" | ||
| else | ||
| CNI_DIR_TMP="cni-plugins-linux-amd64-v${packageVersion}" | ||
| fi | ||
|
|
||
| if [ -d "$CNI_DOWNLOADS_DIR/${CNI_DIR_TMP}" ]; then | ||
| #not clear to me when this would ever happen. assume its related to the line above Latest VHD should have the untar, older should have the tgz. | ||
| mv ${CNI_DOWNLOADS_DIR}/${CNI_DIR_TMP}/* $CNI_BIN_DIR | ||
| else | ||
| echo "CNI tarball should already be unzipped by components.json" | ||
| exit $ERR_CNI_VERSION_INVALID | ||
| fi | ||
|
|
||
| chown -R root:root $CNI_BIN_DIR | ||
| fi |
There was a problem hiding this comment.
Logic error: This code assumes "cni-plugins" package is cached in the VHD downloads directory, but according to the VHD build script (vhdbuilder/packer/install-dependencies.sh:335-473), there is NO case handler for "cni-plugins", which means it's never downloaded or extracted during VHD build. The test file (vhdbuilder/packer/test/linux-vhd-content-test.sh:236-238) explicitly states: "cni-plugins is a special case that it is still in components.json for backward compatibility but we don't cache it."
This means the check at line 182 will always fail (directory doesn't exist), and the code will always exit with ERR_CNI_VERSION_INVALID at line 187. The entire code block (lines 152-191) appears to be attempting to handle a "cni-plugins" entry that was never installed on the VHD, making it non-functional.
If the intent is backward compatibility with old VHDs that have "containernetworking-plugins" but new CSE scripts that reference "cni-plugins", the logic is backwards. The code should check if "cni-plugins" exists in components.json AND was actually cached on the VHD during build. Since "cni-plugins" is never cached, this entire code path is broken.
| fi | ||
| updatePackageVersions "${cniPackage}" "${os}" "${os_version}" "${OS_VARIANT}" | ||
|
|
||
| #should change to ne |
There was a problem hiding this comment.
Unclear comment. Line 167 says "#should change to ne" but it's not clear what "ne" means or what should be changed. This appears to be an incomplete thought or TODO that should either be completed or removed.
| #should change to ne |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
What this PR does / why we need it:
Which issue(s) this PR fixes:
Fixes #