Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions crates/stackable-operator/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Added

- BREAKING: Add the `OpenShiftRoute` Listener service type, configured by `ListenerClass.spec.openshiftRoute`.
Exhaustive matches on `ServiceType` must handle the new variant.

## [0.119.0] - 2026-09-23

### Removed
Expand Down
23 changes: 23 additions & 0 deletions crates/stackable-operator/crds/ListenerClass.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ spec:
Ignored unless serviceType is LoadBalancer.
nullable: true
type: string
openshiftRoute:
description: |-
Configures the OpenShift Route when `serviceType` is `OpenShiftRoute`.

Ignored for other service types.
nullable: true
properties:
port:
description: |-
Name of the Listener port to expose.

A Route can only expose a single port. May be omitted if the Listener only has one port.
nullable: true
type: string
tls:
default: Passthrough
description: How the Route handles TLS. Defaults to `Passthrough`.
enum:
- Passthrough
- None
type: string
type: object
pinnedNodePorts:
default: false
description: |-
Expand Down Expand Up @@ -106,6 +128,7 @@ spec:
- NodePort
- LoadBalancer
- ClusterIP
- OpenShiftRoute
type: string
required:
- serviceType
Expand Down
39 changes: 39 additions & 0 deletions crates/stackable-operator/src/crd/listener/class/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ pub mod versioned {
pub struct ListenerClassSpec {
pub service_type: core_v1alpha1::ServiceType,

/// Configures the OpenShift Route when `serviceType` is `OpenShiftRoute`.
///
/// Ignored for other service types.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub openshift_route: Option<OpenShiftRouteConfig>,

/// Configures whether a LoadBalancer service should also allocate node ports (like NodePort).
///
/// Ignored unless serviceType is LoadBalancer.
Expand Down Expand Up @@ -121,6 +127,32 @@ pub mod versioned {
#[schemars(schema_with = "raw_object_schema")]
pub service_overrides: Service,
}

/// Configures how a Listener is exposed through an OpenShift Route.
#[derive(Clone, Debug, Default, Deserialize, JsonSchema, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OpenShiftRouteConfig {
/// Name of the Listener port to expose.
///
/// A Route can only expose a single port. May be omitted if the Listener only has one port.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub port: Option<String>,

/// How the Route handles TLS. Defaults to `Passthrough`.
#[serde(default)]
pub tls: OpenShiftRouteTls,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, JsonSchema, PartialEq, Eq, Serialize)]
pub enum OpenShiftRouteTls {
/// Forward TLS traffic to the application, which must terminate TLS itself.
/// Exposed on port 443.
#[default]
Passthrough,

/// Forward plain HTTP traffic. Exposed on port 80.
None,
}
}

#[cfg(test)]
Expand All @@ -130,6 +162,13 @@ impl stackable_versioned::test_utils::RoundtripTestData for v1alpha1::ListenerCl
- serviceType: ClusterIP
- serviceType: NodePort
- serviceType: LoadBalancer
- serviceType: OpenShiftRoute
- serviceType: OpenShiftRoute
openshiftRoute:
port: https
- serviceType: OpenShiftRoute
openshiftRoute:
tls: None
- serviceType: ClusterIP
loadBalancerAllocateNodePorts: false
loadBalancerClass: foo
Expand Down
5 changes: 5 additions & 0 deletions crates/stackable-operator/src/crd/listener/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ pub mod versioned {
/// Assigns an IP address from a pool of IP addresses that your cluster has reserved for
/// that purpose.
ClusterIP,

/// Expose a single port through an OpenShift Route, using a hostname assigned by OpenShift.
///
/// Only available on OpenShift. Configured by `ListenerClass.spec.openshiftRoute`.
OpenShiftRoute,
}

/// Service Internal Traffic Policy enables internal traffic restrictions to only route internal
Expand Down
Loading