Skip to content

Commit c805f72

Browse files
authored
chore: Listener class at webserver role level only (#645)
* chore: Listener class as webserver role level only * review feedback * remove hard-coded role name * retain rolegroup as label on sts * fixed arguments for logging test
1 parent a93cdc1 commit c805f72

40 files changed

+172
-223
lines changed

CHANGELOG.md

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

3435
### Fixed
3536

@@ -48,6 +49,7 @@
4849
[#625]: https://github.com/stackabletech/airflow-operator/pull/625
4950
[#630]: https://github.com/stackabletech/airflow-operator/pull/630
5051
[#636]: https://github.com/stackabletech/airflow-operator/pull/636
52+
[#645]: https://github.com/stackabletech/airflow-operator/pull/645
5153

5254
## [25.3.0] - 2025-03-21
5355

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

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,10 +1332,6 @@ spec:
13321332
description: Time period Pods have to gracefully shut down, e.g. `30m`, `1h` or `2d`. Consult the operator documentation for details.
13331333
nullable: true
13341334
type: string
1335-
listenerClass:
1336-
description: This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
1337-
nullable: true
1338-
type: string
13391335
logging:
13401336
default:
13411337
containers: {}
@@ -1480,11 +1476,16 @@ spec:
14801476
x-kubernetes-preserve-unknown-fields: true
14811477
roleConfig:
14821478
default:
1479+
listenerClass: cluster-internal
14831480
podDisruptionBudget:
14841481
enabled: true
14851482
maxUnavailable: null
14861483
description: This is a product-agnostic RoleConfig, which is sufficient for most of the products.
14871484
properties:
1485+
listenerClass:
1486+
default: cluster-internal
1487+
description: This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
1488+
type: string
14881489
podDisruptionBudget:
14891490
default:
14901491
enabled: true
@@ -1553,10 +1554,6 @@ spec:
15531554
description: Time period Pods have to gracefully shut down, e.g. `30m`, `1h` or `2d`. Consult the operator documentation for details.
15541555
nullable: true
15551556
type: string
1556-
listenerClass:
1557-
description: This field controls which [ListenerClass](https://docs.stackable.tech/home/nightly/listener-operator/listenerclass.html) is used to expose the webserver.
1558-
nullable: true
1559-
type: string
15601557
logging:
15611558
default:
15621559
containers: {}

docs/modules/airflow/examples/example-airflow-dags-configmap.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ spec:
1919
mountPath: /dags/test_airflow_dag.py # <6>
2020
subPath: test_airflow_dag.py # <7>
2121
webservers:
22-
config:
22+
roleConfig:
2323
listenerClass: external-unstable
2424
roleGroups:
2525
default:

docs/modules/airflow/examples/example-airflow-incluster.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ spec:
1111
exposeConfig: false
1212
credentialsSecret: simple-airflow-credentials
1313
webservers:
14-
config:
14+
roleConfig:
1515
listenerClass: external-unstable
1616
roleGroups:
1717
default:

docs/modules/airflow/examples/example-airflow-kubernetes-executor-s3-logging.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ spec:
77
productVersion: 2.10.5
88
clusterConfig: {}
99
webservers:
10-
config:
10+
roleConfig:
1111
listenerClass: external-unstable
1212
envOverrides: &envOverrides
1313
AIRFLOW__LOGGING__REMOTE_LOGGING: "True"

docs/modules/airflow/examples/example-airflow-kubernetes-executor-s3-xcom.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ spec:
77
productVersion: 2.10.5
88
clusterConfig: {}
99
webservers:
10-
config:
10+
roleConfig:
1111
listenerClass: external-unstable
1212
envOverrides: &envOverrides
1313
AIRFLOW__CORE__XCOM_BACKEND: airflow.providers.common.io.xcom.backend.XComObjectStorageBackend

docs/modules/airflow/examples/getting_started/code/airflow.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ spec:
1111
exposeConfig: false
1212
credentialsSecret: simple-airflow-credentials
1313
webservers:
14-
config:
14+
roleConfig:
1515
listenerClass: external-unstable
1616
roleGroups:
1717
default:

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@
22
:description: Configure Airflow service exposure with ListenerClasses: cluster-internal, external-unstable, or external-stable.
33

44
The operator deploys a xref:listener-operator:listener.adoc[Listener] for the Webserver pod.
5-
The listener defaults to only being accessible from within the Kubernetes cluster, but this can be changed by setting `.spec.webservers.config.listenerClass`:
5+
The listener defaults to only being accessible from within the Kubernetes cluster, but this can be changed by setting `.spec.webservers.roleConfig.listenerClass`:
66

77
[source,yaml]
88
----
99
spec:
1010
webservers:
11-
config:
11+
roleConfig:
1212
listenerClass: external-unstable # <1>
13+
config:
14+
...
1315
schedulers:
1416
...
1517
celeryExecutors:
1618
...
1719
----
18-
<1> Specify a ListenerClass, such as `external-stable`, `external-unstable`, or `cluster-internal` (the default setting is `cluster-internal`).
20+
<1> Specify a ListenerClass, such as `external-stable`, `external-unstable`, or `cluster-internal` (the default setting is `cluster-internal`) at role-level.
1921
This can be set only for the webservers role.

examples/simple-airflow-cluster-dags-cmap.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ spec:
9696
mountPath: /dags/test_airflow_dag.py
9797
subPath: test_airflow_dag.py
9898
webservers:
99-
config:
99+
roleConfig:
100100
listenerClass: external-unstable
101101
roleGroups:
102102
default:

examples/simple-airflow-cluster-ldap-insecure-tls.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ spec:
157157
- authenticationClass: airflow-with-ldap-insecure-tls-ldap
158158
userRegistrationRole: Admin
159159
webservers:
160-
config:
160+
roleConfig:
161161
listenerClass: external-unstable
162162
roleGroups:
163163
default:

examples/simple-airflow-cluster-ldap.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ spec:
155155
- authenticationClass: airflow-with-ldap-server-veri-tls-ldap
156156
userRegistrationRole: Admin
157157
webservers:
158-
config:
158+
roleConfig:
159159
listenerClass: external-unstable
160160
roleGroups:
161161
default:

examples/simple-airflow-cluster.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ spec:
2828
exposeConfig: false
2929
credentialsSecret: simple-airflow-credentials
3030
webservers:
31-
config:
31+
roleConfig:
3232
listenerClass: external-unstable
3333
roleGroups:
3434
default:

rust/operator-binary/src/airflow_controller.rs

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use stackable_operator::{
5353
core::{DeserializeGuard, error_boundary},
5454
runtime::{controller::Action, reflector::ObjectRef},
5555
},
56-
kvp::{Annotation, Label, LabelError, Labels},
56+
kvp::{Annotation, Label, LabelError, Labels, ObjectLabels},
5757
logging::controller::ReconcilerError,
5858
product_config_utils::{
5959
CONFIG_OVERRIDE_FILE_FOOTER_KEY, CONFIG_OVERRIDE_FILE_HEADER_KEY, env_vars_from,
@@ -512,26 +512,6 @@ pub async fn reconcile_airflow(
512512
&git_sync_resources,
513513
)?;
514514

515-
if let Some(listener_class) =
516-
airflow.merged_listener_class(&airflow_role, &rolegroup.role_group)
517-
{
518-
if let Some(listener_group_name) =
519-
airflow.group_listener_name(&airflow_role, &rolegroup)
520-
{
521-
let rg_group_listener = build_group_listener(
522-
airflow,
523-
&resolved_product_image,
524-
&rolegroup,
525-
listener_class.to_string(),
526-
listener_group_name,
527-
)?;
528-
cluster_resources
529-
.add(client, rg_group_listener)
530-
.await
531-
.context(ApplyGroupListenerSnafu)?;
532-
}
533-
}
534-
535515
ss_cond_builder.add(
536516
cluster_resources
537517
.add(client, rg_statefulset)
@@ -568,6 +548,27 @@ pub async fn reconcile_airflow(
568548
.await
569549
.context(FailedToCreatePdbSnafu)?;
570550
}
551+
552+
if let Some(listener_class) = airflow_role.listener_class_name(airflow) {
553+
if let Some(listener_group_name) = airflow.group_listener_name(&airflow_role) {
554+
let rg_group_listener = build_group_listener(
555+
airflow,
556+
build_recommended_labels(
557+
airflow,
558+
AIRFLOW_CONTROLLER_NAME,
559+
&resolved_product_image.app_version_label,
560+
role_name,
561+
"none",
562+
),
563+
listener_class.to_string(),
564+
listener_group_name,
565+
)?;
566+
cluster_resources
567+
.add(client, rg_group_listener)
568+
.await
569+
.context(ApplyGroupListenerSnafu)?;
570+
}
571+
}
571572
}
572573

573574
cluster_resources
@@ -840,8 +841,7 @@ fn build_rolegroup_metadata(
840841

841842
pub fn build_group_listener(
842843
airflow: &v1alpha1::AirflowCluster,
843-
resolved_product_image: &ResolvedProductImage,
844-
rolegroup: &RoleGroupRef<v1alpha1::AirflowCluster>,
844+
object_labels: ObjectLabels<v1alpha1::AirflowCluster>,
845845
listener_class: String,
846846
listener_group_name: String,
847847
) -> Result<listener::v1alpha1::Listener> {
@@ -851,13 +851,7 @@ pub fn build_group_listener(
851851
.name(listener_group_name)
852852
.ownerreference_from_resource(airflow, None, Some(true))
853853
.context(ObjectMissingMetadataForOwnerRefSnafu)?
854-
.with_recommended_labels(build_recommended_labels(
855-
airflow,
856-
AIRFLOW_CONTROLLER_NAME,
857-
&resolved_product_image.app_version_label,
858-
&rolegroup.role,
859-
&rolegroup.role_group,
860-
))
854+
.with_recommended_labels(object_labels)
861855
.context(ObjectMetaSnafu)?
862856
.build(),
863857
spec: listener::v1alpha1::ListenerSpec {
@@ -1019,7 +1013,7 @@ fn build_server_rolegroup_statefulset(
10191013

10201014
let mut pvcs: Option<Vec<PersistentVolumeClaim>> = None;
10211015

1022-
if let Some(listener_group_name) = airflow.group_listener_name(airflow_role, rolegroup_ref) {
1016+
if let Some(listener_group_name) = airflow.group_listener_name(airflow_role) {
10231017
// Listener endpoints for the Webserver role will use persistent volumes
10241018
// so that load balancers can hard-code the target addresses. This will
10251019
// be the case even when no class is set (and the value defaults to

0 commit comments

Comments
 (0)