diff --git a/ENV_VARIABLES.md b/ENV_VARIABLES.md index 750d3c3ed..0eef2eb2b 100644 --- a/ENV_VARIABLES.md +++ b/ENV_VARIABLES.md @@ -171,3 +171,6 @@ | SE_DISTRIBUTOR_BACKEND_URL | | Redis URL for Distributor connection when using RedisBackedDistributor implementation, e.g. redis://redis:6379 | --distributor-backend-url | | SE_DISTRIBUTOR_IMPLEMENTATION | | Configure external datastore for Distributor. When enabled, all replicas share state through the backend (node registrations, slot reservations, health-check coordination) | --distributor-implementation | | SE_TCP_TUNNEL | false | | --tcp-tunnel | +| SE_SESSION_QUEUE_BACKEND_URL | | | | +| SE_SESSION_QUEUE_IMPLEMENTATION | | | | +| SE_VIDEO_SESSION_SUBFOLDER | false | | | diff --git a/SessionQueue/Dockerfile b/SessionQueue/Dockerfile index 7c627cc90..f74495993 100644 --- a/SessionQueue/Dockerfile +++ b/SessionQueue/Dockerfile @@ -4,22 +4,28 @@ FROM ${NAMESPACE}/base:${VERSION} ARG AUTHORS LABEL authors=${AUTHORS} -USER ${SEL_UID} +USER root #======================== # Selenium SessionQueue Configuration #======================== +COPY --chown="${SEL_UID}:${SEL_GID}" start-selenium-grid-session-queue.sh generate_config \ + /opt/bin/ +RUN chmod +x /opt/bin/start-selenium-grid-session-queue.sh /opt/bin/generate_config + +COPY selenium-grid-session-queue.conf /etc/supervisor/conf.d/ + +USER ${SEL_UID} + # In seconds, maps to "--session-request-timeout" ENV SE_SESSION_REQUEST_TIMEOUT="300" \ # In seconds, maps to "--session-retry-interval" SE_SESSION_RETRY_INTERVAL="15" \ SE_SESSION_QUEUE_PORT="5559" \ - SE_OTEL_SERVICE_NAME="selenium-session-queue" + SE_OTEL_SERVICE_NAME="selenium-session-queue" \ + GENERATE_CONFIG="true" \ + SE_SESSION_QUEUE_IMPLEMENTATION="" \ + SE_SESSION_QUEUE_BACKEND_URL="" EXPOSE 5559 - -COPY --chown="${SEL_UID}:${SEL_GID}" start-selenium-grid-session-queue.sh \ - /opt/bin/ - -COPY selenium-grid-session-queue.conf /etc/supervisor/conf.d/ diff --git a/SessionQueue/generate_config b/SessionQueue/generate_config new file mode 100644 index 000000000..8cbe7c08e --- /dev/null +++ b/SessionQueue/generate_config @@ -0,0 +1,17 @@ +#!/bin/bash + +if [[ -z "$CONFIG_FILE" ]]; then + FILENAME="/opt/selenium/config.toml" +else + FILENAME="$CONFIG_FILE" +fi + +echo "[sessionqueue]" >"$FILENAME" + +if [[ -n "${SE_SESSION_QUEUE_IMPLEMENTATION}" ]]; then + echo "implementation = \"${SE_SESSION_QUEUE_IMPLEMENTATION}\"" >>"$FILENAME" +fi + +if [[ -n "${SE_SESSION_QUEUE_BACKEND_URL}" ]]; then + echo "backend-url = \"${SE_SESSION_QUEUE_BACKEND_URL}\"" >>"$FILENAME" +fi diff --git a/SessionQueue/start-selenium-grid-session-queue.sh b/SessionQueue/start-selenium-grid-session-queue.sh index 8d95ddd31..0cd26544b 100755 --- a/SessionQueue/start-selenium-grid-session-queue.sh +++ b/SessionQueue/start-selenium-grid-session-queue.sh @@ -87,6 +87,15 @@ if [ ! -z "$SE_REGISTRATION_SECRET" ]; then append_se_opts "--registration-secret" "${SE_REGISTRATION_SECRET}" "false" fi +if [ "$GENERATE_CONFIG" = true ]; then + echo "Generating Selenium Config for SessionQueue" + /opt/bin/generate_config +fi + +if [ ! -z "${CONFIG_FILE}" ]; then + append_se_opts "--config" "${CONFIG_FILE}" +fi + EXTRA_LIBS="" if [ -n "${SE_EXTRA_LIBS}" ]; then EXTRA_LIBS="--ext ${SE_EXTRA_LIBS}" diff --git a/charts/selenium-grid/CONFIGURATION.md b/charts/selenium-grid/CONFIGURATION.md index f90591705..dfe6a5a02 100644 --- a/charts/selenium-grid/CONFIGURATION.md +++ b/charts/selenium-grid/CONFIGURATION.md @@ -322,6 +322,10 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes | components.sessionQueue.imagePullPolicy | string | `"IfNotPresent"` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | | components.sessionQueue.imagePullSecret | string | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) | | components.sessionQueue.sessionRequestTimeout | string | `""` | Override global sessionRequestTimeout | +| components.sessionQueue.externalDatastore | object | `{"backend":"redis","enabled":false,"redis":{"implementation":"org.openqa.selenium.grid.sessionqueue.redis.RedisBackedNewSessionQueue","url":"redis://{{ $.Release.Name }}-redis:6379"}}` | Configure external datastore for SessionQueue. When enabled, all replicas share the queue state in Redis, allowing the tier to scale out horizontally behind a load balancer or Kubernetes Service. | +| components.sessionQueue.externalDatastore.enabled | bool | `false` | Enable external datastore for SessionQueue | +| components.sessionQueue.externalDatastore.backend | string | `"redis"` | Backend for external datastore (supported: redis) | +| components.sessionQueue.externalDatastore.redis | object | `{"implementation":"org.openqa.selenium.grid.sessionqueue.redis.RedisBackedNewSessionQueue","url":"redis://{{ $.Release.Name }}-redis:6379"}` | Configure Redis backed SessionQueue | | components.sessionQueue.extraEnvironmentVariables | list | `[]` | Specify extra environment variables for Session Queue | | components.sessionQueue.extraEnvFrom | list | `[]` | Specify extra environment variables from ConfigMap and Secret for Session Queue | | components.sessionQueue.affinity | object | `{}` | Specify affinity for Session Queue pods, this overwrites global.seleniumGrid.affinity parameter | diff --git a/charts/selenium-grid/templates/session-queue-configmap.yaml b/charts/selenium-grid/templates/session-queue-configmap.yaml index a1bfc88cd..c5ee39c65 100644 --- a/charts/selenium-grid/templates/session-queue-configmap.yaml +++ b/charts/selenium-grid/templates/session-queue-configmap.yaml @@ -10,6 +10,17 @@ metadata: labels: {{- include "seleniumGrid.commonLabels" $ | nindent 4 }} data: +{{- if .Values.components.sessionQueue.externalDatastore.enabled }} +{{- $backend := .Values.components.sessionQueue.externalDatastore.backend -}} +{{- with (get .Values.components.sessionQueue.externalDatastore $backend) }} +{{- with .implementation }} + SE_SESSION_QUEUE_IMPLEMENTATION: {{ tpl . $ | quote }} +{{- end }} +{{- with .url }} + SE_SESSION_QUEUE_BACKEND_URL: {{ tpl . $ | quote }} +{{- end }} +{{- end }} +{{- end }} {{- range $key, $value := $.Values.sessionQueueConfigMap.data }} {{ $key }}: {{ tpl $value $ | quote }} {{- end }} diff --git a/charts/selenium-grid/templates/session-queue-deployment.yaml b/charts/selenium-grid/templates/session-queue-deployment.yaml index ab0a95dc1..976ca0e25 100644 --- a/charts/selenium-grid/templates/session-queue-deployment.yaml +++ b/charts/selenium-grid/templates/session-queue-deployment.yaml @@ -61,6 +61,8 @@ spec: {{- tpl (toYaml .) $ | nindent 12 }} {{- end }} envFrom: + - configMapRef: + name: {{ template "seleniumGrid.sessionQueue.configmap.fullname" . }} - configMapRef: name: {{ template "seleniumGrid.logging.configmap.fullname" $ }} - configMapRef: diff --git a/charts/selenium-grid/values.yaml b/charts/selenium-grid/values.yaml index 72f7134bd..0a297361d 100644 --- a/charts/selenium-grid/values.yaml +++ b/charts/selenium-grid/values.yaml @@ -813,6 +813,19 @@ components: # -- Override global sessionRequestTimeout sessionRequestTimeout: "" + # -- Configure external datastore for SessionQueue. When enabled, all replicas share the queue + # state in Redis, allowing the tier to scale out horizontally behind a load balancer or + # Kubernetes Service. + externalDatastore: + # -- Enable external datastore for SessionQueue + enabled: false + # -- Backend for external datastore (supported: redis) + backend: redis + # -- Configure Redis backed SessionQueue + redis: + implementation: "org.openqa.selenium.grid.sessionqueue.redis.RedisBackedNewSessionQueue" + url: "redis://{{ $.Release.Name }}-redis:6379" + # -- Specify extra environment variables for Session Queue extraEnvironmentVariables: [] # -- Specify extra environment variables from ConfigMap and Secret for Session Queue diff --git a/docker-compose-v3-full-grid-external-redis-backed.yml b/docker-compose-v3-full-grid-external-redis-backed.yml index d8608a5d5..515d11e6f 100644 --- a/docker-compose-v3-full-grid-external-redis-backed.yml +++ b/docker-compose-v3-full-grid-external-redis-backed.yml @@ -34,6 +34,9 @@ services: container_name: selenium-session-queue ports: - "5559:5559" + environment: + - SE_SESSION_QUEUE_IMPLEMENTATION=org.openqa.selenium.grid.sessionqueue.redis.RedisBackedNewSessionQueue + - SE_SESSION_QUEUE_BACKEND_URL=redis://redis:6379 selenium-distributor: image: selenium/distributor:4.44.0-20260505 diff --git a/scripts/generate_list_env_vars/description.yaml b/scripts/generate_list_env_vars/description.yaml index 56e536bf9..6ca367651 100644 --- a/scripts/generate_list_env_vars/description.yaml +++ b/scripts/generate_list_env_vars/description.yaml @@ -566,3 +566,12 @@ - name: SE_TCP_TUNNEL description: '' cli: --tcp-tunnel +- name: SE_SESSION_QUEUE_BACKEND_URL + description: '' + cli: '' +- name: SE_SESSION_QUEUE_IMPLEMENTATION + description: '' + cli: '' +- name: SE_VIDEO_SESSION_SUBFOLDER + description: '' + cli: '' diff --git a/scripts/generate_list_env_vars/value.yaml b/scripts/generate_list_env_vars/value.yaml index 75d9260bc..3af676d88 100644 --- a/scripts/generate_list_env_vars/value.yaml +++ b/scripts/generate_list_env_vars/value.yaml @@ -248,8 +248,12 @@ default: '' - name: SE_SESSIONS_MAP_PORT default: '5556' +- name: SE_SESSION_QUEUE_BACKEND_URL + default: '' - name: SE_SESSION_QUEUE_HOST default: '' +- name: SE_SESSION_QUEUE_IMPLEMENTATION + default: '' - name: SE_SESSION_QUEUE_PORT default: '5559' - name: SE_SESSION_REQUEST_TIMEOUT @@ -320,6 +324,8 @@ default: '1' - name: SE_VIDEO_RECORD_STANDALONE default: '' +- name: SE_VIDEO_SESSION_SUBFOLDER + default: 'false' - name: SE_VIDEO_UPLOAD_BATCH_CHECK default: '' - name: SE_VIDEO_UPLOAD_ENABLED diff --git a/tests/charts/make/chart_test.sh b/tests/charts/make/chart_test.sh index d3210d4b2..50229aab1 100755 --- a/tests/charts/make/chart_test.sh +++ b/tests/charts/make/chart_test.sh @@ -248,6 +248,10 @@ elif [ "${TEST_EXTERNAL_DATASTORE}" = "redis" ]; then --set components.distributor.externalDatastore.enabled=true \ --set components.distributor.externalDatastore.backend=redis \ " + HELM_COMMAND_SET_IMAGES="${HELM_COMMAND_SET_IMAGES} \ + --set components.sessionQueue.externalDatastore.enabled=true \ + --set components.sessionQueue.externalDatastore.backend=redis \ + " fi if [ "${SELENIUM_GRID_MONITORING}" = "true" ] && [ "${TEST_EXISTING_PTS}" = "true" ]; then