Compare commits

..

1 Commits

Author SHA1 Message Date
Manuel Huber
b21651b657 kata-deploy: Check kata-tarball size limits
For kata tarballs we eventually release to GitHub, check their
size against the GitHub size limit. With this, we fail in case of
an ongoing release process in 'CI | Publish Kata Containers payload'
instead of only later on in the 'Release Kata Containers' action,
and we fail during PR builds, avoiding this situation at all.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2026-03-18 15:51:48 -07:00
16 changed files with 244 additions and 124 deletions

View File

@@ -347,6 +347,16 @@ jobs:
./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-artifacts versions.yaml
env:
RELEASE: ${{ inputs.stage == 'release' && 'yes' || 'no' }}
- name: Check kata tarball size (GitHub release asset limit)
run: |
# https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases#storage-and-bandwidth-quotas
GITHUB_ASSET_MAX_BYTES=2147483648
tarball_size=$(stat -c "%s" kata-static.tar.zst)
if [[ "${tarball_size}" -ge "${GITHUB_ASSET_MAX_BYTES}" ]]; then
echo "::error::tarball size (${tarball_size} bytes) >= GitHub release asset limit (${GITHUB_ASSET_MAX_BYTES} bytes)"
exit 1
fi
echo "tarball size: ${tarball_size} bytes"
- name: store-artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
@@ -447,6 +457,16 @@ jobs:
./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-tools-artifacts versions.yaml kata-tools-static.tar.zst
env:
RELEASE: ${{ inputs.stage == 'release' && 'yes' || 'no' }}
- name: Check kata-tools tarball size (GitHub release asset limit)
run: |
# https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases#storage-and-bandwidth-quotas
GITHUB_ASSET_MAX_BYTES=2147483648
tarball_size=$(stat -c "%s" kata-tools-static.tar.zst)
if [[ "${tarball_size}" -ge "${GITHUB_ASSET_MAX_BYTES}" ]]; then
echo "::error::tarball size (${tarball_size} bytes) >= GitHub release asset limit (${GITHUB_ASSET_MAX_BYTES} bytes)"
exit 1
fi
echo "tarball size: ${tarball_size} bytes"
- name: store-artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:

View File

@@ -326,6 +326,16 @@ jobs:
./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-artifacts versions.yaml
env:
RELEASE: ${{ inputs.stage == 'release' && 'yes' || 'no' }}
- name: Check kata tarball size (GitHub release asset limit)
run: |
# https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases#storage-and-bandwidth-quotas
GITHUB_ASSET_MAX_BYTES=2147483648
tarball_size=$(stat -c "%s" kata-static.tar.zst)
if [[ "${tarball_size}" -ge "${GITHUB_ASSET_MAX_BYTES}" ]]; then
echo "::error::tarball size (${tarball_size} bytes) >= GitHub release asset limit (${GITHUB_ASSET_MAX_BYTES} bytes)"
exit 1
fi
echo "tarball size: ${tarball_size} bytes"
- name: store-artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:

View File

@@ -262,6 +262,16 @@ jobs:
./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-artifacts versions.yaml
env:
RELEASE: ${{ inputs.stage == 'release' && 'yes' || 'no' }}
- name: Check kata tarball size (GitHub release asset limit)
run: |
# https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases#storage-and-bandwidth-quotas
GITHUB_ASSET_MAX_BYTES=2147483648
tarball_size=$(stat -c "%s" kata-static.tar.zst)
if [[ "${tarball_size}" -ge "${GITHUB_ASSET_MAX_BYTES}" ]]; then
echo "::error::tarball size (${tarball_size} bytes) >= GitHub release asset limit (${GITHUB_ASSET_MAX_BYTES} bytes)"
exit 1
fi
echo "tarball size: ${tarball_size} bytes"
- name: store-artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:

View File

@@ -350,6 +350,16 @@ jobs:
./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-artifacts versions.yaml
env:
RELEASE: ${{ inputs.stage == 'release' && 'yes' || 'no' }}
- name: Check kata tarball size (GitHub release asset limit)
run: |
# https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases#storage-and-bandwidth-quotas
GITHUB_ASSET_MAX_BYTES=2147483648
tarball_size=$(stat -c "%s" kata-static.tar.zst)
if [[ "${tarball_size}" -ge "${GITHUB_ASSET_MAX_BYTES}" ]]; then
echo "::error::tarball size (${tarball_size} bytes) >= GitHub release asset limit (${GITHUB_ASSET_MAX_BYTES} bytes)"
exit 1
fi
echo "tarball size: ${tarball_size} bytes"
- name: store-artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:

View File

@@ -1,3 +1,3 @@
[toolchain]
# Keep in sync with versions.yaml
channel = "1.92"
channel = "1.91"

View File

