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