Skip to content
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
the new labels ([#799]).
- Environment variable overrides (`envOverrides`) are now applied after all environment
variables set by the operator ([#799]).
- Make operations infallible where dependent on static inputs ([#803]).

### Fixed

Expand All @@ -41,6 +42,7 @@
[#795]: https://github.com/stackabletech/hbase-operator/pull/795
[#797]: https://github.com/stackabletech/hbase-operator/pull/797
[#799]: https://github.com/stackabletech/hbase-operator/pull/799
[#803]: https://github.com/stackabletech/hbase-operator/pull/803

## [26.7.0] - 2026-07-21

Expand Down
28 changes: 15 additions & 13 deletions rust/operator-binary/src/controller/build/kerberos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,18 @@ const PROTECTION_PRIVACY: &str = "privacy";

#[derive(Snafu, Debug)]
pub enum Error {
#[snafu(display("failed to build Kerberos secret volume"))]
BuildKerberosSecretVolume {
#[snafu(display("failed to build Kerberos secret volume source"))]
BuildKerberosSecretVolumeSource {
source: stackable_operator::builder::pod::volume::SecretOperatorVolumeSourceBuilderError,
},

#[snafu(display("failed to build TLS secret volume"))]
BuildTlsSecretVolume {
#[snafu(display("failed to build TLS secret volume source"))]
BuildTlsSecretVolumeSource {
source: stackable_operator::builder::pod::volume::SecretOperatorVolumeSourceBuilderError,
},

#[snafu(display("failed to add needed volume"))]
AddVolume { source: builder::pod::Error },

#[snafu(display("failed to add needed volumeMount"))]
AddVolumeMount {
source: builder::pod::container::Error,
},
}

/// The `hbase-site.xml` Kerberos properties for `cluster`, gated on Kerberos being enabled
Expand Down Expand Up @@ -229,6 +224,13 @@ pub fn kerberos_ssl_client_settings() -> BTreeMap<String, String> {
truststore_settings("client")
}

/// Adds the Kerberos keytab and TLS keystore volumes to the [`PodBuilder`] and their mounts to the
/// [`ContainerBuilder`], for whichever of the two secret classes are configured.
///
/// # Panics
///
/// Panics if the volume mounts cannot be added to the container builder. Only call this on a
/// container builder whose mount paths are still distinct from the ones added here.
pub fn add_kerberos_pod_config(
cluster: &ValidatedCluster,
metrics_service_name: &str,
Expand All @@ -247,15 +249,15 @@ pub fn add_kerberos_pod_config(
.with_kerberos_service_name(kerberos_service_name())
.with_kerberos_service_name("HTTP")
.build()
.context(BuildKerberosSecretVolumeSnafu)?;
.context(BuildKerberosSecretVolumeSourceSnafu)?;
pb.add_volume(
VolumeBuilder::new(&*KERBEROS_VOLUME_NAME)
.ephemeral(kerberos_secret_operator_volume)
.build(),
)
.context(AddVolumeSnafu)?;
cb.add_volume_mount(&*KERBEROS_VOLUME_NAME, STACKABLE_KERBEROS_DIR)
.context(AddVolumeMountSnafu)?;
.expect("The mount paths are statically defined and there should be no duplicates.");
}

if let Some(https_secret_class) = &cluster.cluster_config.https_secret_class {
Expand All @@ -277,13 +279,13 @@ pub fn add_kerberos_pod_config(
.with_tls_pkcs12_password(TLS_STORE_PASSWORD)
.with_auto_tls_cert_lifetime(requested_secret_lifetime)
.build()
.context(BuildTlsSecretVolumeSnafu)?,
.context(BuildTlsSecretVolumeSourceSnafu)?,
)
.build(),
)
.context(AddVolumeSnafu)?;
cb.add_volume_mount(&*TLS_STORE_VOLUME_NAME, TLS_STORE_DIR)
.context(AddVolumeMountSnafu)?;
.expect("The mount paths are statically defined and there should be no duplicates.");
}
Ok(())
}
Expand Down
21 changes: 14 additions & 7 deletions rust/operator-binary/src/controller/build/resource/listener.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
//! Build the listener `Volume`/`PersistentVolumeClaim` exposing a rolegroup.

use std::{str::FromStr, sync::LazyLock};
use std::str::FromStr;

use snafu::{ResultExt, Snafu};
use stackable_operator::{
builder::pod::volume::{
ListenerOperatorVolumeSourceBuilder, ListenerOperatorVolumeSourceBuilderError,
ListenerReference, VolumeBuilder,
},
constant,
k8s_openapi::api::core::v1::{PersistentVolumeClaim, Volume},
kvp::Labels,
v2::{
Expand All @@ -21,12 +22,7 @@ use stackable_operator::{

use crate::crd::{AnyServiceConfig, HbaseRole, LISTENER_VOLUME_NAME};

/// The rest servers' listener `PersistentVolumeClaim` reuses the listener volume name
/// ([`LISTENER_VOLUME_NAME`]); the claim and the volume must share a name.
static LISTENER_PVC_NAME: LazyLock<PersistentVolumeClaimName> = LazyLock::new(|| {
PersistentVolumeClaimName::from_str(LISTENER_VOLUME_NAME)
.expect("LISTENER_VOLUME_NAME is a valid PersistentVolumeClaim name")
});
constant!(LISTENER_PVC_NAME: PersistentVolumeClaimName = LISTENER_VOLUME_NAME);

#[derive(Snafu, Debug)]
pub enum Error {
Expand Down Expand Up @@ -89,3 +85,14 @@ pub fn build_listener_pvc(
)]),
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_constants() {
// Test that dereferencing the constants does not panic.
let _ = *LISTENER_PVC_NAME;
}
}
15 changes: 5 additions & 10 deletions rust/operator-binary/src/controller/build/resource/statefulset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,6 @@ pub enum Error {
#[snafu(display("failed to add needed volume"))]
AddVolume { source: builder::pod::Error },

#[snafu(display("failed to add needed volumeMount"))]
AddVolumeMount {
source: builder::pod::container::Error,
},

#[snafu(display("failed to build listener volume"))]
ListenerVolume { source: super::listener::Error },
}
Expand Down Expand Up @@ -192,15 +187,15 @@ pub fn build_rolegroup_statefulset(
}])
.add_env_vars(merged_env)
.add_volume_mount(&*HBASE_CONFIG_VOLUME_NAME, HBASE_CONFIG_TMP_DIR)
.context(AddVolumeMountSnafu)?
.expect("The mount paths are statically defined and there should be no duplicates.")
.add_volume_mount(&*HDFS_DISCOVERY_VOLUME_NAME, HDFS_DISCOVERY_TMP_DIR)
.context(AddVolumeMountSnafu)?
.expect("The mount paths are statically defined and there should be no duplicates.")
.add_volume_mount(&*LOG_CONFIG_VOLUME_NAME, HBASE_LOG_CONFIG_TMP_DIR)
.context(AddVolumeMountSnafu)?
.expect("The mount paths are statically defined and there should be no duplicates.")
.add_volume_mount(&*LOG_VOLUME_NAME, STACKABLE_LOG_DIR)
.context(AddVolumeMountSnafu)?
.expect("The mount paths are statically defined and there should be no duplicates.")
.add_volume_mount(LISTENER_VOLUME_NAME, LISTENER_VOLUME_DIR)
.context(AddVolumeMountSnafu)?
.expect("The mount paths are statically defined and there should be no duplicates.")
.add_container_ports(ports)
.resources(merged_config.resources().clone().into())
.startup_probe(startup_probe)
Expand Down
Loading