@@ -110,10 +110,8 @@ impl Namespace {
unshare(cf)?;
if ns_type == NamespaceType::Uts {
if let Some(host) = hostname {
nix::unistd::sethostname(host)?;
}
if ns_type == NamespaceType::Uts && hostname.is_some() {
nix::unistd::sethostname(hostname.unwrap())?;
}
// Bind mount the new namespace from the current thread onto the mount point to persist it.

View File

@@ -173,7 +173,7 @@
"encryption_key=ephemeral"
],
"source": "",
"mount_point": "$(spath)/$(b64_device_id)",
"mount_point": "^$(spath)/$(b64_device_id)$",
"fstype": "ext4",
"options": [],
"shared": true

View File

@@ -1306,7 +1306,6 @@ allow_storage_source(p_storage, i_storage, bundle_id) if {
allow_storage_options(p_storage, i_storage) if {
print("allow_storage_options 1: start")
p_storage.driver != "blk"
p_storage.driver != "overlayfs"
p_storage.options == i_storage.options
@@ -1390,7 +1389,7 @@ allow_mount_point_by_device_id(p_storage, i_storage) if {
mount3 := replace(mount2, "$(b64_device_id)", base64url.encode(i_storage.source))
print("allow_mount_point_by_device_id: mount3 =", mount3)
mount3 == i_storage.mount_point
regex.match(mount3, i_storage.mount_point)
print("allow_mount_point_by_device_id: true")
}

View File

@@ -168,10 +168,10 @@ fn get_empty_dir_mount_and_storage(
source: settings_empty_dir.source.clone(),
fstype: settings_empty_dir.fstype.clone(),
options,
mount_point: if settings_empty_dir.mount_point.ends_with('/') {
format!("{}{}$", &settings_empty_dir.mount_point, &yaml_mount.name)
} else {
mount_point: if settings_empty_dir.mount_point.ends_with('$') {
settings_empty_dir.mount_point.clone()
} else {
format!("{}{}$", &settings_empty_dir.mount_point, &yaml_mount.name)
},
fs_group: protobuf::MessageField::none(),
shared: settings_empty_dir.shared,

View File

@@ -1232,9 +1232,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.32"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
dependencies = [
"futures-core",
"futures-sink",
@@ -1242,9 +1242,9 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.32"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-executor"
@@ -1259,9 +1259,9 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.32"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
[[package]]
name = "futures-lite"
@@ -1278,9 +1278,9 @@ dependencies = [
[[package]]
name = "futures-macro"
version = "0.3.32"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
@@ -1289,27 +1289,21 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.32"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
[[package]]
name = "futures-task"
version = "0.3.32"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
[[package]]
name = "futures-timer"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
[[package]]
name = "futures-util"
version = "0.3.32"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
"futures-channel",
"futures-core",
@@ -1319,6 +1313,7 @@ dependencies = [
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
@@ -1890,7 +1885,6 @@ dependencies = [
"quick-xml",
"reqwest",
"ron",
"rstest",
"semver",
"serde",
"serde_json",
@@ -3150,12 +3144,6 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "relative-path"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
[[package]]
name = "rend"
version = "0.4.2"
@@ -3304,35 +3292,6 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "rstest"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49"
dependencies = [
"futures-timer",
"futures-util",
"rstest_macros",
]
[[package]]
name = "rstest_macros"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0"
dependencies = [
"cfg-if 1.0.0",
"glob",
"proc-macro-crate",
"proc-macro2",
"quote",
"regex",
"relative-path",
"rustc_version",
"syn 2.0.87",
"unicode-ident",
]
[[package]]
name = "rtnetlink"
version = "0.19.0"
@@ -3392,15 +3351,6 @@ version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "0.38.25"
@@ -4464,9 +4414,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.24"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-segmentation"

View File

@@ -57,7 +57,6 @@ quick-xml = { version = "0.28", features = ["serialize"] }
csv = "1.2"
serde_with = "2.3"
chrono = { version = "0.4", features = ["serde"] }
rstest = "0.26.1"
[target.'cfg(target_arch = "s390x")'.dependencies]
reqwest = { version = "0.11", default-features = false, features = [

View File

@@ -78,9 +78,10 @@ pub enum Commands {
}
#[derive(Debug, Args, Error)]
#[error("Argument is not valid: {command:?}")]
#[error("Argument is not valid")]
pub struct CheckArgument {
#[clap(subcommand)]
#[allow(unused_assignments)]
pub command: CheckSubCommand,
}

View File

@@ -157,12 +157,10 @@ pub fn get_sandbox_id_for_volume(volume_path: &str) -> Result<String> {
#[cfg(test)]
mod tests {
use super::*;
use anyhow::anyhow;
use kata_types::mount::DirectVolumeMountInfo;
use rstest::{fixture, rstest};
use serial_test::serial;
use std::{collections::HashMap, fs};
use tempfile::{tempdir, TempDir};
use std::{collections::HashMap, fs, path::PathBuf};
use tempfile::tempdir;
use test_utils::skip_if_not_root;
#[test]
@@ -197,38 +195,61 @@ mod tests {
fs::remove_dir_all(&joined_volume_path).expect("failed to cleanup test")
}
#[fixture]
fn root_fs() -> TempDir {
tempdir().expect("failed to create tmpdir")
}
#[test]
fn test_path_join() {
#[derive(Debug)]
struct TestData<'a> {
rootfs: &'a str,
volume_path: &'a str,
result: Result<PathBuf>,
}
// the safe_path::scoped_join requires the prefix path to exist on testing machine
let root_fs = tempdir().expect("failed to create tmpdir").into_path();
let root_fs_str = root_fs.to_str().unwrap();
#[rstest]
#[case::relative_secret_path("../../etc/passwd", "Li4vLi4vZXRjL3Bhc3N3ZA==")] // "Li4vLi4vZXRjL3Bhc3N3ZA==" is b64 encoded url of "../../etc/passwd"
#[case::byte_array_path("abcdddd", "YWJjZGRkZA==")] // "YWJjZGRkZA==" is the b64 url encoded string of "abcdddd"
fn test_path_join(
root_fs: TempDir,
#[case] volume_path: &str,
#[case] expected_encoded_path: &str,
) {
let root_str = root_fs.path().to_str().unwrap();
let relative_secret_path = "../../etc/passwd";
let b64_relative_secret_path =
base64::encode_config(relative_secret_path, base64::URL_SAFE);
let result = join_path(root_str, volume_path).expect("Should return Ok for valid paths");
// byte array of "abcdddd"
let b64_abs_path = vec![97, 98, 99, 100, 100, 100, 100];
// b64urlencoded string of "abcdddd"
let b64urlencodes_relative_path = "YWJjZGRkZA==";
let expected = root_fs.path().join(expected_encoded_path);
assert_eq!(result, expected);
}
let tests = &[
TestData {
rootfs: root_fs_str,
volume_path: "",
result: Err(anyhow!(std::io::ErrorKind::NotFound)),
},
TestData {
rootfs: root_fs_str,
volume_path: relative_secret_path,
result: Ok(root_fs.join(b64_relative_secret_path)),
},
TestData {
rootfs: root_fs_str,
volume_path: unsafe { std::str::from_utf8_unchecked(&b64_abs_path) },
result: Ok(root_fs.join(b64urlencodes_relative_path)),
},
];
#[rstest]
fn test_path_join_empty_path_error(root_fs: TempDir) {
let root_str = root_fs.path().to_str().unwrap();
let result = join_path(root_str, "");
let err = result.expect_err("Should fail for empty volume_path");
assert_eq!(
err.to_string(),
anyhow!(std::io::ErrorKind::NotFound).to_string()
);
for (i, d) in tests.iter().enumerate() {
let msg = format!("test[{i}]: {d:?}");
let result = join_path(d.rootfs, d.volume_path);
let msg = format!("{msg}, result: {result:?}");
if result.is_ok() {
assert!(
result.as_ref().unwrap() == d.result.as_ref().unwrap(),
"{}",
msg
);
continue;
}
let expected_error = format!("{}", d.result.as_ref().unwrap_err());
let actual_error = format!("{}", result.unwrap_err());
assert!(actual_error == expected_error, "{}", msg);
}
}
#[test]

View File

@@ -103,7 +103,6 @@ long_options=(
[no-arch]="Run/list all tests except architecture-specific ones"
[only-arch]="Only run/list architecture-specific tests"
[repo:]="Specify GitHub URL of repo to use (github.com/user/repo)"
[repo-path:]="Specify path to repository to check (default: \$GOPATH/src/\$repo)"
[scripts]="Check script files"
[vendor]="Check vendor files"
[versions]="Check versions files"
@@ -597,6 +596,19 @@ check_url()
local curl_ua_args
[ -n "$user_agent" ] && curl_ua_args="-A '$user_agent'"
{ run_url_check_cmd "$url" "$curl_out" "$curl_ua_args"; ret=$?; } || true
# A transitory error, or the URL is incorrect,
# but capture either way.
if [ "$ret" -ne 0 ]; then
errors+=("Failed to check URL '$url' (user agent: '$user_agent', return code $ret)")
# Try again with another UA since it appears that some return codes
# indicate the server was unhappy with the details
# presented by the client.
continue
fi
local http_statuses
http_statuses=$(grep -E "^HTTP" "$curl_out" |\
@@ -786,13 +798,111 @@ static_check_docs()
# Convert the list of files into an grep(1) alternation pattern.
exclude_pattern=$(echo "${exclude_doc_regexs[@]}"|sed 's, ,|,g')
# Every document in the repo (except a small handful of exceptions)
# should be referenced by another document.
for doc in $md_docs_to_check
do
# Check the ignore list for markdown files that do not need to
# be referenced by others.
echo "$doc"|grep -q -E "(${exclude_pattern})" && continue
grep -q "$doc" "$md_links" || die "Document $doc is not referenced"
done
info "Checking document code blocks"
local doc_to_script_cmd="${cidir}/kata-doc-to-script.sh"
for doc in $docs
do
bash "${doc_to_script_cmd}" -csv "$doc"
# Look for URLs in the document
urls=$("${doc_to_script_cmd}" -i "$doc" - | "$cmd")
# Gather URLs
for url in $urls
do
printf "%s\t%s\n" "${url}" "${doc}" >> "$url_map"
done
done
# Get unique list of URLs
urls=$(awk '{print $1}' "$url_map" | sort -u)
info "Checking all document URLs"
local invalid_urls_dir=$(mktemp -d)
files_to_remove+=("${invalid_urls_dir}")
for url in $urls
do
if [ "$specific_branch" != "true" ]
then
# If the URL is new on this PR, it cannot be checked.
echo "$new_urls" | grep -q -E "\<${url}\>" && \
info "ignoring new (but correct) URL: $url" && continue
fi
# Ignore local URLs. The only time these are used is in
# examples (meaning these URLs won't exist).
echo "$url" | grep -q "^file://" && continue
echo "$url" | grep -q "^http://localhost" && continue
# Ignore the install guide URLs that contain a shell variable
echo "$url" | grep -q "\\$" && continue
# This prefix requires the client to be logged in to github, so ignore
echo "$url" | grep -q 'https://github.com/pulls' && continue
# Sigh.
echo "$url"|grep -q 'https://example.com' && continue
# Google APIs typically require an auth token.
echo "$url"|grep -q 'https://www.googleapis.com' && continue
# Git repo URL check
if echo "$url"|grep -q '^https.*git'
then
timeout "${KATA_NET_TIMEOUT}" git ls-remote "$url" > /dev/null 2>&1 && continue
fi
# Check the URL, saving it if invalid
#
# Each URL is checked in a separate process as each unique URL
# requires us to hit the network.
check_url "$url" "$invalid_urls_dir" &
done
# Synchronisation point
wait
# Combine all the separate invalid URL files into one
local invalid_files=$(ls "$invalid_urls_dir")
if [ -n "$invalid_files" ]; then
pushd "$invalid_urls_dir" &>/dev/null
cat $(echo "$invalid_files"|tr '\n' ' ') > "$invalid_urls"
popd &>/dev/null
fi
if [ -s "$invalid_urls" ]
then
local files
cat "$invalid_urls" | while read url
do
files=$(grep "^${url}" "$url_map" | awk '{print $2}' | sort -u)
echo >&2 -e "ERROR: Invalid URL '$url' found in the following files:\n"
for file in $files
do
echo >&2 "$file"
done
done
exit 1
fi
# Now, spell check the docs
cmd="${test_dir}/cmd/check-spelling/kata-spell-check.sh"
@@ -1406,8 +1516,6 @@ main()
local func=
repo_path=""
while [ $# -gt 1 ]
do
case "$1" in
@@ -1428,7 +1536,6 @@ main()
--only-arch) handle_funcs="arch-specific" ;;
--rego) func=static_check_rego ;;
--repo) repo="$2"; shift ;;
--repo-path) repo_path="$2"; shift ;;
--scripts) func=static_check_shell ;;
--vendor) func=static_check_vendor;;
--versions) func=static_check_versions ;;
@@ -1461,10 +1568,7 @@ main()
test_path="${test_path:-"${repo}/tests"}"
test_dir="${GOPATH}/src/${test_path}"
if [ -z "$repo_path" ]
then
repo_path=$GOPATH/src/$repo
fi
repo_path=$GOPATH/src/$repo
announce

View File

@@ -19,8 +19,6 @@ paths:
- "^ci/openshift-ci/": []
- "^\\.github/workflows/static-checks": ["static"]
- "^\\.github/workflows/": []
- "^docs/": ["static"]
- "^mkdocs\\.yaml$": ["static"]
- "\\.md$": ["static"]
# TODO: Expand filters
# Sources

View File

@@ -479,12 +479,12 @@ languages:
description: "Rust language"
notes: "'version' is the default minimum version used by this project."
# Keep in sync with rust-toolchain.toml
version: "1.92"
version: "1.91"
meta:
description: |
'newest-version' is the latest version known to work when
building Kata
newest-version: "1.92"
newest-version: "1.91"
golangci-lint:
description: "golangci-lint"