diff --git a/charts/hivemq-platform/templates/_helpers.tpl b/charts/hivemq-platform/templates/_helpers.tpl
index 6d5426e6..e4bc43e6 100644
--- a/charts/hivemq-platform/templates/_helpers.tpl
+++ b/charts/hivemq-platform/templates/_helpers.tpl
@@ -358,7 +358,9 @@ Usage: {{ include "hivemq-platform.validate-services" (dict "services" .Values.s
{{- include "hivemq-platform.validate-service-container-ports" . -}}
{{- include "hivemq-platform.validate-default-service-ports" . -}}
{{- include "hivemq-platform.validate-metrics-services" . -}}
-{{- include "hivemq-platform.validate-proxy-protocol-services" . -}}
+{{- include "hivemq-platform.validate-hivemq-proxy-protocol-services" . -}}
+{{- include "hivemq-platform.validate-hivemq-listener-name-services" . -}}
+{{- include "hivemq-platform.validate-external-traffic-policy" . -}}
{{- include "hivemq-platform.validate-legacy-services" . -}}
{{- end -}}
@@ -476,14 +478,44 @@ Usage: {{ include "hivemq-platform.validate-metrics-services" . }}
{{- end -}}
{{/*
-Validates that proxy protocol value is only used by either MQTT or WebSocket services.
-Usage: {{ include "hivemq-platform.validate-proxy-protocol-services" . }}
+Validates that proxy protocol value is only used by either MQTT or WebSocket services and the service is exposed.
+Usage: {{ include "hivemq-platform.validate-hivemq-proxy-protocol-services" . }}
*/}}
-{{- define "hivemq-platform.validate-proxy-protocol-services" -}}
+{{- define "hivemq-platform.validate-hivemq-proxy-protocol-services" -}}
{{- $services := .Values.services }}
{{- range $service := $services }}
{{- if and ($service.exposed) (hasKey $service "hivemqProxyProtocol") (and (not (eq $service.type "mqtt")) (not (eq $service.type "websocket"))) }}
- {{- fail (printf "\nService type %s with container port %d is using PROXY protocol value. PROXY protocol is only supported for MQTT and WebSocket services" $service.type (int64 $service.containerPort)) }}
+ {{- fail (printf "\nService type `%s` with container port `%d` is using `hivemqProxyProtocol` value. HiveMQ PROXY protocol is only supported by MQTT and WebSocket services" $service.type (int64 $service.containerPort)) }}
+ {{- end }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Validates that HiveMQ listener name value is only used by either MQTT or WebSocket services and the service is exposed.
+Usage: {{ include "hivemq-platform.validate-hivemq-listener-name-services" . }}
+*/}}
+{{- define "hivemq-platform.validate-hivemq-listener-name-services" -}}
+{{- $services := .Values.services }}
+{{- range $service := $services }}
+ {{- if and ($service.exposed) (hasKey $service "hivemqListenerName") (and (not (eq $service.type "mqtt")) (not (eq $service.type "websocket"))) }}
+ {{- fail (printf "\nService type `%s` with container port `%d` is using `hivemqListenerName` value. HiveMQ listener names are only supported by MQTT and WebSocket services" $service.type (int64 $service.containerPort)) }}
+ {{- end }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Validates that external traffic policy value is only present when the service type value is set to either NodePort or LoadBalancer
+and the service is exposed.
+Usage: {{ include "hivemq-platform.validate-external-traffic-policy" . }}
+*/}}
+{{- define "hivemq-platform.validate-external-traffic-policy" -}}
+{{- $services := .Values.services }}
+{{- range $service := $services }}
+ {{- if and ($service.exposed) (hasKey $service "externalTrafficPolicy") (not (hasKey $service "serviceType")) }}
+ {{- fail (printf "\nService type `%s` with container port `%d` is using `externalTrafficPolicy` value but `serviceType` value is not defined. Service type value is mandatory when using external traffic policy" $service.type (int64 $service.containerPort)) }}
+ {{- end }}
+ {{- if and ($service.exposed) (hasKey $service "externalTrafficPolicy") (hasKey $service "serviceType") (and (not (eq $service.serviceType "NodePort")) (not (eq $service.serviceType "LoadBalancer")) ) }}
+ {{- fail (printf "\nService type `%s` with container port `%d` is using `externalTrafficPolicy` value. External traffic policy is only supported by NodePort and LoadBalancer service types" $service.serviceType (int64 $service.containerPort)) }}
{{- end }}
{{- end }}
{{- end -}}
diff --git a/charts/hivemq-platform/templates/hivemq-custom-resource.yml b/charts/hivemq-platform/templates/hivemq-custom-resource.yml
index de9caae7..c995168f 100644
--- a/charts/hivemq-platform/templates/hivemq-custom-resource.yml
+++ b/charts/hivemq-platform/templates/hivemq-custom-resource.yml
@@ -258,6 +258,9 @@ spec:
{{- if and $service.serviceType (or (eq $service.serviceType "NodePort") (eq $service.serviceType "LoadBalancer")) }}
type: {{ $service.serviceType }}
{{- end }}
+ {{- if $service.externalTrafficPolicy }}
+ externalTrafficPolicy: {{ $service.externalTrafficPolicy }}
+ {{- end }}
{{- if and (eq $service.type "control-center") (not (hasKey $service "sessionAffinity")) }}
sessionAffinity: ClientIP
{{- else if hasKey $service "sessionAffinity" }}
diff --git a/charts/hivemq-platform/tests/configuration/configmap/hivemq_control_center_listeners_configuration_test.yaml b/charts/hivemq-platform/tests/configuration/configmap/hivemq_control_center_listeners_configuration_test.yaml
index 3f8fddf6..412fd7bd 100644
--- a/charts/hivemq-platform/tests/configuration/configmap/hivemq_control_center_listeners_configuration_test.yaml
+++ b/charts/hivemq-platform/tests/configuration/configmap/hivemq_control_center_listeners_configuration_test.yaml
@@ -577,14 +577,3 @@ tests:
- notMatchRegex:
path: data["config.xml"]
pattern: "(?s).*?.*?.*?8443.*?.*?.*?8443.*?.*?.*?"
-
- - it: with a Control Center service exposed and a listener name, schema validation fails
- template: hivemq-custom-resource.yml
- set:
- services:
- - type: control-center
- exposed: true
- containerPort: 8081
- hivemqListenerName: my-custom-cc-listener
- asserts:
- - failedTemplate: {}
diff --git a/charts/hivemq-platform/tests/configuration/configmap/hivemq_rest_api_listeners_configuration_test.yaml b/charts/hivemq-platform/tests/configuration/configmap/hivemq_rest_api_listeners_configuration_test.yaml
index bf064dc5..cd85dc55 100644
--- a/charts/hivemq-platform/tests/configuration/configmap/hivemq_rest_api_listeners_configuration_test.yaml
+++ b/charts/hivemq-platform/tests/configuration/configmap/hivemq_rest_api_listeners_configuration_test.yaml
@@ -112,14 +112,3 @@ tests:
- notMatchRegex:
path: data["config.xml"]
pattern: "(?s).*?.*?.*?8890.*?.*?.*?8890.*?.*?.*?"
-
- - it: with a REST API service exposed and a listener name, schema validation fails
- template: hivemq-custom-resource.yml
- set:
- services:
- - type: rest-api
- exposed: true
- containerPort: 8890
- hivemqListenerName: my-custom-rest-api-listener
- asserts:
- - failedTemplate: {}
diff --git a/charts/hivemq-platform/tests/configuration/configmap/hivemq_websocket_listeners_configuration_test.yaml b/charts/hivemq-platform/tests/configuration/configmap/hivemq_websocket_listeners_configuration_test.yaml
index b74077b5..a9f5e8c5 100644
--- a/charts/hivemq-platform/tests/configuration/configmap/hivemq_websocket_listeners_configuration_test.yaml
+++ b/charts/hivemq-platform/tests/configuration/configmap/hivemq_websocket_listeners_configuration_test.yaml
@@ -840,13 +840,3 @@ tests:
- hasDocuments:
count: 1
- - it: with a non MQTT or WebSocket service exposed and a listener name, schema validation fails
- template: hivemq-custom-resource.yml
- set:
- services:
- - type: control-center
- exposed: true
- containerPort: 8081
- hivemqListenerName: my-custom-cc-listener
- asserts:
- - failedTemplate: {}
diff --git a/charts/hivemq-platform/tests/services/hivemq_control_center_services_test.yaml b/charts/hivemq-platform/tests/services/hivemq_control_center_services_test.yaml
index 2268bc9c..bc2c24f8 100644
--- a/charts/hivemq-platform/tests/services/hivemq_control_center_services_test.yaml
+++ b/charts/hivemq-platform/tests/services/hivemq_control_center_services_test.yaml
@@ -132,7 +132,7 @@ tests:
hivemqProxyProtocol: true
asserts:
- failedTemplate:
- errorPattern: Service type control-center with container port 8081 is using PROXY protocol value. PROXY protocol is only supported for MQTT and WebSocket services
+ errorPattern: Service type `control-center` with container port `8081` is using `hivemqProxyProtocol` value. HiveMQ PROXY protocol is only supported by MQTT and WebSocket services
- it: with a Control Center service disabled and PROXY protocol enabled, validation succeeds
set:
@@ -145,3 +145,26 @@ tests:
- notFailedTemplate: {}
- hasDocuments:
count: 1
+
+ - it: with a Control Center service enabled and HiveMQ listener name enabled, validation fails
+ set:
+ services:
+ - type: control-center
+ exposed: true
+ containerPort: 8081
+ hivemqListenerName: foobar
+ asserts:
+ - failedTemplate:
+ errorPattern: Service type `control-center` with container port `8081` is using `hivemqListenerName` value. HiveMQ listener names are only supported by MQTT and WebSocket services
+
+ - it: with a Control Center service disabled and HiveMQ listener name enabled, validation succeeds
+ set:
+ services:
+ - type: control-center
+ exposed: false
+ containerPort: 8081
+ hivemqListenerName: foobar
+ asserts:
+ - notFailedTemplate: {}
+ - hasDocuments:
+ count: 1
diff --git a/charts/hivemq-platform/tests/services/hivemq_metrics_services_test.yaml b/charts/hivemq-platform/tests/services/hivemq_metrics_services_test.yaml
index 0942ff68..fbbc3260 100644
--- a/charts/hivemq-platform/tests/services/hivemq_metrics_services_test.yaml
+++ b/charts/hivemq-platform/tests/services/hivemq_metrics_services_test.yaml
@@ -959,7 +959,7 @@ tests:
hivemqProxyProtocol: true
asserts:
- failedTemplate:
- errorPattern: Service type metrics with container port 9399 is using PROXY protocol value. PROXY protocol is only supported for MQTT and WebSocket services
+ errorPattern: Service type `metrics` with container port `9399` is using `hivemqProxyProtocol` value. HiveMQ PROXY protocol is only supported by MQTT and WebSocket services
- it: with a Metrics service disabled and PROXY protocol enabled, validation succeeds
set:
@@ -972,3 +972,26 @@ tests:
- notFailedTemplate: {}
- hasDocuments:
count: 1
+
+ - it: with a Metrics service enabled and HiveMQ listener name enabled, validation fails
+ set:
+ services:
+ - type: metrics
+ exposed: true
+ containerPort: 9399
+ hivemqListenerName: foobar
+ asserts:
+ - failedTemplate:
+ errorPattern: Service type `metrics` with container port `9399` is using `hivemqListenerName` value. HiveMQ listener names are only supported by MQTT and WebSocket services
+
+ - it: with a Metrics service disabled and HiveMQ listener name enabled, validation succeeds
+ set:
+ services:
+ - type: metrics
+ exposed: false
+ containerPort: 9399
+ hivemqListenerName: foobar
+ asserts:
+ - notFailedTemplate: {}
+ - hasDocuments:
+ count: 1
diff --git a/charts/hivemq-platform/tests/services/hivemq_rest_api_services_test.yaml b/charts/hivemq-platform/tests/services/hivemq_rest_api_services_test.yaml
index 8a83a787..d704f139 100644
--- a/charts/hivemq-platform/tests/services/hivemq_rest_api_services_test.yaml
+++ b/charts/hivemq-platform/tests/services/hivemq_rest_api_services_test.yaml
@@ -134,7 +134,7 @@ tests:
hivemqProxyProtocol: true
asserts:
- failedTemplate:
- errorPattern: Service type rest-api with container port 8888 is using PROXY protocol value. PROXY protocol is only supported for MQTT and WebSocket services
+ errorPattern: Service type `rest-api` with container port `8888` is using `hivemqProxyProtocol` value. HiveMQ PROXY protocol is only supported by MQTT and WebSocket services
- it: with a REST API service disabled and PROXY protocol enabled, validation succeeds
set:
@@ -147,3 +147,26 @@ tests:
- notFailedTemplate: {}
- hasDocuments:
count: 1
+
+ - it: with a REST API service enabled and HiveMQ listener name enabled, validation fails
+ set:
+ services:
+ - type: rest-api
+ exposed: true
+ containerPort: 8888
+ hivemqListenerName: foobar
+ asserts:
+ - failedTemplate:
+ errorPattern: Service type `rest-api` with container port `8888` is using `hivemqListenerName` value. HiveMQ listener names are only supported by MQTT and WebSocket services
+
+ - it: with a REST API service disabled and HiveMQ listener name enabled, validation succeeds
+ set:
+ services:
+ - type: rest-api
+ exposed: false
+ containerPort: 8888
+ hivemqListenerName: foobar
+ asserts:
+ - notFailedTemplate: {}
+ - hasDocuments:
+ count: 1
diff --git a/charts/hivemq-platform/tests/services/hivemq_services_test.yaml b/charts/hivemq-platform/tests/services/hivemq_services_test.yaml
index b4826a40..bb40e2f9 100644
--- a/charts/hivemq-platform/tests/services/hivemq_services_test.yaml
+++ b/charts/hivemq-platform/tests/services/hivemq_services_test.yaml
@@ -915,3 +915,130 @@ tests:
foo: bar
asserts:
- failedTemplate: {}
+
+ - it: with invalid external traffic policy set, schema validation fails
+ set:
+ services:
+ - type: mqtt
+ exposed: true
+ containerPort: 1883
+ serviceType: NodePort
+ externalTrafficPolicy: foobar
+ asserts:
+ - failedTemplate: {}
+
+ - it: with default service values, external traffic policy not set
+ set:
+ services:
+ - type: mqtt
+ exposed: true
+ containerPort: 1883
+ asserts:
+ - exists:
+ path: spec.services
+ - contains:
+ path: spec.services
+ content:
+ metadata:
+ name: hivemq-test-hivemq-platform-mqtt-1883
+ spec:
+ ports:
+ - name: mqtt-1883
+ targetPort: mqtt-1883
+ port: 1883
+
+ - it: with external traffic policy value set to Cluster, external traffic policy service specification set to Cluster
+ set:
+ services:
+ - type: mqtt
+ exposed: true
+ containerPort: 1883
+ serviceType: LoadBalancer
+ externalTrafficPolicy: Cluster
+ asserts:
+ - exists:
+ path: spec.services
+ - contains:
+ path: spec.services
+ content:
+ metadata:
+ name: hivemq-test-hivemq-platform-mqtt-1883
+ spec:
+ externalTrafficPolicy: Cluster
+ type: LoadBalancer
+ ports:
+ - name: mqtt-1883
+ targetPort: mqtt-1883
+ port: 1883
+
+ - it: with external traffic policy value set to Local, external traffic policy service specification set to Local
+ set:
+ services:
+ - type: mqtt
+ exposed: true
+ containerPort: 1883
+ serviceType: LoadBalancer
+ externalTrafficPolicy: Local
+ asserts:
+ - exists:
+ path: spec.services
+ - contains:
+ path: spec.services
+ content:
+ metadata:
+ name: hivemq-test-hivemq-platform-mqtt-1883
+ spec:
+ externalTrafficPolicy: Local
+ type: LoadBalancer
+ ports:
+ - name: mqtt-1883
+ targetPort: mqtt-1883
+ port: 1883
+
+ - it: with external traffic policy value set but service type not set, validation fails
+ set:
+ services:
+ - type: mqtt
+ exposed: true
+ containerPort: 1883
+ externalTrafficPolicy: Cluster
+ asserts:
+ - failedTemplate:
+ errorPattern: Service type `mqtt` with container port `1883` is using `externalTrafficPolicy` value but `serviceType` value is not defined. Service type value is mandatory when using external traffic policy
+
+ - it: with external traffic policy value set and service type not set but service not exposed, validation succeeds
+ set:
+ services:
+ - type: mqtt
+ exposed: false
+ containerPort: 1883
+ externalTrafficPolicy: Cluster
+ asserts:
+ - notFailedTemplate: {}
+ - hasDocuments:
+ count: 1
+
+ - it: with external traffic policy value set and service type ClusterIP, validation fails
+ set:
+ services:
+ - type: mqtt
+ exposed: true
+ containerPort: 1883
+ serviceType: ClusterIP
+ externalTrafficPolicy: Cluster
+ asserts:
+ - failedTemplate:
+ errorPattern: Service type `ClusterIP` with container port `1883` is using `externalTrafficPolicy` value. External traffic policy is only supported by NodePort and LoadBalancer service types
+
+ - it: with external traffic policy value set and service type ClusterIP but service not exposed, validation succeeds
+ set:
+ services:
+ - type: mqtt
+ exposed: false
+ containerPort: 1883
+ serviceType: ClusterIP
+ externalTrafficPolicy: Cluster
+ asserts:
+ - notFailedTemplate: {}
+ - hasDocuments:
+ count: 1
diff --git a/charts/hivemq-platform/values.schema.json b/charts/hivemq-platform/values.schema.json
index 6e44cabf..3d65bbd1 100644
--- a/charts/hivemq-platform/values.schema.json
+++ b/charts/hivemq-platform/values.schema.json
@@ -683,27 +683,6 @@
},
"services" : {
"items" : {
- "if" : {
- "properties" : {
- "hivemqListenerName" : {
- "description" : "Defines the optional custom name for the MQTT and WebSocket listeners.",
- "type" : "string"
- }
- },
- "required" : [
- "hivemqListenerName"
- ]
- },
- "then" : {
- "properties" : {
- "type" : {
- "enum" : [
- "mqtt",
- "websocket"
- ]
- }
- }
- },
"properties" : {
"annotations" : {
"type" : "object"
@@ -716,6 +695,18 @@
"exposed" : {
"type" : "boolean"
},
+ "externalTrafficPolicy" : {
+ "description" : "Describes if the Service routes external traffic to node-local or cluster-wide endpoints. See https://kubernetes.io/docs/reference/networking/virtual-ips/#external-traffic-policy.",
+ "enum" : [
+ "Cluster",
+ "Local"
+ ],
+ "type": "string"
+ },
+ "hivemqListenerName" : {
+ "description" : "Defines the optional custom name for the MQTT and WebSocket listeners.",
+ "type" : "string"
+ },
"hivemqProxyProtocol" : {
"type" : "boolean"
},
@@ -756,12 +747,12 @@
"type" : "integer"
},
"serviceType" : {
- "type" : "string",
"enum" : [
"ClusterIP",
"LoadBalancer",
"NodePort"
- ]
+ ],
+ "type" : "string"
},
"sessionAffinity" : {
"additionalProperties" : false,
diff --git a/charts/hivemq-platform/values.yaml b/charts/hivemq-platform/values.yaml
index 5e7b2a5f..61541d68 100644
--- a/charts/hivemq-platform/values.yaml
+++ b/charts/hivemq-platform/values.yaml
@@ -267,6 +267,11 @@ services:
# # Session affinity type. Must be `ClientIP` or `None`.
# # Defaults to `ClientIP` for the `control-center` service type.
# type: None
+ # Configures whether this Service routes external traffic to node-local or cluster-wide endpoints.
+ # Affects the network traffic routing behavior, client source IP preservation, and load balancing across Kubernetes nodes.
+ # Only applicable to LoadBalancer or NodePort service types. Possible values are `Cluster` or `Local`.
+ # See: https://kubernetes.io/docs/reference/networking/virtual-ips/#external-traffic-policy
+ # externalTrafficPolicy: Cluster
# Secure MQTT service configuration
- type: mqtt