Skip to content

Commit 61f2478

Browse files
committed
test: add e2e tests for startContainer hook env inheritance
Add two integration tests to verify startContainer hook environment variable behavior: - start_container_env_inherit: verifies hooks inherit process.env when no explicit env is set - start_container_env_explicit: verifies hooks use only their explicit env and do not inherit process.env
1 parent 5c58ad5 commit 61f2478

File tree

3 files changed

+145
-1
lines changed

3 files changed

+145
-1
lines changed

tests/contest/contest/src/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::tests::example::get_example_test;
1717
use crate::tests::exec::get_exec_test;
1818
use crate::tests::exec_cpu_affinity::get_exec_cpu_affinity_test;
1919
use crate::tests::fd_control::get_fd_control_test;
20-
use crate::tests::hooks::get_hooks_tests;
20+
use crate::tests::hooks::{get_hooks_tests, get_start_container_env_tests};
2121
use crate::tests::hostname::get_hostname_test;
2222
use crate::tests::intel_rdt::get_intel_rdt_test;
2323
use crate::tests::io_priority::get_io_priority_test;
@@ -124,6 +124,7 @@ fn main() -> Result<()> {
124124
let pidfile = get_pidfile_test();
125125
let ns_itype = get_ns_itype_tests();
126126
let hooks = get_hooks_tests();
127+
let start_container_env = get_start_container_env_tests();
127128
let poststart = get_poststart_tests();
128129
let poststop = get_poststop_tests();
129130
let poststart_fail = get_poststart_fail_tests();
@@ -177,6 +178,7 @@ fn main() -> Result<()> {
177178
tm.add_test_group(Box::new(pidfile));
178179
tm.add_test_group(Box::new(ns_itype));
179180
tm.add_test_group(Box::new(hooks));
181+
tm.add_test_group(Box::new(start_container_env));
180182
tm.add_test_group(Box::new(poststart));
181183
tm.add_test_group(Box::new(poststart_fail));
182184
tm.add_test_group(Box::new(poststop));
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
mod invoke;
2+
mod start_container_env;
23
pub use invoke::get_hooks_tests;
4+
pub use start_container_env::get_start_container_env_tests;
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
use std::time::Duration;
2+
3+
use anyhow::anyhow;
4+
use oci_spec::runtime::{HookBuilder, HooksBuilder, ProcessBuilder, SpecBuilder};
5+
use test_framework::{Test, TestGroup, TestResult};
6+
7+
use crate::utils::{
8+
CreateOptions, LifecycleStatus, WaitTarget, create_container, delete_container, generate_uuid,
9+
kill_container, prepare_bundle, set_config, start_container, wait_for_state,
10+
};
11+
12+
const STATE_WAIT_TIMEOUT_SECS: u64 = 5;
13+
const STATE_POLL_INTERVAL_MILLIS: u64 = 100;
14+
15+
fn wait_for_target(id: &str, bundle_path: &std::path::Path, target: WaitTarget) {
16+
wait_for_state(
17+
id,
18+
bundle_path,
19+
target,
20+
Duration::from_secs(STATE_WAIT_TIMEOUT_SECS),
21+
Duration::from_millis(STATE_POLL_INTERVAL_MILLIS),
22+
)
23+
.unwrap();
24+
}
25+
26+
fn run_hook_env_test(
27+
shell_condition: &str,
28+
process_env: Vec<String>,
29+
hook_env: Option<Vec<String>>,
30+
) -> TestResult {
31+
let id = generate_uuid();
32+
let id_str = id.to_string();
33+
let bundle = prepare_bundle().unwrap();
34+
35+
let shell_cmd = format!("if {shell_condition}; then exit 0; else exit 1; fi");
36+
let hook_args = vec!["sh".to_string(), "-c".to_string(), shell_cmd];
37+
let hook = if let Some(env) = hook_env {
38+
HookBuilder::default()
39+
.path("/bin/sh")
40+
.args(hook_args)
41+
.env(env)
42+
} else {
43+
HookBuilder::default().path("/bin/sh").args(hook_args)
44+
};
45+
46+
let mut process = ProcessBuilder::default()
47+
.args(vec!["true".to_string()])
48+
.build()
49+
.unwrap();
50+
let mut env = process.env().clone().unwrap();
51+
for e in process_env {
52+
env.push(e);
53+
}
54+
process.set_env(Some(env));
55+
56+
let spec = SpecBuilder::default()
57+
.process(process)
58+
.hooks(
59+
HooksBuilder::default()
60+
.start_container(vec![
61+
hook.build().expect("could not build startContainer hook"),
62+
])
63+
.build()
64+
.expect("could not build hooks"),
65+
)
66+
.build()
67+
.unwrap();
68+
set_config(&bundle, &spec).unwrap();
69+
70+
create_container(&id_str, &bundle, &CreateOptions::default())
71+
.unwrap()
72+
.wait()
73+
.unwrap();
74+
wait_for_target(
75+
&id_str,
76+
bundle.path(),
77+
WaitTarget::Status(LifecycleStatus::Created),
78+
);
79+
let start_result =
80+
start_container(&id_str, &bundle).and_then(|mut child| child.wait().map_err(Into::into));
81+
let test_passed = match &start_result {
82+
Ok(status) => status.success(),
83+
Err(_) => false,
84+
};
85+
86+
let _ = kill_container(&id_str, &bundle).and_then(|mut c| c.wait().map_err(Into::into));
87+
let _ = delete_container(&id_str, &bundle).and_then(|mut c| c.wait().map_err(Into::into));
88+
let _ = wait_for_state(
89+
&id_str,
90+
bundle.path(),
91+
WaitTarget::Deleted,
92+
Duration::from_secs(STATE_WAIT_TIMEOUT_SECS),
93+
Duration::from_millis(STATE_POLL_INTERVAL_MILLIS),
94+
);
95+
96+
if test_passed {
97+
TestResult::Passed
98+
} else {
99+
TestResult::Failed(anyhow!(
100+
"startContainer hook env check failed — hook exited non-zero \
101+
(start result: {:?})",
102+
start_result
103+
))
104+
}
105+
}
106+
107+
fn get_test_inherit_env() -> Test {
108+
Test::new(
109+
"start_container_env_inherit",
110+
Box::new(|| {
111+
run_hook_env_test(
112+
r#"test "$ONE" = "two" && test "$FOO" = "bar""#,
113+
vec!["ONE=two".to_string(), "FOO=bar".to_string()],
114+
None,
115+
)
116+
}),
117+
)
118+
}
119+
120+
fn get_test_explicit_env() -> Test {
121+
Test::new(
122+
"start_container_env_explicit",
123+
Box::new(|| {
124+
run_hook_env_test(
125+
r#"test "$HOOK_VAR" = "hook_value" && test -z "$PROC_VAR""#,
126+
vec!["PROC_VAR=should_not_appear".to_string()],
127+
Some(vec!["HOOK_VAR=hook_value".to_string()]),
128+
)
129+
}),
130+
)
131+
}
132+
133+
pub fn get_start_container_env_tests() -> TestGroup {
134+
let mut tg = TestGroup::new("start_container_env");
135+
tg.add(vec![
136+
Box::new(get_test_inherit_env()),
137+
Box::new(get_test_explicit_env()),
138+
]);
139+
tg
140+
}

0 commit comments

Comments
 (0)