runtime-rs: Fix issues for empty initdata annotation test

Currently, there are 2 issues for the empty initdata annotation
test:

- Empty string handling
- "\[CDH\] \[ERROR\]: Get Resource failed" not appearing

`add_hypervisor_initdata_overrides()` does not handle
an empty string, which might lead to panic like:

```
called `Result::unwrap()` on an `Err` value: gz decoder failed
Caused by:
    failed to fill whole buffer
```

This commit makes the function return an empty string
for a given empty input and updates the assertion string
to one that appears in both go-runtime and runtime-rs.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
Signed-off-by: Hyounggyu Choi <Hyounggyu.Choi@ibm.com>
This commit is contained in:
Hyounggyu Choi 2025-08-19 12:39:24 +02:00
parent 93ec470928
commit 1f978ecc31
2 changed files with 144 additions and 4 deletions

View File

@ -8,6 +8,7 @@ use flate2::read::GzDecoder;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256, Sha384, Sha512};
use std::{collections::HashMap, io::Read};
use crate::sl;
/// Currently, initdata only supports version 0.1.0.
const INITDATA_VERSION: &str = "0.1.0";
@ -203,12 +204,18 @@ pub fn calculate_initdata_digest(
Ok(b64encoded_digest)
}
/// The argument `initda_annotation` is a Standard base64 encoded string containing a TOML formatted content.
/// The argument `initdata_annotation` is a Standard base64 encoded string containing a TOML formatted content.
/// This function decodes the base64 string, parses the TOML content into an InitData structure.
pub fn add_hypervisor_initdata_overrides(initda_annotation: &str) -> Result<String> {
pub fn add_hypervisor_initdata_overrides(initdata_annotation: &str) -> Result<String> {
// If the initdata is empty, return an empty string
if initdata_annotation.is_empty() {
info!(sl!(), "initdata_annotation is empty");
return Ok("".to_string());
}
// Base64 decode the annotation value
let b64_decoded =
base64::decode_config(initda_annotation, base64::STANDARD).context("base64 decode")?;
base64::decode_config(initdata_annotation, base64::STANDARD).context("base64 decode")?;
// Gzip decompress the decoded data
let mut gz_decoder = GzDecoder::new(&b64_decoded[..]);
@ -231,6 +238,139 @@ mod tests {
use flate2::Compression;
use std::io::Write;
// create gzipped and base64 encoded string
fn create_encoded_input(content: &str) -> String {
let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
encoder.write_all(content.as_bytes()).unwrap();
let compressed = encoder.finish().unwrap();
base64::encode_config(&compressed, base64::STANDARD)
}
#[test]
fn test_empty_annotation() {
// Test with empty string input
let result = add_hypervisor_initdata_overrides("");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "");
}
#[test]
fn test_empty_data_section() {
// Test with empty data section
let toml_content = r#"
algorithm = "sha384"
version = "0.1.0"
[data]
"#;
let encoded = create_encoded_input(toml_content);
let result = add_hypervisor_initdata_overrides(&encoded);
assert!(result.is_ok());
}
#[test]
fn test_valid_complete_initdata() {
// Test with complete InitData structure
let toml_content = r#"
algorithm = "sha384"
version = "0.1.0"
[data]
"aa.toml" = '''
[token_configs]
[token_configs.coco_as]
url = 'http://kbs-service.xxx.cluster.local:8080'
[token_configs.kbs]
url = 'http://kbs-service.xxx.cluster.local:8080'
'''
"cdh.toml" = '''
socket = 'unix:///run/guest-services/cdh.sock'
credentials = []
[kbc]
name = 'cc_kbc'
url = 'http://kbs-service.xxx.cluster.local:8080'
'''
"#;
let encoded = create_encoded_input(toml_content);
let result = add_hypervisor_initdata_overrides(&encoded);
assert!(result.is_ok());
let output = result.unwrap();
assert!(!output.is_empty());
assert!(output.contains("algorithm"));
assert!(output.contains("version"));
}
#[test]
fn test_invalid_base64() {
// Test with invalid base64 string
let invalid_base64 = "This is not valid base64!";
let result = add_hypervisor_initdata_overrides(invalid_base64);
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.to_string().contains("base64 decode"));
}
#[test]
fn test_valid_base64_invalid_gzip() {
// Test with valid base64 but invalid gzip content
let not_gzipped = "This is not gzipped content";
let encoded = base64::encode_config(not_gzipped.as_bytes(), base64::STANDARD);
let result = add_hypervisor_initdata_overrides(&encoded);
assert!(result.is_err());
let error = result.unwrap_err();
assert!(error.to_string().contains("gz decoder failed"));
}
#[test]
fn test_missing_algorithm() {
// Test with missing algorithm field
let toml_content = r#"
version = "0.1.0"
[data]
"test.toml" = '''
key = "value"
'''
"#;
let encoded = create_encoded_input(toml_content);
let result = add_hypervisor_initdata_overrides(&encoded);
// This might fail depending on whether algorithm is required
if result.is_err() {
assert!(result.unwrap_err().to_string().contains("parse initdata"));
}
}
#[test]
fn test_missing_version() {
// Test with missing version field
let toml_content = r#"
algorithm = "sha384"
[data]
"test.toml" = '''
key = "value"
'''
"#;
let encoded = create_encoded_input(toml_content);
let result = add_hypervisor_initdata_overrides(&encoded);
// This might fail depending on whether version is required
if result.is_err() {
assert!(result.unwrap_err().to_string().contains("parse initdata"));
}
}
/// Test InitData creation and serialization
#[test]
fn test_init_data() {

View File

@ -182,7 +182,7 @@ EOF
return 1
fi
assert_logs_contain "${node}" kata "${node_start_time}" "\[CDH\] \[ERROR\]: Get Resource failed"
assert_logs_contain "${node}" kata "${node_start_time}" "\[CDH\] \[ERROR\]: Image Client error: Initialize resource provider failed: Get resource failed"
}
teardown() {