Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
- The `runAsUser` and `runAsGroup` fields will not be set anymore by the operator
- The defaults from the docker images itself will now apply, which will be different from 1000/0 going forward
- This is marked as breaking because tools and policies might exist, which require these fields to be set
- Changed listener class to be role-only ([#643]).

### Fixed

Expand All @@ -43,6 +44,7 @@
[#631]: https://github.com/stackabletech/superset-operator/pull/631
[#635]: https://github.com/stackabletech/superset-operator/pull/635
[#637]: https://github.com/stackabletech/superset-operator/pull/637
[#643]: https://github.com/stackabletech/superset-operator/pull/643

## [25.3.0] - 2025-03-21

Expand Down
13 changes: 5 additions & 8 deletions deploy/helm/superset-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,6 @@ spec:
description: Time period Pods have to gracefully shut down, e.g. `30m`, `1h` or `2d`. Consult the operator documentation for details.
nullable: true
type: string
listenerClass:
description: This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
nullable: true
type: string
logging:
default:
containers: {}
Expand Down Expand Up @@ -393,11 +389,16 @@ spec:
x-kubernetes-preserve-unknown-fields: true
roleConfig:
default:
listenerClass: cluster-internal
podDisruptionBudget:
enabled: true
maxUnavailable: null
description: This is a product-agnostic RoleConfig, which is sufficient for most of the products.
properties:
listenerClass:
default: cluster-internal
description: This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
type: string
podDisruptionBudget:
default:
enabled: true
Expand Down Expand Up @@ -466,10 +467,6 @@ spec:
description: Time period Pods have to gracefully shut down, e.g. `30m`, `1h` or `2d`. Consult the operator documentation for details.
nullable: true
type: string
listenerClass:
description: This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
nullable: true
type: string
logging:
default:
containers: {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ sleep 10

echo "Starting port-forwarding of port 8088"
# tag::port-forwarding[]
kubectl port-forward service/simple-superset-external 8088 > /dev/null 2>&1 &
kubectl port-forward service/simple-superset-node 8088 > /dev/null 2>&1 &
# end::port-forwarding[]
PORT_FORWARD_PID=$!
# shellcheck disable=2064 # we want the PID evaluated now, not at the time the trap is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ sleep 10

echo "Starting port-forwarding of port 8088"
# tag::port-forwarding[]
kubectl port-forward service/simple-superset-external 8088 > /dev/null 2>&1 &
kubectl port-forward service/simple-superset-node 8088 > /dev/null 2>&1 &
# end::port-forwarding[]
PORT_FORWARD_PID=$!
# shellcheck disable=2064 # we want the PID evaluated now, not at the time the trap is
Expand Down
3 changes: 2 additions & 1 deletion docs/modules/superset/examples/getting_started/superset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ spec:
productVersion: 4.1.2
clusterConfig:
credentialsSecret: simple-superset-credentials
listenerClass: external-unstable
nodes:
roleConfig:
listenerClass: external-unstable
roleGroups:
default:
config:
Expand Down
6 changes: 3 additions & 3 deletions docs/modules/superset/pages/usage-guide/listenerclass.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

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

[source,yaml]
----
spec:
nodes:
config:
roleConfig:
listenerClass: external-stable # <1>
----
<1> Specify one of `external-stable`, `external-unstable`, `cluster-internal` (the default setting is `cluster-internal`).
<1> Specify one of `external-stable`, `external-unstable`, `cluster-internal` at role-level (the default setting is `cluster-internal`).
3 changes: 2 additions & 1 deletion examples/superset-with-ldap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@ spec:
- authenticationClass: superset-with-ldap-server-veri-tls-ldap
userRegistrationRole: Admin
credentialsSecret: superset-with-ldap-server-veri-tls-credentials
listenerClass: external-unstable
nodes:
roleConfig:
listenerClass: external-unstable
roleGroups:
default:
replicas: 1
82 changes: 64 additions & 18 deletions rust/operator-binary/src/crd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ use stackable_operator::{
};
use strum::{Display, EnumIter, EnumString, IntoEnumIterator};

use crate::crd::v1alpha1::{SupersetConfigFragment, SupersetRoleConfig};

pub mod affinity;
pub mod authentication;
pub mod druidconnection;
Expand Down Expand Up @@ -139,7 +141,19 @@ pub mod versioned {

// no doc - docs in the struct.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub nodes: Option<Role<v1alpha1::SupersetConfigFragment>>,
pub nodes: Option<Role<v1alpha1::SupersetConfigFragment, SupersetRoleConfig>>,
}

// TODO: move generic version to op-rs?
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SupersetRoleConfig {
#[serde(flatten)]
pub common: GenericRoleConfig,

/// This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
#[serde(default = "default_listener_class")]
pub listener_class: String,
}

#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
Expand Down Expand Up @@ -223,10 +237,6 @@ pub mod versioned {
/// Time period Pods have to gracefully shut down, e.g. `30m`, `1h` or `2d`. Consult the operator documentation for details.
#[fragment_attrs(serde(default))]
pub graceful_shutdown_timeout: Option<Duration>,

/// This field controls which [ListenerClass](DOCS_BASE_URL_PLACEHOLDER/listener-operator/listenerclass.html) is used to expose the webserver.
#[serde(default)]
pub listener_class: String,
}

#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
Expand Down Expand Up @@ -292,6 +302,19 @@ pub mod versioned {
}
}

impl Default for v1alpha1::SupersetRoleConfig {
fn default() -> Self {
v1alpha1::SupersetRoleConfig {
listener_class: default_listener_class(),
common: Default::default(),
}
}
}

fn default_listener_class() -> String {
"cluster-internal".to_string()
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SupersetCredentials {
Expand Down Expand Up @@ -324,6 +347,18 @@ pub enum SupersetRole {
Node,
}

impl SupersetRole {
pub fn listener_class_name(&self, superset: &v1alpha1::SupersetCluster) -> Option<String> {
match self {
Self::Node => superset
.spec
.nodes
.to_owned()
.map(|node| node.role_config.listener_class),
}
}
}

/// A reference to a [`v1alpha1::SupersetCluster`]
#[derive(Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -416,7 +451,6 @@ impl v1alpha1::SupersetConfig {
graceful_shutdown_timeout: Some(DEFAULT_NODE_GRACEFUL_SHUTDOWN_TIMEOUT),
row_limit: None,
webserver_timeout: None,
listener_class: Some("cluster-internal".to_owned()),
}
}
}
Expand Down Expand Up @@ -482,14 +516,32 @@ impl HasStatusCondition for v1alpha1::SupersetCluster {
}

impl v1alpha1::SupersetCluster {
/// The name of the group-listener provided for a specific role-group.
/// The UI will use this group listener so that only one load balancer
/// is needed (per role group).
pub fn group_listener_name(&self, rolegroup: &RoleGroupRef<Self>) -> String {
rolegroup.object_name()
/// The name of the group-listener provided for a specific role.
/// Nodes will use this group listener so that only one load balancer
/// is needed for that role.
pub fn group_listener_name(&self, role: &SupersetRole) -> Option<String> {
match role {
SupersetRole::Node => Some(format!(
"{cluster_name}-{role}",
cluster_name = self.name_any()
)),
}
}

pub fn generic_role_config(&self, role: &SupersetRole) -> Option<GenericRoleConfig> {
self.get_role_config(role).map(|r| r.common.to_owned())
}

pub fn get_role_config(&self, role: &SupersetRole) -> Option<&SupersetRoleConfig> {
match role {
SupersetRole::Node => self.spec.nodes.as_ref().map(|c| &c.role_config),
}
}

pub fn get_role(&self, role: &SupersetRole) -> Option<&Role<v1alpha1::SupersetConfigFragment>> {
pub fn get_role(
&self,
role: &SupersetRole,
) -> Option<&Role<SupersetConfigFragment, SupersetRoleConfig>> {
match role {
SupersetRole::Node => self.spec.nodes.as_ref(),
}
Expand All @@ -507,12 +559,6 @@ impl v1alpha1::SupersetCluster {
}
}

pub fn role_config(&self, role: &SupersetRole) -> Option<&GenericRoleConfig> {
match role {
SupersetRole::Node => self.spec.nodes.as_ref().map(|n| &n.role_config),
}
}

pub fn get_opa_config(&self) -> Option<&v1alpha1::SupersetOpaRoleMappingConfig> {
self.spec
.cluster_config
Expand Down
Loading