diff --git a/crates/stackable-operator/CHANGELOG.md b/crates/stackable-operator/CHANGELOG.md index 89026426..ab5f0db3 100644 --- a/crates/stackable-operator/CHANGELOG.md +++ b/crates/stackable-operator/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- Add new `PreferredAddressType::HostnameConservative` ([#903]). + +### Changed + +- BREAKING: Split `ListenerClass.spec.preferred_address_type` into a new `PreferredAddressType` type. Use `resolve_preferred_address_type()` to access the `AddressType` as before. ([#903]) + +[#903]: https://github.com/stackabletech/operator-rs/pull/903 + ## [0.80.0] - 2024-10-23 ### Changed diff --git a/crates/stackable-operator/src/commons/listener.rs b/crates/stackable-operator/src/commons/listener.rs index d7e590f3..abcda429 100644 --- a/crates/stackable-operator/src/commons/listener.rs +++ b/crates/stackable-operator/src/commons/listener.rs @@ -65,11 +65,13 @@ pub struct ListenerClassSpec { pub service_external_traffic_policy: KubernetesTrafficPolicy, /// Whether addresses should prefer using the IP address (`IP`) or the hostname (`Hostname`). + /// Can also be set to `HostnameConservative`, which will use `IP` for `NodePort` service types, but `Hostname` for everything else. /// /// The other type will be used if the preferred type is not available. - /// By default `Hostname` is used. + /// + /// Defaults to `HostnameConservative`. #[serde(default = "ListenerClassSpec::default_preferred_address_type")] - pub preferred_address_type: AddressType, + pub preferred_address_type: PreferredAddressType, } impl ListenerClassSpec { @@ -77,8 +79,13 @@ impl ListenerClassSpec { KubernetesTrafficPolicy::Local } - const fn default_preferred_address_type() -> AddressType { - AddressType::Hostname + const fn default_preferred_address_type() -> PreferredAddressType { + PreferredAddressType::HostnameConservative + } + + /// Resolves [`Self::preferred_address_type`]'s "smart" modes depending on the rest of `self`. + pub fn resolve_preferred_address_type(&self) -> AddressType { + self.preferred_address_type.resolve(self) } } @@ -197,14 +204,47 @@ pub struct ListenerIngress { pub ports: BTreeMap, } +/// The type of a given address. #[derive(Serialize, Deserialize, Clone, Copy, Debug, JsonSchema, PartialEq, Eq)] #[serde(rename_all = "PascalCase")] pub enum AddressType { + /// A resolvable DNS hostname. Hostname, + + /// A resolved IP address. #[serde(rename = "IP")] Ip, } +/// A mode for deciding the preferred [`AddressType`]. +/// +/// These can vary depending on the rest of the [`ListenerClass`]. +#[derive(Serialize, Deserialize, Clone, Copy, Debug, JsonSchema, PartialEq, Eq)] +pub enum PreferredAddressType { + /// Like [`AddressType::Hostname`], but prefers [`AddressType::Ip`] for [`ServiceType::NodePort`], since their hostnames are less likely to be resolvable. + HostnameConservative, + + // Like the respective variants of AddressType. Ideally we would refer to them instead of copy/pasting, but that breaks due to upstream issues: + // - https://github.com/GREsau/schemars/issues/222 + // - https://github.com/kube-rs/kube/issues/1622 + Hostname, + #[serde(rename = "IP")] + Ip, +} + +impl PreferredAddressType { + pub fn resolve(self, listener_class: &ListenerClassSpec) -> AddressType { + match self { + PreferredAddressType::HostnameConservative => match listener_class.service_type { + ServiceType::NodePort => AddressType::Ip, + _ => AddressType::Hostname, + }, + PreferredAddressType::Hostname => AddressType::Hostname, + PreferredAddressType::Ip => AddressType::Ip, + } + } +} + /// Informs users about Listeners that are bound by a given Pod. /// /// This is not expected to be created or modified by users. It will be created by