Skip to content

Commit 9c14190

Browse files
committed
feat: kubernetes operator for agent lifecycle management
Add a kube-rs based Kubernetes operator (openshell-operator crate) that provides CRD-driven declarative sandbox lifecycle management. Components: - AgentSandbox CRD with spec for image, resources, policy, and provider refs - Reconciler loop with exponential backoff and status condition reporting - Admission webhooks (validating + mutating) for CRD validation - Manifest builders for sandbox Pod, Service, and RBAC resources - Label conventions for sandbox discovery and ownership tracking - SandboxRuntimeManager gRPC service for operator-gateway communication - Gateway integration via multiplex listener and config flags New crate: crates/openshell-operator (16 files) New proto: proto/sandbox_runtime_manager.proto Modified: openshell-core (config, proto), openshell-server (cli, grpc, multiplex) Tests: 2,239 passed, 0 failed Closes #1719
1 parent 6461677 commit 9c14190

28 files changed

Lines changed: 2832 additions & 9 deletions

Cargo.lock

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ kube = { version = "0.90", features = ["runtime", "derive"] }
113113
kube-runtime = "0.90"
114114
k8s-openapi = { version = "0.21.1", features = ["v1_26"] }
115115

116+
# CRD support (operator)
117+
schemars = "0.8"
118+
json-patch = "1"
119+
116120
# IDs
117121
uuid = { version = "1.10", features = ["v4"] }
118122

crates/openshell-core/src/config.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,9 @@ pub struct Config {
400400

401401
/// Browser-facing sandbox service routing configuration.
402402
pub service_routing: ServiceRoutingConfig,
403+
404+
/// Whether the SandboxRuntime operator bridge is enabled.
405+
pub operator_enabled: bool,
403406
}
404407

405408
/// Browser-facing sandbox service routing configuration.
@@ -584,6 +587,7 @@ impl Config {
584587
grpc_rate_limit_requests: None,
585588
grpc_rate_limit_window_secs: None,
586589
service_routing: ServiceRoutingConfig::default(),
590+
operator_enabled: false,
587591
}
588592
}
589593

@@ -705,6 +709,13 @@ impl Config {
705709
self.service_routing.enable_loopback_service_http = enabled;
706710
self
707711
}
712+
713+
/// Enable or disable the SandboxRuntime operator bridge.
714+
#[must_use]
715+
pub const fn with_operator_enabled(mut self, enabled: bool) -> Self {
716+
self.operator_enabled = enabled;
717+
self
718+
}
708719
}
709720

710721
impl Default for ServiceRoutingConfig {

crates/openshell-core/src/proto/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,22 @@ pub mod inference {
7979
}
8080
}
8181

82+
#[allow(
83+
clippy::all,
84+
clippy::pedantic,
85+
clippy::nursery,
86+
unused_qualifications,
87+
rust_2018_idioms
88+
)]
89+
pub mod runtime {
90+
pub mod v1 {
91+
include!(concat!(env!("OUT_DIR"), "/openshell.runtime.v1.rs"));
92+
}
93+
}
94+
8295
pub use datamodel::v1::*;
8396
pub use inference::v1::*;
8497
pub use openshell::*;
98+
pub use runtime::v1::*;
8599
pub use sandbox::v1::*;
86100
pub use test::ObjectForTest;
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
[package]
5+
name = "openshell-operator"
6+
description = "Kubernetes operator for SandboxRuntime CRD lifecycle management"
7+
version.workspace = true
8+
edition.workspace = true
9+
rust-version.workspace = true
10+
license.workspace = true
11+
repository.workspace = true
12+
13+
[[bin]]
14+
name = "openshell-operator"
15+
path = "src/main.rs"
16+
17+
[[bin]]
18+
name = "openshell-crd-gen"
19+
path = "src/bin/crd_gen.rs"
20+
21+
[lib]
22+
name = "openshell_operator"
23+
path = "src/lib.rs"
24+
25+
[dependencies]
26+
# Kubernetes (inherits workspace features: runtime, derive)
27+
# Additional "admission" feature for webhook support
28+
kube = { workspace = true, features = ["admission"] }
29+
k8s-openapi = { workspace = true }
30+
31+
# CRD schema generation
32+
schemars = { workspace = true }
33+
34+
# Webhook JSON patches
35+
json-patch = { workspace = true }
36+
37+
# gRPC / Protobuf (for bridge service types)
38+
tonic = { workspace = true }
39+
prost = { workspace = true }
40+
41+
# HTTP server (webhook endpoints)
42+
axum = { workspace = true }
43+
tower = { workspace = true }
44+
hyper = { workspace = true }
45+
hyper-util = { workspace = true }
46+
47+
# TLS (webhook HTTPS)
48+
tokio-rustls = { workspace = true }
49+
rustls = { workspace = true }
50+
rustls-pemfile = { workspace = true }
51+
52+
# Async runtime
53+
tokio = { workspace = true }
54+
tokio-stream = { workspace = true }
55+
futures = { workspace = true }
56+
57+
# Serialization
58+
serde = { workspace = true }
59+
serde_json = { workspace = true }
60+
serde_yml = { workspace = true }
61+
62+
# Error handling
63+
thiserror = { workspace = true }
64+
anyhow = { workspace = true }
65+
66+
# Logging
67+
tracing = { workspace = true }
68+
tracing-subscriber = { workspace = true }
69+
70+
# CLI (operator binary args)
71+
clap = { workspace = true }
72+
73+
[dev-dependencies]
74+
tokio = { workspace = true, features = ["full", "test-util"] }
75+
76+
[lints]
77+
workspace = true
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! Utility to generate the SandboxRuntime CRD YAML for Helm chart deployment.
5+
6+
use kube::CustomResourceExt;
7+
use openshell_operator::crd::SandboxRuntime;
8+
9+
fn main() {
10+
print!(
11+
"{}",
12+
serde_yml::to_string(&SandboxRuntime::crd()).unwrap()
13+
);
14+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! Configuration types for the operator binary.
5+
6+
/// Configuration for the operator binary.
7+
#[derive(Clone, Debug)]
8+
pub struct OperatorConfig {
9+
/// Namespace to watch. `None` = all namespaces.
10+
pub namespace: Option<String>,
11+
12+
/// Metrics server bind address.
13+
pub metrics_addr: String,
14+
15+
/// Webhook server bind address.
16+
pub webhook_addr: String,
17+
18+
/// Path to TLS certificate for webhook server.
19+
pub tls_cert_path: Option<String>,
20+
21+
/// Path to TLS private key for webhook server.
22+
pub tls_key_path: Option<String>,
23+
}

0 commit comments

Comments
 (0)