Skip to content

Commit c8d527e

Browse files
authored
chore: Listener class at node role level only (#643)
* chore: Listener class at webserver role level only * changelog * add version, extend assert * remove unused error
1 parent b84d165 commit c8d527e

File tree

20 files changed

+154
-129
lines changed

20 files changed

+154
-129
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
- The `runAsUser` and `runAsGroup` fields will not be set anymore by the operator
2828
- The defaults from the docker images itself will now apply, which will be different from 1000/0 going forward
2929
- This is marked as breaking because tools and policies might exist, which require these fields to be set
30+
- Changed listener class to be role-only ([#643]).
3031

3132
### Fixed
3233

@@ -43,6 +44,7 @@
4344
[#631]: https://github.com/stackabletech/superset-operator/pull/631
4445
[#635]: https://github.com/stackabletech/superset-operator/pull/635
4546
[#637]: https://github.com/stackabletech/superset-operator/pull/637
47+
[#643]: https://github.com/stackabletech/superset-operator/pull/643
4648

4749
## [25.3.0] - 2025-03-21
4850

deploy/helm/superset-operator/crds/crds.yaml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,6 @@ spec:
234234
description: Time period Pods have to gracefully shut down, e.g. `30m`, `1h` or `2d`. Consult the operator documentation for details.
235235
nullable: true
236236
type: string
237-
listenerClass:
238-
description: This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
239-
nullable: true
240-
type: string
241237
logging:
242238
default:
243239
containers: {}
@@ -393,11 +389,16 @@ spec:
393389
x-kubernetes-preserve-unknown-fields: true
394390
roleConfig:
395391
default:
392+
listenerClass: cluster-internal
396393
podDisruptionBudget:
397394
enabled: true
398395
maxUnavailable: null
399396
description: This is a product-agnostic RoleConfig, which is sufficient for most of the products.
400397
properties:
398+
listenerClass:
399+
default: cluster-internal
400+
description: This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
401+
type: string
401402
podDisruptionBudget:
402403
default:
403404
enabled: true
@@ -466,10 +467,6 @@ spec:
466467
description: Time period Pods have to gracefully shut down, e.g. `30m`, `1h` or `2d`. Consult the operator documentation for details.
467468
nullable: true
468469
type: string
469-
listenerClass:
470-
description: This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
471-
nullable: true
472-
type: string
473470
logging:
474471
default:
475472
containers: {}

docs/modules/superset/examples/getting_started/getting_started.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ sleep 10
9090

9191
echo "Starting port-forwarding of port 8088"
9292
# tag::port-forwarding[]
93-
kubectl port-forward service/simple-superset-external 8088 > /dev/null 2>&1 &
93+
kubectl port-forward service/simple-superset-node 8088 > /dev/null 2>&1 &
9494
# end::port-forwarding[]
9595
PORT_FORWARD_PID=$!
9696
# shellcheck disable=2064 # we want the PID evaluated now, not at the time the trap is

docs/modules/superset/examples/getting_started/getting_started.sh.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ sleep 10
9090

9191
echo "Starting port-forwarding of port 8088"
9292
# tag::port-forwarding[]
93-
kubectl port-forward service/simple-superset-external 8088 > /dev/null 2>&1 &
93+
kubectl port-forward service/simple-superset-node 8088 > /dev/null 2>&1 &
9494
# end::port-forwarding[]
9595
PORT_FORWARD_PID=$!
9696
# shellcheck disable=2064 # we want the PID evaluated now, not at the time the trap is

docs/modules/superset/examples/getting_started/superset.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ spec:
88
productVersion: 4.1.2
99
clusterConfig:
1010
credentialsSecret: simple-superset-credentials
11-
listenerClass: external-unstable
1211
nodes:
12+
roleConfig:
13+
listenerClass: external-unstable
1314
roleGroups:
1415
default:
1516
config:

docs/modules/superset/pages/usage-guide/listenerclass.adoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33

44
Apache Superset offers a web UI and an API.
55
The operator deploys a xref:listener-operator:listener.adoc[Listener] for the Nodes pod.
6-
The listener defaults to only being accessible from within the Kubernetes cluster, but this can be changed by setting `.spec.nodes.config.listenerClass`:
6+
The listener defaults to only being accessible from within the Kubernetes cluster, but this can be changed by setting `.spec.nodes.roleConfig.listenerClass`:
77

88
[source,yaml]
99
----
1010
spec:
1111
nodes:
12-
config:
12+
roleConfig:
1313
listenerClass: external-stable # <1>
1414
----
15-
<1> Specify one of `external-stable`, `external-unstable`, `cluster-internal` (the default setting is `cluster-internal`).
15+
<1> Specify one of `external-stable`, `external-unstable`, `cluster-internal` at role-level (the default setting is `cluster-internal`).

examples/superset-with-ldap.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,9 @@ spec:
155155
- authenticationClass: superset-with-ldap-server-veri-tls-ldap
156156
userRegistrationRole: Admin
157157
credentialsSecret: superset-with-ldap-server-veri-tls-credentials
158-
listenerClass: external-unstable
159158
nodes:
159+
roleConfig:
160+
listenerClass: external-unstable
160161
roleGroups:
161162
default:
162163
replicas: 1

rust/operator-binary/src/crd/mod.rs

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ use stackable_operator::{
3232
};
3333
use strum::{Display, EnumIter, EnumString, IntoEnumIterator};
3434

35+
use crate::crd::v1alpha1::{SupersetConfigFragment, SupersetRoleConfig};
36+
3537
pub mod affinity;
3638
pub mod authentication;
3739
pub mod druidconnection;
@@ -139,7 +141,19 @@ pub mod versioned {
139141

140142
// no doc - docs in the struct.
141143
#[serde(default, skip_serializing_if = "Option::is_none")]
142-
pub nodes: Option<Role<v1alpha1::SupersetConfigFragment>>,
144+
pub nodes: Option<Role<v1alpha1::SupersetConfigFragment, SupersetRoleConfig>>,
145+
}
146+
147+
// TODO: move generic version to op-rs?
148+
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
149+
#[serde(rename_all = "camelCase")]
150+
pub struct SupersetRoleConfig {
151+
#[serde(flatten)]
152+
pub common: GenericRoleConfig,
153+
154+
/// This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
155+
#[serde(default = "default_listener_class")]
156+
pub listener_class: String,
143157
}
144158

145159
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
@@ -223,10 +237,6 @@ pub mod versioned {
223237
/// Time period Pods have to gracefully shut down, e.g. `30m`, `1h` or `2d`. Consult the operator documentation for details.
224238
#[fragment_attrs(serde(default))]
225239
pub graceful_shutdown_timeout: Option<Duration>,
226-
227-
/// This field controls which [ListenerClass](DOCS_BASE_URL_PLACEHOLDER/listener-operator/listenerclass.html) is used to expose the webserver.
228-
#[serde(default)]
229-
pub listener_class: String,
230240
}
231241

232242
#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
@@ -292,6 +302,19 @@ pub mod versioned {
292302
}
293303
}
294304

305+
impl Default for v1alpha1::SupersetRoleConfig {
306+
fn default() -> Self {
307+
v1alpha1::SupersetRoleConfig {
308+
listener_class: default_listener_class(),
309+
common: Default::default(),
310+
}
311+
}
312+
}
313+
314+
fn default_listener_class() -> String {
315+
"cluster-internal".to_string()
316+
}
317+
295318
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
296319
#[serde(rename_all = "camelCase")]
297320
pub struct SupersetCredentials {
@@ -324,6 +347,18 @@ pub enum SupersetRole {
324347
Node,
325348
}
326349

350+
impl SupersetRole {
351+
pub fn listener_class_name(&self, superset: &v1alpha1::SupersetCluster) -> Option<String> {
352+
match self {
353+
Self::Node => superset
354+
.spec
355+
.nodes
356+
.to_owned()
357+
.map(|node| node.role_config.listener_class),
358+
}
359+
}
360+
}
361+
327362
/// A reference to a [`v1alpha1::SupersetCluster`]
328363
#[derive(Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
329364
#[serde(rename_all = "camelCase")]
@@ -416,7 +451,6 @@ impl v1alpha1::SupersetConfig {
416451
graceful_shutdown_timeout: Some(DEFAULT_NODE_GRACEFUL_SHUTDOWN_TIMEOUT),
417452
row_limit: None,
418453
webserver_timeout: None,
419-
listener_class: Some("cluster-internal".to_owned()),
420454
}
421455
}
422456
}
@@ -482,14 +516,32 @@ impl HasStatusCondition for v1alpha1::SupersetCluster {
482516
}
483517

484518
impl v1alpha1::SupersetCluster {
485-
/// The name of the group-listener provided for a specific role-group.
486-
/// The UI will use this group listener so that only one load balancer
487-
/// is needed (per role group).
488-
pub fn group_listener_name(&self, rolegroup: &RoleGroupRef<Self>) -> String {
489-
rolegroup.object_name()
519+
/// The name of the group-listener provided for a specific role.
520+
/// Nodes will use this group listener so that only one load balancer
521+
/// is needed for that role.
522+
pub fn group_listener_name(&self, role: &SupersetRole) -> Option<String> {
523+
match role {
524+
SupersetRole::Node => Some(format!(
525+
"{cluster_name}-{role}",
526+
cluster_name = self.name_any()
527+
)),
528+
}
529+
}
530+
531+
pub fn generic_role_config(&self, role: &SupersetRole) -> Option<GenericRoleConfig> {
532+
self.get_role_config(role).map(|r| r.common.to_owned())
533+
}
534+
535+
pub fn get_role_config(&self, role: &SupersetRole) -> Option<&SupersetRoleConfig> {
536+
match role {
537+
SupersetRole::Node => self.spec.nodes.as_ref().map(|c| &c.role_config),
538+
}
490539
}
491540

492-
pub fn get_role(&self, role: &SupersetRole) -> Option<&Role<v1alpha1::SupersetConfigFragment>> {
541+
pub fn get_role(
542+
&self,
543+
role: &SupersetRole,
544+
) -> Option<&Role<SupersetConfigFragment, SupersetRoleConfig>> {
493545
match role {
494546
SupersetRole::Node => self.spec.nodes.as_ref(),
495547
}
@@ -507,12 +559,6 @@ impl v1alpha1::SupersetCluster {
507559
}
508560
}
509561

510-
pub fn role_config(&self, role: &SupersetRole) -> Option<&GenericRoleConfig> {
511-
match role {
512-
SupersetRole::Node => self.spec.nodes.as_ref().map(|n| &n.role_config),
513-
}
514-
}
515-
516562
pub fn get_opa_config(&self) -> Option<&v1alpha1::SupersetOpaRoleMappingConfig> {
517563
self.spec
518564
.cluster_config

0 commit comments

Comments
 (0)