This is an automated email from the ASF dual-hosted git repository.

Miretpl pushed a commit to branch chart/v1-2x-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/chart/v1-2x-test by this push:
     new 6061eb0ca8c [chart/v1-2x-test] Add Flower HTTPRoute support to Helm 
chart (#69945) (#70263)
6061eb0ca8c is described below

commit 6061eb0ca8c44faa4af875d4679b9ccdc79417c3
Author: Aaron Chen <[email protected]>
AuthorDate: Fri Jul 24 05:31:49 2026 +0800

    [chart/v1-2x-test] Add Flower HTTPRoute support to Helm chart (#69945) 
(#70263)
    
    * Add Flower HTTPRoute support to Helm chart
    
    * Update chart/tests/helm_tests/other/test_httproute_flower.py
    
    
    
    * Clarify Flower HTTPRoute configuration guidance
    
    * Update chart/docs/production-guide.rst
    
    
    
    * Simplify HTTPRoute configuration guidance
    
    ---------
    (cherry picked from commit 02a956f5cf9467b89a37dbbff9b434d7849a0be7)
    
    Co-authored-by: Przemysław Mirowski 
<[email protected]>
---
 chart/docs/production-guide.rst                    |  37 +-
 chart/templates/flower/flower-httproute.yaml       |  70 ++++
 chart/templates/flower/flower-ingress.yaml         |   3 +
 chart/values.schema.json                           |  96 +++++
 chart/values.yaml                                  |  52 ++-
 .../airflow_aux/test_basic_helm_chart.py           |  58 ++-
 .../helm_tests/other/test_httproute_flower.py      | 424 +++++++++++++++++++++
 7 files changed, 720 insertions(+), 20 deletions(-)

diff --git a/chart/docs/production-guide.rst b/chart/docs/production-guide.rst
index 2c5994bc22d..8c03421aae5 100644
--- a/chart/docs/production-guide.rst
+++ b/chart/docs/production-guide.rst
@@ -398,14 +398,16 @@ For more information on ``Ingress``, see the
 Gateway API (HTTPRoute)
 ^^^^^^^^^^^^^^^^^^^^^^^
 
-As an alternative to ``Ingress``, the chart can create a
-`Kubernetes Gateway API <https://gateway-api.sigs.k8s.io/>`_ ``HTTPRoute`` for 
the API server.
+As an alternative to ``Ingress``, the chart can create
+`Kubernetes Gateway API <https://gateway-api.sigs.k8s.io/>`_ ``HTTPRoute`` 
resources for the API server and Flower.
 This requires the Gateway API CRDs to be installed in the cluster and a 
``Gateway`` to already exist —
-the chart only creates the ``HTTPRoute`` and attaches it to the Gateway via 
``parentRefs``.
+the chart only creates the ``HTTPRoute`` resources and attaches them to the 
Gateway via ``parentRefs``.
 
 .. code-block:: yaml
    :caption: values.yaml
 
+   executor: CeleryExecutor
+
    apiServer:
      httpRoute:
        enabled: true
@@ -416,16 +418,31 @@ the chart only creates the ``HTTPRoute`` and attaches it 
to the Gateway via ``pa
        hostnames:
          - airflow.example.com
 
-For fine-grained routing, supply ``apiServer.httpRoute.rules`` directly — the 
entry mirrors the
-upstream ``HTTPRouteRule`` schema and overrides the default rule generated 
from ``path`` + ``pathType``.
+   flower:
+     enabled: true
+     httpRoute:
+       enabled: true
+       parentRefs:
+         - name: main-gateway
+           namespace: gateway-system
+           sectionName: https
+       hostnames:
+         - flower.example.com
+
+Flower HTTPRoute resources are only created when Flower itself is created, so 
``flower.enabled`` must be
+``true`` and the executor must include ``CeleryExecutor`` or 
``CeleryKubernetesExecutor``.
+
+For fine-grained routing, supply ``apiServer.httpRoute.rules`` or 
``flower.httpRoute.rules`` directly —
+the entry mirrors the upstream ``HTTPRouteRule`` schema and overrides the 
default rule generated from
+the corresponding ``apiServer.httpRoute.path`` and 
``apiServer.httpRoute.pathType``, or
+``flower.httpRoute.path`` and ``flower.httpRoute.pathType`` values.
 
 .. note::
 
-   ``HTTPRoute`` is an alternative to the API server ``Ingress``, so enable 
only one of
-   ``ingress.apiServer`` or ``apiServer.httpRoute`` — enabling both at the 
same time fails template
-   rendering. When ``apiServer.httpRoute.enabled`` is ``true``, the chart also 
verifies (via Helm
-   ``Capabilities``) that the Gateway API CRDs are installed and fails with a 
clear message if they
-   are not.
+   ``HTTPRoute`` is an alternative to ``Ingress`` for the same component, so 
enable only one routing
+   mechanism for each component. Enabling both for the same component fails 
template rendering.
+   When an ``HTTPRoute`` is enabled, the chart also verifies (via Helm 
``Capabilities``) that the Gateway
+   API CRDs are installed and fails with a clear message if they are not.
 
 LoadBalancer Service
 ^^^^^^^^^^^^^^^^^^^^
diff --git a/chart/templates/flower/flower-httproute.yaml 
b/chart/templates/flower/flower-httproute.yaml
new file mode 100644
index 00000000000..2b0807b7ddb
--- /dev/null
+++ b/chart/templates/flower/flower-httproute.yaml
@@ -0,0 +1,70 @@
+{{/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/}}
+
+###########################
+## Airflow Flower HTTPRoute
+###########################
+{{- if and .Values.flower.enabled .Values.flower.httpRoute.enabled (or 
(contains "CeleryExecutor" .Values.executor) (contains 
"CeleryKubernetesExecutor" .Values.executor)) }}
+{{- if or .Values.ingress.flower.enabled .Values.ingress.enabled }}
+{{- fail "`flower.httpRoute.enabled` and 
`ingress.flower.enabled`/`ingress.enabled` are both enabled. HTTPRoute (Gateway 
API) is an alternative to the Flower Ingress; enable only one of them." }}
+{{- end }}
+{{- if not (.Capabilities.APIVersions.Has "gateway.networking.k8s.io/v1") }}
+{{- fail "`flower.httpRoute.enabled` is `true` but the Gateway API HTTPRoute 
CRD (`gateway.networking.k8s.io/v1`) is not installed in the cluster. Install 
the Gateway API CRDs 
(https://gateway-api.sigs.k8s.io/guides/#installing-gateway-api) before 
enabling `flower.httpRoute`." }}
+{{- end }}
+{{- if not .Values.flower.httpRoute.parentRefs }}
+{{- fail "`flower.httpRoute.enabled` is `true` but 
`flower.httpRoute.parentRefs` is empty. An HTTPRoute must reference at least 
one parent Gateway; set `flower.httpRoute.parentRefs`." }}
+{{- end }}
+{{- $fullname := include "airflow.fullname" . }}
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: {{ $fullname }}-flower-httproute
+  labels:
+    tier: airflow
+    component: flower-httproute
+    release: {{ .Release.Name }}
+    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
+    heritage: {{ .Release.Service }}
+    {{- if or .Values.labels .Values.flower.labels 
.Values.flower.httpRoute.labels }}
+      {{- mustMerge .Values.flower.httpRoute.labels .Values.flower.labels 
.Values.labels | toYaml | nindent 4 }}
+    {{- end }}
+  {{- with .Values.flower.httpRoute.annotations }}
+  annotations: {{- toYaml . | nindent 4 }}
+  {{- end }}
+spec:
+  parentRefs: {{- toYaml .Values.flower.httpRoute.parentRefs | nindent 4 }}
+  {{- with .Values.flower.httpRoute.hostnames }}
+  hostnames:
+    {{- range . }}
+    - {{ tpl . $ | quote }}
+    {{- end }}
+  {{- end }}
+  rules:
+    {{- if .Values.flower.httpRoute.rules }}
+    {{- toYaml .Values.flower.httpRoute.rules | nindent 4 }}
+    {{- else }}
+    - matches:
+        - path:
+            type: {{ .Values.flower.httpRoute.pathType }}
+            value: {{ .Values.flower.httpRoute.path | quote }}
+      backendRefs:
+        - name: {{ $fullname }}-flower
+          port: {{ .Values.ports.flowerUI }}
+    {{- end }}
+{{- end }}
diff --git a/chart/templates/flower/flower-ingress.yaml 
b/chart/templates/flower/flower-ingress.yaml
index 11ba85a0939..1a04d358f45 100644
--- a/chart/templates/flower/flower-ingress.yaml
+++ b/chart/templates/flower/flower-ingress.yaml
@@ -22,6 +22,9 @@
 #################################
 {{- if .Values.flower.enabled }}
 {{- if and (or .Values.ingress.flower.enabled .Values.ingress.enabled) (or 
(contains "CeleryExecutor" .Values.executor) (contains 
"CeleryKubernetesExecutor" .Values.executor)) }}
+{{- if .Values.flower.httpRoute.enabled }}
+{{- fail "`ingress.flower.enabled`/`ingress.enabled` and 
`flower.httpRoute.enabled` are both enabled. The Flower Ingress is an 
alternative to HTTPRoute (Gateway API); enable only one of them." }}
+{{- end }}
 {{- $fullname := include "airflow.fullname" . }}
 apiVersion: networking.k8s.io/v1
 kind: Ingress
diff --git a/chart/values.schema.json b/chart/values.schema.json
index 7ed990770d1..e57cacdb7f0 100644
--- a/chart/values.schema.json
+++ b/chart/values.schema.json
@@ -8742,6 +8742,102 @@
                     "type": "boolean",
                     "default": false
                 },
+                "httpRoute": {
+                    "description": "Kubernetes Gateway API (HTTPRoute) 
configuration for Flower.",
+                    "type": "object",
+                    "additionalProperties": false,
+                    "properties": {
+                        "enabled": {
+                            "description": "Enable Flower HTTPRoute resource.",
+                            "type": "boolean",
+                            "default": false
+                        },
+                        "labels": {
+                            "description": "Extra labels for the Flower 
HTTPRoute.",
+                            "type": "object",
+                            "default": {},
+                            "additionalProperties": {
+                                "type": "string"
+                            }
+                        },
+                        "annotations": {
+                            "description": "Annotations for the Flower 
HTTPRoute.",
+                            "type": "object",
+                            "default": {},
+                            "additionalProperties": {
+                                "type": "string"
+                            }
+                        },
+                        "parentRefs": {
+                            "description": "List of parent Gateway references 
this HTTPRoute attaches to. Required when enabled.",
+                            "type": [
+                                "array",
+                                "null"
+                            ],
+                            "default": null,
+                            "minItems": 1,
+                            "items": {
+                                "type": "object",
+                                "properties": {
+                                    "name": {
+                                        "description": "Name of the referenced 
Gateway.",
+                                        "type": "string"
+                                    },
+                                    "namespace": {
+                                        "description": "Namespace of the 
referenced Gateway. Defaults to the local namespace.",
+                                        "type": "string"
+                                    },
+                                    "sectionName": {
+                                        "description": "Name of the Gateway 
listener section this route attaches to.",
+                                        "type": "string"
+                                    },
+                                    "port": {
+                                        "description": "Port of the Gateway 
listener this route attaches to.",
+                                        "type": "integer"
+                                    },
+                                    "kind": {
+                                        "description": "Kind of the referenced 
resource. Defaults to `Gateway`.",
+                                        "type": "string"
+                                    },
+                                    "group": {
+                                        "description": "API group of the 
referenced resource. Defaults to `gateway.networking.k8s.io`.",
+                                        "type": "string"
+                                    }
+                                },
+                                "required": [
+                                    "name"
+                                ]
+                            }
+                        },
+                        "hostnames": {
+                            "description": "Hostnames this HTTPRoute should 
match (templated). Empty matches all.",
+                            "type": "array",
+                            "default": [],
+                            "items": {
+                                "type": "string"
+                            }
+                        },
+                        "path": {
+                            "description": "Default routing rule path (used 
only when `flower.httpRoute.rules` is empty).",
+                            "type": "string",
+                            "default": "/"
+                        },
+                        "pathType": {
+                            "description": "The pathType for the default path: 
PathPrefix, Exact, or RegularExpression.",
+                            "type": "string",
+                            "default": "PathPrefix"
+                        },
+                        "rules": {
+                            "description": "Custom routing rules. When set, 
overrides the default rule generated from `path` + `pathType`. Each entry 
follows the upstream Gateway API `HTTPRouteRule` schema.",
+                            "type": "array",
+                            "default": [],
+                            "items": {
+                                "type": "object",
+                                "additionalProperties": {}
+                            }
+                        }
+                    }
+                },
                 "livenessProbe": {
                     "description": "Liveness probe configuration.",
                     "type": "object",
diff --git a/chart/values.yaml b/chart/values.yaml
index aef2a7f0256..b9d4b708510 100644
--- a/chart/values.yaml
+++ b/chart/values.yaml
@@ -244,7 +244,8 @@ ingress:
 
   # Configs for the Ingress of the flower Service
   flower:
-    # Enable web ingress resource
+    # Enable Flower ingress resource.
+    # Mutually exclusive with `flower.httpRoute.enabled` (Gateway API); enable 
only one of them.
     enabled: false
 
     # Annotations for the flower Ingress
@@ -2278,8 +2279,6 @@ apiServer:
   # Requires the Gateway API CRDs to be installed in the cluster
   # (https://gateway-api.sigs.k8s.io/guides/#installing-gateway-api).
   # The HTTPRoute references an externally managed Gateway via `parentRefs`.
-  # This is an alternative to the API server Ingress (`ingress.apiServer`);
-  # the two are mutually exclusive and enabling both will fail rendering.
   httpRoute:
     # Enable API Server HTTPRoute resource.
     # Mutually exclusive with `ingress.apiServer.enabled`; enable only one of 
them.
@@ -2292,8 +2291,6 @@ apiServer:
     annotations: {}
 
     # List of parent Gateway references this HTTPRoute attaches to. Required 
when enabled.
-    # Defaults to `~` (null) so the schema's `minItems: 1` fails fast on an 
explicitly
-    # empty list (`[]`); a still-null value while enabled is caught by the 
template guard.
     # See 
https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ParentReference
     parentRefs: ~
     # - name: my-gateway
@@ -3269,6 +3266,51 @@ flower:
   # If True, and using CeleryExecutor/CeleryKubernetesExecutor, will deploy 
flower app.
   enabled: false
 
+  # Kubernetes Gateway API (HTTPRoute) configuration for Flower.
+  # Requires the Gateway API CRDs to be installed in the cluster
+  # (https://gateway-api.sigs.k8s.io/guides/#installing-gateway-api).
+  # The HTTPRoute references an externally managed Gateway via `parentRefs`.
+  httpRoute:
+    # Enable Flower HTTPRoute resource.
+    # Mutually exclusive with `ingress.flower.enabled` and the legacy 
`ingress.enabled`;
+    # enable only one routing mechanism.
+    enabled: false
+
+    # Extra labels for the Flower HTTPRoute
+    labels: {}
+
+    # Annotations for the Flower HTTPRoute
+    annotations: {}
+
+    # List of parent Gateway references this HTTPRoute attaches to. Required 
when enabled.
+    # See 
https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.ParentReference
+    parentRefs: ~
+    # - name: my-gateway
+    #   namespace: gateway-system
+    #   sectionName: https
+
+    # Hostnames this HTTPRoute should match (templated). Empty matches all.
+    hostnames: []
+    # - "flower.example.com"
+
+    # Default routing rule path (used only when `flower.httpRoute.rules` is 
empty)
+    path: "/"
+
+    # The pathType for the default path. PathPrefix | Exact | RegularExpression
+    pathType: PathPrefix
+
+    # Custom routing rules. When set, overrides the default rule generated 
from `path` + `pathType`.
+    # Use this for non-standard Flower service port layouts.
+    # See 
https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteRule
+    rules: []
+    # - matches:
+    #     - path:
+    #         type: PathPrefix
+    #         value: /
+    #   backendRefs:
+    #     - name: my-flower-service
+    #       port: 5555
+
   livenessProbe:
     initialDelaySeconds: 10
     timeoutSeconds: 5
diff --git a/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py 
b/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py
index bf10319c209..22120bc2805 100644
--- a/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py
+++ b/helm-tests/tests/helm_tests/airflow_aux/test_basic_helm_chart.py
@@ -371,7 +371,50 @@ class TestBaseChartTest:
             ["default", "CeleryExecutor,KubernetesExecutor"],
         ],
     )
-    def test_labels_are_valid(self, airflow_version, executor):
+    @pytest.mark.parametrize(
+        ("flower_routing_values", "flower_routing_resource", "api_versions"),
+        [
+            pytest.param(
+                {
+                    "ingress": {
+                        "enabled": True,
+                        "flower": {"enabled": True},
+                        "apiServer": {"enabled": True},
+                    },
+                    "flower": {"enabled": True},
+                },
+                ("flower-ingress", "Ingress", "flower-ingress"),
+                [],
+                id="flower-ingress",
+            ),
+            pytest.param(
+                {
+                    "ingress": {
+                        "web": {"enabled": True},
+                        "apiServer": {"enabled": True},
+                    },
+                    "flower": {
+                        "enabled": True,
+                        "httpRoute": {
+                            "enabled": True,
+                            "parentRefs": [{"name": "main-gateway"}],
+                        },
+                    },
+                },
+                ("flower-httproute", "HTTPRoute", "flower-httproute"),
+                ["gateway.networking.k8s.io/v1"],
+                id="flower-httproute",
+            ),
+        ],
+    )
+    def test_labels_are_valid(
+        self,
+        airflow_version,
+        executor,
+        flower_routing_values,
+        flower_routing_resource,
+        api_versions,
+    ):
         """Test labels are correctly applied on all objects created by this 
chart."""
         release_name = "test-basic"
 
@@ -391,11 +434,9 @@ class TestBaseChartTest:
             },
             "pgbouncer": {"enabled": True},
             "redis": {"enabled": True},
-            "ingress": {"enabled": True},
             "networkPolicies": {"enabled": True},
             "cleanup": {"enabled": True},
             "databaseCleanup": {"enabled": True},
-            "flower": {"enabled": True},
             "dagProcessor": {"enabled": True},
             "logs": {"persistence": {"enabled": True}},
             "dags": {"persistence": {"enabled": True}},
@@ -404,16 +445,19 @@ class TestBaseChartTest:
                 {"name": "class1", "value": 10000},
             ],
         }
+        values.update(flower_routing_values)
 
         if airflow_version != "default":
             values["airflowVersion"] = airflow_version
 
-        k8s_objects = render_chart(name=release_name, values=values)
+        k8s_objects = render_chart(name=release_name, values=values, 
api_versions=api_versions)
         kind_k8s_obj_labels_tuples = {
             (k8s_object["metadata"]["name"], k8s_object["kind"]): 
k8s_object["metadata"]["labels"]
             for k8s_object in k8s_objects
         }
 
+        flower_routing_name, flower_routing_kind, flower_routing_component = 
flower_routing_resource
+
         kind_names_tuples = [
             (f"{release_name}-airflow-cleanup", "ServiceAccount", 
"airflow-cleanup-pods"),
             (f"{release_name}-airflow-database-cleanup", "ServiceAccount", 
"database-cleanup"),
@@ -442,7 +486,11 @@ class TestBaseChartTest:
             (f"{release_name}-flower", "Deployment", "flower"),
             (f"{release_name}-flower", "Service", "flower"),
             (f"{release_name}-flower-policy", "NetworkPolicy", 
"airflow-flower-policy"),
-            (f"{release_name}-flower-ingress", "Ingress", "flower-ingress"),
+            (
+                f"{release_name}-{flower_routing_name}",
+                flower_routing_kind,
+                flower_routing_component,
+            ),
             (f"{release_name}-pgbouncer", "Deployment", "pgbouncer"),
             (f"{release_name}-pgbouncer", "Service", "pgbouncer"),
             (f"{release_name}-pgbouncer-config", "Secret", "pgbouncer"),
diff --git a/helm-tests/tests/helm_tests/other/test_httproute_flower.py 
b/helm-tests/tests/helm_tests/other/test_httproute_flower.py
new file mode 100644
index 00000000000..80ecbd7498f
--- /dev/null
+++ b/helm-tests/tests/helm_tests/other/test_httproute_flower.py
@@ -0,0 +1,424 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+import jmespath
+import pytest
+from chart_utils.helm_template_generator import HelmFailedError, render_chart
+
+SHOW_ONLY = ["templates/flower/flower-httproute.yaml"]
+FLOWER_INGRESS_SHOW_ONLY = ["templates/flower/flower-ingress.yaml"]
+
+GATEWAY_API_VERSIONS = ["gateway.networking.k8s.io/v1"]
+MINIMAL_PARENT_REFS = [{"name": "main-gateway"}]
+
+
+class TestHTTPRouteFlower:
+    """Tests HTTPRoute Flower (Kubernetes Gateway API)."""
+
+    def test_should_pass_validation_with_minimal_config(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {"enabled": True, "parentRefs": 
MINIMAL_PARENT_REFS},
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert len(docs) == 1
+        assert jmespath.search("kind", docs[0]) == "HTTPRoute"
+        assert jmespath.search("metadata.name", docs[0]) == 
"release-name-flower-httproute"
+
+    def test_should_set_api_version_and_kind(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {"enabled": True, "parentRefs": 
MINIMAL_PARENT_REFS},
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search("apiVersion", docs[0]) == 
"gateway.networking.k8s.io/v1"
+        assert jmespath.search("kind", docs[0]) == "HTTPRoute"
+
+    def test_should_allow_more_than_one_annotation(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {
+                        "enabled": True,
+                        "parentRefs": MINIMAL_PARENT_REFS,
+                        "annotations": {"aa": "bb", "cc": "dd"},
+                    },
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search("metadata.annotations", docs[0]) == {"aa": 
"bb", "cc": "dd"}
+
+    def test_should_add_extra_labels(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {
+                        "enabled": True,
+                        "parentRefs": MINIMAL_PARENT_REFS,
+                        "labels": {"custom": "value"},
+                    },
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search('metadata.labels."custom"', docs[0]) == "value"
+
+    def test_should_pass_parent_refs_through(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {
+                        "enabled": True,
+                        "parentRefs": [
+                            {"name": "main-gateway", "namespace": 
"gateway-system"},
+                            {"name": "main-gateway", "namespace": 
"gateway-system", "sectionName": "https"},
+                        ],
+                    },
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search("spec.parentRefs", docs[0]) == [
+            {"name": "main-gateway", "namespace": "gateway-system"},
+            {"name": "main-gateway", "namespace": "gateway-system", 
"sectionName": "https"},
+        ]
+
+    def test_should_set_hostnames(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {
+                        "enabled": True,
+                        "parentRefs": MINIMAL_PARENT_REFS,
+                        "hostnames": ["flower.example.com", 
"flower2.example.com"],
+                    },
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search("spec.hostnames", docs[0]) == [
+            "flower.example.com",
+            "flower2.example.com",
+        ]
+
+    def test_hostnames_should_be_templated(self):
+        docs = render_chart(
+            name="airflow",
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {
+                        "enabled": True,
+                        "parentRefs": MINIMAL_PARENT_REFS,
+                        "hostnames": ["{{ .Release.Name }}.example.com"],
+                    },
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search("spec.hostnames", docs[0]) == 
["airflow.example.com"]
+
+    def test_should_default_to_path_prefix_and_flower_backend(self):
+        docs = render_chart(
+            name="my-release",
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {"enabled": True, "parentRefs": 
MINIMAL_PARENT_REFS},
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search("spec.rules", docs[0]) == [
+            {
+                "matches": [{"path": {"type": "PathPrefix", "value": "/"}}],
+                "backendRefs": [{"name": "my-release-flower", "port": 5555}],
+            },
+        ]
+
+    def test_custom_path_and_path_type_should_apply(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {
+                        "enabled": True,
+                        "parentRefs": MINIMAL_PARENT_REFS,
+                        "path": "/flower",
+                        "pathType": "Exact",
+                    },
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search("spec.rules[0].matches[0].path.type", docs[0]) 
== "Exact"
+        assert jmespath.search("spec.rules[0].matches[0].path.value", docs[0]) 
== "/flower"
+
+    def test_custom_rules_override_default_rule(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {
+                        "enabled": True,
+                        "parentRefs": MINIMAL_PARENT_REFS,
+                        "rules": [
+                            {
+                                "matches": [{"path": {"type": "PathPrefix", 
"value": "/custom-flower"}}],
+                                "backendRefs": [{"name": "external-flower", 
"port": 8443}],
+                            },
+                        ],
+                    },
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search("spec.rules", docs[0]) == [
+            {
+                "matches": [{"path": {"type": "PathPrefix", "value": 
"/custom-flower"}}],
+                "backendRefs": [{"name": "external-flower", "port": 8443}],
+            },
+        ]
+
+    def test_should_use_flower_ui_port_for_default_backend(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "ports": {"flowerUI": 9000},
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {"enabled": True, "parentRefs": 
MINIMAL_PARENT_REFS},
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search("spec.rules[0].backendRefs[0].port", docs[0]) 
== 9000
+
+    def test_httproute_not_created_when_unset(self):
+        docs = render_chart(
+            values={"executor": "CeleryExecutor", "flower": {"enabled": True, 
"httpRoute": {}}},
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert docs == []
+
+    def test_httproute_not_created_when_disabled(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {"enabled": True, "httpRoute": {"enabled": False}},
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert docs == []
+
+    @pytest.mark.parametrize("executor", ["CeleryExecutor", 
"CeleryKubernetesExecutor"])
+    def test_httproute_created_when_enabled(self, executor):
+        docs = render_chart(
+            values={
+                "executor": executor,
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {"enabled": True, "parentRefs": 
MINIMAL_PARENT_REFS},
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert len(docs) == 1
+
+    def test_should_not_render_when_flower_disabled(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "flower": {
+                    "enabled": False,
+                    "httpRoute": {"enabled": True, "parentRefs": 
MINIMAL_PARENT_REFS},
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert docs == []
+
+    @pytest.mark.parametrize(
+        "executor", ["LocalExecutor", "KubernetesExecutor", 
"LocalExecutor,KubernetesExecutor"]
+    )
+    def test_should_not_render_without_celery_executor(self, executor):
+        docs = render_chart(
+            values={
+                "executor": executor,
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {"enabled": True, "parentRefs": 
MINIMAL_PARENT_REFS},
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert docs == []
+
+    def test_should_fail_when_gateway_api_crd_missing(self):
+        with pytest.raises(HelmFailedError) as exc_info:
+            render_chart(
+                values={
+                    "executor": "CeleryExecutor",
+                    "flower": {
+                        "enabled": True,
+                        "httpRoute": {"enabled": True, "parentRefs": 
MINIMAL_PARENT_REFS},
+                    },
+                },
+                show_only=SHOW_ONLY,
+            )
+        assert "Gateway API HTTPRoute CRD" in exc_info.value.stderr.decode()
+
+    def test_should_fail_when_parent_refs_empty(self):
+        with pytest.raises(HelmFailedError) as exc_info:
+            render_chart(
+                values={
+                    "executor": "CeleryExecutor",
+                    "flower": {"enabled": True, "httpRoute": {"enabled": 
True}},
+                },
+                show_only=SHOW_ONLY,
+                api_versions=GATEWAY_API_VERSIONS,
+            )
+        assert "parentRefs" in exc_info.value.stderr.decode()
+
+    def test_should_fail_schema_when_parent_refs_explicitly_empty(self):
+        with pytest.raises(HelmFailedError) as exc_info:
+            render_chart(
+                values={
+                    "executor": "CeleryExecutor",
+                    "flower": {"enabled": True, "httpRoute": {"enabled": True, 
"parentRefs": []}},
+                },
+                show_only=SHOW_ONLY,
+                api_versions=GATEWAY_API_VERSIONS,
+            )
+        assert "parentRefs" in exc_info.value.stderr.decode()
+
+    @pytest.mark.parametrize(
+        "ingress_values",
+        [{"flower": {"enabled": True}}, {"enabled": True}],
+        ids=["flower-ingress", "legacy-ingress"],
+    )
+    def test_should_fail_when_ingress_and_httproute_both_enabled(self, 
ingress_values):
+        with pytest.raises(HelmFailedError) as exc_info:
+            render_chart(
+                values={
+                    "executor": "CeleryExecutor",
+                    "ingress": ingress_values,
+                    "flower": {"enabled": True, "httpRoute": {"enabled": 
True}},
+                },
+                show_only=SHOW_ONLY,
+                api_versions=GATEWAY_API_VERSIONS,
+            )
+        assert "enable only one of them" in exc_info.value.stderr.decode()
+
+    @pytest.mark.parametrize(
+        "ingress_values",
+        [{"flower": {"enabled": True}}, {"enabled": True}],
+        ids=["flower-ingress", "legacy-ingress"],
+    )
+    def 
test_should_fail_when_ingress_template_sees_ingress_and_httproute_both_enabled(self,
 ingress_values):
+        with pytest.raises(HelmFailedError) as exc_info:
+            render_chart(
+                values={
+                    "executor": "CeleryExecutor",
+                    "ingress": ingress_values,
+                    "flower": {"enabled": True, "httpRoute": {"enabled": 
True}},
+                },
+                show_only=FLOWER_INGRESS_SHOW_ONLY,
+                api_versions=GATEWAY_API_VERSIONS,
+            )
+        assert "enable only one of them" in exc_info.value.stderr.decode()
+
+    def test_backend_service_name_with_fullname_override(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "fullnameOverride": "airflow-fullname-override",
+                "useStandardNaming": True,
+                "flower": {
+                    "enabled": True,
+                    "httpRoute": {"enabled": True, "parentRefs": 
MINIMAL_PARENT_REFS},
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert (
+            jmespath.search("spec.rules[0].backendRefs[0].name", docs[0])
+            == "airflow-fullname-override-flower"
+        )
+
+    def test_should_add_component_specific_labels(self):
+        docs = render_chart(
+            values={
+                "executor": "CeleryExecutor",
+                "labels": {"label1": "value1", "label2": "value2"},
+                "flower": {
+                    "enabled": True,
+                    "labels": {"test_label": "test_label_value"},
+                    "httpRoute": {
+                        "enabled": True,
+                        "parentRefs": MINIMAL_PARENT_REFS,
+                        "labels": {"route_label": "route_value"},
+                    },
+                },
+            },
+            show_only=SHOW_ONLY,
+            api_versions=GATEWAY_API_VERSIONS,
+        )
+        assert jmespath.search('metadata.labels."label1"', docs[0]) == "value1"
+        assert jmespath.search('metadata.labels."test_label"', docs[0]) == 
"test_label_value"
+        assert jmespath.search('metadata.labels."route_label"', docs[0]) == 
"route_value"


Reply via email to