Skip to content

Commit 3b61c9c

Browse files
authored
feat(k8s): support nodeSelector and tolerations from platform_config (#1327)
Extract node_selector and tolerations from the sandbox template's platform_config and apply them to the pod spec. This allows callers to schedule sandbox pods on specific node pools and tolerate taints without requiring first-class proto fields.
1 parent df5a8b9 commit 3b61c9c

1 file changed

Lines changed: 110 additions & 0 deletions

File tree

  • crates/openshell-driver-kubernetes/src

crates/openshell-driver-kubernetes/src/driver.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,12 @@ fn sandbox_template_to_k8s(
10781078
serde_json::json!(runtime_class),
10791079
);
10801080
}
1081+
if let Some(node_selector) = platform_config_struct(template, "node_selector") {
1082+
spec.insert("nodeSelector".to_string(), node_selector);
1083+
}
1084+
if let Some(tolerations) = platform_config_struct(template, "tolerations") {
1085+
spec.insert("tolerations".to_string(), tolerations);
1086+
}
10811087

10821088
// Per-sandbox platform_config.host_users overrides the cluster-wide default.
10831089
let use_user_namespaces = platform_config_bool(template, "host_users")
@@ -2322,4 +2328,108 @@ mod tests {
23222328
);
23232329
assert!(cr["spec"].get("logLevel").is_none());
23242330
}
2331+
2332+
#[test]
2333+
fn node_selector_from_platform_config() {
2334+
let template = SandboxTemplate {
2335+
platform_config: Some(Struct {
2336+
fields: std::iter::once((
2337+
"node_selector".to_string(),
2338+
Value {
2339+
kind: Some(Kind::StructValue(Struct {
2340+
fields: std::iter::once((
2341+
"gpu-pool".to_string(),
2342+
Value {
2343+
kind: Some(Kind::StringValue("true".to_string())),
2344+
},
2345+
))
2346+
.collect(),
2347+
})),
2348+
},
2349+
))
2350+
.collect(),
2351+
}),
2352+
..SandboxTemplate::default()
2353+
};
2354+
2355+
let pod_template = {
2356+
let params = SandboxPodParams::default();
2357+
sandbox_template_to_k8s(
2358+
&template,
2359+
false,
2360+
&std::collections::HashMap::new(),
2361+
false,
2362+
&params,
2363+
)
2364+
};
2365+
2366+
assert_eq!(
2367+
pod_template["spec"]["nodeSelector"]["gpu-pool"],
2368+
serde_json::json!("true")
2369+
);
2370+
}
2371+
2372+
#[test]
2373+
fn tolerations_from_platform_config() {
2374+
let toleration = Struct {
2375+
fields: [
2376+
(
2377+
"key".to_string(),
2378+
Value {
2379+
kind: Some(Kind::StringValue("nvidia.com/gpu".to_string())),
2380+
},
2381+
),
2382+
(
2383+
"operator".to_string(),
2384+
Value {
2385+
kind: Some(Kind::StringValue("Exists".to_string())),
2386+
},
2387+
),
2388+
(
2389+
"effect".to_string(),
2390+
Value {
2391+
kind: Some(Kind::StringValue("NoSchedule".to_string())),
2392+
},
2393+
),
2394+
]
2395+
.into_iter()
2396+
.collect(),
2397+
};
2398+
2399+
let template = SandboxTemplate {
2400+
platform_config: Some(Struct {
2401+
fields: std::iter::once((
2402+
"tolerations".to_string(),
2403+
Value {
2404+
kind: Some(Kind::ListValue(prost_types::ListValue {
2405+
values: vec![Value {
2406+
kind: Some(Kind::StructValue(toleration)),
2407+
}],
2408+
})),
2409+
},
2410+
))
2411+
.collect(),
2412+
}),
2413+
..SandboxTemplate::default()
2414+
};
2415+
2416+
let pod_template = {
2417+
let params = SandboxPodParams::default();
2418+
sandbox_template_to_k8s(
2419+
&template,
2420+
false,
2421+
&std::collections::HashMap::new(),
2422+
false,
2423+
&params,
2424+
)
2425+
};
2426+
2427+
let tolerations = pod_template["spec"]["tolerations"]
2428+
.as_array()
2429+
.expect("tolerations should be an array");
2430+
assert_eq!(tolerations.len(), 1);
2431+
assert_eq!(tolerations[0]["key"], "nvidia.com/gpu");
2432+
assert_eq!(tolerations[0]["operator"], "Exists");
2433+
assert_eq!(tolerations[0]["effect"], "NoSchedule");
2434+
}
23252435
}

0 commit comments

Comments
 (0)