Skip to content
Merged
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
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