Skip to content

Commit d94fb6a

Browse files
committed
feat(supervisor): add independent application listener and endpoints
Signed-off-by: Taylor Mutch <taylormutch@gmail.com>
1 parent 9f1cdb4 commit d94fb6a

42 files changed

Lines changed: 2987 additions & 184 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/helm-dev-environment/SKILL.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,3 +611,14 @@ for dependencies still declared in `Chart.yaml`.
611611
| `deploy/kube/manifests/envoy-gateway-openshell.yaml` | GatewayClass and BackendTrafficPolicy for Envoy Gateway (`mise run helm:gateway:apply`) |
612612
| `tasks/scripts/helm-k3s-local.sh` | k3d cluster create/delete/start/stop/status |
613613
| `tasks/scripts/keycloak-k8s-setup.sh` | Keycloak deploy, realm import, and development TLS trust anchor |
614+
615+
## App listener fixture
616+
617+
The opt-in `deploy/helm/openshell/ci/values-app-listener.yaml` enables the
618+
supervisor listener at port 9443 without discovery or a proxy. Provision the
619+
operator TLS Secret and an ingress-client NetworkPolicy first. Follow
620+
`e2e/kubernetes/app-listener/README.md` for direct in-cluster verification,
621+
shared-member selection, and the HA follow-up checks. Keep the fixture disabled
622+
in default profiles. Shared supervisors expose app ports on their Pod IPs
623+
without a shared app Service. Select the member owning the sandbox; automatic
624+
owner selection belongs to the later discovery API.

‎Cargo.lock‎

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! Driver-independent application listener configuration.
5+
6+
use serde::{Deserialize, Serialize};
7+
8+
/// Explicitly enabled application ingress. Deployment details such as TLS
9+
/// Secret names belong to the driver, not to this common configuration.
10+
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
11+
#[serde(default, deny_unknown_fields)]
12+
pub struct AppListenerConfig {
13+
pub enabled: bool,
14+
pub port: u16,
15+
pub domain: String,
16+
}
17+
18+
impl Default for AppListenerConfig {
19+
fn default() -> Self {
20+
Self {
21+
enabled: false,
22+
port: 8443,
23+
domain: String::new(),
24+
}
25+
}
26+
}
27+
28+
impl AppListenerConfig {
29+
pub fn validate(&self) -> Result<(), String> {
30+
if !self.enabled {
31+
return Ok(());
32+
}
33+
if self.port < 1024 {
34+
return Err("supervisor.app_listener.port must be at least 1024".into());
35+
}
36+
if self.domain.len() > 253
37+
|| !self.domain.split('.').all(|label| {
38+
!label.is_empty()
39+
&& label.len() <= 63
40+
&& !label.starts_with('-')
41+
&& !label.ends_with('-')
42+
&& label
43+
.bytes()
44+
.all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'-')
45+
})
46+
{
47+
return Err("supervisor.app_listener.domain must be a lowercase DNS name".into());
48+
}
49+
Ok(())
50+
}
51+
}
52+
53+
#[cfg(test)]
54+
mod tests {
55+
use super::*;
56+
57+
#[test]
58+
fn only_explicit_enablement_requires_a_valid_endpoint() {
59+
assert!(!AppListenerConfig::default().enabled);
60+
assert!(AppListenerConfig::default().validate().is_ok());
61+
let mut config = AppListenerConfig {
62+
enabled: true,
63+
..Default::default()
64+
};
65+
assert!(config.validate().is_err());
66+
config.domain = "services.example.com".into();
67+
assert!(config.validate().is_ok());
68+
config.port = 0;
69+
assert!(config.validate().is_err());
70+
}
71+
}

‎crates/openshell-core/src/config.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ pub struct Config {
332332

333333
/// Browser-facing sandbox service routing configuration.
334334
pub service_routing: ServiceRoutingConfig,
335+
pub supervisor_app_listener: crate::app_listener::AppListenerConfig,
335336
}
336337

337338
/// Browser-facing sandbox service routing configuration.
@@ -1015,6 +1016,7 @@ impl Config {
10151016
grpc_rate_limit_requests: None,
10161017
grpc_rate_limit_window_secs: None,
10171018
service_routing: ServiceRoutingConfig::default(),
1019+
supervisor_app_listener: crate::app_listener::AppListenerConfig::default(),
10181020
}
10191021
}
10201022

‎crates/openshell-core/src/grpc_client.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,6 +1863,7 @@ pub struct CachedOpenShellClient {
18631863
/// Settings poll result returned by [`CachedOpenShellClient::poll_settings`].
18641864
#[derive(Clone, Debug)]
18651865
pub struct SettingsPollResult {
1866+
pub service_routes: Vec<crate::proto::SandboxServiceRoute>,
18661867
pub configuration_instance_id: String,
18671868
pub configuration_admitted: bool,
18681869
pub configuration_error: String,
@@ -1890,6 +1891,7 @@ pub struct SettingsPollResult {
18901891

18911892
fn settings_poll_result(inner: crate::proto::GetSandboxConfigResponse) -> SettingsPollResult {
18921893
SettingsPollResult {
1894+
service_routes: inner.service_routes,
18931895
configuration_instance_id: inner.configuration_instance_id,
18941896
configuration_admitted: inner.configuration_admitted,
18951897
configuration_error: inner.configuration_error,
@@ -1919,6 +1921,7 @@ fn settings_poll_result(inner: crate::proto::GetSandboxConfigResponse) -> Settin
19191921
impl From<crate::proto::SandboxConfigSnapshot> for SettingsPollResult {
19201922
fn from(snapshot: crate::proto::SandboxConfigSnapshot) -> Self {
19211923
settings_poll_result(crate::proto::GetSandboxConfigResponse {
1924+
service_routes: snapshot.service_routes,
19221925
policy: snapshot.policy,
19231926
version: snapshot.version,
19241927
policy_hash: snapshot.policy_hash,

‎crates/openshell-core/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//! - Build version metadata
1111
1212
pub mod activity;
13+
pub mod app_listener;
1314
pub mod auth;
1415
pub mod config;
1516
pub mod container_paths;

0 commit comments

Comments
 (0)