diff --git a/Cargo.lock b/Cargo.lock index 2aef72b..7d69790 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3666,7 +3666,7 @@ dependencies = [ [[package]] name = "wasmcloud-operator-types" -version = "0.1.5" +version = "0.1.6" dependencies = [ "k8s-openapi", "kube", diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index f083a05..9ee412e 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmcloud-operator-types" -version = "0.1.5" +version = "0.1.6" edition = "2021" [dependencies] diff --git a/crates/types/src/v1alpha1/wasmcloud_host_config.rs b/crates/types/src/v1alpha1/wasmcloud_host_config.rs index f1accb0..4a5b6d1 100644 --- a/crates/types/src/v1alpha1/wasmcloud_host_config.rs +++ b/crates/types/src/v1alpha1/wasmcloud_host_config.rs @@ -76,6 +76,8 @@ pub struct WasmCloudHostConfigSpec { pub policy_service: Option, /// Kubernetes scheduling options for the wasmCloud host. pub scheduling_options: Option, + /// Observability options for configuring the OpenTelemetry integration + pub observability: Option, } #[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] @@ -101,6 +103,45 @@ pub struct KubernetesSchedulingOptions { pub pod_template_additions: Option, } +#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct ObservabilityConfiguration { + #[serde(default)] + pub enable: bool, + pub endpoint: String, + pub protocol: Option, + pub logs: Option, + pub metrics: Option, + pub traces: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub enum OtelProtocol { + Grpc, + Http, +} + +impl std::fmt::Display for OtelProtocol { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + OtelProtocol::Grpc => "grpc", + OtelProtocol::Http => "http", + } + ) + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub struct OtelSignalConfiguration { + pub enable: Option, + pub endpoint: Option, +} + /// This is a workaround for the fact that we can't override the PodSpec schema to make containers /// an optional field. It generates the OpenAPI schema for the PodSpec type the same way that /// kube.rs does while dropping any required fields. diff --git a/src/controller.rs b/src/controller.rs index 70bea59..187d98e 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -31,7 +31,7 @@ use std::sync::Arc; use tokio::{sync::RwLock, time::Duration}; use tracing::{debug, info, warn}; use wasmcloud_operator_types::v1alpha1::{ - AppStatus, WasmCloudHostConfig, WasmCloudHostConfigStatus, + AppStatus, WasmCloudHostConfig, WasmCloudHostConfigSpec, WasmCloudHostConfigStatus, }; pub static CLUSTER_CONFIG_FINALIZER: &str = "operator.k8s.wasmcloud.dev/wasmcloud-host-config"; @@ -396,6 +396,8 @@ fn pod_template(config: &WasmCloudHostConfig, _ctx: Arc) -> PodTemplate } } + let wasmcloud_args = configure_observability(&config.spec); + let mut nats_resources: Option = None; let mut wasmcloud_resources: Option = None; if let Some(scheduling_options) = &config.spec.scheduling_options { @@ -461,6 +463,8 @@ fn pod_template(config: &WasmCloudHostConfig, _ctx: Arc) -> PodTemplate Container { name: "wasmcloud-host".to_string(), image: Some(image), + command: Some(vec!["wasmcloud".to_string()]), + args: Some(wasmcloud_args), env: Some(wasmcloud_env), resources: wasmcloud_resources, ..Default::default() @@ -531,6 +535,51 @@ fn pod_template(config: &WasmCloudHostConfig, _ctx: Arc) -> PodTemplate template } +fn configure_observability(spec: &WasmCloudHostConfigSpec) -> Vec { + let mut args = Vec::::new(); + if let Some(observability) = &spec.observability { + if observability.enable { + args.push("--enable-observability".to_string()); + } + if !observability.endpoint.is_empty() { + args.push("--override-observability-endpoint".to_string()); + args.push(observability.endpoint.clone()); + } + if let Some(protocol) = &observability.protocol { + args.push("--observability-protocol".to_string()); + args.push(protocol.to_string()); + } + if let Some(traces) = &observability.traces { + if traces.enable.unwrap_or(false) { + args.push("--enable-traces".to_string()) + } + if let Some(traces_endpoint) = &traces.endpoint { + args.push("--override-traces-endpoint".to_string()); + args.push(traces_endpoint.to_owned()); + } + } + if let Some(metrics) = &observability.metrics { + if metrics.enable.unwrap_or(false) { + args.push("--enable-metrics".to_string()) + } + if let Some(metrics_endpoint) = &metrics.endpoint { + args.push("--override-metrics-endpoint".to_string()); + args.push(metrics_endpoint.to_owned()); + } + } + if let Some(logs) = &observability.logs { + if logs.enable.unwrap_or(false) { + args.push("--enable-logs".to_string()) + } + if let Some(logs_endpoint) = &logs.endpoint { + args.push("--override-logs-endpoint".to_string()); + args.push(logs_endpoint.to_owned()); + } + } + } + args +} + fn deployment_spec(config: &WasmCloudHostConfig, ctx: Arc) -> DeploymentSpec { let pod_template = pod_template(config, ctx); let ls = LabelSelector {