mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-22 17:59:31 +00:00
Merge pull request #11693 from BbolroC/revert-initdata-annotation
runtime-rs: Fix issues for initdata
This commit is contained in:
commit
014ab2fce6
@ -272,7 +272,8 @@ pub const KATA_ANNO_CFG_HYPERVISOR_VIRTIO_FS_EXTRA_ARGS: &str =
|
|||||||
/// A sandbox annotation to specify as the msize for 9p shares.
|
/// A sandbox annotation to specify as the msize for 9p shares.
|
||||||
pub const KATA_ANNO_CFG_HYPERVISOR_MSIZE_9P: &str = "io.katacontainers.config.hypervisor.msize_9p";
|
pub const KATA_ANNO_CFG_HYPERVISOR_MSIZE_9P: &str = "io.katacontainers.config.hypervisor.msize_9p";
|
||||||
/// The initdata annotation passed in when CVM launchs
|
/// The initdata annotation passed in when CVM launchs
|
||||||
pub const KATA_ANNO_CFG_RUNTIME_INIT_DATA: &str = "io.katacontainers.config.runtime.cc_init_data";
|
pub const KATA_ANNO_CFG_HYPERVISOR_INIT_DATA: &str =
|
||||||
|
"io.katacontainers.config.hypervisor.cc_init_data";
|
||||||
|
|
||||||
/// GPU specific annotations for remote hypervisor to help with instance selection
|
/// GPU specific annotations for remote hypervisor to help with instance selection
|
||||||
/// It's for minimum number of GPUs required for the VM.
|
/// It's for minimum number of GPUs required for the VM.
|
||||||
@ -893,7 +894,7 @@ impl Annotation {
|
|||||||
hv.security_info.validate_path(value)?;
|
hv.security_info.validate_path(value)?;
|
||||||
hv.security_info.guest_hook_path = value.to_string();
|
hv.security_info.guest_hook_path = value.to_string();
|
||||||
}
|
}
|
||||||
KATA_ANNO_CFG_RUNTIME_INIT_DATA => {
|
KATA_ANNO_CFG_HYPERVISOR_INIT_DATA => {
|
||||||
hv.security_info.initdata =
|
hv.security_info.initdata =
|
||||||
add_hypervisor_initdata_overrides(value).unwrap();
|
add_hypervisor_initdata_overrides(value).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use flate2::read::GzDecoder;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{Digest, Sha256, Sha384, Sha512};
|
use sha2::{Digest, Sha256, Sha384, Sha512};
|
||||||
use std::{collections::HashMap, io::Read};
|
use std::{collections::HashMap, io::Read};
|
||||||
|
use crate::sl;
|
||||||
|
|
||||||
/// Currently, initdata only supports version 0.1.0.
|
/// Currently, initdata only supports version 0.1.0.
|
||||||
const INITDATA_VERSION: &str = "0.1.0";
|
const INITDATA_VERSION: &str = "0.1.0";
|
||||||
@ -203,12 +204,18 @@ pub fn calculate_initdata_digest(
|
|||||||
Ok(b64encoded_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.
|
/// 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
|
// Base64 decode the annotation value
|
||||||
let b64_decoded =
|
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
|
// Gzip decompress the decoded data
|
||||||
let mut gz_decoder = GzDecoder::new(&b64_decoded[..]);
|
let mut gz_decoder = GzDecoder::new(&b64_decoded[..]);
|
||||||
@ -231,6 +238,139 @@ mod tests {
|
|||||||
use flate2::Compression;
|
use flate2::Compression;
|
||||||
use std::io::Write;
|
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 InitData creation and serialization
|
||||||
#[test]
|
#[test]
|
||||||
fn test_init_data() {
|
fn test_init_data() {
|
||||||
|
@ -147,6 +147,7 @@ DEFMAXMEMSZ := 0
|
|||||||
##VAR DEFBRIDGES=<number> Default number of bridges
|
##VAR DEFBRIDGES=<number> Default number of bridges
|
||||||
DEFBRIDGES := 0
|
DEFBRIDGES := 0
|
||||||
DEFENABLEANNOTATIONS := [\"kernel_params\"]
|
DEFENABLEANNOTATIONS := [\"kernel_params\"]
|
||||||
|
DEFENABLEANNOTATIONS_COCO := [\"kernel_params\",\"cc_init_data\"]
|
||||||
DEFDISABLEGUESTSECCOMP := true
|
DEFDISABLEGUESTSECCOMP := true
|
||||||
DEFDISABLEGUESTEMPTYDIR := false
|
DEFDISABLEGUESTEMPTYDIR := false
|
||||||
##VAR DEFAULTEXPFEATURES=[features] Default experimental features enabled
|
##VAR DEFAULTEXPFEATURES=[features] Default experimental features enabled
|
||||||
@ -482,6 +483,7 @@ USER_VARS += DEFVIRTIOFSCACHE
|
|||||||
USER_VARS += DEFVIRTIOFSQUEUESIZE
|
USER_VARS += DEFVIRTIOFSQUEUESIZE
|
||||||
USER_VARS += DEFVIRTIOFSEXTRAARGS
|
USER_VARS += DEFVIRTIOFSEXTRAARGS
|
||||||
USER_VARS += DEFENABLEANNOTATIONS
|
USER_VARS += DEFENABLEANNOTATIONS
|
||||||
|
USER_VARS += DEFENABLEANNOTATIONS_COCO
|
||||||
USER_VARS += DEFENABLEIOTHREADS
|
USER_VARS += DEFENABLEIOTHREADS
|
||||||
USER_VARS += DEFSECCOMPSANDBOXPARAM
|
USER_VARS += DEFSECCOMPSANDBOXPARAM
|
||||||
USER_VARS += DEFGUESTSELINUXLABEL
|
USER_VARS += DEFGUESTSELINUXLABEL
|
||||||
|
@ -45,7 +45,7 @@ confidential_guest = true
|
|||||||
# List of valid annotation names for the hypervisor
|
# List of valid annotation names for the hypervisor
|
||||||
# Each member of the list is a regular expression, which is the base name
|
# Each member of the list is a regular expression, which is the base name
|
||||||
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
|
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
|
||||||
enable_annotations = @DEFENABLEANNOTATIONS@
|
enable_annotations = @DEFENABLEANNOTATIONS_COCO@
|
||||||
|
|
||||||
# List of valid annotations values for the hypervisor
|
# List of valid annotations values for the hypervisor
|
||||||
# Each member of the list is a path pattern as described by glob(3).
|
# Each member of the list is a path pattern as described by glob(3).
|
||||||
|
@ -14,8 +14,8 @@ use kata_types::{
|
|||||||
cri_containerd::{SANDBOX_NAMESPACE_LABEL_KEY, SANDBOX_NAME_LABEL_KEY},
|
cri_containerd::{SANDBOX_NAMESPACE_LABEL_KEY, SANDBOX_NAME_LABEL_KEY},
|
||||||
KATA_ANNO_CFG_HYPERVISOR_DEFAULT_GPUS, KATA_ANNO_CFG_HYPERVISOR_DEFAULT_GPU_MODEL,
|
KATA_ANNO_CFG_HYPERVISOR_DEFAULT_GPUS, KATA_ANNO_CFG_HYPERVISOR_DEFAULT_GPU_MODEL,
|
||||||
KATA_ANNO_CFG_HYPERVISOR_DEFAULT_MEMORY, KATA_ANNO_CFG_HYPERVISOR_DEFAULT_VCPUS,
|
KATA_ANNO_CFG_HYPERVISOR_DEFAULT_MEMORY, KATA_ANNO_CFG_HYPERVISOR_DEFAULT_VCPUS,
|
||||||
KATA_ANNO_CFG_HYPERVISOR_IMAGE_PATH, KATA_ANNO_CFG_HYPERVISOR_MACHINE_TYPE,
|
KATA_ANNO_CFG_HYPERVISOR_IMAGE_PATH, KATA_ANNO_CFG_HYPERVISOR_INIT_DATA,
|
||||||
KATA_ANNO_CFG_RUNTIME_INIT_DATA,
|
KATA_ANNO_CFG_HYPERVISOR_MACHINE_TYPE,
|
||||||
},
|
},
|
||||||
capabilities::{Capabilities, CapabilityBits},
|
capabilities::{Capabilities, CapabilityBits},
|
||||||
};
|
};
|
||||||
@ -127,7 +127,7 @@ impl RemoteInner {
|
|||||||
config.boot_info.image.to_string(),
|
config.boot_info.image.to_string(),
|
||||||
);
|
);
|
||||||
annotations.insert(
|
annotations.insert(
|
||||||
KATA_ANNO_CFG_RUNTIME_INIT_DATA.to_string(),
|
KATA_ANNO_CFG_HYPERVISOR_INIT_DATA.to_string(),
|
||||||
config.security_info.initdata.to_string(),
|
config.security_info.initdata.to_string(),
|
||||||
);
|
);
|
||||||
annotations.insert(
|
annotations.insert(
|
||||||
|
@ -217,7 +217,7 @@ DEFMAXMEMSZ := 0
|
|||||||
#Default number of bridges
|
#Default number of bridges
|
||||||
DEFBRIDGES := 1
|
DEFBRIDGES := 1
|
||||||
DEFENABLEANNOTATIONS := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\"]
|
DEFENABLEANNOTATIONS := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\"]
|
||||||
DEFENABLEANNOTATIONSTEE := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"default_vcpus\", \"default_memory\"]
|
DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"]
|
||||||
DEFDISABLEGUESTSECCOMP := true
|
DEFDISABLEGUESTSECCOMP := true
|
||||||
DEFDISABLEGUESTEMPTYDIR := false
|
DEFDISABLEGUESTEMPTYDIR := false
|
||||||
#Default experimental features enabled
|
#Default experimental features enabled
|
||||||
@ -731,7 +731,7 @@ USER_VARS += DEFVIRTIOFSCACHE
|
|||||||
USER_VARS += DEFVIRTIOFSQUEUESIZE
|
USER_VARS += DEFVIRTIOFSQUEUESIZE
|
||||||
USER_VARS += DEFVIRTIOFSEXTRAARGS
|
USER_VARS += DEFVIRTIOFSEXTRAARGS
|
||||||
USER_VARS += DEFENABLEANNOTATIONS
|
USER_VARS += DEFENABLEANNOTATIONS
|
||||||
USER_VARS += DEFENABLEANNOTATIONSTEE
|
USER_VARS += DEFENABLEANNOTATIONS_COCO
|
||||||
USER_VARS += DEFENABLEIOTHREADS
|
USER_VARS += DEFENABLEIOTHREADS
|
||||||
USER_VARS += DEFSECCOMPSANDBOXPARAM
|
USER_VARS += DEFSECCOMPSANDBOXPARAM
|
||||||
USER_VARS += DEFENABLEVHOSTUSERSTORE
|
USER_VARS += DEFENABLEVHOSTUSERSTORE
|
||||||
|
@ -55,7 +55,7 @@ rootfs_type=@DEFROOTFSTYPE@
|
|||||||
# List of valid annotation names for the hypervisor
|
# List of valid annotation names for the hypervisor
|
||||||
# Each member of the list is a regular expression, which is the base name
|
# Each member of the list is a regular expression, which is the base name
|
||||||
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
|
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
|
||||||
enable_annotations = @DEFENABLEANNOTATIONSTEE@
|
enable_annotations = @DEFENABLEANNOTATIONS_COCO@
|
||||||
|
|
||||||
# List of valid annotations values for the hypervisor
|
# List of valid annotations values for the hypervisor
|
||||||
# Each member of the list is a path pattern as described by glob(3).
|
# Each member of the list is a path pattern as described by glob(3).
|
||||||
|
@ -40,7 +40,7 @@ confidential_guest = true
|
|||||||
# List of valid annotation names for the hypervisor
|
# List of valid annotation names for the hypervisor
|
||||||
# Each member of the list is a regular expression, which is the base name
|
# Each member of the list is a regular expression, which is the base name
|
||||||
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
|
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
|
||||||
enable_annotations = @DEFENABLEANNOTATIONS@
|
enable_annotations = @DEFENABLEANNOTATIONS_COCO@
|
||||||
|
|
||||||
# List of valid annotations values for the hypervisor
|
# List of valid annotations values for the hypervisor
|
||||||
# Each member of the list is a path pattern as described by glob(3).
|
# Each member of the list is a path pattern as described by glob(3).
|
||||||
|
@ -49,7 +49,7 @@ confidential_guest = true
|
|||||||
# List of valid annotation names for the hypervisor
|
# List of valid annotation names for the hypervisor
|
||||||
# Each member of the list is a regular expression, which is the base name
|
# Each member of the list is a regular expression, which is the base name
|
||||||
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
|
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
|
||||||
enable_annotations = @DEFENABLEANNOTATIONSTEE@
|
enable_annotations = @DEFENABLEANNOTATIONS_COCO@
|
||||||
|
|
||||||
# List of valid annotations values for the hypervisor
|
# List of valid annotations values for the hypervisor
|
||||||
# Each member of the list is a path pattern as described by glob(3).
|
# Each member of the list is a path pattern as described by glob(3).
|
||||||
|
@ -885,6 +885,9 @@ func TestAddRuntimeAnnotations(t *testing.T) {
|
|||||||
|
|
||||||
runtimeConfig := RuntimeConfig{
|
runtimeConfig := RuntimeConfig{
|
||||||
HypervisorType: vc.QemuHypervisor,
|
HypervisorType: vc.QemuHypervisor,
|
||||||
|
HypervisorConfig: vc.HypervisorConfig{
|
||||||
|
EnableAnnotations: []string{"cc_init_data"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ocispec.Annotations[vcAnnotations.DisableGuestSeccomp] = "true"
|
ocispec.Annotations[vcAnnotations.DisableGuestSeccomp] = "true"
|
||||||
|
@ -245,7 +245,7 @@ const (
|
|||||||
EnableRootlessHypervisor = kataAnnotHypervisorPrefix + "rootless"
|
EnableRootlessHypervisor = kataAnnotHypervisorPrefix + "rootless"
|
||||||
|
|
||||||
// Initdata is the initdata passed in when CreateVM
|
// Initdata is the initdata passed in when CreateVM
|
||||||
Initdata = kataConfAnnotationsPrefix + "runtime.cc_init_data"
|
Initdata = kataConfAnnotationsPrefix + "hypervisor.cc_init_data"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Runtime related annotations
|
// Runtime related annotations
|
||||||
|
@ -174,7 +174,7 @@ function create_coco_pod_yaml() {
|
|||||||
# This function creates pod yaml. Parameters
|
# This function creates pod yaml. Parameters
|
||||||
# - $1: image reference
|
# - $1: image reference
|
||||||
# - $2: annotation `io.katacontainers.config.hypervisor.kernel_params`
|
# - $2: annotation `io.katacontainers.config.hypervisor.kernel_params`
|
||||||
# - $3: anootation `io.katacontainers.config.runtime.cc_init_data`
|
# - $3: annotation `io.katacontainers.config.hypervisor.cc_init_data`
|
||||||
# - $4: node
|
# - $4: node
|
||||||
function create_coco_pod_yaml_with_annotations() {
|
function create_coco_pod_yaml_with_annotations() {
|
||||||
image=$1
|
image=$1
|
||||||
@ -183,7 +183,7 @@ function create_coco_pod_yaml_with_annotations() {
|
|||||||
node=${4:-}
|
node=${4:-}
|
||||||
|
|
||||||
kernel_params_annotation_key="io.katacontainers.config.hypervisor.kernel_params"
|
kernel_params_annotation_key="io.katacontainers.config.hypervisor.kernel_params"
|
||||||
cc_initdata_annotation_key="io.katacontainers.config.runtime.cc_init_data"
|
cc_initdata_annotation_key="io.katacontainers.config.hypervisor.cc_init_data"
|
||||||
|
|
||||||
# Note: this is not local as we use it in the caller test
|
# Note: this is not local as we use it in the caller test
|
||||||
kata_pod="$(new_pod_config "$image" "kata-${KATA_HYPERVISOR}")"
|
kata_pod="$(new_pod_config "$image" "kata-${KATA_HYPERVISOR}")"
|
||||||
|
@ -182,7 +182,7 @@ EOF
|
|||||||
return 1
|
return 1
|
||||||
fi
|
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() {
|
teardown() {
|
||||||
|
Loading…
Reference in New Issue
Block a user