Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 4
feat: Support configuring ListenerClass preset (with sensible defaults)#414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
dd593a849039e32d96b64a8db362ca2895b263b9cd3e69cd9be8fade3281de13ff1776fd044d23019ae38d838f0bfa6b25File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| use clap::ValueEnum; | ||
| use snafu::ResultExt; | ||
| use stackable_operator::{ | ||
| k8s_openapi::api::core::v1::Node, | ||
| kube::{Api, Client, api::ListParams}, | ||
| }; | ||
| use tokio::sync::OnceCell; | ||
| use tracing::{debug, info, instrument}; | ||
| pub static LISTENER_CLASS_PRESET: OnceCell<ListenerClassPreset> = OnceCell::const_new(); | ||
| /// Represents the `preset` value in the Listener Operator Helm Chart | ||
| #[derive(Copy, Clone, Debug, ValueEnum)] | ||
| pub enum ListenerClassPreset { | ||
| None, | ||
| StableNodes, | ||
| EphemeralNodes, | ||
| } | ||
| impl ListenerClassPreset { | ||
| pub fn as_helm_values(&self) -> String { | ||
| let preset_value = match self { | ||
| Self::None => "none", | ||
| Self::StableNodes => "stable-nodes", | ||
| Self::EphemeralNodes => "ephemeral-nodes", | ||
| }; | ||
| format!("preset: {preset_value}") | ||
| } | ||
| } | ||
| #[instrument] | ||
| pub async fn determine_and_store_listener_class_preset(from_cli: Option<&ListenerClassPreset>) { | ||
| if let Some(from_cli) = from_cli { | ||
| LISTENER_CLASS_PRESET | ||
| .set(*from_cli) | ||
| .expect("LISTENER_CLASS_PRESET should be unset"); | ||
| return; | ||
| } | ||
| let kubernetes_environment = guess_kubernetes_environment().await.unwrap_or_else(|err| { | ||
| info!("failed to determine Kubernetes environment, using defaults: {err:#?}"); | ||
| KubernetesEnvironment::Unknown | ||
| }); | ||
| let listener_class_preset = match kubernetes_environment { | ||
| // Kind does not support LoadBalancers out of the box, so avoid that | ||
| KubernetesEnvironment::Kind => ListenerClassPreset::StableNodes, | ||
| // LoadBalancer support in k3s is optional, so let's be better safe than sorry and not use | ||
| // them | ||
| KubernetesEnvironment::K3s => ListenerClassPreset::StableNodes, | ||
| // Weekly node rotations and LoadBalancer support | ||
| KubernetesEnvironment::Ionos => ListenerClassPreset::EphemeralNodes, | ||
| // Don't pin nodes and assume we have LoadBalancer support | ||
| KubernetesEnvironment::Unknown => ListenerClassPreset::EphemeralNodes, | ||
| }; | ||
| debug!( | ||
| preset = ?listener_class_preset, | ||
| kubernetes.environment = ?kubernetes_environment, | ||
| "Using ListenerClass preset" | ||
| ); | ||
| LISTENER_CLASS_PRESET | ||
| .set(listener_class_preset) | ||
| .expect("LISTENER_CLASS_PRESET should be unset"); | ||
| } | ||
| #[derive(Debug)] | ||
| enum KubernetesEnvironment { | ||
| Kind, | ||
| K3s, | ||
| Ionos, | ||
| Unknown, | ||
| } | ||
| /// Tries to guess what Kubernetes environment stackablectl is connecting to. | ||
| /// | ||
| /// Returns an error in case anything goes wrong. This could e.g. be the case in case no | ||
| /// Kubernetes context is configured, stackablectl is missing RBAC permission to retrieve nodes or | ||
| /// simply a network error. | ||
| #[instrument] | ||
| async fn guess_kubernetes_environment() -> Result<KubernetesEnvironment, snafu::Whatever> { | ||
| let client = Client::try_default() | ||
| .await | ||
| .whatever_context("failed to construct Kubernetes client")?; | ||
| let node_api: Api<Node> = Api::all(client); | ||
| let nodes = node_api | ||
| .list(&ListParams::default()) | ||
| .await | ||
| .whatever_context("failed to list Kubernetes nodes")?; | ||
| for node in nodes { | ||
| if let Some(spec) = node.spec { | ||
| if let Some(provider_id) = spec.provider_id { | ||
| if provider_id.starts_with("kind://") { | ||
| return Ok(KubernetesEnvironment::Kind); | ||
| } else if provider_id.starts_with("k3s://") { | ||
| return Ok(KubernetesEnvironment::K3s); | ||
| } else if provider_id.starts_with("ionos://") { | ||
| return Ok(KubernetesEnvironment::Ionos); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Ok(KubernetesEnvironment::Unknown) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,11 @@ | ||
| mod cluster; | ||
| mod file; | ||
| mod namespace; | ||
| mod operator_configs; | ||
| mod repo; | ||
| pub use cluster::*; | ||
| pub use file::*; | ||
| pub use namespace::*; | ||
| pub use operator_configs::*; | ||
| pub use repo::*; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| use clap::Args; | ||
| use stackable_cockpit::platform::operator::listener_operator::ListenerClassPreset; | ||
| #[derive(Debug, Args)] | ||
| #[command(next_help_heading = "Operator specific configurations")] | ||
| pub struct CommonOperatorConfigsArgs { | ||
| /// Choose the ListenerClass preset (`none`, `ephemeral-nodes` or `stable-nodes`). | ||
| /// | ||
| /// This maps to the listener-operator Helm Chart preset value, see | ||
| /// [the listener-operator documentation](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass/#presets) | ||
| /// for details. | ||
| #[arg(long, global = true)] | ||
| pub listener_class_preset: Option<ListenerClassPreset>, | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.