diff --git a/.agents/skills/debug-openshell-cluster/SKILL.md b/.agents/skills/debug-openshell-cluster/SKILL.md index 86395af148..dae597e131 100644 --- a/.agents/skills/debug-openshell-cluster/SKILL.md +++ b/.agents/skills/debug-openshell-cluster/SKILL.md @@ -19,12 +19,17 @@ The target deployment flow is: 4. The CLI registers a reachable gateway endpoint with `openshell gateway add`. 5. The gateway creates sandboxes through the selected compute driver. -The standard gateway binary explicitly installs its compiled Docker, Podman, -Kubernetes, and VM registrations at startup. With no configured driver, the -gateway probes only installed registrations in priority order (Kubernetes, -Podman, then Docker); VM has no probe and remains opt-in. A custom gateway -binary may install a different set, so confirm the binary's registered drivers -when auto-detection reports that no suitable driver is available. +The standard gateway binary's default feature set explicitly installs its +compiled Docker, Podman, Kubernetes, and VM registrations at startup. Source +builds can compile any subset with the `compute-driver-docker`, +`compute-driver-podman`, `compute-driver-kubernetes`, and `compute-driver-vm` +features. With no configured driver, the gateway probes only installed +registrations in priority order (Kubernetes, Podman, then Docker); VM has no +probe and remains opt-in. A subset or custom gateway build may install a +different set, so confirm the binary's registered drivers when auto-detection +reports that no suitable driver is available. If configuration selects a +driver that was not compiled in, the gateway treats the name as an external +driver and reports a missing `socket_path` unless an endpoint is configured. For local evaluation only, TLS may be disabled and the gateway can be reached through `http://127.0.0.1:`. diff --git a/.github/workflows/branch-checks.yml b/.github/workflows/branch-checks.yml index b779974a0a..8ac08b1903 100644 --- a/.github/workflows/branch-checks.yml +++ b/.github/workflows/branch-checks.yml @@ -176,6 +176,15 @@ jobs: cargo build -p openshell-sandbox --bin openshell-sandbox --no-default-features --features defaults-without-telemetry tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-sandbox + - name: Verify selective gateway compute-driver builds + run: | + cargo check -p openshell-server --all-targets --no-default-features + cargo check -p openshell-server --all-targets --no-default-features --features compute-driver-docker + cargo check -p openshell-server --all-targets --no-default-features --features compute-driver-kubernetes + cargo check -p openshell-server --all-targets --no-default-features --features compute-driver-podman + cargo check -p openshell-server --all-targets --no-default-features --features compute-driver-vm + cargo check -p openshell-server --all-targets --no-default-features --features compute-driver-docker,compute-driver-vm + - name: Verify the defaults-without-telemetry feature alias tracks the default feature set run: tasks/scripts/verify-defaults-without-telemetry.sh diff --git a/README.md b/README.md index 28674cbdbf..0e46718ce2 100644 --- a/README.md +++ b/README.md @@ -268,6 +268,18 @@ cargo build --release -p openshell-driver-vm --no-default-features --features de The resulting binaries contain no telemetry endpoint, no telemetry HTTP client, and no emission code. With telemetry compiled out, the gateway emits nothing and reports telemetry disabled to the sandboxes it launches. Cargo has no way to subtract a single default feature, so `defaults-without-telemetry` must be paired with `--no-default-features`; passing it on its own leaves the defaults in place and fails the build rather than producing a binary that still emits. +The gateway also exposes separate Cargo features for its built-in compute drivers: `compute-driver-kubernetes`, `compute-driver-docker`, `compute-driver-podman`, and `compute-driver-vm`. Disable the default feature set, then enable only the drivers and telemetry mode required by the target binary. For example: + +```shell +# Docker only, with telemetry support. +cargo build --release -p openshell-server --no-default-features --features telemetry,compute-driver-docker + +# Docker and VM only, with telemetry compiled out. +cargo build --release -p openshell-server --no-default-features --features compute-driver-docker,compute-driver-vm +``` + +Regular builds still include all four drivers through the default `in-tree-compute-drivers` compatibility feature. + Telemetry events are limited to anonymous operational categories and counts, such as sandbox lifecycle outcomes, provider profile buckets, policy decision counts, and aggregate network activity denial categories. OpenShell telemetry does not collect sandbox names or IDs, hostnames, file paths, binary paths, prompts, credentials, provider names, model names, or user content. Opting out applies only to telemetry emitted by OpenShell. Third-party services, model providers, inference endpoints, agents, or tools that you configure and use with OpenShell may have their own terms and privacy practices. diff --git a/architecture/compute-runtimes.md b/architecture/compute-runtimes.md index 200e15fe72..0580abb2e7 100644 --- a/architecture/compute-runtimes.md +++ b/architecture/compute-runtimes.md @@ -120,11 +120,15 @@ to `run_cli_with_compute_drivers`; factories receive merged driver config and finish through the same in-process runtime adapter. A configured UDS endpoint still takes precedence over a compiled registration with the same name. -The standard server crate groups first-party registrations behind the -`in-tree-compute-drivers` feature. Protocol-only gateway builds disable that -feature and link no compute-driver crates. E2E lanes compose that gateway with -Docker, Podman, Kubernetes, and VM driver executables over the public UDS gRPC -contract so an in-tree driver cannot silently depend on a server-only API. +The standard server crate exposes one feature per first-party registration: +`compute-driver-kubernetes`, `compute-driver-docker`, +`compute-driver-podman`, and `compute-driver-vm`. Builds can enable any subset. +The default `in-tree-compute-drivers` feature remains an alias for all four, so +existing gateway builds retain the full driver set. Protocol-only gateway +builds disable the default features and link no compute-driver crates. E2E +lanes compose that gateway with Docker, Podman, Kubernetes, and VM driver +executables over the public UDS gRPC contract so an in-tree driver cannot +silently depend on a server-only API. External Kubernetes drivers support shared and managed workspace modes. Operator mode requires an in-process dynamic namespace allowlist and is rejected when Kubernetes is configured through an external endpoint. diff --git a/crates/openshell-server/Cargo.toml b/crates/openshell-server/Cargo.toml index 1cfd214f20..235fb5aa3b 100644 --- a/crates/openshell-server/Cargo.toml +++ b/crates/openshell-server/Cargo.toml @@ -127,13 +127,20 @@ openshell-driver-mxc = { path = "../openshell-driver-mxc" } [features] default = ["telemetry", "in-tree-compute-drivers"] -## Link the first-party compute drivers into the standard gateway binary. -## Disable this feature for a protocol-only gateway that uses external drivers. +## Link every first-party compute driver into the standard gateway binary. +## This compatibility alias preserves the historical all-drivers feature. in-tree-compute-drivers = [ - "dep:openshell-driver-docker", - "dep:openshell-driver-kubernetes", - "dep:openshell-driver-podman", + "compute-driver-docker", + "compute-driver-kubernetes", + "compute-driver-podman", + "compute-driver-vm", ] +## Link individual first-party compute drivers. Start with +## `--no-default-features` when building a gateway with a selected subset. +compute-driver-docker = ["dep:openshell-driver-docker"] +compute-driver-kubernetes = ["dep:openshell-driver-kubernetes"] +compute-driver-podman = ["dep:openshell-driver-podman"] +compute-driver-vm = [] ## Compile in anonymous telemetry emission (forwards to openshell-core/telemetry). ## On by default; build with `--no-default-features` for a telemetry-free gateway ## that contains no telemetry endpoint, HTTP client, or emission code. diff --git a/crates/openshell-server/src/cli.rs b/crates/openshell-server/src/cli.rs index f22e1355e4..1ac9f594c8 100644 --- a/crates/openshell-server/src/cli.rs +++ b/crates/openshell-server/src/cli.rs @@ -1946,7 +1946,7 @@ mem_mib = "not-a-number" } #[test] - #[cfg(not(target_os = "windows"))] + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] fn driver_inherits_shared_image_from_gateway_section() { // [openshell.gateway].default_image inherits into the K8s driver // table when the driver-specific table does not set it. @@ -1972,7 +1972,7 @@ namespace = "agents" } #[test] - #[cfg(not(target_os = "windows"))] + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] fn driver_specific_value_overrides_gateway_inheritance() { let file = config_file_from_toml( r#" diff --git a/crates/openshell-server/src/compute/driver_config.rs b/crates/openshell-server/src/compute/driver_config.rs index c25c63ded2..df60347134 100644 --- a/crates/openshell-server/src/compute/driver_config.rs +++ b/crates/openshell-server/src/compute/driver_config.rs @@ -7,7 +7,15 @@ //! driver-specific environment overrides, and applying gateway startup defaults. //! It does not acquire, connect to, or start compute drivers. -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all( + not(target_os = "windows"), + any( + feature = "compute-driver-docker", + feature = "compute-driver-kubernetes", + feature = "compute-driver-podman", + feature = "compute-driver-vm" + ) +))] pub mod builtin; use crate::config_file; diff --git a/crates/openshell-server/src/compute/driver_config/builtin.rs b/crates/openshell-server/src/compute/driver_config/builtin.rs index dea867237d..2be73e0775 100644 --- a/crates/openshell-server/src/compute/driver_config/builtin.rs +++ b/crates/openshell-server/src/compute/driver_config/builtin.rs @@ -3,17 +3,40 @@ //! Configuration construction for built-in compute drivers. -use super::{DriverStartupContext, GuestTlsPaths, driver_config_from_context}; +#[cfg(any( + feature = "compute-driver-docker", + feature = "compute-driver-podman", + feature = "compute-driver-vm" +))] +use super::GuestTlsPaths; +use super::{DriverStartupContext, driver_config_from_context}; +#[cfg(feature = "compute-driver-vm")] use crate::compute::VmComputeConfig; -#[cfg(test)] +#[cfg(all( + test, + any( + feature = "compute-driver-docker", + feature = "compute-driver-podman", + feature = "compute-driver-vm" + ) +))] use crate::config_file; use openshell_core::{ComputeDriverKind, Result}; +#[cfg(feature = "compute-driver-docker")] use openshell_driver_docker::DockerComputeConfig; +#[cfg(feature = "compute-driver-kubernetes")] use openshell_driver_kubernetes::KubernetesComputeConfig; +#[cfg(feature = "compute-driver-podman")] use openshell_driver_podman::PodmanComputeConfig; +#[cfg(any( + feature = "compute-driver-docker", + feature = "compute-driver-podman", + feature = "compute-driver-vm" +))] use std::path::PathBuf; /// Build the selected Kubernetes config from TOML plus runtime defaults. +#[cfg(feature = "compute-driver-kubernetes")] pub fn kubernetes_config_from_context( context: DriverStartupContext<'_>, ) -> Result { @@ -23,6 +46,7 @@ pub fn kubernetes_config_from_context( } /// Build the selected Podman config from TOML plus runtime defaults. +#[cfg(feature = "compute-driver-podman")] pub fn podman_config_from_context( context: DriverStartupContext<'_>, ) -> Result { @@ -32,6 +56,7 @@ pub fn podman_config_from_context( } /// Build the selected Docker config from TOML plus runtime defaults. +#[cfg(feature = "compute-driver-docker")] pub fn docker_config_from_context( context: DriverStartupContext<'_>, ) -> Result { @@ -41,12 +66,14 @@ pub fn docker_config_from_context( } /// Build the selected VM config from TOML plus runtime defaults. +#[cfg(feature = "compute-driver-vm")] pub fn vm_config_from_context(context: DriverStartupContext<'_>) -> Result { let mut cfg = driver_config_from_context(context, ComputeDriverKind::Vm.as_str())?; apply_vm_runtime_defaults(&mut cfg, context); Ok(cfg) } +#[cfg(feature = "compute-driver-kubernetes")] fn apply_kubernetes_runtime_defaults(k8s: &mut KubernetesComputeConfig) { if let Ok(size) = std::env::var("OPENSHELL_K8S_WORKSPACE_DEFAULT_STORAGE_SIZE") { k8s.workspace_default_storage_size = size; @@ -56,6 +83,7 @@ fn apply_kubernetes_runtime_defaults(k8s: &mut KubernetesComputeConfig) { } } +#[cfg(feature = "compute-driver-podman")] fn apply_podman_runtime_defaults( podman: &mut PodmanComputeConfig, context: DriverStartupContext<'_>, @@ -70,6 +98,7 @@ fn apply_podman_runtime_defaults( ); } +#[cfg(feature = "compute-driver-docker")] fn apply_docker_runtime_defaults(cfg: &mut DockerComputeConfig, context: DriverStartupContext<'_>) { apply_guest_tls_defaults_to_split_fields( &mut cfg.guest_tls_ca, @@ -79,6 +108,7 @@ fn apply_docker_runtime_defaults(cfg: &mut DockerComputeConfig, context: DriverS ); } +#[cfg(feature = "compute-driver-vm")] fn apply_vm_runtime_defaults(cfg: &mut VmComputeConfig, context: DriverStartupContext<'_>) { if cfg.state_dir.as_os_str().is_empty() { cfg.state_dir = VmComputeConfig::default_state_dir(); @@ -102,6 +132,11 @@ fn apply_vm_runtime_defaults(cfg: &mut VmComputeConfig, context: DriverStartupCo ); } +#[cfg(any( + feature = "compute-driver-docker", + feature = "compute-driver-podman", + feature = "compute-driver-vm" +))] fn apply_guest_tls_defaults_to_split_fields( ca: &mut Option, cert: &mut Option, @@ -119,6 +154,7 @@ fn apply_guest_tls_defaults_to_split_fields( } } +#[cfg(feature = "compute-driver-podman")] fn apply_podman_env_overrides(podman: &mut PodmanComputeConfig) { if let Ok(p) = std::env::var("OPENSHELL_PODMAN_SOCKET") { podman.socket_path = Some(PathBuf::from(p)); @@ -131,10 +167,18 @@ fn apply_podman_env_overrides(podman: &mut PodmanComputeConfig) { } } -#[cfg(test)] +#[cfg(all( + test, + any( + feature = "compute-driver-docker", + feature = "compute-driver-podman", + feature = "compute-driver-vm" + ) +))] mod tests { use super::*; use std::collections::BTreeMap; + use std::path::PathBuf; fn test_context(file: Option<&config_file::ConfigFile>) -> DriverStartupContext<'_> { static EMPTY_ENDPOINT_OVERRIDES: std::sync::LazyLock> = @@ -148,6 +192,7 @@ mod tests { } } + #[cfg(feature = "compute-driver-podman")] #[test] fn podman_config_reads_bind_mount_opt_in_from_driver_table() { let file: config_file::ConfigFile = toml::from_str( @@ -163,6 +208,7 @@ enable_bind_mounts = true assert!(cfg.enable_bind_mounts); } + #[cfg(feature = "compute-driver-docker")] #[test] fn docker_config_reads_bind_mount_opt_in_from_driver_table() { let file: config_file::ConfigFile = toml::from_str( @@ -178,6 +224,7 @@ enable_bind_mounts = true assert!(cfg.enable_bind_mounts); } + #[cfg(feature = "compute-driver-docker")] #[test] fn docker_config_reads_socket_path_from_driver_table() { let file: config_file::ConfigFile = toml::from_str( @@ -193,6 +240,7 @@ socket_path = "/tmp/docker.sock" assert_eq!(cfg.socket_path, Some(PathBuf::from("/tmp/docker.sock"))); } + #[cfg(feature = "compute-driver-docker")] #[test] fn docker_config_reports_selected_invalid_driver_table() { let file: config_file::ConfigFile = toml::from_str( @@ -211,6 +259,7 @@ unknown_docker_key = true ); } + #[cfg(feature = "compute-driver-vm")] #[test] fn vm_config_reports_selected_invalid_driver_table() { let file: config_file::ConfigFile = toml::from_str( diff --git a/crates/openshell-server/src/compute/mod.rs b/crates/openshell-server/src/compute/mod.rs index 78ae6fddb3..263a3dbb79 100644 --- a/crates/openshell-server/src/compute/mod.rs +++ b/crates/openshell-server/src/compute/mod.rs @@ -5,16 +5,16 @@ pub mod driver_config; pub mod lease; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-vm"))] pub mod vm; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] pub use openshell_driver_docker::DockerComputeConfig; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] pub use openshell_driver_kubernetes::KubernetesComputeConfig; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] pub use openshell_driver_podman::PodmanComputeConfig; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-vm"))] pub use vm::VmComputeConfig; use crate::grpc::policy::SANDBOX_SETTINGS_OBJECT_TYPE; @@ -52,16 +52,16 @@ use openshell_core::proto::{ SandboxTemplate, ServiceEndpoint, SshSession, }; use openshell_core::{ObjectLabels, ObjectWorkspace}; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] use openshell_driver_docker::{ComputeDriverService as DockerDriverService, DockerComputeDriver}; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] use openshell_driver_kubernetes::{ ComputeDriverService as KubernetesDriverService, KubernetesComputeDriver, OperatorNamespaceAllowlist, }; #[cfg(target_os = "windows")] use openshell_driver_mxc::{ComputeDriverService as MxcDriverService, MxcComputeConfig}; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] use openshell_driver_podman::{ComputeDriverService as PodmanDriverService, PodmanComputeDriver}; use prost::Message; use std::collections::HashMap; @@ -306,7 +306,7 @@ pub struct ManagedDriverProcess { } impl ManagedDriverProcess { - #[cfg(all(unix, any(test, feature = "in-tree-compute-drivers")))] + #[cfg(all(unix, any(test, feature = "compute-driver-vm")))] pub(crate) fn new(child: tokio::process::Child, socket_path: PathBuf) -> Self { Self { child: std::sync::Mutex::new(Some(child)), @@ -404,7 +404,7 @@ pub struct AcquiredRemoteDriverEndpoint { } impl AcquiredRemoteDriverEndpoint { - #[cfg(any(test, feature = "in-tree-compute-drivers"))] + #[cfg(feature = "compute-driver-vm")] pub(crate) fn managed_builtin( driver_kind: ComputeDriverKind, channel: Channel, @@ -743,7 +743,7 @@ impl ComputeRuntime { self.lifecycle_gates.entry_count() } - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] pub async fn new_docker( config: openshell_core::Config, docker_config: DockerComputeConfig, @@ -770,7 +770,7 @@ impl ComputeRuntime { .await } - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] pub async fn new_kubernetes( config: KubernetesComputeConfig, store: Arc, @@ -821,7 +821,7 @@ impl ComputeRuntime { .await } - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] pub async fn new_podman( config: PodmanComputeConfig, store: Arc, diff --git a/crates/openshell-server/src/lib.rs b/crates/openshell-server/src/lib.rs index c2306b6632..74ec250534 100644 --- a/crates/openshell-server/src/lib.rs +++ b/crates/openshell-server/src/lib.rs @@ -1228,7 +1228,7 @@ impl ComputeDriverRegistry { pub fn install_default_compute_drivers() -> ComputeDriverRegistry { #[allow(unused_mut)] let mut registry = ComputeDriverRegistry::new(); - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] { registry .install( @@ -1241,6 +1241,9 @@ pub fn install_default_compute_drivers() -> ComputeDriverRegistry { .expect("valid kubernetes registration"), ) .expect("unique kubernetes registration"); + } + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] + { registry .install( ComputeDriverRegistration::new( @@ -1252,6 +1255,9 @@ pub fn install_default_compute_drivers() -> ComputeDriverRegistry { .expect("valid podman registration"), ) .expect("unique podman registration"); + } + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] + { registry .install( ComputeDriverRegistration::new( @@ -1263,6 +1269,9 @@ pub fn install_default_compute_drivers() -> ComputeDriverRegistry { .expect("valid docker registration"), ) .expect("unique docker registration"); + } + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-vm"))] + { registry .install( ComputeDriverRegistration::new("vm", u16::MAX, None, VmComputeDriverFactory) @@ -1425,11 +1434,11 @@ impl ComputeDriverFactory for UnsupportedComputeDriverFactory { } } -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] #[derive(Clone, Copy)] struct KubernetesComputeDriverFactory; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] #[async_trait::async_trait] impl ComputeDriverFactory for KubernetesComputeDriverFactory { async fn build( @@ -1458,11 +1467,11 @@ impl ComputeDriverFactory for KubernetesComputeDriverFactory { } } -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] #[derive(Clone, Copy)] struct DockerComputeDriverFactory; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] #[async_trait::async_trait] impl ComputeDriverFactory for DockerComputeDriverFactory { async fn build( @@ -1489,11 +1498,11 @@ impl ComputeDriverFactory for DockerComputeDriverFactory { } } -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] #[derive(Clone, Copy)] struct PodmanComputeDriverFactory; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] #[async_trait::async_trait] impl ComputeDriverFactory for PodmanComputeDriverFactory { async fn build( @@ -1519,11 +1528,11 @@ impl ComputeDriverFactory for PodmanComputeDriverFactory { } } -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-vm"))] #[derive(Clone, Copy)] struct VmComputeDriverFactory; -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all(not(target_os = "windows"), feature = "compute-driver-vm"))] #[async_trait::async_trait] impl ComputeDriverFactory for VmComputeDriverFactory { async fn build( @@ -1681,7 +1690,7 @@ fn resolve_configured_compute_driver( Ok(ConfiguredComputeDriver::Remote { name }) } -#[cfg(any(test, feature = "in-tree-compute-drivers"))] +#[cfg(any(test, feature = "compute-driver-kubernetes"))] fn kubernetes_sandbox_jwt_expiry_disabled(config: &Config) -> bool { config .gateway_jwt @@ -1689,7 +1698,7 @@ fn kubernetes_sandbox_jwt_expiry_disabled(config: &Config) -> bool { .is_some_and(|jwt| jwt.ttl_secs == 0) } -#[cfg(feature = "in-tree-compute-drivers")] +#[cfg(feature = "compute-driver-kubernetes")] fn warn_if_kubernetes_sandbox_jwt_expiry_disabled(config: &Config) { if kubernetes_sandbox_jwt_expiry_disabled(config) { warn!( @@ -2353,6 +2362,29 @@ mod tests { assert!(err.to_string().contains("kubernetes,podman")); } + #[cfg(not(target_os = "windows"))] + #[test] + fn default_registry_contains_exactly_the_enabled_compute_drivers() { + let expected: Vec<&str> = vec![ + #[cfg(feature = "compute-driver-docker")] + "docker", + #[cfg(feature = "compute-driver-kubernetes")] + "kubernetes", + #[cfg(feature = "compute-driver-podman")] + "podman", + #[cfg(feature = "compute-driver-vm")] + "vm", + ]; + + assert_eq!( + test_compute_drivers() + .installed_driver_names() + .collect::>(), + expected + ); + } + + #[cfg(feature = "compute-driver-podman")] #[test] fn configured_compute_driver_accepts_podman() { let config = Config::new(None).with_compute_drivers([ComputeDriverKind::Podman]); @@ -2368,6 +2400,7 @@ mod tests { )); } + #[cfg(feature = "compute-driver-vm")] #[test] fn configured_compute_driver_accepts_vm() { let config = Config::new(None).with_compute_drivers([ComputeDriverKind::Vm]); @@ -2383,6 +2416,7 @@ mod tests { )); } + #[cfg(feature = "compute-driver-docker")] #[test] fn configured_compute_driver_accepts_docker() { let config = Config::new(None).with_compute_drivers([ComputeDriverKind::Docker]); diff --git a/crates/openshell-server/src/tracing_setup.rs b/crates/openshell-server/src/tracing_setup.rs index edcf303072..f1cfc9dac7 100644 --- a/crates/openshell-server/src/tracing_setup.rs +++ b/crates/openshell-server/src/tracing_setup.rs @@ -38,71 +38,72 @@ impl TracingHandle { #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum InProcessDriverTracing { - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] Docker, - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] Kubernetes, - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] Podman, } impl InProcessDriverTracing { - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] fn target_prefix(self) -> &'static str { match self { + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] Self::Docker => openshell_driver_docker::otel_tracing::IN_PROCESS_TARGET_PREFIX, + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] Self::Kubernetes => openshell_driver_kubernetes::otel_tracing::IN_PROCESS_TARGET_PREFIX, + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] Self::Podman => openshell_driver_podman::otel_tracing::IN_PROCESS_TARGET_PREFIX, } } } fn in_process_driver_tracing(driver: &ConfiguredComputeDriver) -> Option { - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] match driver { + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] ConfiguredComputeDriver::Registered(registration) if registration.name == "docker" => { Some(InProcessDriverTracing::Docker) } + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] ConfiguredComputeDriver::Registered(registration) if registration.name == "podman" => { Some(InProcessDriverTracing::Podman) } + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] ConfiguredComputeDriver::Registered(registration) if registration.name == "kubernetes" => { Some(InProcessDriverTracing::Kubernetes) } _ => None, } - #[cfg(not(all(not(target_os = "windows"), feature = "in-tree-compute-drivers")))] - { - let _ = driver; - None - } } fn in_process_driver_target_prefix(driver: Option) -> Option<&'static str> { - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] - { - driver.map(InProcessDriverTracing::target_prefix) - } - #[cfg(not(all(not(target_os = "windows"), feature = "in-tree-compute-drivers")))] - { - let _ = driver; - None - } + driver.map(InProcessDriverTracing::target_prefix) } -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all( + not(target_os = "windows"), + any( + feature = "compute-driver-docker", + feature = "compute-driver-kubernetes", + feature = "compute-driver-podman" + ) +))] fn in_process_driver_provider( driver: Option, endpoint: Option<&str>, gateway_name: Option<&str>, ) -> (Option, Option) { match driver { + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] Some(InProcessDriverTracing::Docker) => { openshell_driver_docker::otel_tracing::provider_for(endpoint, gateway_name) } + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] Some(InProcessDriverTracing::Kubernetes) => { openshell_driver_kubernetes::otel_tracing::provider_for(endpoint, gateway_name) } + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] Some(InProcessDriverTracing::Podman) => { openshell_driver_podman::otel_tracing::provider_for(endpoint, gateway_name) } @@ -110,7 +111,14 @@ fn in_process_driver_provider( } } -#[cfg(not(all(not(target_os = "windows"), feature = "in-tree-compute-drivers")))] +#[cfg(not(all( + not(target_os = "windows"), + any( + feature = "compute-driver-docker", + feature = "compute-driver-kubernetes", + feature = "compute-driver-podman" + ) +)))] fn in_process_driver_provider( _driver: Option, _endpoint: Option<&str>, @@ -119,7 +127,14 @@ fn in_process_driver_provider( (None, None) } -#[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] +#[cfg(all( + not(target_os = "windows"), + any( + feature = "compute-driver-docker", + feature = "compute-driver-kubernetes", + feature = "compute-driver-podman" + ) +))] fn in_process_driver_layer( provider: &Option, driver: Option, @@ -128,12 +143,15 @@ where S: tracing::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>, { provider.as_ref().map(|provider| match driver { + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-docker"))] Some(InProcessDriverTracing::Docker) => { openshell_driver_docker::otel_tracing::in_process_layer(provider) } + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-kubernetes"))] Some(InProcessDriverTracing::Kubernetes) => { openshell_driver_kubernetes::otel_tracing::in_process_layer(provider) } + #[cfg(all(not(target_os = "windows"), feature = "compute-driver-podman"))] Some(InProcessDriverTracing::Podman) => { openshell_driver_podman::otel_tracing::in_process_layer(provider) } @@ -141,7 +159,14 @@ where }) } -#[cfg(not(all(not(target_os = "windows"), feature = "in-tree-compute-drivers")))] +#[cfg(not(all( + not(target_os = "windows"), + any( + feature = "compute-driver-docker", + feature = "compute-driver-kubernetes", + feature = "compute-driver-podman" + ) +)))] fn in_process_driver_layer( _provider: &Option, _driver: Option, @@ -196,9 +221,24 @@ pub fn install( #[cfg(test)] mod tests { + #[cfg(all( + not(target_os = "windows"), + any( + feature = "compute-driver-docker", + feature = "compute-driver-kubernetes", + feature = "compute-driver-podman" + ) + ))] use super::*; - #[cfg(all(not(target_os = "windows"), feature = "in-tree-compute-drivers"))] + #[cfg(all( + not(target_os = "windows"), + any( + feature = "compute-driver-docker", + feature = "compute-driver-kubernetes", + feature = "compute-driver-podman" + ) + ))] #[test] fn in_process_driver_tracing_selects_registered_compute_drivers() { let registry = crate::install_default_compute_drivers(); @@ -210,14 +250,17 @@ mod tests { .clone(), ) }; + #[cfg(feature = "compute-driver-podman")] assert_eq!( in_process_driver_tracing(®istered("podman")), Some(InProcessDriverTracing::Podman) ); + #[cfg(feature = "compute-driver-docker")] assert_eq!( in_process_driver_tracing(®istered("docker")), Some(InProcessDriverTracing::Docker) ); + #[cfg(feature = "compute-driver-kubernetes")] assert_eq!( in_process_driver_tracing(®istered("kubernetes")), Some(InProcessDriverTracing::Kubernetes)