diff --git a/.circleci/config.yml b/.circleci/config.yml index be6808bd95..f0f05a5881 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -205,6 +205,8 @@ jobs: BUILD_ARGS: << parameters.build-args >> MAKE_TARGETS: << parameters.make-targets >> DEPLOY_BRANCH: trunk + RELEASE: selenium-4.16.0 + SELENIUM_VERSION: 4.16.1 GITHUB_USER: seleniumhq-community GITHUB_REPO: docker-seleniarm steps: @@ -227,7 +229,7 @@ jobs: - run: name: "Prepare workflow environment variables" command: | - export SELENIUM_VERSION=$(grep selenium-server Base/Dockerfile | sed 's/.*-\([^-]*\)\.jar \\/\1/' | head -n 1) + #export SELENIUM_VERSION=$(grep selenium-server Base/Dockerfile | sed 's/.*-\([^-]*\)\.jar \\/\1/' | head -n 1) echo "Prepare workflow environment variables" echo 'export BRANCH='$SELENIUM_VERSION >> $BASH_ENV echo 'export BUILD_DATE=$(date '+%Y%m%d')' >> $BASH_ENV @@ -244,6 +246,8 @@ jobs: echo DEPLOY_BRANCH="$DEPLOY_BRANCH" echo GITHUB_USER="$GITHUB_USER" echo GITHUB_REPO="$GITHUB_REPO" + echo SELENIUM_VERSION="$SELENIUM_VERSION" + echo RELEASE="$RELEASE" - run: uname -a - run: docker info - run: @@ -277,6 +281,7 @@ jobs: export NAME=${NAMESPACE} export VERSION=${BRANCH} + export RELEASE=${RELEASE} export BUILD_DATE=${BUILD_DATE} export PLATFORMS=${PLATFORMS} export BUILD_ARGS=${BUILD_ARGS} diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 88d78879e3..ada8e271b1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -19,14 +19,15 @@ body: validations: required: true - type: textarea - id: repro-command + id: reproduce-command attributes: - label: Command used to start Selenium Grid with Docker + label: Command used to start Selenium Grid with Docker (or Kubernetes) description: | - What command do you use to start Selenium Grid with Docker? + What command do you use to start Selenium Grid with Docker (or Kubernetes)? placeholder: | Please share the script or docker-compose file used. This will be automatically formatted into code, so no need for backticks. + If Kubernetes used, please share the YAML file, or chart values used to deploy the cluster. Be sure to include an SSCCE (Short, Self Contained, Correct [compilable] example) http://sscce.org/ render: shell @@ -47,14 +48,14 @@ body: attributes: label: Operating System description: What host operating system are you using to run docker-selenium? - placeholder: Windows 10? macOS BigSur? Ubuntu? + placeholder: Windows 10? macOS BigSur? Ubuntu? Kubernetes (Minikube, EKS, GKE, AKS, OpenShift, Rancher, etc.) version? validations: required: true - type: input id: version attributes: - label: Docker Selenium version (tag) + label: Docker Selenium version (tag or chart version) description: What version of Docker Selenium are you using? - placeholder: 4.12.1-20230920? Please use the full tag, avoid "latest" + placeholder: 4.16.0-20231206? Please use the full tag, avoid "latest" validations: - required: true \ No newline at end of file + required: true diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index faef306c63..b40db3af6b 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -9,10 +9,8 @@ permissions: jobs: build-and-test: - # Skip job based on the commit message, only works in push to branches for now - if: contains(toJson(github.event.commits), '[skip ci]') == false name: Build & test Docker images with random user - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: matrix: use-random-user: [false, true] @@ -20,10 +18,11 @@ jobs: - uses: actions/checkout@v4 - name: Output Docker info run: docker info - - name: Set up Python 3.8 - uses: actions/setup-python@v4.7.0 + - name: Set up Python + uses: actions/setup-python@v5.0.0 with: - python-version: 3.8 + python-version: '3.11' + check-latest: true - name: Get branch name (only for push to branch) if: github.event_name == 'push' run: echo "BRANCH=$(echo ${PUSH_BRANCH##*/})" >> $GITHUB_ENV @@ -41,7 +40,11 @@ jobs: - name: Build Docker images run: VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make build - name: Test Docker images - run: USE_RANDOM_USER_ID=${USE_RANDOM_USER} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make test + uses: nick-invision/retry@v2.9.0 + with: + timeout_minutes: 20 + max_attempts: 3 + command: | + USE_RANDOM_USER_ID=${USE_RANDOM_USER} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make test env: USE_RANDOM_USER: ${{ matrix.use-random-user }} - diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6ea166dbee..de0ac5db98 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,7 +10,7 @@ jobs: # Only continue if the commit message has '[deploy]' in it if: contains(toJson(github.event.commits), '[deploy]') == true name: Deploy Docker images - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 @@ -51,25 +51,25 @@ jobs: DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}} DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}} - name: Deploy new images - uses: nick-invision/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd # v2 + uses: nick-invision/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 20 max_attempts: 3 command: VERSION="${GRID_VERSION}" BUILD_DATE=${BUILD_DATE} make release - name: Tag images as latest - uses: nick-invision/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd # v2 + uses: nick-invision/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 20 max_attempts: 3 command: VERSION="${GRID_VERSION}" BUILD_DATE=${BUILD_DATE} make tag_latest - name: Deploy latest tag - uses: nick-invision/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd # v2 + uses: nick-invision/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 20 max_attempts: 3 command: VERSION="${GRID_VERSION}" BUILD_DATE=${BUILD_DATE} make release_latest - name: Tag browser images - uses: nick-invision/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd # v2 + uses: nick-invision/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 20 max_attempts: 3 @@ -78,9 +78,9 @@ jobs: run: | git config --local user.email "selenium-ci@users.noreply.github.com" git config --local user.name "Selenium CI Bot" - git commit -m "Update tag in docs and files [skip ci]" -a + git commit -m "Update tag in docs and files" -a - name: Push changes - uses: ad-m/github-push-action@40bf560936a8022e68a3c00e7d2abefaf01305a6 # master + uses: ad-m/github-push-action@d91a481090679876dfc4178fef17f286781251df # master with: github_token: ${{ secrets.SELENIUM_CI_TOKEN }} branch: trunk diff --git a/.github/workflows/helm-chart-release.yml b/.github/workflows/helm-chart-release.yml index 6a5722f3e5..252ca18406 100644 --- a/.github/workflows/helm-chart-release.yml +++ b/.github/workflows/helm-chart-release.yml @@ -6,6 +6,7 @@ on: - trunk paths: - 'charts/selenium-grid/Chart.yaml' + workflow_dispatch: jobs: release: @@ -23,6 +24,6 @@ jobs: git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - name: Run chart-releaser - uses: helm/chart-releaser-action@v1.5.0 + uses: helm/chart-releaser-action@v1.6.0 env: CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/helm-chart-test.yml b/.github/workflows/helm-chart-test.yml new file mode 100644 index 0000000000..7c34c5eb91 --- /dev/null +++ b/.github/workflows/helm-chart-test.yml @@ -0,0 +1,76 @@ +name: Lint and Test Helm Charts + +on: + push: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + build-and-test: + name: Test Helm charts + runs-on: ubuntu-latest + strategy: + matrix: + test-strategy: [chart_test, chart_test_parallel_autoscaling] + steps: + - uses: actions/checkout@v4 + - name: Output Docker info + run: docker info + - name: Set up Python + uses: actions/setup-python@v5.0.0 + with: + python-version: '3.11' + check-latest: true + - name: Get branch name (only for push to branch) + if: github.event_name == 'push' + run: echo "BRANCH=$(echo ${PUSH_BRANCH##*/})" >> $GITHUB_ENV + env: + PUSH_BRANCH: ${{ github.ref }} + - name: Get target branch name (only for PRs) + if: github.event_name == 'pull_request' + run: echo "BRANCH=$(echo ${TARGET_BRANCH##*/})" >> $GITHUB_ENV + env: + TARGET_BRANCH: ${{ github.head_ref }} + - name: Output branch name + run: echo ${BRANCH} + - name: Sets build date + run: | + echo "BUILD_DATE=$(date '+%Y%m%d')" >> $GITHUB_ENV + echo "IMAGE_REGISTRY=artifactory/selenium" >> $GITHUB_ENV + - name: Setup Kubernetes environment + run: make chart_setup_env + - name: Build Docker images + run: NAME=${IMAGE_REGISTRY} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make build + - name: Build and lint charts + run: | + BUILD_DATE=${BUILD_DATE} make chart_build + echo "CHART_PACKAGE_PATH=$(cat /tmp/selenium_chart_version)" >> $GITHUB_ENV + echo "CHART_FILE_NAME=$(basename $(cat /tmp/selenium_chart_version))" >> $GITHUB_ENV + - name: Setup Kubernetes cluster + run: NAME=${IMAGE_REGISTRY} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make chart_cluster_setup + - name: Test Selenium Grid on Kubernetes + uses: nick-invision/retry@v2.9.0 + with: + timeout_minutes: 30 + max_attempts: 3 + command: | + NAME=${IMAGE_REGISTRY} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make ${{ matrix.test-strategy }} + - name: Cleanup Kubernetes cluster + if: always() + run: make chart_cluster_cleanup + - name: Upload Helm chart package + if: always() + uses: actions/upload-artifact@v3 + with: + name: ${{ env.CHART_FILE_NAME }} + path: ${{ env.CHART_PACKAGE_PATH }} + - name: Upload Helm chart template rendered + if: always() + uses: actions/upload-artifact@v3 + with: + name: chart_template_rendered.yaml + path: ./tests/tests/output_deployment.yaml + if-no-files-found: ignore diff --git a/.github/workflows/label-commenter.yml b/.github/workflows/label-commenter.yml index 08861192ac..bf2e02b255 100644 --- a/.github/workflows/label-commenter.yml +++ b/.github/workflows/label-commenter.yml @@ -11,7 +11,7 @@ permissions: jobs: comment: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Label Commenter diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 599e1c54f7..8a7b86c644 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -14,7 +14,7 @@ jobs: action: runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@be8aa5be94131386884a6da4189effda9b14aa21 # v3 + - uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v3 with: process-only: 'issues' issue-lock-inactive-days: '30' diff --git a/.github/workflows/test-video.yml b/.github/workflows/test-video.yml index b5de436e26..65b2241f29 100644 --- a/.github/workflows/test-video.yml +++ b/.github/workflows/test-video.yml @@ -9,18 +9,17 @@ permissions: jobs: build-and-test: - # Skip job based on the commit message, only works in push to branches for now - if: contains(toJson(github.event.commits), '[skip ci]') == false name: Test video recorded through Docker Selenium - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Output Docker info run: docker info - - name: Set up Python 3.8 - uses: actions/setup-python@v4.7.0 + - name: Set up Python + uses: actions/setup-python@v5.0.0 with: - python-version: 3.8 + python-version: '3.11' + check-latest: true - name: Get branch name (only for push to branch) if: github.event_name == 'push' run: echo "BRANCH=$(echo ${PUSH_BRANCH##*/})" >> $GITHUB_ENV @@ -51,4 +50,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: firefox_video - path: ./tests/videos/firefox_video.mp4 \ No newline at end of file + path: ./tests/videos/firefox_video.mp4 diff --git a/.gitignore b/.gitignore index 7377b135bf..f77615fd47 100644 --- a/.gitignore +++ b/.gitignore @@ -147,4 +147,6 @@ ENV/ # End of https://www.gitignore.io/api/python .DS_Store - +/charts/*/charts +/charts/*/**.lock +/charts/*.tgz diff --git a/Base/Dockerfile b/Base/Dockerfile index d8a0f18081..ef79b22bcb 100644 --- a/Base/Dockerfile +++ b/Base/Dockerfile @@ -5,23 +5,24 @@ #FROM ubuntu:focal-20220415 #FROM ubuntu:focal-20220531 #FROM ubuntu:focal-20230301 -FROM debian:bullseye +FROM debian:bookworm LABEL authors="Selenium " +ARG VERSION +ARG RELEASE=selenium-${VERSION} #================================================ # Customize sources for apt-get #================================================ -#RUN echo "deb http://archive.ubuntu.com/ubuntu focal main universe\n" > /etc/apt/sources.list \ -# && echo "deb http://archive.ubuntu.com/ubuntu focal-updates main universe\n" >> /etc/apt/sources.list \ -# && echo "deb http://security.ubuntu.com/ubuntu focal-security main universe\n" >> /etc/apt/sources.list - +#RUN echo "deb http://archive.ubuntu.com/ubuntu jammy main universe\n" > /etc/apt/sources.list \ +# && echo "deb http://archive.ubuntu.com/ubuntu jammy-updates main universe\n" >> /etc/apt/sources.list \ +# && echo "deb http://security.ubuntu.com/ubuntu jammy-security main universe\n" >> /etc/apt/sources.list ARG TARGETARCH ARG TARGETVARIANT # No interactive frontend during docker build ENV DEBIAN_FRONTEND=noninteractive \ DEBCONF_NONINTERACTIVE_SEEN=true - +RUN echo "VERSION is $VERSION" && echo "RELEASE is $RELEASE" #======================== # Miscellaneous packages @@ -33,7 +34,6 @@ RUN apt-get -qqy update \ acl \ bzip2 \ ca-certificates \ - openjdk-11-jre-headless \ tzdata \ sudo \ unzip \ @@ -42,6 +42,11 @@ RUN apt-get -qqy update \ curl \ supervisor \ gnupg2 \ + && mkdir -p /etc/apt/keyrings \ + && wget -O - https://packages.adoptium.net/artifactory/api/gpg/key/public | tee /etc/apt/keyrings/adoptium.asc \ + && echo "deb [signed-by=/etc/apt/keyrings/adoptium.asc] https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" | tee /etc/apt/sources.list.d/adoptium.list \ + && apt-get update -y \ + && apt-get install temurin-11-jre -y \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/* #=================== @@ -51,7 +56,7 @@ RUN if [ $TARGETARCH = "arm" ] && [ $TARGETVARIANT = "v7" ]; then \ else \ export ARCH=$TARGETARCH ; \ fi \ - && sed -i 's/securerandom\.source=file:\/dev\/random/securerandom\.source=file:\/dev\/urandom/' ./usr/lib/jvm/java-11-openjdk-$ARCH/conf/security/java.security + && sed -i 's/securerandom\.source=file:\/dev\/random/securerandom\.source=file:\/dev\/urandom/' ./usr/lib/jvm/temurin-11-jre-$ARCH/conf/security/java.security #=================== @@ -59,8 +64,9 @@ RUN if [ $TARGETARCH = "arm" ] && [ $TARGETVARIANT = "v7" ]; then \ # Possible alternative: https://github.com/docker/docker/issues/3359#issuecomment-32150214 #=================== ENV TZ "UTC" -RUN echo "${TZ}" > /etc/timezone \ - && dpkg-reconfigure --frontend noninteractive tzdata +RUN ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime && \ + dpkg-reconfigure -f noninteractive tzdata && \ + cat /etc/timezone #======================================== # Add normal user and group with passwordless sudo @@ -93,10 +99,8 @@ COPY supervisord.conf /etc RUN mkdir -p /opt/selenium /opt/selenium/assets /var/run/supervisor /var/log/supervisor \ && touch /opt/selenium/config.toml \ && chmod -R 777 /opt/selenium /opt/selenium/assets /var/run/supervisor /var/log/supervisor /etc/passwd \ - && wget --no-verbose https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.10.0/selenium-server-4.10.0.jar \ + && wget --no-verbose https://github.com/SeleniumHQ/selenium/releases/download/${RELEASE}/selenium-server-${VERSION}.jar \ -O /opt/selenium/selenium-server.jar \ - && wget --no-verbose https://repo1.maven.org/maven2/org/seleniumhq/selenium/selenium-http-jdk-client/4.10.0/selenium-http-jdk-client-4.10.0.jar \ - -O /opt/selenium/selenium-http-jdk-client.jar \ && chgrp -R 0 /opt/selenium ${HOME} /opt/selenium/assets /var/run/supervisor /var/log/supervisor \ && chmod -R g=u /opt/selenium ${HOME} /opt/selenium/assets /var/run/supervisor /var/log/supervisor \ && setfacl -Rm u:seluser:rwx /opt /opt/selenium ${HOME} /opt/selenium/assets /var/run/supervisor /var/log/supervisor @@ -114,11 +118,15 @@ RUN if [ `arch` = "aarch64" ]; then \ && chmod -R 775 /external_jars ; \ fi -RUN if [ -f "/tmp/cs" ]; then \ - /tmp/cs fetch --classpath --cache /external_jars io.opentelemetry:opentelemetry-exporter-otlp:1.28.0 io.opentelemetry:opentelemetry-exporter-jaeger:1.28.0 io.grpc:grpc-netty:1.57.1 > /external_jars/.classpath.txt ; \ +RUN if [ -f "/tmp/cs" ]; then \ + /tmp/cs fetch --classpath --cache /external_jars \ + io.opentelemetry:opentelemetry-exporter-otlp:1.31.0 \ + io.opentelemetry:opentelemetry-exporter-jaeger:1.31.0 \ + io.grpc:grpc-netty:1.59.0 > /external_jars/.classpath.txt ; \ fi RUN if [ -f "/tmp/cs" ]; then chmod 664 /external_jars/.classpath.txt ; fi +RUN rm -fr /root/.cache/* #=================================================== # Run the following commands as non-privileged user diff --git a/Distributor/start-selenium-grid-distributor.sh b/Distributor/start-selenium-grid-distributor.sh index 0a653e81ed..b51340c911 100755 --- a/Distributor/start-selenium-grid-distributor.sh +++ b/Distributor/start-selenium-grid-distributor.sh @@ -54,20 +54,21 @@ if [ ! -z "$SE_DISTRIBUTOR_PORT" ]; then PORT_CONFIG="--port ${SE_DISTRIBUTOR_PORT}" fi -EXTRA_LIBS="/opt/selenium/selenium-http-jdk-client.jar" +EXTRA_LIBS="" if [ ! -z "$SE_ENABLE_TRACING" ]; then EXTERNAL_JARS=$(error.log - docker run -v $$(pwd):$$(pwd) -w $$(pwd) jrottenberg/ffmpeg:4.3.1-ubuntu2004 -v error -i ./tests/videos/firefox_video.mp4 -f null - 2>error.log - docker run -v $$(pwd):$$(pwd) -w $$(pwd) jrottenberg/ffmpeg:4.3.1-ubuntu2004 -v error -i ./tests/videos/edge_video.mp4 -f null - 2>error.log + docker run -v $$(pwd):$$(pwd) -w $$(pwd) $(FFMPEG_BASED_NAME)/ffmpeg:$(FFMPEG_BASED_TAG) -v error -i ./tests/videos/chrome_video.mp4 -f null - 2>error.log + docker run -v $$(pwd):$$(pwd) -w $$(pwd) $(FFMPEG_BASED_NAME)/ffmpeg:$(FFMPEG_BASED_TAG) -v error -i ./tests/videos/firefox_video.mp4 -f null - 2>error.log + docker run -v $$(pwd):$$(pwd) -w $$(pwd) $(FFMPEG_BASED_NAME)/ffmpeg:$(FFMPEG_BASED_TAG) -v error -i ./tests/videos/edge_video.mp4 -f null - 2>error.log + +chart_setup_env: + ./tests/charts/make/chart_setup_env.sh + +chart_cluster_setup: + VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_cluster_setup.sh + +chart_cluster_cleanup: + ./tests/charts/make/chart_cluster_cleanup.sh + +chart_build: + VERSION=$(TAG_VERSION) ./tests/charts/make/chart_build.sh + +chart_test: chart_test_template \ + chart_test_chrome \ + chart_test_firefox \ + chart_test_edge + +chart_test_template: + ./tests/charts/bootstrap.sh + +chart_test_chrome: + VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_test.sh NodeChrome + +chart_test_firefox: + VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_test.sh NodeFirefox + +chart_test_edge: + VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_test.sh NodeEdge + +chart_test_parallel_autoscaling: + VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_test.sh ParallelAutoscaling .PHONY: \ all \ diff --git a/NodeBase/Dockerfile b/NodeBase/Dockerfile index dda04b9c89..4ca8345fc8 100644 --- a/NodeBase/Dockerfile +++ b/NodeBase/Dockerfile @@ -64,7 +64,7 @@ RUN apt-get update -qqy \ # fonts-ipafont-gothic ~13 MB # fonts-wqy-zenhei ~17 MB # fonts-tlwg-loma-otf ~300 KB -# ttf-ubuntu-font-family ~5 MB +# fonts-ubuntu ~5 MB # Ubuntu Font Family, sans-serif typeface hinted for clarity # Removed packages: # xfonts-100dpi ~6 MB @@ -78,13 +78,14 @@ RUN apt-get -qqy update \ && apt-get -qqy --no-install-recommends install \ libfontconfig \ libfreetype6 \ - xfonts-cyrillic \ + #xfonts-cyrillic \ xfonts-scalable \ fonts-liberation \ fonts-ipafont-gothic \ fonts-wqy-zenhei \ fonts-tlwg-loma-otf \ # ttf-ubuntu-font-family \ + # fonts-ubuntu \ fonts-noto-color-emoji \ && rm -rf /var/lib/apt/lists/* \ && apt-get -qyy clean diff --git a/NodeBase/generate_config b/NodeBase/generate_config index 9537435924..4e52766664 100755 --- a/NodeBase/generate_config +++ b/NodeBase/generate_config @@ -52,19 +52,11 @@ echo "max-sessions = ${SE_NODE_MAX_SESSIONS} " >> "$FILENAME" SE_NODE_BROWSER_NAME=$(cat /opt/selenium/browser_name) -if [[ "${SE_NODE_BROWSER_NAME}" == "chrome" ]]; then - SE_NODE_BROWSER_VERSION=$(short_version $(google-chrome --version | awk '{print $3}')) -elif [[ "${SE_NODE_BROWSER_NAME}" == "chromium" ]]; then - SE_NODE_BROWSER_NAME=chrome - SE_NODE_BROWSER_VERSION=$(short_version $(chromium --version | awk '{print $2}')) -elif [[ "${SE_NODE_BROWSER_NAME}" == "firefox" ]]; then - SE_NODE_BROWSER_VERSION=$(short_version $(firefox --version | awk '{print $3}')) -elif [[ "${SE_NODE_BROWSER_NAME}" == "MicrosoftEdge" ]]; then - SE_NODE_BROWSER_VERSION=$(short_version $(microsoft-edge --version | awk '{print $3}')) -fi +SE_NODE_BROWSER_VERSION=$(short_version $(cat /opt/selenium/browser_version)) +SE__BROWSER_BINARY_LOCATION=$(cat /opt/selenium/browser_binary_location) if [[ -z "$SE_NODE_STEREOTYPE" ]]; then -SE_NODE_STEREOTYPE="{\"browserName\": \"${SE_NODE_BROWSER_NAME}\", \"browserVersion\": \"${SE_NODE_BROWSER_VERSION}\", \"platformName\": \"Linux\"}" +SE_NODE_STEREOTYPE="{\"browserName\": \"${SE_NODE_BROWSER_NAME}\", \"browserVersion\": \"${SE_NODE_BROWSER_VERSION}\", \"platformName\": \"Linux\", ${SE__BROWSER_BINARY_LOCATION}}" else SE_NODE_STEREOTYPE="$SE_NODE_STEREOTYPE" fi diff --git a/NodeBase/start-selenium-node.sh b/NodeBase/start-selenium-node.sh index fc5dc2f555..4b069c7dd0 100755 --- a/NodeBase/start-selenium-node.sh +++ b/NodeBase/start-selenium-node.sh @@ -31,16 +31,22 @@ if [ ! -z "$SE_OPTS" ]; then echo "Appending Selenium options: ${SE_OPTS}" fi +if [ ! -z "$SE_NODE_SESSION_TIMEOUT" ]; then + SE_OPTS="$SE_OPTS --session-timeout $SE_NODE_SESSION_TIMEOUT" + echo "Appending Selenium node session timeout via SE_OPTS: ${SE_OPTS}" +fi + if [ "$GENERATE_CONFIG" = true ]; then echo "Generating Selenium Config" /opt/bin/generate_config fi -EXTRA_LIBS="/opt/selenium/selenium-http-jdk-client.jar" +EXTRA_LIBS="" if [ ! -z "$SE_ENABLE_TRACING" ]; then EXTERNAL_JARS=$(/dev/null \ && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \ && apt-get update -qqy \ && apt-get -qqy install \ @@ -49,13 +49,15 @@ RUN if [ ! -z "$CHROME_DRIVER_VERSION" ]; \ && echo "Using ChromeDriver version: "$CHROME_DRIVER_VERSION \ && wget --no-verbose -O /tmp/chromedriver_linux64.zip $CHROME_DRIVER_URL \ && rm -rf /opt/selenium/chromedriver \ - && sudo unzip /tmp/chromedriver_linux64.zip -d /opt/selenium \ + && unzip /tmp/chromedriver_linux64.zip -d /opt/selenium \ && rm /tmp/chromedriver_linux64.zip \ - && sudo mv /opt/selenium/chromedriver-linux64/chromedriver /opt/selenium/chromedriver-$CHROME_DRIVER_VERSION \ - && sudo chmod 755 /opt/selenium/chromedriver-$CHROME_DRIVER_VERSION \ + && mv /opt/selenium/chromedriver-linux64/chromedriver /opt/selenium/chromedriver-$CHROME_DRIVER_VERSION \ + && chmod 755 /opt/selenium/chromedriver-$CHROME_DRIVER_VERSION \ && sudo ln -fs /opt/selenium/chromedriver-$CHROME_DRIVER_VERSION /usr/bin/chromedriver #============================================ -# Dumping Browser name and version for config +# Dumping Browser information for config #============================================ RUN echo "chrome" > /opt/selenium/browser_name +RUN google-chrome --version | awk '{print $3}' > /opt/selenium/browser_version +RUN echo "\"goog:chromeOptions\": {\"binary\": \"/usr/bin/google-chrome\"}" > /opt/selenium/browser_binary_location diff --git a/NodeChromium/Dockerfile b/NodeChromium/Dockerfile index 93e6a9d360..85e10c1097 100644 --- a/NodeChromium/Dockerfile +++ b/NodeChromium/Dockerfile @@ -6,9 +6,16 @@ LABEL authors=${AUTHORS} USER root +#ENV LANGUAGE=en_US.UTF-8 +#ENV LC_ALL=en_US.UTF-8 +#ENV LANG=en_US.UTF-8 + +# Deal with the usr merge issues in Debian +#RUN apt install usrmerge + # Install Chromium # RUN echo "deb http://http.us.debian.org/debian/ stable non-free contrib main" >> /etc/apt/sources.list \ -RUN echo "deb http://deb.debian.org/debian/ sid main" >> /etc/apt/sources.list \ +RUN echo "deb http://deb.debian.org/debian/ bookworm main" >> /etc/apt/sources.list \ && apt-get update -qqy \ # && apt-get -qqy install chromium=89.0.4389.82-1 \ # && apt-get -qqy install chromium=90.0.4430.212-1 \ @@ -31,7 +38,9 @@ RUN apt-get update -qqy \ && apt-get -qqy install chromium-driver \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/* -RUN echo "chromium" > /opt/selenium/browser_name +RUN echo "chrome" > /opt/selenium/browser_name +RUN chromium --version | awk '{print $2}' > /opt/selenium/browser_version +RUN echo "\"goog:chromeOptions\": {\"binary\": \"/usr/bin/chromium\"}" > /opt/selenium/browser_binary_location USER 1200 diff --git a/NodeDocker/config.toml b/NodeDocker/config.toml index e15b1e5e6d..bfe4bd0713 100644 --- a/NodeDocker/config.toml +++ b/NodeDocker/config.toml @@ -2,9 +2,9 @@ # Configs have a mapping between the Docker image to use and the capabilities that need to be matched to # start a container with the given image. configs = [ - "selenium/standalone-firefox:4.12.1-20230920", '{"browserName": "firefox", "platformName": "linux"}', - "selenium/standalone-chrome:4.12.1-20230920", '{"browserName": "chrome", "platformName": "linux"}', - "selenium/standalone-edge:4.12.1-20230920", '{"browserName": "MicrosoftEdge", "platformName": "linux"}' + "selenium/standalone-firefox:4.16.0-20231206", '{"browserName": "firefox", "platformName": "linux"}', + "selenium/standalone-chrome:4.16.0-20231206", '{"browserName": "chrome", "platformName": "linux"}', + "selenium/standalone-edge:4.16.0-20231206", '{"browserName": "MicrosoftEdge", "platformName": "linux"}' ] # URL for connecting to the docker daemon @@ -14,7 +14,7 @@ configs = [ # socat -4 TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/docker.sock url = "http://127.0.0.1:2375" # Docker image used for video recording -video-image = "selenium/video:ffmpeg-4.3.1-20230920" +video-image = "selenium/video:ffmpeg-6.1-20231206" # Uncomment the following section if you are running the node on a separate VM # Fill out the placeholders with appropriate values diff --git a/NodeDocker/start-selenium-grid-docker.sh b/NodeDocker/start-selenium-grid-docker.sh index 760c34a853..0220a1ec96 100755 --- a/NodeDocker/start-selenium-grid-docker.sh +++ b/NodeDocker/start-selenium-grid-docker.sh @@ -29,20 +29,21 @@ if [ ! -z "$SE_NODE_GRID_URL" ]; then SE_GRID_URL="--grid-url ${SE_NODE_GRID_URL}" fi -EXTRA_LIBS="/opt/selenium/selenium-http-jdk-client.jar" +EXTRA_LIBS="" if [ ! -z "$SE_ENABLE_TRACING" ]; then EXTERNAL_JARS=$(/dev/null \ && echo "deb https://packages.microsoft.com/repos/edge stable main" >> /etc/apt/sources.list.d/microsoft-edge.list \ && apt-get update -qqy \ && apt-get -qqy install ${EDGE_VERSION} \ @@ -26,8 +26,6 @@ RUN wget -q -O - https://packages.microsoft.com/keys/microsoft.asc | apt-key add COPY wrap_edge_binary /opt/bin/wrap_edge_binary RUN /opt/bin/wrap_edge_binary -USER 1200 - #============================================ # Edge webdriver #============================================ @@ -46,9 +44,13 @@ RUN if [ -z "$EDGE_DRIVER_VERSION" ]; \ && rm /tmp/msedgedriver_linux64.zip \ && mv /opt/selenium/msedgedriver /opt/selenium/msedgedriver-$EDGE_DRIVER_VERSION \ && chmod 755 /opt/selenium/msedgedriver-$EDGE_DRIVER_VERSION \ - && sudo ln -fs /opt/selenium/msedgedriver-$EDGE_DRIVER_VERSION /usr/bin/msedgedriver + && ln -fs /opt/selenium/msedgedriver-$EDGE_DRIVER_VERSION /usr/bin/msedgedriver + +USER 1200 #============================================ -# Dumping Browser name and version for config +# Dumping Browser information for config #============================================ RUN echo "MicrosoftEdge" > /opt/selenium/browser_name +RUN microsoft-edge --version | awk '{print $3}' > /opt/selenium/browser_version +RUN echo "\"ms:edgeOptions\": {\"binary\": \"/usr/bin/microsoft-edge\"}" > /opt/selenium/browser_binary_location diff --git a/NodeFirefox/Dockerfile b/NodeFirefox/Dockerfile index 0590f1678c..e79f641be3 100644 --- a/NodeFirefox/Dockerfile +++ b/NodeFirefox/Dockerfile @@ -12,10 +12,10 @@ USER root ARG FIREFOX_VERSION=latest RUN FIREFOX_DOWNLOAD_URL=$(if [ $FIREFOX_VERSION = "latest" ] || [ $FIREFOX_VERSION = "beta-latest" ] || [ $FIREFOX_VERSION = "nightly-latest" ] || [ $FIREFOX_VERSION = "devedition-latest" ] || [ $FIREFOX_VERSION = "esr-latest" ]; then echo "https://download.mozilla.org/?product=firefox-$FIREFOX_VERSION-ssl&os=linux64&lang=en-US"; else echo "https://download-installer.cdn.mozilla.net/pub/firefox/releases/$FIREFOX_VERSION/linux-x86_64/en-US/firefox-$FIREFOX_VERSION.tar.bz2"; fi) \ && apt-get update -qqy \ - && apt-get -qqy --no-install-recommends install firefox libavcodec-extra \ + && apt-get -qqy --no-install-recommends install libavcodec-extra \ + libgtk-3-dev libdbus-glib-1-dev \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/* \ && wget --no-verbose -O /tmp/firefox.tar.bz2 $FIREFOX_DOWNLOAD_URL \ - && apt-get -y purge firefox \ && rm -rf /opt/firefox \ && tar -C /opt -xjf /tmp/firefox.tar.bz2 \ && rm /tmp/firefox.tar.bz2 \ @@ -36,9 +36,21 @@ RUN GK_VERSION=$(if [ ${GECKODRIVER_VERSION:-latest} = "latest" ]; then echo "0. && chmod 755 /opt/geckodriver-$GK_VERSION \ && ln -fs /opt/geckodriver-$GK_VERSION /usr/bin/geckodriver +# Workaround for issue launch Firefox Webdriver "Failed to read marionette port" +RUN mkdir -p /home/seluser/.cache /home/seluser/.mozilla /.cache \ + && chmod 777 /home/seluser/.cache /home/seluser/.mozilla /.cache + USER 1200 +RUN if ! whoami &> /dev/null; then \ + if [ -w /tmp/passwd ]; then \ + echo "${USER_NAME:-default}:x:$(id -u):0:${USER_NAME:-default} user:/home/seluser:/tmp:/bin/bash" >> /tmp/passwd; \ + fi \ +fi + #============================================ -# Dumping Browser name and version for config +# Dumping Browser information for config #============================================ RUN echo "firefox" > /opt/selenium/browser_name +RUN firefox --version | awk '{print $3}' > /opt/selenium/browser_version +RUN echo "\"moz:firefoxOptions\": {\"binary\": \"/usr/bin/firefox\"}" > /opt/selenium/browser_binary_location diff --git a/NodeFirefox/Dockerfile.multi-arch b/NodeFirefox/Dockerfile.multi-arch index ec549e640f..93e7b64c54 100644 --- a/NodeFirefox/Dockerfile.multi-arch +++ b/NodeFirefox/Dockerfile.multi-arch @@ -11,6 +11,9 @@ ARG GECKODRIVER_VERSION=0.33.0 USER root +# Deal with the usr merge issues in Debian +#RUN apt install usrmerge + #========= # Firefox #========= @@ -24,8 +27,9 @@ USER root RUN echo "deb http://deb.debian.org/debian/ sid main" >> /etc/apt/sources.list \ && apt-get update -qqy \ && apt-get install libavcodec-extra -y \ - && wget https://snapshot.debian.org/archive/debian/20230924T210045Z/pool/main/f/firefox/firefox_117.0.1-1_`dpkg --print-architecture`.deb -O firefox.deb \ - && apt install ./firefox.deb -y \ + && wget https://snapshot.debian.org/archive/debian/20231208T150859Z/pool/main/f/firefox/firefox_120.0.1-1_`dpkg --print-architecture`.deb -O firefox.deb + +RUN apt install ./firefox.deb -y \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/* ./firefox.deb #============= @@ -51,9 +55,11 @@ RUN if [ $TARGETARCH = "arm" ] && [ $TARGETVARIANT = "v7" ]; then \ rm /tmp/geckodriver.tar.gz ; \ mkdir -p /opt/geckodriver-bin ; \ mv /tmp/geckodriver /opt/geckodriver-bin/geckodriver ; \ - echo "Symlinking geckodriver to /usr/local/bin/geckodriver" ; \ + echo "Symlinking geckodriver to /usr/local/bin/geckodriver and /usr/bin/geckodriver" ; \ ln -s /opt/geckodriver-bin/geckodriver /usr/local/bin/geckodriver ; \ - chmod 755 /usr/local/bin/geckodriver + chmod 755 /usr/local/bin/geckodriver ; \ + ln -s /opt/geckodriver-bin/geckodriver /usr/bin/geckodriver ; \ + chmod 755 /usr/bin/geckodriver USER 1200 @@ -61,3 +67,5 @@ USER 1200 # Dumping Browser name and version for config #============================================ RUN echo "firefox" > /opt/selenium/browser_name +RUN firefox --version | awk '{print $3}' > /opt/selenium/browser_version +RUN echo "\"moz:firefoxOptions\": {\"binary\": \"/usr/bin/firefox\"}" > /opt/selenium/browser_binary_location diff --git a/README.md b/README.md index 12a4d86edd..ed3309820c 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ The project is made possible by volunteer contributors who have put in thousands and made the source code freely available under the [Apache License 2.0](LICENSE.md). These Docker images come with a handful of tags to simplify its usage, have a look at them in one of -our [releases](https://github.com/SeleniumHQ/docker-selenium/releases/tag/4.12.1-20230920). +our [releases](https://github.com/SeleniumHQ/docker-selenium/releases/tag/4.16.0-20231206). To get notifications of new releases, add yourself as a "Releases only" watcher. @@ -153,7 +153,7 @@ Talk to us at https://www.selenium.dev/support/ 1. Start a Docker container with Firefox ```bash -docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-firefox:4.12.1-20230920 +docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-firefox:4.16.0-20231206 ``` 2. Point your WebDriver tests to http://localhost:4444 @@ -340,17 +340,17 @@ For more information on the Dev and Beta channel container images, see the blog ![Firefox](https://raw.githubusercontent.com/alrra/browser-logos/main/src/firefox/firefox_24x24.png) Firefox ```bash -docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-firefox:4.12.1-20230920 +docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-firefox:4.16.0-20231206 ``` ![Chrome](https://raw.githubusercontent.com/alrra/browser-logos/main/src/chrome/chrome_24x24.png) Chrome ```bash -docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-chrome:4.12.1-20230920 +docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-chrome:4.16.0-20231206 ``` ![Edge](https://raw.githubusercontent.com/alrra/browser-logos/main/src/edge/edge_24x24.png) Edge ```bash -docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-edge:4.12.1-20230920 +docker run -d -p 4444:4444 --shm-size="2g" selenium/standalone-edge:4.16.0-20231206 ``` _Note: Only one Standalone container can run on port_ `4444` _at the same time._ @@ -369,44 +369,44 @@ A Docker [network](https://docs.docker.com/engine/reference/commandline/network_ ```bash $ docker network create grid -$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.12.1-20230920 +$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \ --shm-size="2g" \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ - selenium/node-chrome:4.12.1-20230920 + selenium/node-chrome:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \ --shm-size="2g" \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ - selenium/node-edge:4.12.1-20230920 + selenium/node-edge:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \ --shm-size="2g" \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ - selenium/node-firefox:4.12.1-20230920 + selenium/node-firefox:4.16.0-20231206 ``` ##### Windows PowerShell ```powershell $ docker network create grid -$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.12.1-20230920 +$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub ` --shm-size="2g" ` -e SE_EVENT_BUS_PUBLISH_PORT=4442 ` -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ` - selenium/node-chrome:4.12.1-20230920 + selenium/node-chrome:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub ` --shm-size="2g" ` -e SE_EVENT_BUS_PUBLISH_PORT=4442 ` -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ` - selenium/node-edge:4.12.1-20230920 + selenium/node-edge:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub ` --shm-size="2g" ` -e SE_EVENT_BUS_PUBLISH_PORT=4442 ` -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ` - selenium/node-firefox:4.12.1-20230920 + selenium/node-firefox:4.16.0-20231206 ``` When you are done using the Grid, and the containers have exited, the network can be removed with the following command: @@ -423,7 +423,7 @@ configured to expose different ports. ##### Hub - Machine/VM 1 ```bash -$ docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:4.12.1-20230920 +$ docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:4.16.0-20231206 ``` ##### Node Chrome - Machine/VM 2 @@ -437,7 +437,7 @@ $ docker run -d -p 5555:5555 \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ -e SE_NODE_HOST= \ - selenium/node-chrome:4.12.1-20230920 + selenium/node-chrome:4.16.0-20231206 ``` ###### Windows PowerShell @@ -449,7 +449,7 @@ $ docker run -d -p 5555:5555 ` -e SE_EVENT_BUS_PUBLISH_PORT=4442 ` -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ` -e SE_NODE_HOST= ` - selenium/node-chrome:4.12.1-20230920 + selenium/node-chrome:4.16.0-20231206 ``` @@ -464,7 +464,7 @@ $ docker run -d -p 5555:5555 \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ -e SE_NODE_HOST= \ - selenium/node-edge:4.12.1-20230920 + selenium/node-edge:4.16.0-20231206 ``` ###### Windows PowerShell @@ -476,7 +476,7 @@ $ docker run -d -p 5555:5555 ` -e SE_EVENT_BUS_PUBLISH_PORT=4442 ` -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ` -e SE_NODE_HOST= ` - selenium/node-edge:4.12.1-20230920 + selenium/node-edge:4.16.0-20231206 ``` ##### Node Firefox - Machine/VM 4 @@ -490,7 +490,7 @@ $ docker run -d -p 5555:5555 \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ -e SE_NODE_HOST= \ - selenium/node-firefox:4.12.1-20230920 + selenium/node-firefox:4.16.0-20231206 ``` ###### Windows PowerShell @@ -502,7 +502,7 @@ $ docker run -d -p 5555:5555 ` -e SE_EVENT_BUS_PUBLISH_PORT=4442 ` -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ` -e SE_NODE_HOST= ` - selenium/node-firefox:4.12.1-20230920 + selenium/node-firefox:4.16.0-20231206 ``` ##### Node Chrome - Machine/VM 4 @@ -517,7 +517,7 @@ $ docker run -d -p 5556:5556 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ -e SE_NODE_HOST= \ -e SE_NODE_PORT=5556 \ - selenium/node-chrome:4.12.1-20230920 + selenium/node-chrome:4.16.0-20231206 ``` ###### Windows PowerShell @@ -530,7 +530,7 @@ $ docker run -d -p 5556:5556 ` -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ` -e SE_NODE_HOST= ` -e SE_NODE_PORT=5556 ` - selenium/node-chrome:4.12.1-20230920 + selenium/node-chrome:4.16.0-20231206 ``` #### Docker Compose @@ -562,7 +562,7 @@ ___ ## Video recording -Tests execution can be recorded by using the `selenium/video:ffmpeg-4.3.1-20230920` +Tests execution can be recorded by using the `selenium/video:ffmpeg-6.1-20231206` Docker image. One container is needed per each container where a browser is running. This means if you are running 5 Nodes/Standalone containers, you will need 5 video containers, the mapping is 1-1. @@ -588,8 +588,8 @@ This example shows how to start the containers manually: ``` bash $ docker network create grid -$ docker run -d -p 4444:4444 -p 6900:5900 --net grid --name selenium --shm-size="2g" selenium/standalone-chrome:4.12.1-20230920 -$ docker run -d --net grid --name video -v /tmp/videos:/videos selenium/video:ffmpeg-4.3.1-20230920 +$ docker run -d -p 4444:4444 -p 6900:5900 --net grid --name selenium --shm-size="2g" selenium/standalone-chrome:4.16.0-20231206 +$ docker run -d --net grid --name video -v /tmp/videos:/videos selenium/video:ffmpeg-6.1-20231206 # Run your tests $ docker stop video && docker rm video $ docker stop selenium && docker rm selenium @@ -621,9 +621,9 @@ You can save this file locally and name it, for example, `config.toml`. # Configs have a mapping between the Docker image to use and the capabilities that need to be matched to # start a container with the given image. configs = [ - "selenium/standalone-firefox:4.12.1-20230920", '{"browserName": "firefox"}', - "selenium/standalone-chrome:4.12.1-20230920", '{"browserName": "chrome"}', - "selenium/standalone-edge:4.12.1-20230920", '{"browserName": "MicrosoftEdge"}' + "selenium/standalone-firefox:4.16.0-20231206", '{"browserName": "firefox"}', + "selenium/standalone-chrome:4.16.0-20231206", '{"browserName": "chrome"}', + "selenium/standalone-edge:4.16.0-20231206", '{"browserName": "MicrosoftEdge"}' ] # URL for connecting to the docker daemon @@ -636,7 +636,7 @@ configs = [ # Linux: varies from machine to machine, please mount /var/run/docker.sock. If this does not work, please create an issue. url = "http://127.0.0.1:2375" # Docker image used for video recording -video-image = "selenium/video:ffmpeg-4.3.1-20230920" +video-image = "selenium/video:ffmpeg-6.1-20231206" # Uncomment the following section if you are running the node on a separate VM # Fill out the placeholders with appropriate values @@ -655,28 +655,28 @@ virtual machines. ```bash $ docker network create grid -$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.12.1-20230920 +$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ -v ${PWD}/config.toml:/opt/bin/config.toml \ -v ${PWD}/assets:/opt/selenium/assets \ -v /var/run/docker.sock:/var/run/docker.sock \ - selenium/node-docker:4.12.1-20230920 + selenium/node-docker:4.16.0-20231206 ``` #### Windows PowerShell ```powershell $ docker network create grid -$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.12.1-20230920 +$ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub ` -e SE_EVENT_BUS_PUBLISH_PORT=4442 ` -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 ` -v ${PWD}/config.toml:/opt/bin/config.toml ` -v ${PWD}/assets:/opt/selenium/assets ` -v /var/run/docker.sock:/var/run/docker.sock ` - selenium/node-docker:4.12.1-20230920 + selenium/node-docker:4.16.0-20231206 ``` To have the assets saved on your host, please mount your host path to `/opt/selenium/assets`. @@ -697,7 +697,7 @@ docker run --rm --name selenium-docker -p 4444:4444 \ -v ${PWD}/config.toml:/opt/bin/config.toml \ -v ${PWD}/assets:/opt/selenium/assets \ -v /var/run/docker.sock:/var/run/docker.sock \ - selenium/standalone-docker:4.12.1-20230920 + selenium/standalone-docker:4.16.0-20231206 ``` #### Windows PowerShell @@ -707,7 +707,7 @@ docker run --rm --name selenium-docker -p 4444:4444 ` -v ${PWD}/config.toml:/opt/bin/config.toml ` -v ${PWD}/assets:/opt/selenium/assets ` -v /var/run/docker.sock:/var/run/docker.sock ` - selenium/standalone-docker:4.12.1-20230920 + selenium/standalone-docker:4.16.0-20231206 ``` ### Using Dynamic Grid in different machines/VMs @@ -715,7 +715,7 @@ docker run --rm --name selenium-docker -p 4444:4444 ` #### Hub - Machine/VM 1 ```bash -$ docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:4.12.1-20230920 +$ docker run -d -p 4442-4444:4442-4444 --name selenium-hub selenium/hub:4.16.0-20231206 ``` #### Node Chrome - Machine/VM 2 @@ -730,7 +730,7 @@ $ docker run -d -p 5555:5555 \ -v ${PWD}/config.toml:/opt/bin/config.toml \ -v ${PWD}/assets:/opt/selenium/assets \ -v /var/run/docker.sock:/var/run/docker.sock \ - selenium/node-docker:4.12.1-20230920 + selenium/node-docker:4.16.0-20231206 ``` #### Windows PowerShell @@ -743,7 +743,7 @@ $ docker run -d -p 5555:5555 ` -v ${PWD}/config.toml:/opt/bin/config.toml ` -v ${PWD}/assets:/opt/selenium/assets ` -v /var/run/docker.sock:/var/run/docker.sock ` - selenium/node-docker:4.12.1-20230920 + selenium/node-docker:4.16.0-20231206 ``` Complete the `[server]` section in the `config.toml` file. @@ -752,9 +752,9 @@ Complete the `[server]` section in the `config.toml` file. # Configs have a mapping between the Docker image to use and the capabilities that need to be matched to # start a container with the given image. configs = [ - "selenium/standalone-firefox:4.12.1-20230920", "{\"browserName\": \"firefox\"}", - "selenium/standalone-chrome:4.12.1-20230920", "{\"browserName\": \"chrome\"}", - "selenium/standalone-edge:4.12.1-20230920", "{\"browserName\": \"MicrosoftEdge\"}" + "selenium/standalone-firefox:4.16.0-20231206", "{\"browserName\": \"firefox\"}", + "selenium/standalone-chrome:4.16.0-20231206", "{\"browserName\": \"chrome\"}", + "selenium/standalone-edge:4.16.0-20231206", "{\"browserName\": \"MicrosoftEdge\"}" ] # URL for connecting to the docker daemon @@ -767,7 +767,7 @@ configs = [ # Linux: varies from machine to machine, please mount /var/run/docker.sock. If this does not work, please create an issue. url = "http://127.0.0.1:2375" # Docker image used for video recording -video-image = "selenium/video:ffmpeg-4.3.1-20230920" +video-image = "selenium/video:ffmpeg-6.1-20231206" # Uncomment the following section if you are running the node on a separate VM # Fill out the placeholders with appropriate values @@ -801,7 +801,7 @@ docker run --rm --name selenium-docker -p 4444:4444 \ -v ${PWD}/config.toml:/opt/bin/config.toml \ -v ${PWD}/assets:/opt/selenium/assets \ -v /var/run/docker.sock:/var/run/docker.sock \ - selenium/standalone-docker:4.12.1-20230920 + selenium/standalone-docker:4.16.0-20231206 ``` #### Windows PowerShell @@ -812,7 +812,7 @@ docker run --rm --name selenium-docker -p 4444:4444 ` -v ${PWD}/config.toml:/opt/bin/config.toml ` -v ${PWD}/assets:/opt/selenium/assets ` -v /var/run/docker.sock:/var/run/docker.sock ` - selenium/standalone-docker:4.12.1-20230920 + selenium/standalone-docker:4.16.0-20231206 ``` @@ -850,7 +850,7 @@ ___ You can pass `SE_OPTS` variable with additional command line parameters for starting a hub or a node. ``` bash -$ docker run -d -p 4444:4444 -e SE_OPTS="--log-level FINE" --name selenium-hub selenium/hub:4.12.1-20230920 +$ docker run -d -p 4444:4444 -e SE_OPTS="--log-level FINE" --name selenium-hub selenium/hub:4.16.0-20231206 ``` ### SE_JAVA_OPTS Java Environment Options @@ -858,7 +858,7 @@ $ docker run -d -p 4444:4444 -e SE_OPTS="--log-level FINE" --name selenium-hub s You can pass `SE_JAVA_OPTS` environment variable to the Java process. ``` bash -$ docker run -d -p 4444:4444 -e SE_JAVA_OPTS=-Xmx512m --name selenium-hub selenium/hub:4.12.1-20230920 +$ docker run -d -p 4444:4444 -e SE_JAVA_OPTS=-Xmx512m --name selenium-hub selenium/hub:4.16.0-20231206 ``` ### Node configuration options @@ -880,7 +880,7 @@ $ docker run -d \ -e SE_EVENT_BUS_HOST= \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 -e SE_NODE_STEREOTYPE="{\"browserName\":\"${SE_NODE_BROWSER_NAME}\",\"browserVersion\":\"${SE_NODE_BROWSER_VERSION}\",\"platformName\": \"Linux\"}" \ - --shm-size="2g" selenium/node-chrome:4.12.1-20230920 + --shm-size="2g" selenium/node-chrome:4.16.0-20231206 ``` ### Setting Sub Path @@ -899,7 +899,7 @@ These settings can be adjusted by specifying `SE_SCREEN_WIDTH`, `SE_SCREEN_HEIGH environmental variables when starting the container. ``` bash -docker run -d -e SE_SCREEN_WIDTH=1366 -e SE_SCREEN_HEIGHT=768 -e SE_SCREEN_DEPTH=24 -e SE_SCREEN_DPI=74 selenium/standalone-firefox:4.12.1-20230920 +docker run -d -e SE_SCREEN_WIDTH=1366 -e SE_SCREEN_HEIGHT=768 -e SE_SCREEN_DEPTH=24 -e SE_SCREEN_DPI=74 selenium/standalone-firefox:4.16.0-20231206 ``` ### Grid Url and Session Timeout @@ -949,7 +949,7 @@ To avoid starting the server you can set the `START_XVFB` environment variable t ``` bash $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ - -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 -e START_XVFB=false --shm-size="2g" selenium/node-chrome:4.12.1-20230920 + -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 -e START_XVFB=false --shm-size="2g" selenium/node-chrome:4.16.0-20231206 ``` For more information, see this GitHub [issue](https://github.com/SeleniumHQ/docker-selenium/issues/567). @@ -962,7 +962,7 @@ pod and then scale a new one after N sessions. Set the environment variable `SE_ a value higher than zero to enable this behaviour. ``` bash -$ docker run -e SE_DRAIN_AFTER_SESSION_COUNT=5 --shm-size="2g" selenium/standalone-firefox:4.12.1-20230920 +$ docker run -e SE_DRAIN_AFTER_SESSION_COUNT=5 --shm-size="2g" selenium/standalone-firefox:4.16.0-20231206 ``` With the previous command, the Standalone container will shut down after 5 sessions have been executed. @@ -1054,22 +1054,22 @@ $ docker network create grid $ docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub \ --health-cmd='/opt/bin/check-grid.sh --host 0.0.0.0 --port 4444' \ --health-interval=15s --health-timeout=30s --health-retries=5 \ - selenium/hub:4.12.1-20230920 + selenium/hub:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \ --shm-size="2g" \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ - selenium/node-chrome:4.12.1-20230920 + selenium/node-chrome:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \ --shm-size="2g" \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ - selenium/node-edge:4.12.1-20230920 + selenium/node-edge:4.16.0-20231206 $ docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \ --shm-size="2g" \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ - selenium/node-firefox:4.12.1-20230920 + selenium/node-firefox:4.16.0-20231206 ``` **Note:** The `\` line delimiter won't work on Windows-based terminals, try either `^` or a backtick. @@ -1202,7 +1202,7 @@ RUN mkdir -p -m755 /seluser/.pki/nssdb \ && chown -R 1200:1201 /seluser # Start from Selenium image and add relevant files from build image -FROM selenium/node-chrome:4.12.1-20230920 +FROM selenium/node-chrome:4.16.0-20231206 USER root COPY --from=build /seluser/ /home/seluser/ USER seluser @@ -1217,7 +1217,7 @@ RUN mkdir -p "/distribution" "/certs" && \ echo '{ "policies": { "Certificates": { "Install": ["/opt/firefox-latest/YOUR_CA.pem"] }} }' >"/distribution/policies.json" # Start from Selenium image and add relevant files from build image -FROM selenium/node-firefox:4.12.1-20230920 +FROM selenium/node-firefox:4.16.0-20231206 USER root COPY --from=build /certs /opt/firefox-latest COPY --from=build /distribution /opt/firefox-latest/distribution @@ -1240,9 +1240,9 @@ You can override it with the `SE_VNC_PORT` environment variable in case you want Here is an example with the standalone images, the same concept applies to the node images. ``` bash -$ docker run -d -p 4444:4444 -p 5900:5900 --shm-size="2g" selenium/standalone-chrome:4.12.1-20230920 -$ docker run -d -p 4445:4444 -p 5901:5900 --shm-size="2g" selenium/standalone-edge:4.12.1-20230920 -$ docker run -d -p 4446:4444 -p 5902:5900 --shm-size="2g" selenium/standalone-firefox:4.12.1-20230920 +$ docker run -d -p 4444:4444 -p 5900:5900 --shm-size="2g" selenium/standalone-chrome:4.16.0-20231206 +$ docker run -d -p 4445:4444 -p 5901:5900 --shm-size="2g" selenium/standalone-edge:4.16.0-20231206 +$ docker run -d -p 4446:4444 -p 5902:5900 --shm-size="2g" selenium/standalone-firefox:4.16.0-20231206 ``` Then, you would use in your VNC client: @@ -1268,9 +1268,9 @@ You can also override it with the `SE_NO_VNC_PORT` environment variable in case Here is an example with the standalone images, the same concept applies to the node images. ``` bash -$ docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-chrome:4.12.1-20230920 -$ docker run -d -p 4445:4444 -p 7901:7900 --shm-size="2g" selenium/standalone-edge:4.12.1-20230920 -$ docker run -d -p 4446:4444 -p 7902:7900 --shm-size="2g" selenium/standalone-firefox:4.12.1-20230920 +$ docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-chrome:4.16.0-20231206 +$ docker run -d -p 4445:4444 -p 7901:7900 --shm-size="2g" selenium/standalone-edge:4.16.0-20231206 +$ docker run -d -p 4446:4444 -p 7902:7900 --shm-size="2g" selenium/standalone-firefox:4.16.0-20231206 ``` Then, you would use in your browser: @@ -1295,28 +1295,28 @@ In order to enable tracing in the Selenium Grid container, the following command ```bash docker network create grid docker run -d -p 16686:16686 -p 14250:14250 --net grid --name jaeger jaegertracing/all-in-one:1.17 -docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.12.1-20230920 +docker run -d -p 4442-4444:4442-4444 --net grid --name selenium-hub selenium/hub:4.16.0-20231206 docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \ --shm-size="2g" \ -e SE_ENABLE_TRACING=true \ - -e JAVA_OPTS="-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-hub" \ + -e JAVA_OPTS="-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-node-chrome" \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ - selenium/node-chrome:4.12.1-20230920 + selenium/node-chrome:4.16.0-20231206 docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \ --shm-size="2g" \ -e SE_ENABLE_TRACING=true \ -e JAVA_OPTS="-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-node-edge" \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ - selenium/node-edge:4.12.1-20230920 + selenium/node-edge:4.16.0-20231206 docker run -d --net grid -e SE_EVENT_BUS_HOST=selenium-hub \ --shm-size="2g" \ -e SE_ENABLE_TRACING=true \ -e JAVA_OPTS="-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-node-firefox" \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ - selenium/node-firefox:4.12.1-20230920 + selenium/node-firefox:4.16.0-20231206 ``` You can also refer to the below docker-compose yaml files to be able to start a simple grid (or) a dynamic grid. @@ -1376,7 +1376,7 @@ container in the following way: ```bash docker run -d -p 4444:4444 --shm-size="2g" \ -v /home/ubuntu/files:/home/seluser/files \ - selenium/standalone-chrome:4.12.1-20230920 + selenium/standalone-chrome:4.16.0-20231206 ``` That will mount the host `/home/ubuntu/files` directory diff --git a/Router/start-selenium-grid-router.sh b/Router/start-selenium-grid-router.sh index b99f675e53..1c3103dfc6 100755 --- a/Router/start-selenium-grid-router.sh +++ b/Router/start-selenium-grid-router.sh @@ -54,20 +54,21 @@ if [ ! -z "$SE_ROUTER_PORT" ]; then PORT_CONFIG="--port ${SE_ROUTER_PORT}" fi -EXTRA_LIBS="/opt/selenium/selenium-http-jdk-client.jar" +EXTRA_LIBS="" if [ ! -z "$SE_ENABLE_TRACING" ]; then EXTERNAL_JARS=$(> "$FILENAME" SE_NODE_BROWSER_NAME=$(cat /opt/selenium/browser_name) -if [[ "${SE_NODE_BROWSER_NAME}" == "chrome" ]]; then - SE_NODE_BROWSER_VERSION=$(short_version $(google-chrome --version | awk '{print $3}')) -elif [[ "${SE_NODE_BROWSER_NAME}" == "chromium" ]]; then - SE_NODE_BROWSER_NAME=chrome - SE_NODE_BROWSER_VERSION=$(short_version $(chromium --version | awk '{print $2}')) -elif [[ "${SE_NODE_BROWSER_NAME}" == "firefox" ]]; then - SE_NODE_BROWSER_VERSION=$(short_version $(firefox --version | awk '{print $3}')) -elif [[ "${SE_NODE_BROWSER_NAME}" == "MicrosoftEdge" ]]; then - SE_NODE_BROWSER_VERSION=$(short_version $(microsoft-edge --version | awk '{print $3}')) +SE_NODE_BROWSER_VERSION=$(short_version $(cat /opt/selenium/browser_version)) +SE__BROWSER_BINARY_LOCATION=$(cat /opt/selenium/browser_binary_location) + +if [[ -z "$SE_NODE_STEREOTYPE" ]]; then +SE_NODE_STEREOTYPE="{\"browserName\": \"${SE_NODE_BROWSER_NAME}\", \"browserVersion\": \"${SE_NODE_BROWSER_VERSION}\", \"platformName\": \"Linux\", ${SE__BROWSER_BINARY_LOCATION}}" +else +SE_NODE_STEREOTYPE="$SE_NODE_STEREOTYPE" fi -SE_NODE_STEREOTYPE="{\"browserName\": \"${SE_NODE_BROWSER_NAME}\", \"browserVersion\": \"${SE_NODE_BROWSER_VERSION}\", \"platformName\": \"Linux\"}" echo "[[node.driver-configuration]]" >> "$FILENAME" echo "display-name = \"${SE_NODE_BROWSER_NAME}\"" >> "$FILENAME" echo "stereotype = '${SE_NODE_STEREOTYPE}'" >> "$FILENAME" diff --git a/Standalone/start-selenium-standalone.sh b/Standalone/start-selenium-standalone.sh index 7af58b6e8b..cfde62d8eb 100755 --- a/Standalone/start-selenium-standalone.sh +++ b/Standalone/start-selenium-standalone.sh @@ -17,21 +17,29 @@ echo "Selenium Grid Standalone configuration: " cat /opt/selenium/config.toml echo "Starting Selenium Grid Standalone..." -EXTRA_LIBS="/opt/selenium/selenium-http-jdk-client.jar" +EXTRA_LIBS="" if [ ! -z "$SE_ENABLE_TRACING" ]; then EXTERNAL_JARS=$( /etc/apt/sources.list \ - && echo "deb http://archive.ubuntu.com/ubuntu focal-updates main universe\n" >> /etc/apt/sources.list \ - && echo "deb http://security.ubuntu.com/ubuntu focal-security main universe\n" >> /etc/apt/sources.list +RUN echo "deb http://archive.ubuntu.com/ubuntu jammy main universe\n" > /etc/apt/sources.list \ + && echo "deb http://archive.ubuntu.com/ubuntu jammy-updates main universe\n" >> /etc/apt/sources.list \ + && echo "deb http://security.ubuntu.com/ubuntu jammy-security main universe\n" >> /etc/apt/sources.list # No interactive frontend during docker build ENV DEBIAN_FRONTEND=noninteractive \ @@ -18,7 +20,10 @@ ENV DEBIAN_FRONTEND=noninteractive \ RUN apt-get -qqy update \ && apt-get upgrade -yq \ && apt-get -qqy --no-install-recommends install \ - supervisor x11-xserver-utils python3-pip \ + supervisor x11-xserver-utils x11-utils curl jq python3-pip \ + && python3 -m pip install --upgrade pip \ + && python3 -m pip install --upgrade setuptools \ + && python3 -m pip install --upgrade wheel \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/* #====================================== @@ -28,7 +33,8 @@ COPY supervisord.conf /etc COPY entry_point.sh video.sh video_ready.py /opt/bin/ RUN cd /opt/bin && pip install psutil -RUN mkdir -p /var/run/supervisor /var/log/supervisor /videos +ENV SE_VIDEO_FOLDER /videos +RUN mkdir -p /var/run/supervisor /var/log/supervisor $SE_VIDEO_FOLDER ENTRYPOINT ["/opt/bin/entry_point.sh"] CMD ["/opt/bin/entry_point.sh"] @@ -41,6 +47,5 @@ ENV SE_FRAME_RATE 15 ENV SE_CODEC libx264 ENV SE_PRESET "-preset ultrafast" ENV FILE_NAME video.mp4 -ENV SE_VIDEO_FOLDER /videos EXPOSE 9000 diff --git a/Video/supervisord.conf b/Video/supervisord.conf index 68d42b8a21..84b7d6ae2f 100644 --- a/Video/supervisord.conf +++ b/Video/supervisord.conf @@ -10,6 +10,7 @@ pidfile=/var/run/supervisor/supervisord.pid ; (supervisord pidfile;default sup nodaemon=true ; (start in foreground if true;default false) minfds=1024 ; (min. avail startup file descriptors;default 1024) minprocs=200 ; (min. avail process descriptors;default 200) +user=root ; (default is current user, required if root) [program:video-recording] priority=0 diff --git a/build-and-push.sh b/build-and-push.sh index 9f237fc8e5..82f960b2d2 100644 --- a/build-and-push.sh +++ b/build-and-push.sh @@ -1,6 +1,6 @@ #!/bin/bash -SELENIUM_VERSION=$(grep selenium-server Base/Dockerfile | sed 's/.*-\([^-]*\)\.jar \\/\1/' | head -n 1) +#SELENIUM_VERSION=$(grep selenium-server Base/Dockerfile | sed 's/.*-\([^-]*\)\.jar \\/\1/' | head -n 1) NAME="${NAME:-seleniarm}" VERSION="${VERSION:-$SELENIUM_VERSION}" BUILD_DATE="${BUILD_DATE:-$(date '+%Y%m%d')}" @@ -19,7 +19,7 @@ docker run --rm --privileged aptman/qus -- -r docker run --rm --privileged aptman/qus -s -- -p if [ "$1" = "base_multi" ]; then - cd ./Base && docker buildx build --platform ${PLATFORMS} ${BUILD_ARGS} -t ${NAME}/base:${TAG_VERSION} . + cd ./Base && docker buildx build --platform ${PLATFORMS} ${BUILD_ARGS} --build-arg RELEASE=${RELEASE} --build-arg VERSION=${VERSION} -t ${NAME}/base:${TAG_VERSION} . elif [ "$1" = "grid_multi" ]; then cd ./Hub && docker buildx build --platform ${PLATFORMS} ${BUILD_ARGS} ${FROM_IMAGE_ARGS} -t ${NAME}/hub:${TAG_VERSION} . diff --git a/charts/selenium-grid/.helmignore b/charts/selenium-grid/.helmignore index 0e8a0eb36f..5bdaa3eb0d 100644 --- a/charts/selenium-grid/.helmignore +++ b/charts/selenium-grid/.helmignore @@ -21,3 +21,4 @@ .idea/ *.tmproj .vscode/ +ci/ diff --git a/charts/selenium-grid/CHANGELOG.md b/charts/selenium-grid/CHANGELOG.md index 32a81cbfb7..4f3e5f4058 100644 --- a/charts/selenium-grid/CHANGELOG.md +++ b/charts/selenium-grid/CHANGELOG.md @@ -2,6 +2,73 @@ All notable changes to this helm chart will be documented in this file. +## :heavy_check_mark: 0.25.3 + +### Changed +- Update image tag to 4.16.0-20231206 +- Update tag in docs and files :: Selenium CI Bot +- test: Add sanity test for download file (#2034) [deploy] :: Viet Nguyen Duc +- feat(chart): distribution registry can be set global and individual component (#2030) :: Viet Nguyen Duc +- Update tag in docs and files [skip ci] :: Selenium CI Bot +- test: Sanity tests Selenium Grid chart via Makefile commands (#2029) :: Viet Nguyen Duc +- Feature run selenium tests grid on kubernetes via helm chart (#2027) :: Amar Deep Singh +- feat: CI Bot bump chart version along with new deploy image version (#2028) :: Viet Nguyen Duc +- Update NodeChrome support latest version from GoogleChromeLabs (#2018) :: Viet Nguyen Duc +- Update tag in docs and files [skip ci] :: Selenium CI Bot +- corrected typo in selenium grid charts (#2010) :: Thabelo Ramabulana + +## :heavy_check_mark: 0.25.1 + +### Changed +- Update image tag to 4.15.0-20231110 +- Bug: Error setting name in helm release #2006 #2007 (#2009) :: Viet Nguyen Duc + +## :heavy_check_mark: 0.25.0 + +### Changed +- Update image tag to 4.15.0-20231110 +- feat(helm-test): Added helm test and linting (#2003) :: Amar Deep Singh +- Update tag in docs and files [skip ci] :: Selenium CI Bot +- Update tag in docs and files [skip ci] :: Selenium CI Bot +- feat: Adding port to nodes service (#1996) :: Viet Nguyen Duc + +## :heavy_check_mark: 0.24.0 + +### Changed +- Update image tag to 4.15.0-20231102 +- Bumping chart version :: Viet Nguyen Duc +- Add chart parameter ingress.paths to configure custom paths (#1994) :: Viet Nguyen Duc +- feat(autoscaling): Unified parameters to set scaled options for browser nodes (#1989) :: Viet Nguyen Duc +- Update tag in docs and files [skip ci] :: Selenium CI Bot +- Improve chart templates in the section videoRecorder (#1987) :: Viet Nguyen Duc +- Improve default value for videoRecorder in chart (#1984) :: Viet Nguyen Duc +- Fix minor issues after PR #1881 and #1981 (#1983) :: Viet Nguyen Duc + +## :heavy_check_mark: 0.23.0 + +### Added + +- Update tag in docs and files [skip ci] :: Selenium CI Bot +- feat: video recording with pluggable upload container (#1881) :: MÃ¥rten Svantesson +- Update Video/Dockerfile with based image ffmpeg:6.0-alpine (#1981) :: Viet Nguyen Duc + +### Changed +- Update image tag to 4.14.1-20231025 + +## :heavy_check_mark: 0.22.0 + +### Added +- feat(keda): bumped up keda 2.12.0 (#1960) :: Amar Deep Singh +- Add missing Ingress namespace field (#1966) :: Cody Lent + +### Changed +- Update image tag to 4.13.0-20231004 + +## :heavy_check_mark: 0.21.3 + +### Changed +- Update image tag to 4.13.0-20230926 + ## :heavy_check_mark: 0.21.2 ### Changed diff --git a/charts/selenium-grid/Chart.yaml b/charts/selenium-grid/Chart.yaml index 3835c24453..a3e55bf716 100644 --- a/charts/selenium-grid/Chart.yaml +++ b/charts/selenium-grid/Chart.yaml @@ -2,11 +2,16 @@ apiVersion: v2 name: selenium-grid description: A Helm chart for creating a Selenium Grid Server in Kubernetes type: application -version: 0.21.2 -appVersion: 4.12.1-20230920 +version: 0.26.0 +appVersion: 4.16.0-20231206 icon: https://github.com/SeleniumHQ/docker-selenium/raw/trunk/logo.png dependencies: - repository: https://kedacore.github.io/charts - version: 2.10.2 + version: 2.12.0 name: keda condition: autoscaling.enabled +maintainers: + - name: SeleniumHQ + email: selenium-developers@googlegroups.com +sources: + - https://github.com/SeleniumHQ/docker-selenium diff --git a/charts/selenium-grid/README.md b/charts/selenium-grid/README.md index 2d77ce9fae..9fb0945079 100644 --- a/charts/selenium-grid/README.md +++ b/charts/selenium-grid/README.md @@ -27,20 +27,22 @@ helm install selenium-grid docker-selenium/selenium-grid --version # In both cases grid exposed by default using ingress. You may want to set hostname for the grid. Default hostname is selenium-grid.local. helm install selenium-grid --set ingress.hostname=selenium-grid.k8s.local docker-selenium/chart/selenium-grid/. +# Verify ingress configuration via kubectl get ingress +# Notes: In case you want to set hostname is selenium-grid.local. You need to add the IP and hostname to the local host file in `/etc/hosts` ``` ## Enable Selenium Grid Autoscaling -Selenium Grid has the ability to autoscale browser nodes up/down based on the pending requests in the +Selenium Grid has the ability to autoscaling browser nodes up/down based on the pending requests in the session queue. -To do this [KEDA](https://keda.sh/docs/2.10/scalers/selenium-grid-scaler/) is used. When enabling +To do this [KEDA](https://keda.sh/docs/latest/scalers/selenium-grid-scaler/) is used. When enabling autoscaling using `autoscaling.enabling` KEDA is installed automatically. To instead use an existing installation of KEDA you can enable autoscaling with `autoscaling.enableWithExistingKEDA` instead. KEDA can scale either with -[deployments](https://keda.sh/docs/2.10/concepts/scaling-deployments/#scaling-of-deployments-and-statefulsets) -or [jobs](https://keda.sh/docs/2.10/concepts/scaling-jobs/) and the charts support both types. This +[deployments](https://keda.sh/docs/latest/concepts/scaling-deployments/#scaling-of-deployments-and-statefulsets) +or [jobs](https://keda.sh/docs/latest/concepts/scaling-jobs/) and the charts support both types. This chart support both modes. It is controlled with `autoscaling.scalingType` that can be set to either job (default) or deployment. @@ -77,151 +79,248 @@ To uninstall: helm uninstall selenium-grid ``` +## Ingress Configuration + +By default, ingress is enabled without annotations set. If NGINX ingress controller is used, you need to set few annotations to override the default timeout values to avoid 504 errors (see #1808). Since in Selenium Grid the default of `SE_NODE_SESSION_TIMEOUT` and `SE_SESSION_REQUEST_TIMEOUT` is `300` seconds. + +In order to make user experience better, there are few annotations will be set by default if NGINX ingress controller is used. Mostly relates to timeouts and buffer sizes. + +If you are not using NGINX ingress controller, you can disable these default annotations by setting `ingress.nginx` to `nil` (aka null) via Helm CLI `--set ingress.nginx=null`) or via an override-values.yaml as below: + +```yaml +ingress: + nginx: + # nginx: null (alternative way) +``` + +Similarly, if you want to disable a sub-config of `ingress.nginx`. For example: `--set ingress.nginx.proxyBuffer=null`) + +You are also able to combine using both default annotations and your own annotations in `ingress.annotations`. Duplicated keys will be merged strategy overwrite with your own annotations in `ingress.annotations` take precedence. + +```yaml +ingress: + nginx: + proxyTimeout: 3600 + annotations: + nginx.ingress.kubernetes.io/proxy-connect-timeout: "7200" # This key will take 7200 instead of 3600 +``` + +List mapping of chart values and default annotation(s) + +```markdown +# `ingress.nginx.proxyTimeout` pass value to annotation(s) +nginx.ingress.kubernetes.io/proxy-connect-timeout +nginx.ingress.kubernetes.io/proxy-send-timeout +nginx.ingress.kubernetes.io/proxy-read-timeout +nginx.ingress.kubernetes.io/proxy-next-upstream-timeout +nginx.ingress.kubernetes.io/auth-keepalive-timeout + +# `ingress.nginx.proxyBuffer` pass value to to annotation(s) +nginx.ingress.kubernetes.io/proxy-request-buffering: "on" +nginx.ingress.kubernetes.io/proxy-buffering: "on" + +# `ingress.nginx.proxyBuffer.size` pass value to to annotation(s) +nginx.ingress.kubernetes.io/proxy-buffer-size +nginx.ingress.kubernetes.io/client-body-buffer-size + +# `ingress.nginx.proxyBuffer.number` pass value to annotation(s) +nginx.ingress.kubernetes.io/proxy-buffers-number +``` + ## Configuration For now, global configuration supported is: -| Parameter | Default | Description | -|---------------------------------------|-------------------|---------------------------------------| -| `global.seleniumGrid.imageTag` | `4.12.1-20230920` | Image tag for all selenium components | -| `global.seleniumGrid.nodesImageTag` | `4.12.1-20230920` | Image tag for browser's nodes | -| `global.seleniumGrid.imagePullSecret` | `""` | Pull secret to be used for all images | -| `global.seleniumGrid.imagePullSecret` | `""` | Pull secret to be used for all images | -| `global.seleniumGrid.affinity` | `{}` | Affinity assigned globally | +| Parameter | Default | Description | +|---------------------------------------|-----------------------|---------------------------------------| +| `global.seleniumGrid.imageRegistry` | `selenium` | Distribution registry to pull images | +| `global.seleniumGrid.imageTag` | `4.16.0-20231206` | Image tag for all selenium components | +| `global.seleniumGrid.nodesImageTag` | `4.16.0-20231206` | Image tag for browser's nodes | +| `global.seleniumGrid.videoImageTag` | `ffmpeg-6.1-20231206` | Image tag for browser's video recoder | +| `global.seleniumGrid.imagePullSecret` | `""` | Pull secret to be used for all images | +| `global.seleniumGrid.imagePullSecret` | `""` | Pull secret to be used for all images | +| `global.seleniumGrid.affinity` | `{}` | Affinity assigned globally | This table contains the configuration parameters of the chart and their default values: -| Parameter | Default | Description | -|---------------------------------------------|---------------------------------------------|----------------------------------------------------------------------------------------------------------------------------| -| `isolateComponents` | `false` | Deploy Router, Distributor, EventBus, SessionMap and Nodes separately | -| `serviceAccount.create` | `true` | Enable or disable creation of service account (if `false`, `serviceAccount.name` MUST be specified | -| `serviceAccount.name` | `""` | Name of the service account to be made or existing service account to use for all deployments and jobs | -| `serviceAccount.annotations` | `{}` | Custom annotations for service account | -| `busConfigMap.name` | `selenium-event-bus-config` | Name of the configmap that contains SE_EVENT_BUS_HOST, SE_EVENT_BUS_PUBLISH_PORT and SE_EVENT_BUS_SUBSCRIBE_PORT variables | -| `busConfigMap.annotations` | `{}` | Custom annotations for configmap | -| `nodeConfigMap.name` | `selenium-node-config` | Name of the configmap that contains common environment variables for browser nodes | -| `nodeConfigMap.annotations` | `{}` | Custom annotations for configmap | -| `ingress.enabled` | `true` | Enable or disable ingress resource | -| `ingress.className` | `""` | Name of ingress class to select which controller will implement ingress resource | -| `ingress.annotations` | `{}` | Custom annotations for ingress resource | -| `ingress.hostname` | `selenium-grid.local` | Default host for the ingress resource | -| `ingress.path` | `/` | Default host path for the ingress resource | -| `ingress.tls` | `[]` | TLS backend configuration for ingress resource | -| `autoscaling.enableWithExistingKEDA` | `false` | Enable autoscaling of browser nodes. | -| `autoscaling.enabled` | `false` | Same as above plus installation of KEDA | -| `autoscaling.scalingType` | `job` | Which typ of KEDA scaling to use: job or deployment | -| `autoscaling.scaledJobOptions` | See `values.yaml` | Options for KEDA ScaledJobs | -| `autoscaling.deregisterLifecycle` | See `values.yaml` | Lifecycle applied to pods of deployments controlled by KEDA. Makes the node deregister from selenium hub | -| `chromeNode.enabled` | `true` | Enable chrome nodes | -| `chromeNode.deploymentEnabled` | `true` | Enable creation of Deployment for chrome nodes | -| `chromeNode.replicas` | `1` | Number of chrome nodes. Disabled if autoscaling is enabled. | -| `chromeNode.imageName` | `selenium/node-chrome` | Image of chrome nodes | -| `chromeNode.imageTag` | `4.12.1-20230920` | Image of chrome nodes | -| `chromeNode.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | -| `chromeNode.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | -| `chromeNode.ports` | `[5555]` | Port list to enable on container | -| `chromeNode.seleniumPort` | `5900` | Selenium port (spec.ports[0].targetPort in kubernetes service) | -| `chromeNode.seleniumServicePort` | `6900` | Selenium port exposed in service (spec.ports[0].port in kubernetes service) | -| `chromeNode.annotations` | `{}` | Annotations for chrome-node pods | -| `chromeNode.labels` | `{}` | Labels for chrome-node pods | -| `chromeNode.resources` | `See values.yaml` | Resources for chrome-node pods | -| `chromeNode.securityContext` | `See values.yaml` | Security context for chrome-node pods | -| `chromeNode.tolerations` | `[]` | Tolerations for chrome-node pods | -| `chromeNode.nodeSelector` | `{}` | Node Selector for chrome-node pods | -| `chromeNode.affinity` | `{}` | Affinity for chrome-node pods | -| `chromeNode.hostAliases` | `nil` | Custom host aliases for chrome nodes | -| `chromeNode.priorityClassName` | `""` | Priority class name for chrome-node pods | -| `chromeNode.extraEnvironmentVariables` | `nil` | Custom environment variables for chrome nodes | -| `chromeNode.extraEnvFrom` | `nil` | Custom environment taken from `configMap` or `secret` variables for chrome nodes | -| `chromeNode.service.enabled` | `true` | Create a service for node | -| `chromeNode.service.type` | `ClusterIP` | Service type | -| `chromeNode.service.annotations` | `{}` | Custom annotations for service | -| `chromeNode.dshmVolumeSizeLimit` | `1Gi` | Size limit for DSH volume mounted in container (if not set, default is "1Gi") | -| `chromeNode.startupProbe` | `{}` | Probe to check pod is started successfully | -| `chromeNode.livenessProbe` | `{}` | Liveness probe settings | -| `chromeNode.terminationGracePeriodSeconds` | `30` | Time to graceful terminate container (default: 30s) | -| `chromeNode.lifecycle` | `{}` | hooks to make pod correctly shutdown or started | -| `chromeNode.extraVolumeMounts` | `[]` | Extra mounts of declared ExtraVolumes into pod | -| `chromeNode.extraVolumes` | `[]` | Extra Volumes declarations to be used in the pod (can be any supported volume type: ConfigMap, Secret, PVC, NFS, etc.) | -| `chromeNode.hpa.url` | `{{ include "seleniumGrid.graphqlURL" . }}` | Graphql Url of the hub or the router | -| `chromeNode.hpa.browserName` | `chrome` | BrowserName from the capability | -| `chromeNode.hpa.browserVersion` | `` | BrowserVersion from the capability | -| `chromeNode.maxReplicaCount` | `8` | Max number of replicas that this browsernode can auto scale up to | -| `chromeNode.minReplicaCount` | `1` | Min number of replicas that this browsernode has when jobs are running | -| `firefoxNode.enabled` | `true` | Enable firefox nodes | -| `firefoxNode.deploymentEnabled` | `true` | Enable creation of Deployment for firefox nodes | -| `firefoxNode.replicas` | `1` | Number of firefox nodes. Disabled if autoscaling is enabled. | -| `firefoxNode.imageName` | `selenium/node-firefox` | Image of firefox nodes | -| `firefoxNode.imageTag` | `4.12.1-20230920` | Image of firefox nodes | -| `firefoxNode.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | -| `firefoxNode.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | -| `firefoxNode.ports` | `[5555]` | Port list to enable on container | -| `firefoxNode.seleniumPort` | `5900` | Selenium port (spec.ports[0].targetPort in kubernetes service) | -| `firefoxNode.seleniumServicePort` | `6900` | Selenium port exposed in service (spec.ports[0].port in kubernetes service) | -| `firefoxNode.annotations` | `{}` | Annotations for firefox-node pods | -| `firefoxNode.labels` | `{}` | Labels for firefox-node pods | -| `firefoxNode.resources` | `See values.yaml` | Resources for firefox-node pods | -| `firefoxNode.securityContext` | `See values.yaml` | Security context for firefox-node pods | -| `firefoxNode.tolerations` | `[]` | Tolerations for firefox-node pods | -| `firefoxNode.nodeSelector` | `{}` | Node Selector for firefox-node pods | -| `firefoxNode.affinity` | `{}` | Affinity for firefox-node pods | -| `firefoxNode.hostAliases` | `nil` | Custom host aliases for firefox nodes | -| `firefoxNode.priorityClassName` | `""` | Priority class name for firefox-node pods | -| `firefoxNode.extraEnvironmentVariables` | `nil` | Custom environment variables for firefox nodes | -| `firefoxNode.extraEnvFrom` | `nil` | Custom environment variables taken from `configMap` or `secret` for firefox nodes | -| `firefoxNode.service.enabled` | `true` | Create a service for node | -| `firefoxNode.service.type` | `ClusterIP` | Service type | -| `firefoxNode.service.annotations` | `{}` | Custom annotations for service | -| `firefoxNode.dshmVolumeSizeLimit` | `1Gi` | Size limit for DSH volume mounted in container (if not set, default is "1Gi") | -| `firefoxNode.startupProbe` | `{}` | Probe to check pod is started successfully | -| `firefoxNode.livenessProbe` | `{}` | Liveness probe settings | -| `firefoxNode.terminationGracePeriodSeconds` | `30` | Time to graceful terminate container (default: 30s) | -| `firefoxNode.lifecycle` | `{}` | hooks to make pod correctly shutdown or started | -| `firefoxNode.extraVolumeMounts` | `[]` | Extra mounts of declared ExtraVolumes into pod | -| `firefoxNode.extraVolumes` | `[]` | Extra Volumes declarations to be used in the pod (can be any supported volume type: ConfigMap, Secret, PVC, NFS, etc.) | -| `firefoxNode.hpa.url` | `{{ include "seleniumGrid.graphqlURL" . }}` | Graphql Url of the hub or the router | -| `firefoxNode.hpa.browserName` | `firefox` | BrowserName from the capability | -| `firefoxNode.hpa.browserVersion` | `` | BrowserVersion from the capability | -| `firefoxNode.maxReplicaCount` | `8` | Max number of replicas that this browsernode can auto scale up to | -| `firefoxNode.minReplicaCount` | `1` | Min number of replicas that this browsernode has when jobs are running | -| `edgeNode.enabled` | `true` | Enable edge nodes | -| `edgeNode.deploymentEnabled` | `true` | Enable creation of Deployment for edge nodes | -| `edgeNode.replicas` | `1` | Number of edge nodes. Disabled if autoscaling is enabled. | -| `edgeNode.imageName` | `selenium/node-edge` | Image of edge nodes | -| `edgeNode.imageTag` | `4.12.1-20230920` | Image of edge nodes | -| `edgeNode.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | -| `edgeNode.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | -| `edgeNode.ports` | `[5555]` | Port list to enable on container | -| `edgeNode.seleniumPort` | `5900` | Selenium port (spec.ports[0].targetPort in kubernetes service) | -| `edgeNode.seleniumServicePort` | `6900` | Selenium port exposed in service (spec.ports[0].port in kubernetes service) | -| `edgeNode.annotations` | `{}` | Annotations for edge-node pods | -| `edgeNode.labels` | `{}` | Labels for edge-node pods | -| `edgeNode.resources` | `See values.yaml` | Resources for edge-node pods | -| `edgeNode.securityContext` | `See values.yaml` | Security context for edge-node pods | -| `edgeNode.tolerations` | `[]` | Tolerations for edge-node pods | -| `edgeNode.nodeSelector` | `{}` | Node Selector for edge-node pods | -| `edgeNode.affinity` | `{}` | Affinity for edge-node pods | -| `edgeNode.hostAliases` | `nil` | Custom host aliases for edge nodes | -| `edgeNode.priorityClassName` | `""` | Priority class name for edge-node pods | -| `edgeNode.extraEnvironmentVariables` | `nil` | Custom environment variables for firefox nodes | -| `edgeNode.extraEnvFrom` | `nil` | Custom environment taken from `configMap` or `secret` variables for firefox nodes | -| `edgeNode.service.enabled` | `true` | Create a service for node | -| `edgeNode.service.type` | `ClusterIP` | Service type | -| `edgeNode.service.annotations` | `{}` | Custom annotations for service | -| `edgeNode.dshmVolumeSizeLimit` | `1Gi` | Size limit for DSH volume mounted in container (if not set, default is "1Gi") | -| `edgeNode.startupProbe` | `{}` | Probe to check pod is started successfully | -| `edgeNode.livenessProbe` | `{}` | Liveness probe settings | -| `edgeNode.terminationGracePeriodSeconds` | `30` | Time to graceful terminate container (default: 30s) | -| `edgeNode.lifecycle` | `{}` | hooks to make pod correctly shutdown or started | -| `edgeNode.extraVolumeMounts` | `[]` | Extra mounts of declared ExtraVolumes into pod | -| `edgeNode.extraVolumes` | `[]` | Extra Volumes declarations to be used in the pod (can be any supported volume type: ConfigMap, Secret, PVC, NFS, etc.) | -| `edgeNode.hpa.url` | `{{ include "seleniumGrid.graphqlURL" . }}` | Graphql Url of the hub or the router | -| `edgeNode.hpa.browserName` | `edge` | BrowserName from the capability | -| `edgeNode.hpa.browserVersion` | `` | BrowserVersion from the capability | -| `edgeNode.maxReplicaCount` | `8` | Max number of replicas that this browsernode can auto scale up to | -| `edgeNode.minReplicaCount` | `1` | Min number of replicas that this browsernode has when jobs are running | -| `customLabels` | `{}` | Custom labels for k8s resources | -| `customLabels` | `{}` | Custom labels for k8s resources | +| Parameter | Default | Description | +|-----------------------------------------------|---------------------------------------------|----------------------------------------------------------------------------------------------------------------------------| +| `basicAuth.enabled` | `true` | Enable or disable basic auth for Selenium Grid | +| `basicAuth.username` | `admin` | Username of basic auth for Selenium Grid | +| `basicAuth.password` | `admin` | Password of basic auth for Selenium Grid | +| `isolateComponents` | `false` | Deploy Router, Distributor, EventBus, SessionMap and Nodes separately | +| `serviceAccount.create` | `true` | Enable or disable creation of service account (if `false`, `serviceAccount.name` MUST be specified | +| `serviceAccount.name` | `""` | Name of the service account to be made or existing service account to use for all deployments and jobs | +| `serviceAccount.annotations` | `{}` | Custom annotations for service account | +| `busConfigMap.name` | `selenium-event-bus-config` | Name of the configmap that contains SE_EVENT_BUS_HOST, SE_EVENT_BUS_PUBLISH_PORT and SE_EVENT_BUS_SUBSCRIBE_PORT variables | +| `busConfigMap.annotations` | `{}` | Custom annotations for configmap | +| `nodeConfigMap.name` | `selenium-node-config` | Name of the configmap that contains common environment variables for browser nodes | +| `nodeConfigMap.annotations` | `{}` | Custom annotations for configmap | +| `ingress.enabled` | `true` | Enable or disable ingress resource | +| `ingress.className` | `""` | Name of ingress class to select which controller will implement ingress resource | +| `ingress.annotations` | `{}` | Custom annotations for ingress resource | +| `ingress.nginx.proxyTimeout` | `3600` | Value is used to set for NGINX ingress annotations related to proxy timeout | +| `ingress.nginx.proxyBuffer.size` | `512M` | Value is used to set for NGINX ingress annotations on size of the buffer proxy_buffer_size used for reading | +| `ingress.nginx.proxyBuffer.number` | `4` | Value is used to set for NGINX ingress annotations on number of the buffers in proxy_buffers used for reading | +| `ingress.hostname` | `` | Default host for the ingress resource | +| `ingress.path` | `/` | Default host path for the ingress resource | +| `ingress.pathType` | `Prefix` | Default path type for the ingress resource | +| `ingress.paths` | `[]` | List of paths config for the ingress resource. This will override the default path | +| `ingress.tls` | `[]` | TLS backend configuration for ingress resource | +| `autoscaling.enableWithExistingKEDA` | `false` | Enable autoscaling of browser nodes. | +| `autoscaling.enabled` | `false` | Same as above plus installation of KEDA | +| `autoscaling.scalingType` | `job` | Which typ of KEDA scaling to use: `job` or `deployment` | +| `autoscaling.scaledOptions` | See `values.yaml` | Common options for KEDA scaled resources (both ScaledJobs and ScaledObjects) | +| `autoscaling.scaledOptions.minReplicaCount` | `0` | Min number of replicas that each browser nodes has when autoscaling | +| `autoscaling.scaledOptions.maxReplicaCount` | `8` | Max number of replicas that each browser nodes can auto scale up to | +| `autoscaling.scaledOptions.pollingInterval` | `10` | The interval to check each trigger on | +| `autoscaling.scaledJobOptions` | See `values.yaml` | Options for KEDA ScaledJobs (when `scalingType` is set to `job`) | +| `autoscaling.scaledObjectOptions` | See `values.yaml` | Options for KEDA ScaledObjects (when `scalingType` is set to `deployment`) | +| `autoscaling.deregisterLifecycle` | See `values.yaml` | Lifecycle applied to pods of deployments controlled by KEDA. Makes the node deregister from selenium hub | +| `chromeNode.enabled` | `true` | Enable chrome nodes | +| `chromeNode.deploymentEnabled` | `true` | Enable creation of Deployment for chrome nodes | +| `chromeNode.replicas` | `1` | Number of chrome nodes. Disabled if autoscaling is enabled. | +| `chromeNode.imageRegistry` | `nil` | Distribution registry to pull the image (this overwrites `.global.seleniumGrid.imageRegistry` value) | +| `chromeNode.imageName` | `node-chrome` | Image of chrome nodes | +| `chromeNode.imageTag` | `4.16.0-20231206` | Image of chrome nodes | +| `chromeNode.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | +| `chromeNode.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | +| `chromeNode.ports` | `[5555]` | Port list to enable on container | +| `chromeNode.seleniumPort` | `5900` | Selenium port (spec.ports[0].targetPort in kubernetes service) | +| `chromeNode.seleniumServicePort` | `6900` | Selenium port exposed in service (spec.ports[0].port in kubernetes service) | +| `chromeNode.annotations` | `{}` | Annotations for chrome-node pods | +| `chromeNode.labels` | `{}` | Labels for chrome-node pods | +| `chromeNode.resources` | `See values.yaml` | Resources for chrome-node pods | +| `chromeNode.securityContext` | `See values.yaml` | Security context for chrome-node pods | +| `chromeNode.tolerations` | `[]` | Tolerations for chrome-node pods | +| `chromeNode.nodeSelector` | `{}` | Node Selector for chrome-node pods | +| `chromeNode.affinity` | `{}` | Affinity for chrome-node pods | +| `chromeNode.hostAliases` | `nil` | Custom host aliases for chrome nodes | +| `chromeNode.priorityClassName` | `""` | Priority class name for chrome-node pods | +| `chromeNode.extraEnvironmentVariables` | `nil` | Custom environment variables for chrome nodes | +| `chromeNode.extraEnvFrom` | `nil` | Custom environment taken from `configMap` or `secret` variables for chrome nodes | +| `chromeNode.service.enabled` | `true` | Create a service for node | +| `chromeNode.service.type` | `ClusterIP` | Service type | +| `chromeNode.service.loadBalancerIP` | `` | Set specific loadBalancerIP when serviceType is LoadBalancer | +| `chromeNode.service.ports` | `[]` | Extra ports exposed in node service | +| `chromeNode.service.annotations` | `{}` | Custom annotations for service | +| `chromeNode.dshmVolumeSizeLimit` | `1Gi` | Size limit for DSH volume mounted in container (if not set, default is "1Gi") | +| `chromeNode.startupProbe` | `{}` | Probe to check pod is started successfully | +| `chromeNode.livenessProbe` | `{}` | Liveness probe settings | +| `chromeNode.terminationGracePeriodSeconds` | `30` | Time to graceful terminate container (default: 30s) | +| `chromeNode.lifecycle` | `{}` | hooks to make pod correctly shutdown or started | +| `chromeNode.extraVolumeMounts` | `[]` | Extra mounts of declared ExtraVolumes into pod | +| `chromeNode.extraVolumes` | `[]` | Extra Volumes declarations to be used in the pod (can be any supported volume type: ConfigMap, Secret, PVC, NFS, etc.) | +| `chromeNode.hpa.url` | `{{ include "seleniumGrid.graphqlURL" . }}` | Graphql Url of the hub or the router | +| `chromeNode.hpa.browserName` | `chrome` | BrowserName from the capability | +| `chromeNode.hpa.browserVersion` | `` | BrowserVersion from the capability | +| `chromeNode.scaledOptions` | See `values.yaml` | Override the global `autoscaling.scaledOptions` with specific scaled options for chrome nodes | +| `chromeNode.scaledJobOptions` | See `values.yaml` | Override the global `autoscaling.scaledJobOptions` with specific scaled options for chrome nodes | +| `chromeNode.scaledObjectOptions` | See `values.yaml` | Override the global `autoscaling.scaledObjectOptions` with specific scaled options for chrome nodes | +| `firefoxNode.enabled` | `true` | Enable firefox nodes | +| `firefoxNode.deploymentEnabled` | `true` | Enable creation of Deployment for firefox nodes | +| `firefoxNode.replicas` | `1` | Number of firefox nodes. Disabled if autoscaling is enabled. | +| `firefoxNode.imageRegistry` | `nil` | Distribution registry to pull the image (this overwrites `.global.seleniumGrid.imageRegistry` value) | +| `firefoxNode.imageName` | `node-firefox` | Image of firefox nodes | +| `firefoxNode.imageTag` | `4.16.0-20231206` | Image of firefox nodes | +| `firefoxNode.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | +| `firefoxNode.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | +| `firefoxNode.ports` | `[5555]` | Port list to enable on container | +| `firefoxNode.seleniumPort` | `5900` | Selenium port (spec.ports[0].targetPort in kubernetes service) | +| `firefoxNode.seleniumServicePort` | `6900` | Selenium port exposed in service (spec.ports[0].port in kubernetes service) | +| `firefoxNode.annotations` | `{}` | Annotations for firefox-node pods | +| `firefoxNode.labels` | `{}` | Labels for firefox-node pods | +| `firefoxNode.resources` | `See values.yaml` | Resources for firefox-node pods | +| `firefoxNode.securityContext` | `See values.yaml` | Security context for firefox-node pods | +| `firefoxNode.tolerations` | `[]` | Tolerations for firefox-node pods | +| `firefoxNode.nodeSelector` | `{}` | Node Selector for firefox-node pods | +| `firefoxNode.affinity` | `{}` | Affinity for firefox-node pods | +| `firefoxNode.hostAliases` | `nil` | Custom host aliases for firefox nodes | +| `firefoxNode.priorityClassName` | `""` | Priority class name for firefox-node pods | +| `firefoxNode.extraEnvironmentVariables` | `nil` | Custom environment variables for firefox nodes | +| `firefoxNode.extraEnvFrom` | `nil` | Custom environment variables taken from `configMap` or `secret` for firefox nodes | +| `firefoxNode.service.enabled` | `true` | Create a service for node | +| `firefoxNode.service.type` | `ClusterIP` | Service type | +| `firefoxNode.service.loadBalancerIP` | `` | Set specific loadBalancerIP when serviceType is LoadBalancer | +| `firefoxNode.service.ports` | `[]` | Extra ports exposed in node service | +| `firefoxNode.service.annotations` | `{}` | Custom annotations for service | +| `firefoxNode.dshmVolumeSizeLimit` | `1Gi` | Size limit for DSH volume mounted in container (if not set, default is "1Gi") | +| `firefoxNode.startupProbe` | `{}` | Probe to check pod is started successfully | +| `firefoxNode.livenessProbe` | `{}` | Liveness probe settings | +| `firefoxNode.terminationGracePeriodSeconds` | `30` | Time to graceful terminate container (default: 30s) | +| `firefoxNode.lifecycle` | `{}` | hooks to make pod correctly shutdown or started | +| `firefoxNode.extraVolumeMounts` | `[]` | Extra mounts of declared ExtraVolumes into pod | +| `firefoxNode.extraVolumes` | `[]` | Extra Volumes declarations to be used in the pod (can be any supported volume type: ConfigMap, Secret, PVC, NFS, etc.) | +| `firefoxNode.hpa.url` | `{{ include "seleniumGrid.graphqlURL" . }}` | Graphql Url of the hub or the router | +| `firefoxNode.hpa.browserName` | `firefox` | BrowserName from the capability | +| `firefoxNode.hpa.browserVersion` | `` | BrowserVersion from the capability | +| `firefoxNode.scaledOptions` | See `values.yaml` | Override the global `autoscaling.scaledOptions` with specific scaled options for firefox nodes | +| `firefoxNode.scaledJobOptions` | See `values.yaml` | Override the global `autoscaling.scaledJobOptions` with specific scaled options for firefox nodes | +| `firefoxNode.scaledObjectOptions` | See `values.yaml` | Override the global `autoscaling.scaledObjectOptions` with specific scaled options for firefox nodes | +| `edgeNode.enabled` | `true` | Enable edge nodes | +| `edgeNode.deploymentEnabled` | `true` | Enable creation of Deployment for edge nodes | +| `edgeNode.replicas` | `1` | Number of edge nodes. Disabled if autoscaling is enabled. | +| `edgeNode.imageRegistry` | `nil` | Distribution registry to pull the image (this overwrites `.global.seleniumGrid.imageRegistry` value) | +| `edgeNode.imageName` | `node-edge` | Image of edge nodes | +| `edgeNode.imageTag` | `4.16.0-20231206` | Image of edge nodes | +| `edgeNode.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | +| `edgeNode.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | +| `edgeNode.ports` | `[5555]` | Port list to enable on container | +| `edgeNode.seleniumPort` | `5900` | Selenium port (spec.ports[0].targetPort in kubernetes service) | +| `edgeNode.seleniumServicePort` | `6900` | Selenium port exposed in service (spec.ports[0].port in kubernetes service) | +| `edgeNode.annotations` | `{}` | Annotations for edge-node pods | +| `edgeNode.labels` | `{}` | Labels for edge-node pods | +| `edgeNode.resources` | `See values.yaml` | Resources for edge-node pods | +| `edgeNode.securityContext` | `See values.yaml` | Security context for edge-node pods | +| `edgeNode.tolerations` | `[]` | Tolerations for edge-node pods | +| `edgeNode.nodeSelector` | `{}` | Node Selector for edge-node pods | +| `edgeNode.affinity` | `{}` | Affinity for edge-node pods | +| `edgeNode.hostAliases` | `nil` | Custom host aliases for edge nodes | +| `edgeNode.priorityClassName` | `""` | Priority class name for edge-node pods | +| `edgeNode.extraEnvironmentVariables` | `nil` | Custom environment variables for firefox nodes | +| `edgeNode.extraEnvFrom` | `nil` | Custom environment taken from `configMap` or `secret` variables for firefox nodes | +| `edgeNode.service.enabled` | `true` | Create a service for node | +| `edgeNode.service.type` | `ClusterIP` | Service type | +| `edgeNode.service.loadBalancerIP` | `` | Set specific loadBalancerIP when serviceType is LoadBalancer | +| `edgeNode.service.ports` | `[]` | Extra ports exposed in node service | +| `edgeNode.service.annotations` | `{}` | Custom annotations for service | +| `edgeNode.dshmVolumeSizeLimit` | `1Gi` | Size limit for DSH volume mounted in container (if not set, default is "1Gi") | +| `edgeNode.startupProbe` | `{}` | Probe to check pod is started successfully | +| `edgeNode.livenessProbe` | `{}` | Liveness probe settings | +| `edgeNode.terminationGracePeriodSeconds` | `30` | Time to graceful terminate container (default: 30s) | +| `edgeNode.lifecycle` | `{}` | hooks to make pod correctly shutdown or started | +| `edgeNode.extraVolumeMounts` | `[]` | Extra mounts of declared ExtraVolumes into pod | +| `edgeNode.extraVolumes` | `[]` | Extra Volumes declarations to be used in the pod (can be any supported volume type: ConfigMap, Secret, PVC, NFS, etc.) | +| `edgeNode.hpa.url` | `{{ include "seleniumGrid.graphqlURL" . }}` | Graphql Url of the hub or the router | +| `edgeNode.hpa.browserName` | `edge` | BrowserName from the capability | +| `edgeNode.hpa.browserVersion` | `` | BrowserVersion from the capability | +| `edgeNode.scaledOptions` | See `values.yaml` | Override the global `autoscaling.scaledOptions` with specific scaled options for edge nodes | +| `edgeNode.scaledJobOptions` | See `values.yaml` | Override the global `autoscaling.scaledJobOptions` with specific scaled options for edge nodes | +| `edgeNode.scaledObjectOptions` | See `values.yaml` | Override the global `autoscaling.scaledObjectOptions` with specific scaled options for edge nodes | +| `videoRecorder.enabled` | `false` | Enable video recorder for node | +| `videoRecorder.imageRegistry` | `nil` | Distribution registry to pull the image (this overwrites `.global.seleniumGrid.imageRegistry` value) | +| `videoRecorder.imageName` | `video` | Selenium video recoder image name | +| `videoRecorder.imageTag` | `ffmpeg-6.1-20231206` | Image tag of video recorder | +| `videoRecorder.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | +| `videoRecorder.uploader` | `false` | Name of the uploader to use. The value `false` is used to disable uploader. Supported default `s3` | +| `videoRecorder.uploadDestinationPrefix` | `false` | Destination URL for uploading video file. The value `false` is used to disable the uploading | +| `videoRecorder.ports` | `[9000]` | Port list to enable on video recorder container | +| `videoRecorder.resources` | `See values.yaml` | Resources for video recorder | +| `videoRecorder.extraEnvironmentVariables` | `nil` | Custom environment variables for video recorder | +| `videoRecorder.extraEnvFrom` | `nil` | Custom environment taken from `configMap` or `secret` variables for video recorder | +| `videoRecorder.terminationGracePeriodSeconds` | `30` | Time to graceful terminate container (default: 30s) | +| `videoRecorder.startupProbe` | `{}` | Probe to check pod is started successfully | +| `videoRecorder.livenessProbe` | `{}` | Liveness probe settings | +| `videoRecorder.volume.name.folder` | `video` | Name is used to set for the volume to persist and share output video folder in container | +| `videoRecorder.volume.name.scripts` | `video-scripts` | Name is used to set for the volume to persist and share video recorder scripts in container | +| `videoRecorder.extraVolumeMounts` | `[]` | Extra mounts of declared ExtraVolumes into pod | +| `videoRecorder.extraVolumes` | `[]` | Extra Volumes declarations to be used in the pod (can be any supported volume type: ConfigMap, Secret, PVC, NFS, etc.) | +| `videoRecorder.s3` | `See values.yaml` | Container spec for the uploader if `videoRecorder.uploader` is `s3`. Similarly, create for your new uploader | +| `videoRecorder.s3.resources` | `See values.yaml` | Resources for video uploader | +| `videoRecorder.s3.extraEnvironmentVariables` | `` | Custom environment variables for video uploader container | +| `videoRecorder.s3.extraEnvFrom` | `` | Custom environment taken from `configMap` or `secret` variables for video uploader | +| `videoRecorder.s3.extraVolumeMounts` | `[]` | Extra mounts of declared ExtraVolumes into pod of video uploader | +| `customLabels` | `{}` | Custom labels for k8s resources | ### Configuration of KEDA @@ -237,7 +336,8 @@ You can configure the Selenium Hub with these values: | Parameter | Default | Description | |---------------------------------|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------| -| `hub.imageName` | `selenium/hub` | Selenium Hub image name | +| `hub.imageRegistry` | `nil` | Distribution registry to pull the image (this overwrites `.global.seleniumGrid.imageRegistry` value) | +| `hub.imageName` | `hub` | Selenium Hub image name | | `hub.imageTag` | `nil` | Selenium Hub image tag (this overwrites `.global.seleniumGrid.imageTag` value) | | `hub.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | | `hub.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | @@ -268,84 +368,89 @@ You can configure the Selenium Hub with these values: If you implement selenium-grid with separate components (`isolateComponents: true`), you can configure all components via the following values: -| Parameter | Default | Description | -|----------------------------------------------|--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------| -| `components.router.imageName` | `selenium/router` | Router image name | -| `components.router.imageTag` | `nil` | Router image tag (this overwrites `.global.seleniumGrid.imageTag` value) | -| `components.router.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | -| `components.router.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | -| `components.router.annotations` | `{}` | Custom annotations for router pod | -| `components.router.port` | `4444` | Router port | -| `components.router.livenessProbe` | `See values.yaml` | Liveness probe settings | -| `components.router.readinessProbe` | `See values.yaml` | Readiness probe settings | -| `components.router.resources` | `{}` | Resources for router pod | -| `components.router.securityContext` | `See values.yaml` | Security context for router pod | -| `components.router.serviceType` | `ClusterIP` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | -| `components.router.loadBalancerIP` | `nil` | Set specific loadBalancerIP when serviceType is LoadBalancer (see https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) | -| `components.router.serviceAnnotations` | `{}` | Custom annotations for router service | -| `components.router.tolerations` | `[]` | Tolerations for router pods | -| `components.router.nodeSelector` | `{}` | Node Selector for router pods | -| `components.router.affinity` | `{}` | Affinity for router pods | -| `components.router.priorityClassName` | `""` | Priority class name for router pods | -| `components.distributor.imageName` | `selenium/distributor` | Distributor image name | -| `components.distributor.imageTag` | `nil` | Distributor image tag (this overwrites `.global.seleniumGrid.imageTag` value) | -| `components.distributor.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | -| `components.distributor.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | -| `components.distributor.annotations` | `{}` | Custom annotations for Distributor pod | -| `components.distributor.port` | `5553` | Distributor port | -| `components.distributor.resources` | `{}` | Resources for Distributor pod | -| `components.distributor.securityContext` | `See values.yaml` | Security context for Distributor pod | -| `components.distributor.serviceType` | `ClusterIP` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | -| `components.distributor.serviceAnnotations` | `{}` | Custom annotations for Distributor service | -| `components.distributor.tolerations` | `[]` | Tolerations for Distributor pods | -| `components.distributor.nodeSelector` | `{}` | Node Selector for Distributor pods | -| `components.distributor.affinity` | `{}` | Affinity for Distributor pods | -| `components.distributor.priorityClassName` | `""` | Priority class name for Distributor pods | -| `components.eventBus.imageName` | `selenium/event-bus` | Event Bus image name | -| `components.eventBus.imageTag` | `nil` | Event Bus image tag (this overwrites `.global.seleniumGrid.imageTag` value) | -| `components.eventBus.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | -| `components.eventBus.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | -| `components.eventBus.annotations` | `{}` | Custom annotations for Event Bus pod | -| `components.eventBus.port` | `5557` | Event Bus port | -| `components.eventBus.publishPort` | `4442` | Port where events are published | -| `components.eventBus.subscribePort` | `4443` | Port where to subscribe for events | -| `components.eventBus.resources` | `{}` | Resources for event-bus pod | -| `components.eventBus.securityContext` | `See values.yaml` | Security context for event-bus pod | -| `components.eventBus.serviceType` | `ClusterIP` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | -| `components.eventBus.serviceAnnotations` | `{}` | Custom annotations for Event Bus service | -| `components.eventBus.tolerations` | `[]` | Tolerations for Event Bus pods | -| `components.eventBus.nodeSelector` | `{}` | Node Selector for Event Bus pods | -| `components.eventBus.affinity` | `{}` | Affinity for Event Bus pods | -| `components.eventBus.priorityClassName` | `""` | Priority class name for Event Bus pods | -| `components.sessionMap.imageName` | `selenium/sessions` | Session Map image name | -| `components.sessionMap.imageTag` | `nil` | Session Map image tag (this overwrites `.global.seleniumGrid.imageTag` value) | -| `components.sessionMap.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | -| `components.sessionMap.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | -| `components.sessionMap.annotations` | `{}` | Custom annotations for Session Map pod | -| `components.sessionMap.resources` | `{}` | Resources for Session Map pod | -| `components.sessionMap.securityContext` | `See values.yaml` | Security context for Session Map pod | -| `components.sessionMap.serviceType` | `ClusterIP` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | -| `components.sessionMap.serviceAnnotations` | `{}` | Custom annotations for Session Map service | -| `components.sessionMap.tolerations` | `[]` | Tolerations for Session Map pods | -| `components.sessionMap.nodeSelector` | `{}` | Node Selector for Session Map pods | -| `components.sessionMap.affinity` | `{}` | Affinity for Session Map pods | -| `components.sessionMap.priorityClassName` | `""` | Priority class name for Session Map pods | -| `components.sessionQueue.imageName` | `selenium/session-queue` | Session Queue image name | -| `components.sessionQueue.imageTag` | `nil` | Session Queue image tag (this overwrites `.global.seleniumGrid.imageTag` value) | -| `components.sessionQueue.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | -| `components.sessionQueue.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | -| `components.sessionQueue.annotations` | `{}` | Custom annotations for Session Queue pod | -| `components.sessionQueue.port` | `5559` | Session Queue Port | -| `components.sessionQueue.resources` | `{}` | Resources for Session Queue pod | -| `components.sessionQueue.securityContext` | `See values.yaml` | Security context for Session Queue pod | -| `components.sessionQueue.serviceType` | `ClusterIP` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | -| `components.sessionQueue.serviceAnnotations` | `{}` | Custom annotations for Session Queue service | -| `components.sessionQueue.tolerations` | `[]` | Tolerations for Session Queue pods | -| `components.sessionQueue.nodeSelector` | `{}` | Node Selector for Session Queue pods | -| `components.sessionQueue.affinity` | `{}` | Affinity for Session Queue pods | -| `components.sessionQueue.priorityClassName` | `""` | Priority class name for Session Queue pods | -| `components.subPath` | `/` | Custom sub path for all components | -| `components.extraEnvironmentVariables` | `nil` | Custom environment variables for all components | -| `components.extraEnvFrom` | `nil` | Custom environment variables taken from `configMap` or `secret` for all components | +| Parameter | Default | Description | +|----------------------------------------------|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------| +| `components.router.imageRegistry` | `nil` | Distribution registry to pull the image (this overwrites `.global.seleniumGrid.imageRegistry` value) | +| `components.router.imageName` | `router` | Router image name | +| `components.router.imageTag` | `nil` | Router image tag (this overwrites `.global.seleniumGrid.imageTag` value) | +| `components.router.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | +| `components.router.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | +| `components.router.annotations` | `{}` | Custom annotations for router pod | +| `components.router.port` | `4444` | Router port | +| `components.router.livenessProbe` | `See values.yaml` | Liveness probe settings | +| `components.router.readinessProbe` | `See values.yaml` | Readiness probe settings | +| `components.router.resources` | `{}` | Resources for router pod | +| `components.router.securityContext` | `See values.yaml` | Security context for router pod | +| `components.router.serviceType` | `ClusterIP` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | +| `components.router.loadBalancerIP` | `nil` | Set specific loadBalancerIP when serviceType is LoadBalancer (see https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) | +| `components.router.serviceAnnotations` | `{}` | Custom annotations for router service | +| `components.router.tolerations` | `[]` | Tolerations for router pods | +| `components.router.nodeSelector` | `{}` | Node Selector for router pods | +| `components.router.affinity` | `{}` | Affinity for router pods | +| `components.router.priorityClassName` | `""` | Priority class name for router pods | +| `components.distributor.imageRegistry` | `nil` | Distribution registry to pull the image (this overwrites `.global.seleniumGrid.imageRegistry` value) | +| `components.distributor.imageName` | `distributor` | Distributor image name | +| `components.distributor.imageTag` | `nil` | Distributor image tag (this overwrites `.global.seleniumGrid.imageTag` value) | +| `components.distributor.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | +| `components.distributor.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | +| `components.distributor.annotations` | `{}` | Custom annotations for Distributor pod | +| `components.distributor.port` | `5553` | Distributor port | +| `components.distributor.resources` | `{}` | Resources for Distributor pod | +| `components.distributor.securityContext` | `See values.yaml` | Security context for Distributor pod | +| `components.distributor.serviceType` | `ClusterIP` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | +| `components.distributor.serviceAnnotations` | `{}` | Custom annotations for Distributor service | +| `components.distributor.tolerations` | `[]` | Tolerations for Distributor pods | +| `components.distributor.nodeSelector` | `{}` | Node Selector for Distributor pods | +| `components.distributor.affinity` | `{}` | Affinity for Distributor pods | +| `components.distributor.priorityClassName` | `""` | Priority class name for Distributor pods | +| `components.eventBus.imageRegistry` | `nil` | Distribution registry to pull the image (this overwrites `.global.seleniumGrid.imageRegistry` value) | +| `components.eventBus.imageName` | `event-bus` | Event Bus image name | +| `components.eventBus.imageTag` | `nil` | Event Bus image tag (this overwrites `.global.seleniumGrid.imageTag` value) | +| `components.eventBus.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | +| `components.eventBus.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | +| `components.eventBus.annotations` | `{}` | Custom annotations for Event Bus pod | +| `components.eventBus.port` | `5557` | Event Bus port | +| `components.eventBus.publishPort` | `4442` | Port where events are published | +| `components.eventBus.subscribePort` | `4443` | Port where to subscribe for events | +| `components.eventBus.resources` | `{}` | Resources for event-bus pod | +| `components.eventBus.securityContext` | `See values.yaml` | Security context for event-bus pod | +| `components.eventBus.serviceType` | `ClusterIP` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | +| `components.eventBus.serviceAnnotations` | `{}` | Custom annotations for Event Bus service | +| `components.eventBus.tolerations` | `[]` | Tolerations for Event Bus pods | +| `components.eventBus.nodeSelector` | `{}` | Node Selector for Event Bus pods | +| `components.eventBus.affinity` | `{}` | Affinity for Event Bus pods | +| `components.eventBus.priorityClassName` | `""` | Priority class name for Event Bus pods | +| `components.sessionMap.imageRegistry` | `nil` | Distribution registry to pull the image (this overwrites `.global.seleniumGrid.imageRegistry` value) | +| `components.sessionMap.imageName` | `sessions` | Session Map image name | +| `components.sessionMap.imageTag` | `nil` | Session Map image tag (this overwrites `.global.seleniumGrid.imageTag` value) | +| `components.sessionMap.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | +| `components.sessionMap.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | +| `components.sessionMap.annotations` | `{}` | Custom annotations for Session Map pod | +| `components.sessionMap.resources` | `{}` | Resources for Session Map pod | +| `components.sessionMap.securityContext` | `See values.yaml` | Security context for Session Map pod | +| `components.sessionMap.serviceType` | `ClusterIP` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | +| `components.sessionMap.serviceAnnotations` | `{}` | Custom annotations for Session Map service | +| `components.sessionMap.tolerations` | `[]` | Tolerations for Session Map pods | +| `components.sessionMap.nodeSelector` | `{}` | Node Selector for Session Map pods | +| `components.sessionMap.affinity` | `{}` | Affinity for Session Map pods | +| `components.sessionMap.priorityClassName` | `""` | Priority class name for Session Map pods | +| `components.sessionQueue.imageRegistry` | `nil` | Distribution registry to pull the image (this overwrites `.global.seleniumGrid.imageRegistry` value) | +| `components.sessionQueue.imageName` | `session-queue` | Session Queue image name | +| `components.sessionQueue.imageTag` | `nil` | Session Queue image tag (this overwrites `.global.seleniumGrid.imageTag` value) | +| `components.sessionQueue.imagePullPolicy` | `IfNotPresent` | Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) | +| `components.sessionQueue.imagePullSecret` | `""` | Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry) | +| `components.sessionQueue.annotations` | `{}` | Custom annotations for Session Queue pod | +| `components.sessionQueue.port` | `5559` | Session Queue Port | +| `components.sessionQueue.resources` | `{}` | Resources for Session Queue pod | +| `components.sessionQueue.securityContext` | `See values.yaml` | Security context for Session Queue pod | +| `components.sessionQueue.serviceType` | `ClusterIP` | Kubernetes service type (see https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | +| `components.sessionQueue.serviceAnnotations` | `{}` | Custom annotations for Session Queue service | +| `components.sessionQueue.tolerations` | `[]` | Tolerations for Session Queue pods | +| `components.sessionQueue.nodeSelector` | `{}` | Node Selector for Session Queue pods | +| `components.sessionQueue.affinity` | `{}` | Affinity for Session Queue pods | +| `components.sessionQueue.priorityClassName` | `""` | Priority class name for Session Queue pods | +| `components.subPath` | `/` | Custom sub path for all components | +| `components.extraEnvironmentVariables` | `nil` | Custom environment variables for all components | +| `components.extraEnvFrom` | `nil` | Custom environment variables taken from `configMap` or `secret` for all components | See how to customize a helm chart installation in the [Helm Docs](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing) for more information. diff --git a/charts/selenium-grid/TESTING.md b/charts/selenium-grid/TESTING.md new file mode 100644 index 0000000000..7e94f85e40 --- /dev/null +++ b/charts/selenium-grid/TESTING.md @@ -0,0 +1,77 @@ +# Testing Selenium Grid Helm Chart + +All related testing to this helm chart will be documented in this file. + +## Test Traceability Matrix + +| Features | TC Description | Coverage | Test via | +|------------------------|----------------------------------------------------------------------|----------|----------| +| Basic Auth | Basic Auth is disabled | ✓ | Cluster | +| | Basic Auth is enabled | ✗ | | +| Auto scaling | Auto scaling with `enableWithExistingKEDA` is `true` | ✓ | Cluster | +| | Auto scaling with `scalingType` is `job` | ✓ | Cluster | +| | Auto scaling with `scalingType` is `deployment` | ✗ | | +| | Auto scaling with `autoscaling.scaledOptions.minReplicaCount` is `0` | ✓ | Cluster | +| | Parallel tests execution against node autoscaling | ✓ | Cluster | +| Ingress | Ingress is enabled without `hostname` | ✓ | Cluster | +| | Ingress is enabled with `hostname` is set | ✗ | | +| | Hub `sub-path` is set with Ingress `ImplementationSpecific` paths | ✓ | Cluster | +| | `ingress.nginx` configs for NGINX ingress controller annotations | ✓ | Template | +| Distributed components | `isolateComponents` is enabled | ✓ | Cluster | +| | `isolateComponents` is disabled | ✓ | Cluster | +| Browser Nodes | Node `nameOverride` is set | ✓ | Cluster | +| | Sanity tests in node | ✓ | Cluster | +| | Video recorder is enabled in node | ✗ | | +| | Node `extraEnvironmentVariables` is set value | ✓ | Cluster | +| General | Set new image registry via `global.seleniumGrid.imageRegistry` | ✓ | Cluster | +| | Components are able to set `.affinity` | ✓ | Template | +| Tracing | Enable tracing via `SE_ENABLE_TRACING` | ✓ | Cluster | +| | Disable tracing via `SE_ENABLE_TRACING` | ✓ | Cluster | + +## Test Chart Template +- By using `helm template` command, the chart template is tested without installing it to Kubernetes cluster. +- Templates are rendered and the output as a YAML manifest file. The manifest file is then asserted with [pyyaml](https://pyyaml.org/wiki/PyYAMLDocumentation). +- Set of values are used to render the templates located in [tests/charts/templates/render](../../tests/charts/templates/render). + +```bash +# Back to root directory +cd ../.. + +# Build chart dependencies and lint +make chart_build + +# Test chart template +make chart_test_template +``` +- Build chart dependencies and lint requires [Chart Testing `ct`](https://github.com/helm/chart-testing). There is a config file [ct.yaml](../../tests/charts/config/ct.yaml) to configure the chart testing. + +## Build & test Docker images with deploy to Kubernetes cluster +Noted: These `make` commands are composed and tested on Linux x86_64. +Run entire commands to build and test Docker images with Helm charts in local environment. + +```bash +# Back to root directory +cd ../.. + +# Setup Kubernetes environment +make chart_setup_env + +# Build Docker images +make build + +# Build and lint charts +make chart_build + +# Setup Kubernetes cluster +make chart_cluster_setup + +# Test Selenium Grid on Kubernetes +make chart_test + +# make chart_test_parallel_autoscaling + +# Cleanup Kubernetes cluster +make chart_cluster_cleanup +``` +- Setup Kubernetes environment requires [Kind](https://kind.sigs.k8s.io/docs/user/quick-start/) and [Kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/). +- Set of values are used to deploy the chart to Kubernetes cluster located in [tests/charts/ci](../../tests/charts/ci). diff --git a/charts/selenium-grid/templates/NOTES.txt b/charts/selenium-grid/templates/NOTES.txt index 80920a44f2..ce79f74b5a 100644 --- a/charts/selenium-grid/templates/NOTES.txt +++ b/charts/selenium-grid/templates/NOTES.txt @@ -1,7 +1,7 @@ Selenium Grid Server deployed successfully. {{- $svcName := ternary (include "seleniumGrid.router.fullname" . ) (include "seleniumGrid.hub.fullname" . ) .Values.isolateComponents }} -{{- $appName := ternary "selenium-router" "selenium-hub" .Values.isolateComponents }} +{{- $appName := ternary (include "seleniumGrid.router.fullname" . ) (include "seleniumGrid.hub.fullname" . ) .Values.isolateComponents }} {{- $serviceType := ternary .Values.components.router.serviceType .Values.hub.serviceType .Values.isolateComponents }} {{- $port := ternary .Values.components.router.port .Values.hub.port .Values.isolateComponents }} {{- $localUrl := ternary "http://localhost:PORT" "http://localhost:PORT/wd/hub" .Values.isolateComponents }} diff --git a/charts/selenium-grid/templates/_helpers.tpl b/charts/selenium-grid/templates/_helpers.tpl index 694b7a5c94..9e44267d95 100644 --- a/charts/selenium-grid/templates/_helpers.tpl +++ b/charts/selenium-grid/templates/_helpers.tpl @@ -80,6 +80,29 @@ Ingress fullname {{- default "selenium-ingress" .Values.ingress.nameOverride | trunc 63 | trimSuffix "-" -}} {{- end -}} +{{- define "seleniumGrid.ingress.nginx.annotations.default" -}} +{{- with .Values.ingress.nginx }} + {{- with .proxyTimeout }} +nginx.ingress.kubernetes.io/proxy-connect-timeout: {{ . | quote }} +nginx.ingress.kubernetes.io/proxy-send-timeout: {{ . | quote }} +nginx.ingress.kubernetes.io/proxy-read-timeout: {{ . | quote }} +nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: {{ . | quote }} +nginx.ingress.kubernetes.io/auth-keepalive-timeout: {{ . | quote }} + {{- end }} + {{- with .proxyBuffer }} +nginx.ingress.kubernetes.io/proxy-request-buffering: "on" +nginx.ingress.kubernetes.io/proxy-buffering: "on" + {{- with .size }} +nginx.ingress.kubernetes.io/proxy-buffer-size: {{ . | quote }} +nginx.ingress.kubernetes.io/client-body-buffer-size: {{ . | quote }} + {{- end }} + {{- with .number }} +nginx.ingress.kubernetes.io/proxy-buffers-number: {{ . | quote }} + {{- end }} + {{- end }} +{{- end }} +{{- end -}} + {{/* Service Account fullname */}} @@ -87,6 +110,13 @@ Service Account fullname {{- .Values.serviceAccount.name | default "selenium-serviceaccount" | trunc 63 | trimSuffix "-" -}} {{- end -}} +{{/* +Video ConfigMap fullname +*/}} +{{- define "seleniumGrid.video.fullname" -}} +{{- default "selenium-video" .Values.videoRecorder.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + {{/* Is autoscaling using KEDA enabled */}} @@ -94,6 +124,46 @@ Is autoscaling using KEDA enabled {{- or .Values.autoscaling.enabled .Values.autoscaling.enableWithExistingKEDA | ternary "true" "" -}} {{- end -}} +{{/* +Common autoscaling spec template +*/}} +{{- define "seleniumGrid.autoscalingTemplate" -}} +{{- $spec := toYaml (dict) -}} +{{/* Merge with precedence from right to left */}} +{{- with .Values.autoscaling.scaledOptions -}} + {{- $spec = mergeOverwrite ($spec | fromYaml) . | toYaml -}} +{{- end -}} +{{- with .node.scaledOptions -}} + {{- $spec = mergeOverwrite ($spec | fromYaml) . | toYaml -}} +{{- end -}} +{{- if eq .Values.autoscaling.scalingType "deployment" -}} + {{- with .Values.autoscaling.scaledObjectOptions -}} + {{- $spec = mergeOverwrite ($spec | fromYaml) . | toYaml -}} + {{- end -}} + {{- with .node.scaledObjectOptions -}} + {{- $spec = mergeOverwrite ($spec | fromYaml) . | toYaml -}} + {{- end -}} + {{- $spec = mergeOverwrite ($spec | fromYaml) (dict "scaleTargetRef" (dict "name" .name)) | toYaml -}} +{{- else if eq .Values.autoscaling.scalingType "job" -}} + {{- with .Values.autoscaling.scaledJobOptions -}} + {{- $spec = mergeOverwrite ($spec | fromYaml) . | toYaml -}} + {{- end -}} + {{- with .node.scaledJobOptions -}} + {{- $spec = mergeOverwrite ($spec | fromYaml) . | toYaml -}} + {{- end -}} + {{- $spec = mergeOverwrite ($spec | fromYaml) (dict "jobTargetRef" .podTemplate) | toYaml -}} +{{- end -}} +{{- if and $spec (ne $spec "{}") -}} + {{ tpl $spec $ }} +{{- end -}} +{{- if not .Values.autoscaling.scaledOptions.triggers }} +triggers: + - type: selenium-grid + {{- with .node.hpa }} + metadata: {{- tpl (toYaml .) $ | nindent 6 }} + {{- end }} +{{- end }} +{{- end -}} {{/* Common pod template @@ -126,7 +196,8 @@ template: containers: - name: {{.name}} {{- $imageTag := default .Values.global.seleniumGrid.nodesImageTag .node.imageTag }} - image: {{ printf "%s:%s" .node.imageName $imageTag }} + {{- $imageRegistry := default .Values.global.seleniumGrid.imageRegistry .node.imageRegistry }} + image: {{ printf "%s/%s:%s" $imageRegistry .node.imageName $imageTag }} imagePullPolicy: {{ .node.imagePullPolicy }} {{- with .node.extraEnvironmentVariables }} env: {{- tpl (toYaml .) $ | nindent 10 }} @@ -137,7 +208,7 @@ template: - configMapRef: name: {{ .Values.nodeConfigMap.name }} {{- with .node.extraEnvFrom }} - {{- toYaml . | nindent 10 }} + {{- tpl (toYaml .) $ | nindent 10 }} {{- end }} {{- if gt (len .node.ports) 0 }} ports: @@ -150,7 +221,7 @@ template: - name: dshm mountPath: /dev/shm {{- if .node.extraVolumeMounts }} - {{- toYaml .node.extraVolumeMounts | nindent 10 }} + {{- tpl (toYaml .node.extraVolumeMounts) $ | nindent 10 }} {{- end }} {{- with .node.resources }} resources: {{- toYaml . | nindent 10 }} @@ -168,6 +239,71 @@ template: {{- if .node.sidecars }} {{- toYaml .node.sidecars | nindent 6 }} {{- end }} + {{- if .Values.videoRecorder.enabled }} + - name: video + {{- $imageTag := default .Values.global.seleniumGrid.videoImageTag .Values.videoRecorder.imageTag }} + {{- $imageRegistry := default .Values.global.seleniumGrid.imageRegistry .Values.videoRecorder.imageRegistry }} + image: {{ printf "%s/%s:%s" $imageRegistry .Values.videoRecorder.imageName $imageTag }} + imagePullPolicy: {{ .Values.videoRecorder.imagePullPolicy }} + env: + - name: UPLOAD_DESTINATION_PREFIX + value: {{ .Values.videoRecorder.uploadDestinationPrefix | quote }} + {{- with .Values.videoRecorder.extraEnvironmentVariables }} + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + envFrom: + - configMapRef: + name: {{ .Values.busConfigMap.name }} + {{- with .Values.videoRecorder.extraEnvFrom }} + {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + {{- if gt (len .Values.videoRecorder.ports) 0 }} + ports: + {{- range .Values.videoRecorder.ports }} + - containerPort: {{ . }} + protocol: TCP + {{- end }} + {{- end }} + volumeMounts: + - name: dshm + mountPath: /dev/shm + {{- tpl (include "seleniumGrid.video.volumeMounts" .) $ | nindent 8 }} + {{- with .Values.videoRecorder.resources }} + resources: {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.videoRecorder.startupProbe }} + startupProbe: {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.videoRecorder.livenessProbe }} + livenessProbe: {{- toYaml . | nindent 10 }} + {{- end }} + {{- if .uploader }} + - name: uploader + image: {{ printf "%s:%s" .uploader.imageName .uploader.imageTag }} + imagePullPolicy: {{ .uploader.imagePullPolicy }} + {{- with .uploader.command }} + command: {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + {{- with .uploader.args }} + args: {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + {{- with .uploader.extraEnvironmentVariables }} + env: {{- tpl (toYaml .) $ | nindent 8 }} + {{- end }} + {{- with .uploader.extraEnvFrom }} + envFrom: + {{- tpl (toYaml .) $ | nindent 10 }} + {{- end }} + volumeMounts: + {{- tpl (include "seleniumGrid.video.uploader.volumeMounts" .) $ | nindent 8 }} + {{- with .uploader.resources }} + resources: {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .uploader.securityContext }} + securityContext: {{- toYaml . | nindent 10 }} + {{- end }} + {{- end }} + {{- end }} {{- if or .Values.global.seleniumGrid.imagePullSecret .node.imagePullSecret }} imagePullSecrets: - name: {{ default .Values.global.seleniumGrid.imagePullSecret .node.imagePullSecret }} @@ -175,6 +311,9 @@ template: {{- with .node.nodeSelector }} nodeSelector: {{- toYaml . | nindent 6 }} {{- end }} + {{- with .node.affinity }} + affinity: {{- toYaml . | nindent 6 }} + {{- end }} {{- with .node.tolerations }} tolerations: {{ toYaml . | nindent 4 }} @@ -189,7 +328,10 @@ template: medium: Memory sizeLimit: {{ default "1Gi" .node.dshmVolumeSizeLimit }} {{- if .node.extraVolumes }} - {{ toYaml .node.extraVolumes | nindent 6 }} + {{ tpl (toYaml .node.extraVolumes) $ | nindent 6 }} + {{- end }} + {{- if .Values.videoRecorder.enabled }} + {{- tpl (include "seleniumGrid.video.volumes" .) $ | nindent 6 }} {{- end }} {{- end -}} @@ -224,3 +366,102 @@ deployment preStop hook to deregister from the selenium hub. lifecycle: {{ $lifecycle | nindent 2 }} {{- end -}} {{- end -}} + +{{/* +Default specs of VolumeMounts and Volumes for video recorder +*/}} +{{- define "seleniumGrid.video.volume.name.folder" -}} +{{- $name := default "video" (((.Values.videoRecorder).volume).name).folder -}} +{{- $name -}} +{{- end -}} + +{{- define "seleniumGrid.video.volume.name.scripts" -}} +{{- $name := default "video-scripts" (((.Values.videoRecorder).volume).name).scripts -}} +{{- $name -}} +{{- end -}} + +{{- define "seleniumGrid.video.volumeMounts.default" -}} +- name: {{ include "seleniumGrid.video.volume.name.scripts" . }} + mountPath: /opt/bin/video.sh + subPath: video.sh +- name: {{ include "seleniumGrid.video.volume.name.folder" . }} + mountPath: /videos +{{- end -}} + +{{- define "seleniumGrid.video.volumes.default" -}} +- name: {{ include "seleniumGrid.video.volume.name.scripts" . }} + configMap: + name: {{ template "seleniumGrid.video.fullname" . }} + defaultMode: 0500 +- name: {{ include "seleniumGrid.video.volume.name.folder" . }} + emptyDir: {} +{{- end -}} + +{{- define "seleniumGrid.video.uploader.volumeMounts.default" -}} +- name: {{ include "seleniumGrid.video.volume.name.folder" . }} + mountPath: /videos +{{- end -}} + +{{/* Combine videoRecorder.extraVolumeMounts with the default ones for container video recorder */}} +{{- define "seleniumGrid.video.volumeMounts" -}} +{{- $videoVolumeMounts := list -}} +{{- if .Values.videoRecorder.extraVolumeMounts -}} + {{- range .Values.videoRecorder.extraVolumeMounts -}} + {{- $videoVolumeMounts = append $videoVolumeMounts . -}} + {{- end -}} +{{- end -}} +{{- $defaultVolumeMounts := (include "seleniumGrid.video.volumeMounts.default" . | toString | fromYamlArray ) -}} +{{- $videoVolumeMounts = include "utils.appendDefaultIfNotExist" (dict "currentArray" $videoVolumeMounts "defaultArray" $defaultVolumeMounts "uniqueKey" "mountPath") -}} +{{- not (empty $videoVolumeMounts) | ternary $videoVolumeMounts "" -}} +{{- end -}} + +{{/* Combine videoRecorder.uploader.extraVolumeMounts with the default ones for container video uploader */}} +{{- define "seleniumGrid.video.uploader.volumeMounts" -}} +{{- $videoUploaderVolumeMounts := list -}} +{{- if .uploader.extraVolumeMounts -}} + {{- range .uploader.extraVolumeMounts -}} + {{- $videoUploaderVolumeMounts = append $videoUploaderVolumeMounts . -}} + {{- end -}} +{{- end }} +{{- $defaultVolumeMounts := (include "seleniumGrid.video.uploader.volumeMounts.default" . | toString | fromYamlArray ) -}} +{{- $videoUploaderVolumeMounts = include "utils.appendDefaultIfNotExist" (dict "currentArray" $videoUploaderVolumeMounts "defaultArray" $defaultVolumeMounts "uniqueKey" "mountPath") -}} +{{- not (empty $videoUploaderVolumeMounts) | ternary $videoUploaderVolumeMounts "" -}} +{{- end -}} + +{{/* Combine videoRecorder.extraVolumes with the default ones for the node pod */}} +{{- define "seleniumGrid.video.volumes" -}} +{{- $videoVolumes := list -}} +{{- if .Values.videoRecorder.extraVolumes -}} + {{- range .Values.videoRecorder.extraVolumes -}} + {{- $videoVolumes = append $videoVolumes . -}} + {{- end -}} +{{- end -}} +{{- $defaultVolumes := (include "seleniumGrid.video.volumes.default" . | toString | fromYamlArray ) -}} +{{- $videoVolumes = include "utils.appendDefaultIfNotExist" (dict "currentArray" $videoVolumes "defaultArray" $defaultVolumes "uniqueKey" "name") -}} +{{- not (empty $videoVolumes) | ternary $videoVolumes "" -}} +{{- end -}} + +{{/* +Is used to append default items needed to an array if they are not already present. Args: currentArray, defaultArray, uniqueKey +Usage: {{- $thisArray = include "utils.appendDefaultIfNotExist" (dict "currentArray" $thisArray "defaultArray" $defaultArray "uniqueKey" $uniqueKey }} +*/}} +{{- define "utils.appendDefaultIfNotExist" -}} + {{- $currentArray := index . "currentArray" -}} + {{- $defaultArray := index . "defaultArray" -}} + {{- $uniqueKey := index . "uniqueKey" -}} + {{- range $default := $defaultArray -}} + {{- if eq (len $currentArray) 0 -}} + {{- $currentArray = append $currentArray $default -}} + {{- end -}} + {{- $isExisting := false -}} + {{- range $current := $currentArray -}} + {{- if eq (index $default $uniqueKey | toString) (index $current $uniqueKey | toString) -}} + {{- $isExisting = true -}} + {{- end -}} + {{- end -}} + {{- if not $isExisting -}} + {{- $currentArray = append $currentArray $default -}} + {{- end -}} + {{- end -}} + {{- $currentArray | toYaml -}} +{{- end -}} diff --git a/charts/selenium-grid/templates/chrome-node-deployment.yaml b/charts/selenium-grid/templates/chrome-node-deployment.yaml index 0b3d2a9b53..e3bf3f1d25 100644 --- a/charts/selenium-grid/templates/chrome-node-deployment.yaml +++ b/charts/selenium-grid/templates/chrome-node-deployment.yaml @@ -5,8 +5,8 @@ metadata: name: {{ template "seleniumGrid.chromeNode.fullname" . }} namespace: {{ .Release.Namespace }} labels: - app: selenium-chrome-node - app.kubernetes.io/name: selenium-chrome-node + app: {{ template "seleniumGrid.chromeNode.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.chromeNode.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.chromeNode.labels }} {{- toYaml . | nindent 4 }} @@ -20,10 +20,11 @@ spec: {{end}} selector: matchLabels: - app: selenium-chrome-node + app: {{ template "seleniumGrid.chromeNode.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- $podScope := deepCopy . -}} -{{- $_ := set $podScope "name" "selenium-chrome-node" -}} -{{- $_ = set $podScope "node" .Values.chromeNode -}} +{{- $_ := set $podScope "name" (include "seleniumGrid.chromeNode.fullname" .) -}} +{{- $_ = set $podScope "node" .Values.chromeNode -}} +{{- $_ = set $podScope "uploader" (get .Values.videoRecorder (.Values.videoRecorder.uploader | toString)) -}} {{- include "seleniumGrid.podTemplate" $podScope | nindent 2 }} {{- end }} diff --git a/charts/selenium-grid/templates/chrome-node-hpa.yaml b/charts/selenium-grid/templates/chrome-node-hpa.yaml index 7cb78043cf..74c5881984 100644 --- a/charts/selenium-grid/templates/chrome-node-hpa.yaml +++ b/charts/selenium-grid/templates/chrome-node-hpa.yaml @@ -11,13 +11,8 @@ metadata: labels: deploymentName: {{ template "seleniumGrid.chromeNode.fullname" . }} spec: - maxReplicaCount: {{ .Values.chromeNode.maxReplicaCount }} - minReplicaCount: {{ .Values.chromeNode.minReplicaCount }} - scaleTargetRef: - name: {{ template "seleniumGrid.chromeNode.fullname" . }} - triggers: - - type: selenium-grid - {{- with .Values.chromeNode.hpa }} - metadata: {{- tpl (toYaml .) $ | nindent 8 }} - {{- end }} + {{- $podScope := deepCopy . -}} + {{- $_ := set $podScope "name" (include "seleniumGrid.chromeNode.fullname" .) -}} + {{- $_ = set $podScope "node" .Values.chromeNode -}} + {{- include "seleniumGrid.autoscalingTemplate" $podScope | nindent 2 }} {{- end }} diff --git a/charts/selenium-grid/templates/chrome-node-scaledjobs.yaml b/charts/selenium-grid/templates/chrome-node-scaledjobs.yaml index 4971aec749..0b0d344432 100644 --- a/charts/selenium-grid/templates/chrome-node-scaledjobs.yaml +++ b/charts/selenium-grid/templates/chrome-node-scaledjobs.yaml @@ -9,8 +9,8 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} labels: - app: selenium-chrome-node - app.kubernetes.io/name: selenium-chrome-node + app: {{ template "seleniumGrid.chromeNode.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.chromeNode.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.chromeNode.labels }} {{- toYaml . | nindent 4 }} @@ -19,21 +19,10 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: - maxReplicaCount: {{ .Values.chromeNode.maxReplicaCount }} - {{- with .Values.autoscaling.scaledJobOptions -}} - {{ toYaml . | nindent 2 }} - {{- end }} - triggers: - - type: selenium-grid - {{- with .Values.chromeNode.hpa }} - metadata: {{- tpl (toYaml .) $ | nindent 8 }} - {{- end }} - jobTargetRef: - parallelism: 1 - completions: 1 - backoffLimit: 0 -{{- $podScope := deepCopy . -}} -{{- $_ := set $podScope "name" "selenium-chrome-node" -}} -{{- $_ = set $podScope "node" .Values.chromeNode -}} -{{- include "seleniumGrid.podTemplate" $podScope | nindent 4 }} + {{- $podScope := deepCopy . -}} + {{- $_ := set $podScope "name" (include "seleniumGrid.chromeNode.fullname" .) -}} + {{- $_ = set $podScope "node" .Values.chromeNode -}} + {{- $_ = set $podScope "uploader" (get .Values.videoRecorder (.Values.videoRecorder.uploader | toString)) -}} + {{- $_ = set $podScope "podTemplate" (include "seleniumGrid.podTemplate" $podScope | fromYaml) }} + {{- include "seleniumGrid.autoscalingTemplate" $podScope | nindent 2 }} {{- end }} diff --git a/charts/selenium-grid/templates/chrome-node-service.yaml b/charts/selenium-grid/templates/chrome-node-service.yaml index 41aebd5705..efe8f1873b 100644 --- a/charts/selenium-grid/templates/chrome-node-service.yaml +++ b/charts/selenium-grid/templates/chrome-node-service.yaml @@ -5,7 +5,7 @@ metadata: name: {{ template "seleniumGrid.chromeNode.fullname" . }} namespace: {{ .Release.Namespace }} labels: - name: selenium-chrome-node + name: {{ template "seleniumGrid.chromeNode.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.chromeNode.service.annotations }} annotations: @@ -14,11 +14,27 @@ metadata: spec: type: {{ .Values.chromeNode.service.type }} selector: - app: selenium-chrome-node + app: {{ template "seleniumGrid.chromeNode.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} + {{- if and (eq .Values.chromeNode.service.type "LoadBalancer") (.Values.chromeNode.service.loadBalancerIP) }} + loadBalancerIP: {{ .Values.chromeNode.service.loadBalancerIP }} + {{- end }} ports: - name: tcp-chrome protocol: TCP port: {{ .Values.chromeNode.seleniumServicePort }} targetPort: {{ .Values.chromeNode.seleniumPort }} + {{- with .Values.chromeNode.service.ports }} + {{- range . }} + - name: {{ .name }} + port: {{ .port }} + targetPort: {{ .targetPort }} + {{- if .protocol }} + protocol: {{ .protocol }} + {{- end }} + {{- if and (eq $.Values.chromeNode.service.type "NodePort") .nodePort }} + nodePort: {{ .nodePort }} + {{- end }} + {{- end }} + {{- end }} {{- end }} diff --git a/charts/selenium-grid/templates/distributor-deployment.yaml b/charts/selenium-grid/templates/distributor-deployment.yaml index bf35d43ed7..07462f15ef 100644 --- a/charts/selenium-grid/templates/distributor-deployment.yaml +++ b/charts/selenium-grid/templates/distributor-deployment.yaml @@ -5,8 +5,8 @@ metadata: name: {{ template "seleniumGrid.distributor.fullname" . }} namespace: {{ .Release.Namespace }} labels: &distributor_labels - app: selenium-distributor - app.kubernetes.io/name: selenium-distributor + app: {{ template "seleniumGrid.distributor.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.distributor.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ spec: replicas: 1 selector: matchLabels: - app: selenium-distributor + app: {{ template "seleniumGrid.distributor.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: @@ -27,9 +27,10 @@ spec: serviceAccountName: {{ template "seleniumGrid.serviceAccount.fullname" . }} serviceAccount: {{ template "seleniumGrid.serviceAccount.fullname" . }} containers: - - name: selenium-distributor + - name: {{ template "seleniumGrid.distributor.fullname" . }} {{- $imageTag := default .Values.global.seleniumGrid.imageTag .Values.components.distributor.imageTag }} - image: {{ printf "%s:%s" .Values.components.distributor.imageName $imageTag }} + {{- $imageRegistry := default .Values.global.seleniumGrid.imageRegistry .Values.components.distributor.imageRegistry }} + image: {{ printf "%s/%s:%s" $imageRegistry .Values.components.distributor.imageName $imageTag }} imagePullPolicy: {{ .Values.components.distributor.imagePullPolicy }} env: - name: SE_SESSIONS_MAP_HOST diff --git a/charts/selenium-grid/templates/distributor-service.yaml b/charts/selenium-grid/templates/distributor-service.yaml index 067be89522..295407fac8 100644 --- a/charts/selenium-grid/templates/distributor-service.yaml +++ b/charts/selenium-grid/templates/distributor-service.yaml @@ -5,7 +5,7 @@ metadata: name: {{ template "seleniumGrid.distributor.fullname" . }} namespace: {{ .Release.Namespace }} labels: - app: selenium-distributor + app: {{ template "seleniumGrid.distributor.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ metadata: {{- end }} spec: selector: - app: selenium-distributor + app: {{ template "seleniumGrid.distributor.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} type: {{ .Values.components.distributor.serviceType }} ports: diff --git a/charts/selenium-grid/templates/edge-node-deployment.yaml b/charts/selenium-grid/templates/edge-node-deployment.yaml index 883a45a766..9802239e8c 100644 --- a/charts/selenium-grid/templates/edge-node-deployment.yaml +++ b/charts/selenium-grid/templates/edge-node-deployment.yaml @@ -5,8 +5,8 @@ metadata: name: {{ template "seleniumGrid.edgeNode.fullname" . }} namespace: {{ .Release.Namespace }} labels: - app: selenium-edge-node - app.kubernetes.io/name: selenium-edge-node + app: {{ template "seleniumGrid.edgeNode.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.edgeNode.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.edgeNode.labels }} {{- toYaml . | nindent 4 }} @@ -20,10 +20,11 @@ spec: {{end}} selector: matchLabels: - app: selenium-edge-node + app: {{ template "seleniumGrid.edgeNode.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- $podScope := deepCopy . -}} -{{- $_ := set $podScope "name" "selenium-edge-node" -}} -{{- $_ = set $podScope "node" .Values.edgeNode -}} +{{- $_ := set $podScope "name" (include "seleniumGrid.edgeNode.fullname" .) -}} +{{- $_ = set $podScope "node" .Values.edgeNode -}} +{{- $_ = set $podScope "uploader" (get .Values.videoRecorder (.Values.videoRecorder.uploader | toString)) -}} {{- include "seleniumGrid.podTemplate" $podScope | nindent 2 }} {{- end }} diff --git a/charts/selenium-grid/templates/edge-node-hpa.yaml b/charts/selenium-grid/templates/edge-node-hpa.yaml index b115de3534..0839a3bdd6 100644 --- a/charts/selenium-grid/templates/edge-node-hpa.yaml +++ b/charts/selenium-grid/templates/edge-node-hpa.yaml @@ -11,13 +11,8 @@ metadata: labels: deploymentName: {{ template "seleniumGrid.edgeNode.fullname" . }} spec: - maxReplicaCount: {{ .Values.edgeNode.maxReplicaCount }} - minReplicaCount: {{ .Values.edgeNode.minReplicaCount }} - scaleTargetRef: - name: {{ template "seleniumGrid.edgeNode.fullname" . }} - triggers: - - type: selenium-grid - {{- with .Values.edgeNode.hpa }} - metadata: {{- tpl (toYaml .) $ | nindent 8 }} - {{- end }} + {{- $podScope := deepCopy . -}} + {{- $_ := set $podScope "name" (include "seleniumGrid.edgeNode.fullname" .) -}} + {{- $_ = set $podScope "node" .Values.edgeNode -}} + {{- include "seleniumGrid.autoscalingTemplate" $podScope | nindent 2 }} {{- end }} diff --git a/charts/selenium-grid/templates/edge-node-scaledjob.yaml b/charts/selenium-grid/templates/edge-node-scaledjob.yaml index 6d113d186d..132792c796 100644 --- a/charts/selenium-grid/templates/edge-node-scaledjob.yaml +++ b/charts/selenium-grid/templates/edge-node-scaledjob.yaml @@ -9,8 +9,8 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} labels: - app: selenium-edge-node - app.kubernetes.io/name: selenium-edge-node + app: {{ template "seleniumGrid.edgeNode.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.edgeNode.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.edgeNode.labels }} {{- toYaml . | nindent 4 }} @@ -19,21 +19,10 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: - maxReplicaCount: {{ .Values.edgeNode.maxReplicaCount }} - {{- with .Values.autoscaling.scaledJobOptions -}} - {{ toYaml . | nindent 2 }} - {{- end }} - triggers: - - type: selenium-grid - {{- with .Values.edgeNode.hpa }} - metadata: {{- tpl (toYaml .) $ | nindent 8 }} - {{- end }} - jobTargetRef: - parallelism: 1 - completions: 1 - backoffLimit: 0 -{{- $podScope := deepCopy . -}} -{{- $_ := set $podScope "name" "selenium-edge-node" -}} -{{- $_ = set $podScope "node" .Values.edgeNode -}} -{{- include "seleniumGrid.podTemplate" $podScope | nindent 4 }} + {{- $podScope := deepCopy . -}} + {{- $_ := set $podScope "name" (include "seleniumGrid.edgeNode.fullname" .) -}} + {{- $_ = set $podScope "node" .Values.edgeNode -}} + {{- $_ = set $podScope "uploader" (get .Values.videoRecorder (.Values.videoRecorder.uploader | toString)) -}} + {{- $_ = set $podScope "podTemplate" (include "seleniumGrid.podTemplate" $podScope | fromYaml) }} + {{- include "seleniumGrid.autoscalingTemplate" $podScope | nindent 2 }} {{- end }} diff --git a/charts/selenium-grid/templates/edge-node-service.yaml b/charts/selenium-grid/templates/edge-node-service.yaml index ae59a4a634..d54dd70a3b 100644 --- a/charts/selenium-grid/templates/edge-node-service.yaml +++ b/charts/selenium-grid/templates/edge-node-service.yaml @@ -5,7 +5,7 @@ metadata: name: {{ template "seleniumGrid.edgeNode.fullname" . }} namespace: {{ .Release.Namespace }} labels: - name: selenium-edge-node + name: {{ template "seleniumGrid.edgeNode.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.edgeNode.service.annotations }} annotations: @@ -14,11 +14,27 @@ metadata: spec: type: {{ .Values.edgeNode.service.type }} selector: - app: selenium-edge-node + app: {{ template "seleniumGrid.edgeNode.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} + {{- if and (eq .Values.edgeNode.service.type "LoadBalancer") (.Values.edgeNode.service.loadBalancerIP) }} + loadBalancerIP: {{ .Values.edgeNode.service.loadBalancerIP }} + {{- end }} ports: - name: tcp-edge protocol: TCP port: {{ .Values.edgeNode.seleniumServicePort }} targetPort: {{ .Values.edgeNode.seleniumPort }} + {{- with .Values.edgeNode.service.ports }} + {{- range . }} + - name: {{ .name }} + port: {{ .port }} + targetPort: {{ .targetPort }} + {{- if .protocol }} + protocol: {{ .protocol }} + {{- end }} + {{- if and (eq $.Values.edgeNode.service.type "NodePort") .nodePort }} + nodePort: {{ .nodePort }} + {{- end }} + {{- end }} + {{- end }} {{- end }} diff --git a/charts/selenium-grid/templates/event-bus-configmap.yaml b/charts/selenium-grid/templates/event-bus-configmap.yaml index efe33fa7d0..05f279bba5 100644 --- a/charts/selenium-grid/templates/event-bus-configmap.yaml +++ b/charts/selenium-grid/templates/event-bus-configmap.yaml @@ -15,6 +15,6 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} data: - SE_EVENT_BUS_HOST: {{ $eventBusHost }} + SE_EVENT_BUS_HOST: {{ $eventBusHost | quote }} SE_EVENT_BUS_PUBLISH_PORT: {{ $eventBusPublishPort | quote }} SE_EVENT_BUS_SUBSCRIBE_PORT: {{ $eventBusSubscribePort | quote }} diff --git a/charts/selenium-grid/templates/event-bus-deployment.yaml b/charts/selenium-grid/templates/event-bus-deployment.yaml index 498921e8cb..8d894790b7 100644 --- a/charts/selenium-grid/templates/event-bus-deployment.yaml +++ b/charts/selenium-grid/templates/event-bus-deployment.yaml @@ -5,8 +5,8 @@ metadata: name: {{ template "seleniumGrid.eventBus.fullname" . }} namespace: {{ .Release.Namespace }} labels: &event_bus_labels - app: selenium-event-bus - app.kubernetes.io/name: selenium-event-bus + app: {{ template "seleniumGrid.eventBus.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.eventBus.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ spec: replicas: 1 selector: matchLabels: - app: selenium-event-bus + app: {{ template "seleniumGrid.eventBus.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: @@ -27,9 +27,10 @@ spec: serviceAccountName: {{ template "seleniumGrid.serviceAccount.fullname" . }} serviceAccount: {{ template "seleniumGrid.serviceAccount.fullname" . }} containers: - - name: selenium-event-bus + - name: {{ template "seleniumGrid.eventBus.fullname" . }} {{- $imageTag := default .Values.global.seleniumGrid.imageTag .Values.components.eventBus.imageTag }} - image: {{ printf "%s:%s" .Values.components.eventBus.imageName $imageTag }} + {{- $imageRegistry := default .Values.global.seleniumGrid.imageRegistry .Values.components.eventBus.imageRegistry }} + image: {{ printf "%s/%s:%s" $imageRegistry .Values.components.eventBus.imageName $imageTag }} imagePullPolicy: {{ .Values.components.eventBus.imagePullPolicy }} ports: - containerPort: {{ .Values.components.eventBus.port }} diff --git a/charts/selenium-grid/templates/event-bus-service.yaml b/charts/selenium-grid/templates/event-bus-service.yaml index 38ff6cd1e1..c3a30bcc0e 100644 --- a/charts/selenium-grid/templates/event-bus-service.yaml +++ b/charts/selenium-grid/templates/event-bus-service.yaml @@ -5,7 +5,7 @@ metadata: name: {{ template "seleniumGrid.eventBus.fullname" . }} namespace: {{ .Release.Namespace }} labels: - app: selenium-event-bus + app: {{ template "seleniumGrid.eventBus.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ metadata: {{- end }} spec: selector: - app: selenium-event-bus + app: {{ template "seleniumGrid.eventBus.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} type: {{ .Values.components.eventBus.serviceType }} ports: diff --git a/charts/selenium-grid/templates/firefox-node-deployment.yaml b/charts/selenium-grid/templates/firefox-node-deployment.yaml index d0b250470f..5a1e96b559 100644 --- a/charts/selenium-grid/templates/firefox-node-deployment.yaml +++ b/charts/selenium-grid/templates/firefox-node-deployment.yaml @@ -5,8 +5,8 @@ metadata: name: {{ template "seleniumGrid.firefoxNode.fullname" . }} namespace: {{ .Release.Namespace }} labels: - app: selenium-firefox-node - app.kubernetes.io/name: selenium-firefox-node + app: {{ template "seleniumGrid.firefoxNode.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.firefoxNode.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.firefoxNode.labels }} {{- toYaml . | nindent 4 }} @@ -20,10 +20,11 @@ spec: {{end}} selector: matchLabels: - app: selenium-firefox-node + app: {{ template "seleniumGrid.firefoxNode.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- $podScope := deepCopy . -}} -{{- $_ := set $podScope "name" "selenium-firefox-node" -}} -{{- $_ = set $podScope "node" .Values.firefoxNode -}} +{{- $_ := set $podScope "name" (include "seleniumGrid.firefoxNode.fullname" .) -}} +{{- $_ = set $podScope "node" .Values.firefoxNode -}} +{{- $_ = set $podScope "uploader" (get .Values.videoRecorder (.Values.videoRecorder.uploader | toString)) -}} {{- include "seleniumGrid.podTemplate" $podScope | nindent 2 }} {{- end }} diff --git a/charts/selenium-grid/templates/firefox-node-hpa.yaml b/charts/selenium-grid/templates/firefox-node-hpa.yaml index 70a463e798..ad18269a57 100644 --- a/charts/selenium-grid/templates/firefox-node-hpa.yaml +++ b/charts/selenium-grid/templates/firefox-node-hpa.yaml @@ -11,13 +11,8 @@ metadata: labels: deploymentName: {{ template "seleniumGrid.firefoxNode.fullname" . }} spec: - maxReplicaCount: {{ .Values.firefoxNode.maxReplicaCount }} - minReplicaCount: {{ .Values.firefoxNode.minReplicaCount }} - scaleTargetRef: - name: {{ template "seleniumGrid.firefoxNode.fullname" . }} - triggers: - - type: selenium-grid - {{- with .Values.firefoxNode.hpa }} - metadata: {{- tpl (toYaml .) $ | nindent 8 }} - {{- end }} + {{- $podScope := deepCopy . -}} + {{- $_ := set $podScope "name" (include "seleniumGrid.firefoxNode.fullname" .) -}} + {{- $_ = set $podScope "node" .Values.firefoxNode -}} + {{- include "seleniumGrid.autoscalingTemplate" $podScope | nindent 2 }} {{- end }} diff --git a/charts/selenium-grid/templates/firefox-node-scaledjob.yaml b/charts/selenium-grid/templates/firefox-node-scaledjob.yaml index de90024c7c..e7992c1fc7 100644 --- a/charts/selenium-grid/templates/firefox-node-scaledjob.yaml +++ b/charts/selenium-grid/templates/firefox-node-scaledjob.yaml @@ -9,8 +9,8 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} labels: - app: selenium-firefox-node - app.kubernetes.io/name: selenium-firefox-node + app: {{ template "seleniumGrid.firefoxNode.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.firefoxNode.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.firefoxNode.labels }} {{- toYaml . | nindent 4 }} @@ -19,21 +19,10 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: - maxReplicaCount: {{ .Values.firefoxNode.maxReplicaCount }} - {{- with .Values.autoscaling.scaledJobOptions -}} - {{ toYaml . | nindent 2 }} - {{- end }} - triggers: - - type: selenium-grid - {{- with .Values.firefoxNode.hpa }} - metadata: {{- tpl (toYaml .) $ | nindent 8 }} - {{- end }} - jobTargetRef: - parallelism: 1 - completions: 1 - backoffLimit: 0 -{{- $podScope := deepCopy . -}} -{{- $_ := set $podScope "name" "selenium-firefox-node" -}} -{{- $_ = set $podScope "node" .Values.firefoxNode -}} -{{- include "seleniumGrid.podTemplate" $podScope | nindent 4 }} + {{- $podScope := deepCopy . -}} + {{- $_ := set $podScope "name" (include "seleniumGrid.firefoxNode.fullname" .) -}} + {{- $_ = set $podScope "node" .Values.firefoxNode -}} + {{- $_ = set $podScope "uploader" (get .Values.videoRecorder (.Values.videoRecorder.uploader | toString)) -}} + {{- $_ = set $podScope "podTemplate" (include "seleniumGrid.podTemplate" $podScope | fromYaml) }} + {{- include "seleniumGrid.autoscalingTemplate" $podScope | nindent 2 }} {{- end }} diff --git a/charts/selenium-grid/templates/firefox-node-service.yaml b/charts/selenium-grid/templates/firefox-node-service.yaml index 473225f934..43ba40380e 100644 --- a/charts/selenium-grid/templates/firefox-node-service.yaml +++ b/charts/selenium-grid/templates/firefox-node-service.yaml @@ -5,7 +5,7 @@ metadata: name: {{ template "seleniumGrid.firefoxNode.fullname" . }} namespace: {{ .Release.Namespace }} labels: - name: selenium-firefox-node + name: {{ template "seleniumGrid.firefoxNode.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.firefoxNode.service.annotations }} annotations: @@ -14,11 +14,27 @@ metadata: spec: type: {{ .Values.firefoxNode.service.type }} selector: - app: selenium-firefox-node + app: {{ template "seleniumGrid.firefoxNode.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} + {{- if and (eq .Values.firefoxNode.service.type "LoadBalancer") (.Values.firefoxNode.service.loadBalancerIP) }} + loadBalancerIP: {{ .Values.firefoxNode.service.loadBalancerIP }} + {{- end }} ports: - name: tcp-firefox protocol: TCP port: {{ .Values.firefoxNode.seleniumServicePort }} targetPort: {{ .Values.firefoxNode.seleniumPort }} + {{- with .Values.firefoxNode.service.ports }} + {{- range . }} + - name: {{ .name }} + port: {{ .port }} + targetPort: {{ .targetPort }} + {{- if .protocol }} + protocol: {{ .protocol }} + {{- end }} + {{- if and (eq $.Values.firefoxNode.service.type "NodePort") .nodePort }} + nodePort: {{ .nodePort }} + {{- end }} + {{- end }} + {{- end }} {{- end }} diff --git a/charts/selenium-grid/templates/hub-deployment.yaml b/charts/selenium-grid/templates/hub-deployment.yaml index 6f9488d121..8b322ecd59 100644 --- a/charts/selenium-grid/templates/hub-deployment.yaml +++ b/charts/selenium-grid/templates/hub-deployment.yaml @@ -5,8 +5,8 @@ metadata: name: {{ template "seleniumGrid.hub.fullname" . }} namespace: {{ .Release.Namespace }} labels: &hub_labels - app: selenium-hub - app.kubernetes.io/name: selenium-hub + app: {{ template "seleniumGrid.hub.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.hub.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.hub.labels }} {{- toYaml . | nindent 4 }} @@ -18,7 +18,7 @@ spec: replicas: 1 selector: matchLabels: - app: selenium-hub + app: {{ template "seleniumGrid.hub.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: @@ -30,9 +30,10 @@ spec: serviceAccountName: {{ template "seleniumGrid.serviceAccount.fullname" . }} serviceAccount: {{ template "seleniumGrid.serviceAccount.fullname" . }} containers: - - name: selenium-hub + - name: {{ template "seleniumGrid.hub.fullname" . }} {{- $imageTag := default .Values.global.seleniumGrid.imageTag .Values.hub.imageTag }} - image: {{ printf "%s:%s" .Values.hub.imageName $imageTag }} + {{- $imageRegistry := default .Values.global.seleniumGrid.imageRegistry .Values.hub.imageRegistry }} + image: {{ printf "%s/%s:%s" $imageRegistry .Values.hub.imageName $imageTag }} imagePullPolicy: {{ .Values.hub.imagePullPolicy }} ports: - containerPort: {{ .Values.hub.port }} diff --git a/charts/selenium-grid/templates/hub-service.yaml b/charts/selenium-grid/templates/hub-service.yaml index 417e9849f6..aa4daa34ca 100644 --- a/charts/selenium-grid/templates/hub-service.yaml +++ b/charts/selenium-grid/templates/hub-service.yaml @@ -5,7 +5,7 @@ metadata: name: {{ template "seleniumGrid.hub.fullname" . }} namespace: {{ .Release.Namespace }} labels: - app: selenium-hub + app: {{ template "seleniumGrid.hub.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ metadata: {{- end }} spec: selector: - app: selenium-hub + app: {{ template "seleniumGrid.hub.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} type: {{ .Values.hub.serviceType }} {{- if and (eq .Values.hub.serviceType "LoadBalancer") ( .Values.hub.loadBalancerIP ) }} diff --git a/charts/selenium-grid/templates/ingress.yaml b/charts/selenium-grid/templates/ingress.yaml index 6df2c95530..215cfbacea 100644 --- a/charts/selenium-grid/templates/ingress.yaml +++ b/charts/selenium-grid/templates/ingress.yaml @@ -14,14 +14,19 @@ apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ template "seleniumGrid.ingress.fullname" . }} + namespace: {{ .Release.Namespace }} labels: {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} {{- end }} - {{- with .Values.ingress.annotations }} + {{- $ingressAnnotations := (include "seleniumGrid.ingress.nginx.annotations.default" . | toString | fromYaml ) }} + {{- with .Values.ingress.annotations -}} + {{- $ingressAnnotations = mergeOverwrite $ingressAnnotations . }} + {{- end }} + {{- if not (empty $ingressAnnotations) }} annotations: - {{- toYaml . | nindent 4 }} + {{- $ingressAnnotations | toYaml | nindent 4 }} {{- end }} spec: {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} @@ -46,8 +51,9 @@ spec: {{- end }} {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.Version }} paths: + {{- if empty (.Values.ingress.paths) }} - path: {{ $.Values.ingress.path | default "/" }} - pathType: Prefix + pathType: {{ $.Values.ingress.pathType | default "Prefix" }} backend: service: {{- if $.Values.isolateComponents }} @@ -59,6 +65,9 @@ spec: port: number: {{ $.Values.hub.port }} {{- end }} + {{- else }} + {{- tpl (toYaml .Values.ingress.paths | nindent 10) . }} + {{- end }} {{- else }} paths: - path: / diff --git a/charts/selenium-grid/templates/node-configmap.yaml b/charts/selenium-grid/templates/node-configmap.yaml index 08d6d49812..da4edab401 100644 --- a/charts/selenium-grid/templates/node-configmap.yaml +++ b/charts/selenium-grid/templates/node-configmap.yaml @@ -12,5 +12,5 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} data: - DRAIN_AFTER_SESSION_COUNT: '{{- and (eq (include "seleniumGrid.useKEDA" .) "true") (eq .Values.autoscaling.scalingType "job") | ternary "1" "0" -}}' + SE_DRAIN_AFTER_SESSION_COUNT: '{{- and (eq (include "seleniumGrid.useKEDA" .) "true") (eq .Values.autoscaling.scalingType "job") | ternary "1" "0" -}}' SE_NODE_GRID_URL: '{{ include "seleniumGrid.url" .}}' diff --git a/charts/selenium-grid/templates/router-deployment.yaml b/charts/selenium-grid/templates/router-deployment.yaml index 037bcbf394..33d98c65aa 100644 --- a/charts/selenium-grid/templates/router-deployment.yaml +++ b/charts/selenium-grid/templates/router-deployment.yaml @@ -5,8 +5,8 @@ metadata: name: {{ template "seleniumGrid.router.fullname" . }} namespace: {{ .Release.Namespace }} labels: &router_labels - app: selenium-router - app.kubernetes.io/name: selenium-router + app: {{ template "seleniumGrid.router.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.router.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ spec: replicas: 1 selector: matchLabels: - app: selenium-router + app: {{ template "seleniumGrid.router.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: @@ -27,9 +27,10 @@ spec: serviceAccountName: {{ template "seleniumGrid.serviceAccount.fullname" . }} serviceAccount: {{ template "seleniumGrid.serviceAccount.fullname" . }} containers: - - name: selenium-router + - name: {{ template "seleniumGrid.router.fullname" . }} {{- $imageTag := default .Values.global.seleniumGrid.imageTag .Values.components.router.imageTag }} - image: {{ printf "%s:%s" .Values.components.router.imageName $imageTag }} + {{- $imageRegistry := default .Values.global.seleniumGrid.imageRegistry .Values.components.router.imageRegistry }} + image: {{ printf "%s/%s:%s" $imageRegistry .Values.components.router.imageName $imageTag }} imagePullPolicy: {{ .Values.components.router.imagePullPolicy }} env: - name: SE_DISTRIBUTOR_HOST diff --git a/charts/selenium-grid/templates/router-service.yaml b/charts/selenium-grid/templates/router-service.yaml index d586c31fed..9eaff79556 100644 --- a/charts/selenium-grid/templates/router-service.yaml +++ b/charts/selenium-grid/templates/router-service.yaml @@ -5,7 +5,7 @@ metadata: name: {{ template "seleniumGrid.router.fullname" . }} namespace: {{ .Release.Namespace }} labels: - app: selenium-router + app: {{ template "seleniumGrid.router.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ metadata: {{- end }} spec: selector: - app: selenium-router + app: {{ template "seleniumGrid.router.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} type: {{ .Values.components.router.serviceType }} {{- if and (eq .Values.components.router.serviceType "LoadBalancer") (.Values.components.router.loadBalancerIP) }} diff --git a/charts/selenium-grid/templates/session-map-deployment.yaml b/charts/selenium-grid/templates/session-map-deployment.yaml index 437c664e25..8aebdefb2c 100644 --- a/charts/selenium-grid/templates/session-map-deployment.yaml +++ b/charts/selenium-grid/templates/session-map-deployment.yaml @@ -5,8 +5,8 @@ metadata: name: {{ template "seleniumGrid.sessionMap.fullname" . }} namespace: {{ .Release.Namespace }} labels: &session_map_labels - app: selenium-session-map - app.kubernetes.io/name: selenium-session-map + app: {{ template "seleniumGrid.sessionMap.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.sessionMap.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ spec: replicas: 1 selector: matchLabels: - app: selenium-session-map + app: {{ template "seleniumGrid.sessionMap.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: @@ -27,9 +27,10 @@ spec: serviceAccountName: {{ template "seleniumGrid.serviceAccount.fullname" . }} serviceAccount: {{ template "seleniumGrid.serviceAccount.fullname" . }} containers: - - name: selenium-session-map + - name: {{ template "seleniumGrid.sessionMap.fullname" . }} {{- $imageTag := default .Values.global.seleniumGrid.imageTag .Values.components.sessionMap.imageTag }} - image: {{ printf "%s:%s" .Values.components.sessionMap.imageName $imageTag }} + {{- $imageRegistry := default .Values.global.seleniumGrid.imageRegistry .Values.components.sessionMap.imageRegistry }} + image: {{ printf "%s/%s:%s" $imageRegistry .Values.components.sessionMap.imageName $imageTag }} imagePullPolicy: {{ .Values.components.sessionMap.imagePullPolicy }} {{- with .Values.components.extraEnvironmentVariables }} env: {{- tpl (toYaml .) $ | nindent 12 }} diff --git a/charts/selenium-grid/templates/session-map-service.yaml b/charts/selenium-grid/templates/session-map-service.yaml index 6df2d9bbf0..13dd963b69 100644 --- a/charts/selenium-grid/templates/session-map-service.yaml +++ b/charts/selenium-grid/templates/session-map-service.yaml @@ -5,7 +5,7 @@ metadata: name: {{ template "seleniumGrid.sessionMap.fullname" . }} namespace: {{ .Release.Namespace }} labels: - app: selenium-session-map + app: {{ template "seleniumGrid.sessionMap.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ metadata: {{- end }} spec: selector: - app: selenium-session-map + app: {{ template "seleniumGrid.sessionMap.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} type: {{ .Values.components.sessionMap.serviceType }} ports: diff --git a/charts/selenium-grid/templates/session-queuer-deployment.yaml b/charts/selenium-grid/templates/session-queuer-deployment.yaml index 0f26f06e5e..557d6774e0 100644 --- a/charts/selenium-grid/templates/session-queuer-deployment.yaml +++ b/charts/selenium-grid/templates/session-queuer-deployment.yaml @@ -5,8 +5,8 @@ metadata: name: {{ template "seleniumGrid.sessionQueue.fullname" . }} namespace: {{ .Release.Namespace }} labels: &session_queue_labels - app: selenium-session-queue - app.kubernetes.io/name: selenium-session-queue + app: {{ template "seleniumGrid.sessionQueue.fullname" . }} + app.kubernetes.io/name: {{ template "seleniumGrid.sessionQueue.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ spec: replicas: 1 selector: matchLabels: - app: selenium-session-queue + app: {{ template "seleniumGrid.sessionQueue.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: @@ -27,9 +27,10 @@ spec: serviceAccountName: {{ template "seleniumGrid.serviceAccount.fullname" . }} serviceAccount: {{ template "seleniumGrid.serviceAccount.fullname" . }} containers: - - name: selenium-session-queue + - name: {{ template "seleniumGrid.sessionQueue.fullname" . }} {{- $imageTag := default .Values.global.seleniumGrid.imageTag .Values.components.sessionQueue.imageTag }} - image: {{ printf "%s:%s" .Values.components.sessionQueue.imageName $imageTag }} + {{- $imageRegistry := default .Values.global.seleniumGrid.imageRegistry .Values.components.sessionQueue.imageRegistry }} + image: {{ printf "%s/%s:%s" $imageRegistry .Values.components.sessionQueue.imageName $imageTag }} imagePullPolicy: {{ .Values.components.sessionQueue.imagePullPolicy }} {{- with .Values.components.extraEnvironmentVariables }} env: {{- tpl (toYaml .) $ | nindent 12 }} diff --git a/charts/selenium-grid/templates/session-queuer-service.yaml b/charts/selenium-grid/templates/session-queuer-service.yaml index be3739ad01..54e535f7b0 100644 --- a/charts/selenium-grid/templates/session-queuer-service.yaml +++ b/charts/selenium-grid/templates/session-queuer-service.yaml @@ -5,7 +5,7 @@ metadata: name: {{ template "seleniumGrid.sessionQueue.fullname" . }} namespace: {{ .Release.Namespace }} labels: - app: selenium-session-queue + app: {{ template "seleniumGrid.sessionQueue.fullname" . }} {{- include "seleniumGrid.commonLabels" . | nindent 4 }} {{- with .Values.customLabels }} {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ metadata: {{- end }} spec: selector: - app: selenium-session-queue + app: {{ template "seleniumGrid.sessionQueue.fullname" . }} app.kubernetes.io/instance: {{ .Release.Name }} type: {{ .Values.components.sessionQueue.serviceType }} ports: diff --git a/charts/selenium-grid/templates/video-cm.yaml b/charts/selenium-grid/templates/video-cm.yaml new file mode 100644 index 0000000000..1b49e026e8 --- /dev/null +++ b/charts/selenium-grid/templates/video-cm.yaml @@ -0,0 +1,98 @@ +{{- if .Values.videoRecorder.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "seleniumGrid.video.fullname" . }} +data: + video.sh: | + #!/usr/bin/env bash + set -em + function finish { + echo exit > /videos/uploadpipe + kill -s SIGINT `cat /var/run/supervisor/supervisord.pid` + } + trap finish EXIT + FRAME_RATE=${FRAME_RATE:-$SE_FRAME_RATE} + CODEC=${CODEC:-$SE_CODEC} + PRESET=${PRESET:-$SE_PRESET} + export DISPLAY=localhost:${DISPLAY_NUM}.0 + + return_code=1 + max_attempts=600 + attempts=0 + if [ ! -p /videos/uploadpipe ]; + then + mkfifo /videos/uploadpipe + fi + if [[ "$UPLOAD_DESTINATION_PREFIX" = "" ]] + then + echo Upload destination not known since UPLOAD_DESTINATION_PREFIX is not set. Exiting video recorder. + exit + fi + echo Checking if the display is open + until xset b off || [[ $attempts = $max_attempts ]] + do + echo Waiting before next display check + sleep 0.5 + attempts=$((attempts+1)) + done + if [[ $attempts = $max_attempts ]] + then + echo Can not open display, exiting. + exit + fi + VIDEO_SIZE=$(xdpyinfo | grep 'dimensions:' | awk '{print $2}') + + recording_started="false" + video_file_name="" + video_file="" + prev_session_id="" + attempts=0 + echo Checking if node API responds + until curl -s --request GET http://localhost:5555/status || [[ $attempts = $max_attempts ]] + do + echo Waiting before next API check + sleep 0.5 + attempts=$((attempts+1)) + done + if [[ $attempts = $max_attempts ]] + then + echo Can not reach node API, exiting. + exit + fi + while curl -s --request GET http://localhost:5555/status > /tmp/status.json + do + session_id=$(jq -r '.[]?.node?.slots | .[0]?.session?.sessionId' /tmp/status.json) + echo $session_id + if [[ "$session_id" != "null" && "$session_id" != "" && "$recording_started" = "false" ]] + then + video_file_name="$session_id.mp4" + video_file="${SE_VIDEO_FOLDER:-/videos}/$video_file_name" + echo "Starting to record video" + ffmpeg -nostdin -y -f x11grab -video_size ${VIDEO_SIZE} -r ${FRAME_RATE} -i ${DISPLAY} -codec:v ${CODEC} ${PRESET} -pix_fmt yuv420p $video_file & + recording_started="true" + echo "Video recording started" + elif [[ "$session_id" != "$prev_session_id" && "$recording_started" = "true" ]] + then + echo "Stopping to record video" + kill -INT %1 + fg || echo ffmpeg exited with code $? + if [[ "$UPLOAD_DESTINATION_PREFIX" != "false" ]] + then + upload_destination=${UPLOAD_DESTINATION_PREFIX}${video_file_name} + echo "Uploading video to $upload_destination" + echo $video_file $upload_destination > /videos/uploadpipe + fi + recording_started="false" + elif [[ $recording_started = "true" ]] + then + echo "Video recording in progress" + sleep 1 + else + echo "No session in progress" + sleep 1 + fi + prev_session_id=$session_id + done + echo +{{- end }} diff --git a/charts/selenium-grid/values.yaml b/charts/selenium-grid/values.yaml index a29c278656..ae9840ce50 100644 --- a/charts/selenium-grid/values.yaml +++ b/charts/selenium-grid/values.yaml @@ -1,20 +1,24 @@ global: seleniumGrid: + # Image registry for all selenium components + imageRegistry: selenium # Image tag for all selenium components - imageTag: 4.12.1-20230920 + imageTag: 4.16.0-20231206 # Image tag for browser's nodes - nodesImageTag: 4.12.1-20230920 + nodesImageTag: 4.16.0-20231206 + # Image tag for browser's video recorder + videoImageTag: ffmpeg-6.1-20231206 # Pull secret for all components, can be overridden individually - imagePullSecret: "" + imagePullSecret: "" # Basic auth settings for Selenium Grid basicAuth: - # Enable or disable basic auth - enabled: true - # Username for basic auth - username: admin - # Password for basic auth - password: admin + # Enable or disable basic auth + enabled: true + # Username for basic auth + username: admin + # Password for basic auth + password: admin # Deploy Router, Distributor, EventBus, SessionMap and Nodes separately isolateComponents: false @@ -24,6 +28,7 @@ serviceAccount: create: true name: "" annotations: {} + # eks.amazonaws.com/role-arn: "arn:aws:iam::12345678:role/video-bucket-permissions" # Configure the ingress resource to access the Grid installation. ingress: @@ -31,12 +36,22 @@ ingress: enabled: true # Name of ingress class to select which controller will implement ingress resource className: "" + # Refer to list nginx annotations: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md#annotations + nginx: + proxyTimeout: 3600 + proxyBuffer: + size: 512M + number: 4 # Custom annotations for ingress resource annotations: {} # Default host for the ingress resource - hostname: selenium-grid.local + hostname: "" # Default host path for the ingress resource path: / + # Default path type for the ingress resource + pathType: Prefix + # List of paths for the ingress resource. This will override the default path + paths: [] # TLS backend configuration for ingress resource tls: [] @@ -58,10 +73,11 @@ components: # Configuration for router component router: + # imageRegistry: selenium # Router image name - imageName: selenium/router + imageName: router # Router image tag (this overwrites global.seleniumGrid.imageTag parameter) - # imageTag: 4.12.1-20230920 + # imageTag: 4.16.0-20231206 # Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) imagePullPolicy: IfNotPresent @@ -109,10 +125,11 @@ components: # Configuration for distributor component distributor: + # imageRegistry: selenium # Distributor image name - imageName: selenium/distributor + imageName: distributor # Distributor image tag (this overwrites global.seleniumGrid.imageTag parameter) - # imageTag: 4.12.1-20230920 + # imageTag: 4.16.0-20231206 # Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) imagePullPolicy: IfNotPresent @@ -140,10 +157,11 @@ components: # Configuration for Event Bus component eventBus: + # imageRegistry: selenium # Event Bus image name - imageName: selenium/event-bus + imageName: event-bus # Event Bus image tag (this overwrites global.seleniumGrid.imageTag parameter) - # imageTag: 4.12.1-20230920 + # imageTag: 4.16.0-20231206 # Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) imagePullPolicy: IfNotPresent @@ -175,10 +193,11 @@ components: # Configuration for Session Map component sessionMap: + # imageRegistry: selenium # Session Map image name - imageName: selenium/sessions + imageName: sessions # Session Map image tag (this overwrites global.seleniumGrid.imageTag parameter) - # imageTag: 4.12.1-20230920 + # imageTag: 4.16.0-20231206 # Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) imagePullPolicy: IfNotPresent @@ -205,10 +224,11 @@ components: # Configuration for Session Queue component sessionQueue: + # imageRegistry: selenium # Session Queue image name - imageName: selenium/session-queue + imageName: session-queue # Session Queue image tag (this overwrites global.seleniumGrid.imageTag parameter) - # imageTag: 4.12.1-20230920 + # imageTag: 4.16.0-20231206 # Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) imagePullPolicy: IfNotPresent @@ -255,10 +275,11 @@ components: # Configuration for selenium hub deployment (applied only if `isolateComponents: false`) hub: + # imageRegistry: selenium # Selenium Hub image name - imageName: selenium/hub + imageName: hub # Selenium Hub image tag (this overwrites global.seleniumGrid.imageTag parameter) - # imageTag: 4.12.1-20230920 + # imageTag: 4.16.0-20231206 # Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) imagePullPolicy: IfNotPresent # Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) @@ -342,16 +363,36 @@ autoscaling: enabled: false # Enable autoscaling without automatically installing KEDA enableWithExistingKEDA: false - # Which typ of KEDA scaling to use: job or deployment + # Which type of KEDA scaling to use: job or deployment scalingType: job # Annotations for KEDA resources: ScaledObject and ScaledJob annotations: helm.sh/hook: post-install,post-upgrade - # Options for KEDA ScaledJobs - scaledJobOptions: + # Options for KEDA scaled resources (keep only common options used for both ScaledJob and ScaledObject) + scaledOptions: + minReplicaCount: 0 + maxReplicaCount: 8 pollingInterval: 10 + # List of triggers. Be careful, the default trigger of selenium-grid will be overwritten if you specify this + # triggers: + # Options for KEDA ScaledJobs (only used when scalingType is set to "job") + # see https://keda.sh/docs/latest/concepts/scaling-jobs/#scaledjob-spec + scaledJobOptions: scalingStrategy: strategy: accurate + # Number of Completed jobs should be kept + successfulJobsHistoryLimit: 0 + # Number of Failed jobs should be kept (for troubleshooting purposes) + failedJobsHistoryLimit: 100 + jobTargetRef: + parallelism: 1 + completions: 1 + backoffLimit: 0 + # Options for KEDA ScaledObjects (only used when scalingType is set to "deployment") + # see https://keda.sh/docs/latest/concepts/scaling-deployments/#scaledobject-spec + scaledObjectOptions: + scaleTargetRef: + kind: Deployment deregisterLifecycle: preStop: exec: @@ -375,10 +416,11 @@ chromeNode: # Number of chrome nodes replicas: 1 + # imageRegistry: selenium # Image of chrome nodes - imageName: selenium/node-chrome + imageName: node-chrome # Image of chrome nodes (this overwrites global.seleniumGrid.nodesImageTag) - # imageTag: 4.12.1-20230920 + # imageTag: 4.16.0-20231206 # Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) imagePullPolicy: IfNotPresent # Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) @@ -439,6 +481,13 @@ chromeNode: enabled: true # Service type type: ClusterIP + # Set specific loadBalancerIP when serviceType is LoadBalancer (see https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) + loadBalancerIP: "" + # Extra ports exposed in node service + ports: + # - name: node-port + # port: 5555 + # targetPort: 5555 # Custom annotations for service annotations: {} # Size limit for DSH volume mounted in container (if not set, default is "1Gi") @@ -471,13 +520,15 @@ chromeNode: # persistentVolumeClaim: # claimName: my-pv-claim - maxReplicaCount: 8 - minReplicaCount: 1 + # Override the scaled options for chrome nodes + # scaledOptions: + # scaledJobOptions: + # scaledObjectOptions: hpa: url: '{{ include "seleniumGrid.graphqlURL" . }}' browserName: chrome # browserVersion: '91.0' # Optional. Only required when supporting multiple versions of browser in your Selenium Grid. - unsafeSsl : 'true' # Optional + unsafeSsl: 'true' # Optional # It is used to add a sidecars proxy in the same pod of the browser node. # It means it will add a new container to the deployment itself. @@ -498,10 +549,11 @@ firefoxNode: # Number of firefox nodes replicas: 1 + # imageRegistry: selenium # Image of firefox nodes - imageName: selenium/node-firefox + imageName: node-firefox # Image of firefox nodes (this overwrites global.seleniumGrid.nodesImageTag) - # imageTag: 4.12.1-20230920 + # imageTag: 4.16.0-20231206 # Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) imagePullPolicy: IfNotPresent # Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) @@ -562,6 +614,13 @@ firefoxNode: enabled: true # Service type type: ClusterIP + # Set specific loadBalancerIP when serviceType is LoadBalancer (see https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) + loadBalancerIP: "" + # Extra ports exposed in node service + ports: + # - name: node-port + # port: 5555 + # targetPort: 5555 # Custom annotations for service annotations: {} # Size limit for DSH volume mounted in container (if not set, default is "1Gi") @@ -593,8 +652,11 @@ firefoxNode: # - name: my-extra-volume-from-pvc # persistentVolumeClaim: # claimName: my-pv-claim - maxReplicaCount: 8 - minReplicaCount: 1 + + # Override the scaled options for firefox nodes + # scaledOptions: + # scaledJobOptions: + # scaledObjectOptions: hpa: url: '{{ include "seleniumGrid.graphqlURL" . }}' browserName: firefox @@ -617,10 +679,11 @@ edgeNode: # Number of edge nodes replicas: 1 + # imageRegistry: selenium # Image of edge nodes - imageName: selenium/node-edge + imageName: node-edge # Image of edge nodes (this overwrites global.seleniumGrid.nodesImageTag) - # imageTag: 4.12.1-20230920 + # imageTag: 4.16.0-20231206 # Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) imagePullPolicy: IfNotPresent # Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) @@ -680,9 +743,15 @@ edgeNode: enabled: true # Service type type: ClusterIP + # Set specific loadBalancerIP when serviceType is LoadBalancer (see https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) + loadBalancerIP: "" + # Extra ports exposed in node service + ports: + # - name: node-port + # port: 5555 + # targetPort: 5555 # Custom annotations for service - annotations: - hello: world + annotations: {} # Size limit for DSH volume mounted in container (if not set, default is "1Gi") dshmVolumeSizeLimit: 1Gi # Priority class name for edge-node pods @@ -712,8 +781,11 @@ edgeNode: # - name: my-extra-volume-from-pvc # persistentVolumeClaim: # claimName: my-pv-claim - maxReplicaCount: 8 - minReplicaCount: 1 + + # Override the scaled options for edge nodes + # scaledOptions: + # scaledJobOptions: + # scaledObjectOptions: hpa: url: '{{ include "seleniumGrid.graphqlURL" . }}' browserName: MicrosoftEdge @@ -724,5 +796,117 @@ edgeNode: # It should be set using the --set-json option sidecars: [] +videoRecorder: + enabled: false + # imageRegistry: selenium + # Image of video recorder + imageName: video + # Image of video recorder + # imageTag: ffmpeg-6.1-20231206 + # Image pull policy (see https://kubernetes.io/docs/concepts/containers/images/#updating-images) + imagePullPolicy: IfNotPresent + # Image pull secret (see https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) + + # What uploader to use. See .videRecorder.s3 for how to create a new one. + # uploader: s3 + uploader: false + # Where to upload the video file. Should be set to something like 's3://myvideobucket/' + uploadDestinationPrefix: false + + ports: + - 9000 + resources: + requests: + memory: "1Gi" + cpu: "1" + limits: + memory: "1Gi" + cpu: "1" + extraEnvironmentVariables: + # - name: SE_VIDEO_FOLDER + # value: /videos + # Custom environment variables by sourcing entire configMap, Secret, etc. for video recorder. + extraEnvFrom: + # - configMapRef: + # name: proxy-settings + # - secretRef: + # name: mysecret + # Wait for pod startup + terminationGracePeriodSeconds: 30 + + # Wait for pod startup + startupProbe: {} + # httpGet: + # path: / + # port: 9000 + # failureThreshold: 120 + # periodSeconds: 5 + + # Liveness probe settings + livenessProbe: {} + + volume: + # name: + # folder: video + # scripts: video-scripts + # Custom video recorder back-end scripts (video.sh, video_ready.py, etc.) further by ConfigMap. + # NOTE: For the mount point with the name "video", or "video-scripts", it will override the default. For other names, it will be appended. + extraVolumeMounts: [] + # - name: video-scripts + # mountPath: /opt/bin/video.sh + # subPath: custom_video.sh + # - name: video-scripts + # mountPath: /opt/bin/video_ready.py + # subPath: video_ready.py + + extraVolumes: [] + # - name: video-scripts + # configMap: + # name: my-video-scripts-cm + # defaultMode: 0500 + # - name: video + # persistentVolumeClaim: + # claimName: video-pv-claim + + # Container spec for the uploader if above it is defined as "uploader: s3" + s3: + imageName: public.ecr.aws/bitnami/aws-cli + imageTag: "2" + imagePullPolicy: IfNotPresent + securityContext: + runAsUser: 0 + command: + - /bin/sh + args: + - -c + - | + while ! [ -p /videos/uploadpipe ] + do + echo Waiting for /videos/uploadpipe to be created + sleep 1 + done + echo Waiting for files to upload + while read FILE DESTINATION < /videos/uploadpipe + do + if [ "$FILE" = "exit" ] + then + echo "$FILE" + break + else + echo "Uploading $FILE to $DESTINATION" + aws s3 cp --no-progress $FILE $DESTINATION + fi + done + extraEnvironmentVariables: + # - name: AWS_ACCESS_KEY_ID + # value: aws_access_key_id + # - name: AWS_SECRET_ACCESS_KEY + # value: aws_secret_access_key + # - name: + # valueFrom: + # secretKeyRef: + # name: secret-name + # key: secret-key + # Custom labels for k8s resources customLabels: {} diff --git a/docker-compose-v2-tracing.yml b/docker-compose-v2-tracing.yml index 9e64e2204a..fe06e3880b 100644 --- a/docker-compose-v2-tracing.yml +++ b/docker-compose-v2-tracing.yml @@ -9,7 +9,7 @@ services: - "16686:16686" - "14250:14250" chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -23,7 +23,7 @@ services: - "6900:5900" edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -37,7 +37,7 @@ services: - "6901:5900" firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -51,7 +51,7 @@ services: - "6902:5900" selenium-hub: - image: selenium/hub:4.12.1-20230920 + image: selenium/hub:4.16.0-20231206 ports: - "4442:4442" - "4443:4443" diff --git a/docker-compose-v2.yml b/docker-compose-v2.yml index ef92434e44..7e2d9ecbfc 100644 --- a/docker-compose-v2.yml +++ b/docker-compose-v2.yml @@ -4,7 +4,7 @@ version: '2' services: chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -16,7 +16,7 @@ services: - "6900:5900" edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -28,7 +28,7 @@ services: - "6901:5900" firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -40,7 +40,7 @@ services: - "6902:5900" selenium-hub: - image: selenium/hub:4.12.1-20230920 + image: selenium/hub:4.16.0-20231206 ports: - "4442:4442" - "4443:4443" diff --git a/docker-compose-v3-basicauth.yml b/docker-compose-v3-basicauth.yml index 64937694ca..bed795e212 100644 --- a/docker-compose-v3-basicauth.yml +++ b/docker-compose-v3-basicauth.yml @@ -4,7 +4,7 @@ version: "3" services: chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -14,7 +14,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -24,7 +24,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -34,7 +34,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium-hub: - image: selenium/hub:4.12.1-20230920 + image: selenium/hub:4.16.0-20231206 container_name: selenium-hub ports: - "4442:4442" diff --git a/docker-compose-v3-dev.yml b/docker-compose-v3-dev.yml index 6cbae14782..029f4311ee 100644 --- a/docker-compose-v3-dev.yml +++ b/docker-compose-v3-dev.yml @@ -4,7 +4,7 @@ version: "3" services: chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar @@ -16,7 +16,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar @@ -28,7 +28,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar @@ -40,7 +40,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium-hub: - image: selenium/hub:4.12.1-20230920 + image: selenium/hub:4.16.0-20231206 container_name: selenium-hub volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar diff --git a/docker-compose-v3-dynamic-grid.yml b/docker-compose-v3-dynamic-grid.yml index a091c6a5dd..6655e11661 100644 --- a/docker-compose-v3-dynamic-grid.yml +++ b/docker-compose-v3-dynamic-grid.yml @@ -4,7 +4,7 @@ version: "3" services: node-docker: - image: selenium/node-docker:4.12.1-20230920 + image: selenium/node-docker:4.16.0-20231206 volumes: - ./assets:/opt/selenium/assets - ./NodeDocker/config.toml:/opt/bin/config.toml @@ -17,7 +17,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium-hub: - image: selenium/hub:4.12.1-20230920 + image: selenium/hub:4.16.0-20231206 container_name: selenium-hub ports: - "4442:4442" diff --git a/docker-compose-v3-full-grid-dev.yml b/docker-compose-v3-full-grid-dev.yml index d4345a7119..d7ceddceb7 100644 --- a/docker-compose-v3-full-grid-dev.yml +++ b/docker-compose-v3-full-grid-dev.yml @@ -4,7 +4,7 @@ version: "3" services: selenium-event-bus: - image: selenium/event-bus:4.12.1-20230920 + image: selenium/event-bus:4.16.0-20231206 volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar container_name: selenium-event-bus @@ -14,7 +14,7 @@ services: - "5557:5557" selenium-sessions: - image: selenium/sessions:4.12.1-20230920 + image: selenium/sessions:4.16.0-20231206 volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar container_name: selenium-sessions @@ -28,7 +28,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium-session-queue: - image: selenium/session-queue:4.12.1-20230920 + image: selenium/session-queue:4.16.0-20231206 volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar container_name: selenium-session-queue @@ -36,7 +36,7 @@ services: - "5559:5559" selenium-distributor: - image: selenium/distributor:4.12.1-20230920 + image: selenium/distributor:4.16.0-20231206 volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar container_name: selenium-distributor @@ -56,7 +56,7 @@ services: - SE_SESSION_QUEUE_PORT=5559 selenium-router: - image: selenium/router:4.12.1-20230920 + image: selenium/router:4.16.0-20231206 volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar container_name: selenium-router @@ -75,7 +75,7 @@ services: - SE_SESSION_QUEUE_PORT=5559 chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar @@ -87,7 +87,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar @@ -99,7 +99,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb volumes: - ./selenium_server_deploy.jar:/opt/selenium/selenium-server.jar diff --git a/docker-compose-v3-full-grid-swarm.yml b/docker-compose-v3-full-grid-swarm.yml index 2f0ca79a35..08175c05eb 100644 --- a/docker-compose-v3-full-grid-swarm.yml +++ b/docker-compose-v3-full-grid-swarm.yml @@ -7,7 +7,7 @@ version: '3.7' services: chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb environment: - SE_EVENT_BUS_HOST=selenium-hub @@ -18,7 +18,7 @@ services: entrypoint: bash -c 'SE_OPTS="--host $$HOSTNAME" /opt/bin/entry_point.sh' edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb environment: - SE_EVENT_BUS_HOST=selenium-hub @@ -29,7 +29,7 @@ services: entrypoint: bash -c 'SE_OPTS="--host $$HOSTNAME" /opt/bin/entry_point.sh' firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb environment: - SE_EVENT_BUS_HOST=selenium-hub @@ -40,7 +40,7 @@ services: entrypoint: bash -c 'SE_OPTS="--host $$HOSTNAME" /opt/bin/entry_point.sh' selenium-hub: - image: selenium/hub:4.12.1-20230920 + image: selenium/hub:4.16.0-20231206 ports: - "4442:4442" - "4443:4443" diff --git a/docker-compose-v3-full-grid-tracing.yml b/docker-compose-v3-full-grid-tracing.yml index d650ad0fc7..9596c563f1 100644 --- a/docker-compose-v3-full-grid-tracing.yml +++ b/docker-compose-v3-full-grid-tracing.yml @@ -9,7 +9,7 @@ services: - "16686:16686" - "14250:14250" selenium-event-bus: - image: selenium/event-bus:4.12.1-20230920 + image: selenium/event-bus:4.16.0-20231206 container_name: selenium-event-bus ports: - "4442:4442" @@ -21,7 +21,7 @@ services: - SE_ENABLE_TRACING=true - JAVA_OPTS=-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-event-bus selenium-sessions: - image: selenium/sessions:4.12.1-20230920 + image: selenium/sessions:4.16.0-20231206 container_name: selenium-sessions ports: - "5556:5556" @@ -34,7 +34,7 @@ services: - SE_ENABLE_TRACING=true - JAVA_OPTS=-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-sessions selenium-session-queue: - image: selenium/session-queue:4.12.1-20230920 + image: selenium/session-queue:4.16.0-20231206 container_name: selenium-session-queue ports: - "5559:5559" @@ -42,7 +42,7 @@ services: - SE_ENABLE_TRACING=true - JAVA_OPTS=-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-session-queue selenium-distributor: - image: selenium/distributor:4.12.1-20230920 + image: selenium/distributor:4.16.0-20231206 container_name: selenium-distributor ports: - "5553:5553" @@ -61,7 +61,7 @@ services: - SE_ENABLE_TRACING=true - JAVA_OPTS=-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-distributor selenium-router: - image: selenium/router:4.12.1-20230920 + image: selenium/router:4.16.0-20231206 container_name: selenium-router ports: - "4444:4444" @@ -79,7 +79,7 @@ services: - SE_ENABLE_TRACING=true - JAVA_OPTS=-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-router chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-event-bus @@ -90,7 +90,7 @@ services: - SE_ENABLE_TRACING=true - JAVA_OPTS=-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-node-chrome edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-event-bus @@ -101,7 +101,7 @@ services: - SE_ENABLE_TRACING=true - JAVA_OPTS=-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-node-edge firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-event-bus diff --git a/docker-compose-v3-full-grid.yml b/docker-compose-v3-full-grid.yml index d97cacc4d8..6c3a08a1ca 100644 --- a/docker-compose-v3-full-grid.yml +++ b/docker-compose-v3-full-grid.yml @@ -4,7 +4,7 @@ version: "3" services: selenium-event-bus: - image: selenium/event-bus:4.12.1-20230920 + image: selenium/event-bus:4.16.0-20231206 container_name: selenium-event-bus ports: - "4442:4442" @@ -12,7 +12,7 @@ services: - "5557:5557" selenium-sessions: - image: selenium/sessions:4.12.1-20230920 + image: selenium/sessions:4.16.0-20231206 container_name: selenium-sessions ports: - "5556:5556" @@ -24,13 +24,13 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium-session-queue: - image: selenium/session-queue:4.12.1-20230920 + image: selenium/session-queue:4.16.0-20231206 container_name: selenium-session-queue ports: - "5559:5559" selenium-distributor: - image: selenium/distributor:4.12.1-20230920 + image: selenium/distributor:4.16.0-20231206 container_name: selenium-distributor ports: - "5553:5553" @@ -48,7 +48,7 @@ services: - SE_SESSION_QUEUE_PORT=5559 selenium-router: - image: selenium/router:4.12.1-20230920 + image: selenium/router:4.16.0-20231206 container_name: selenium-router ports: - "4444:4444" @@ -65,7 +65,7 @@ services: - SE_SESSION_QUEUE_PORT=5559 chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-event-bus @@ -75,7 +75,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-event-bus @@ -85,7 +85,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-event-bus diff --git a/docker-compose-v3-swarm.yml b/docker-compose-v3-swarm.yml index 2f0ca79a35..08175c05eb 100644 --- a/docker-compose-v3-swarm.yml +++ b/docker-compose-v3-swarm.yml @@ -7,7 +7,7 @@ version: '3.7' services: chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb environment: - SE_EVENT_BUS_HOST=selenium-hub @@ -18,7 +18,7 @@ services: entrypoint: bash -c 'SE_OPTS="--host $$HOSTNAME" /opt/bin/entry_point.sh' edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb environment: - SE_EVENT_BUS_HOST=selenium-hub @@ -29,7 +29,7 @@ services: entrypoint: bash -c 'SE_OPTS="--host $$HOSTNAME" /opt/bin/entry_point.sh' firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb environment: - SE_EVENT_BUS_HOST=selenium-hub @@ -40,7 +40,7 @@ services: entrypoint: bash -c 'SE_OPTS="--host $$HOSTNAME" /opt/bin/entry_point.sh' selenium-hub: - image: selenium/hub:4.12.1-20230920 + image: selenium/hub:4.16.0-20231206 ports: - "4442:4442" - "4443:4443" diff --git a/docker-compose-v3-tracing.yml b/docker-compose-v3-tracing.yml index f9611c3ef4..1f81cc6b9a 100644 --- a/docker-compose-v3-tracing.yml +++ b/docker-compose-v3-tracing.yml @@ -9,7 +9,7 @@ services: - "16686:16686" - "14250:14250" chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -21,7 +21,7 @@ services: - JAVA_OPTS=-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-node-chrome edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -33,7 +33,7 @@ services: - JAVA_OPTS=-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-node-edge firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -45,7 +45,7 @@ services: - JAVA_OPTS=-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://jaegar:14250 -Dotel.resource.attributes=service.name=selenium-node-firefox selenium-hub: - image: selenium/hub:4.12.1-20230920 + image: selenium/hub:4.16.0-20231206 container_name: selenium-hub ports: - "4442:4442" diff --git a/docker-compose-v3-video.yml b/docker-compose-v3-video.yml index 3fbfab1995..9ae22f29b0 100644 --- a/docker-compose-v3-video.yml +++ b/docker-compose-v3-video.yml @@ -4,7 +4,7 @@ version: "3" services: chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -14,7 +14,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -24,7 +24,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -34,7 +34,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 chrome_video: - image: selenium/video:ffmpeg-4.3.1-20230920 + image: selenium/video:ffmpeg-6.1-20231206 volumes: - /tmp/videos:/videos depends_on: @@ -44,7 +44,7 @@ services: - FILE_NAME=chrome_video.mp4 edge_video: - image: selenium/video:ffmpeg-4.3.1-20230920 + image: selenium/video:ffmpeg-6.1-20231206 volumes: - /tmp/videos:/videos depends_on: @@ -54,7 +54,7 @@ services: - FILE_NAME=edge_video.mp4 firefox_video: - image: selenium/video:ffmpeg-4.3.1-20230920 + image: selenium/video:ffmpeg-6.1-20231206 volumes: - /tmp/videos:/videos depends_on: @@ -64,7 +64,7 @@ services: - FILE_NAME=firefox_video.mp4 selenium-hub: - image: selenium/hub:4.12.1-20230920 + image: selenium/hub:4.16.0-20231206 container_name: selenium-hub ports: - "4442:4442" diff --git a/docker-compose-v3.yml b/docker-compose-v3.yml index 8636018bc0..e24d65ad84 100644 --- a/docker-compose-v3.yml +++ b/docker-compose-v3.yml @@ -4,7 +4,7 @@ version: "3" services: chrome: - image: selenium/node-chrome:4.12.1-20230920 + image: selenium/node-chrome:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -14,7 +14,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 edge: - image: selenium/node-edge:4.12.1-20230920 + image: selenium/node-edge:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -24,7 +24,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 firefox: - image: selenium/node-firefox:4.12.1-20230920 + image: selenium/node-firefox:4.16.0-20231206 shm_size: 2gb depends_on: - selenium-hub @@ -34,7 +34,7 @@ services: - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 selenium-hub: - image: selenium/hub:4.12.1-20230920 + image: selenium/hub:4.16.0-20231206 container_name: selenium-hub ports: - "4442:4442" diff --git a/generate_release_notes.sh b/generate_release_notes.sh index 014f561565..c2f4e40aeb 100755 --- a/generate_release_notes.sh +++ b/generate_release_notes.sh @@ -17,7 +17,7 @@ CHROMEDRIVER_VERSION=$(docker run --rm selenium/node-chrome:${TAG_VERSION} chrom EDGEDRIVER_VERSION=$(docker run --rm selenium/node-edge:${TAG_VERSION} msedgedriver --version | awk '{print $4}') FIREFOX_VERSION=$(docker run --rm selenium/node-firefox:${TAG_VERSION} firefox --version | awk '{print $3}') GECKODRIVER_VERSION=$(docker run --rm selenium/node-firefox:${TAG_VERSION} geckodriver --version | awk 'NR==1{print $2}') -FFMPEG_VERSION=$(docker run --entrypoint="" --rm selenium/video:ffmpeg-4.3.1-${BUILD_DATE} ffmpeg -version | awk '{print $3}' | head -n 1) +FFMPEG_VERSION=$(docker run --entrypoint="" --rm selenium/video:ffmpeg-6.1-${BUILD_DATE} ffmpeg -version | awk '{print $3}' | head -n 1) echo "" >> release_notes.md diff --git a/tests/K8sSmokeTest.py b/tests/K8sSmokeTest.py deleted file mode 100644 index 57f118be35..0000000000 --- a/tests/K8sSmokeTest.py +++ /dev/null @@ -1,47 +0,0 @@ -import json -import sys -import time - -try: - from urllib2 import urlopen -except ImportError: - from urllib.request import urlopen - -SELENIUM_GRID_URL = sys.argv[1] -max_attempts = 6 -sleep_interval = 10 - - -def get_grid_status(): - try: - response = urlopen('%s/status' % (SELENIUM_GRID_URL)) - print("Response code: " + str(response.getcode())) - response = urlopen('%s/status' % (SELENIUM_GRID_URL)) - encoded_response = response.read() - encoding = response.headers.get_content_charset('utf-8') - decoded_response = encoded_response.decode(encoding) - print("Response: " + decoded_response) - response_json = json.loads(decoded_response) - return response_json['value']['ready'] - except Exception as e: - print(e) - return False - - -def wait_for_grid_to_get_ready(): - result = get_grid_status() - ctr=0 - while(not result): - ctr=ctr+1 - if(ctr>max_attempts): - print("Timed out. Grid is still not in ready state") - sys.exit(1) - - print("Grid is not in ready state. Waiting for {0} secs....".format(sleep_interval)) - time.sleep(sleep_interval) - result = get_grid_status() - print("Grid Status: " + str(result)) - print("Grid is in Ready state now") - - -wait_for_grid_to_get_ready() diff --git a/tests/SeleniumTests/__init__.py b/tests/SeleniumTests/__init__.py index 2590fdfa11..8d5927ad30 100644 --- a/tests/SeleniumTests/__init__.py +++ b/tests/SeleniumTests/__init__.py @@ -1,5 +1,7 @@ import unittest +import concurrent.futures import os +import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait @@ -9,7 +11,8 @@ from selenium.webdriver.chrome.options import Options as ChromeOptions SELENIUM_GRID_HOST = os.environ.get('SELENIUM_GRID_HOST', 'localhost') - +SELENIUM_GRID_PORT = os.environ.get('SELENIUM_GRID_PORT', '4444') +WEB_DRIVER_WAIT_TIMEOUT = int(os.environ.get('WEB_DRIVER_WAIT_TIMEOUT', 60)) class SeleniumGenericTests(unittest.TestCase): @@ -51,7 +54,7 @@ def test_visit_basic_auth_secured_page(self): def test_play_video(self): driver = self.driver driver.get('https://hls-js.netlify.com/demo/') - wait = WebDriverWait(driver, 30) + wait = WebDriverWait(driver, WEB_DRIVER_WAIT_TIMEOUT) video = wait.until( EC.element_to_be_clickable((By.TAG_NAME, 'video')) ) @@ -62,33 +65,70 @@ def test_play_video(self): paused = video.get_property('paused') self.assertFalse(paused) + def test_download_file(self): + driver = self.driver + driver.get('https://demoqa.com/upload-download') + file_name = 'sampleFile.jpeg' + wait = WebDriverWait(driver, 30) + file_link = wait.until( + EC.element_to_be_clickable((By.XPATH, f'//*[@download="{file_name}"]')) + ) + file_link.click() + wait.until( + lambda d: len(d.get_downloadable_files()) > 0 and str(d.get_downloadable_files()[0]).endswith(file_name) + ) + time.sleep(5) + self.assertTrue(str(driver.get_downloadable_files()[0]).endswith(file_name)) + def tearDown(self): self.driver.quit() class ChromeTests(SeleniumGenericTests): def setUp(self): + options = ChromeOptions() + options.enable_downloads = True self.driver = webdriver.Remote( - options=ChromeOptions(), - command_executor="http://%s:4444" % SELENIUM_GRID_HOST + options=options, + command_executor="http://%s:%s" % (SELENIUM_GRID_HOST,SELENIUM_GRID_PORT) ) class EdgeTests(SeleniumGenericTests): def setUp(self): + options = EdgeOptions() + options.enable_downloads = True self.driver = webdriver.Remote( - options=EdgeOptions(), - command_executor="http://%s:4444" % SELENIUM_GRID_HOST + options=options, + command_executor="http://%s:%s" % (SELENIUM_GRID_HOST,SELENIUM_GRID_PORT) ) class FirefoxTests(SeleniumGenericTests): def setUp(self): + options = FirefoxOptions() + options.enable_downloads = True self.driver = webdriver.Remote( - options=FirefoxOptions(), - command_executor="http://%s:4444" % SELENIUM_GRID_HOST + options=options, + command_executor="http://%s:%s" % (SELENIUM_GRID_HOST,SELENIUM_GRID_PORT) ) def test_title_and_maximize_window(self): self.driver.get('https://the-internet.herokuapp.com') self.driver.maximize_window() self.assertTrue(self.driver.title == 'The Internet') + +class ParallelAutoscaling(): + def run(self, test_classes): + with concurrent.futures.ThreadPoolExecutor() as executor: + futures = [] + for test_class in test_classes: + suite = unittest.TestLoader().loadTestsFromTestCase(test_class) + for test in suite: + futures.append(executor.submit(test)) + for future in concurrent.futures.as_completed(futures): + future.result() + +class ParallelAutoscalingTests(unittest.TestCase): + def test_parallel_autoscaling(self): + runner = ParallelAutoscaling() + runner.run([ChromeTests, EdgeTests, FirefoxTests]) diff --git a/tests/SmokeTests/__init__.py b/tests/SmokeTests/__init__.py index 37917b16b0..a2f74c7fad 100644 --- a/tests/SmokeTests/__init__.py +++ b/tests/SmokeTests/__init__.py @@ -9,30 +9,42 @@ from urllib.request import urlopen SELENIUM_GRID_HOST = os.environ.get('SELENIUM_GRID_HOST', 'localhost') - +SELENIUM_GRID_PORT = os.environ.get('SELENIUM_GRID_PORT', '4444') +SELENIUM_GRID_AUTOSCALING = os.environ.get('SELENIUM_GRID_AUTOSCALING', 'false') +SELENIUM_GRID_AUTOSCALING_MIN_REPLICA = os.environ.get('SELENIUM_GRID_AUTOSCALING_MIN_REPLICA', 0) +HUB_CHECKS_MAX_ATTEMPTS = os.environ.get('HUB_CHECKS_MAX_ATTEMPTS', 3) +HUB_CHECKS_INTERVAL = os.environ.get('HUB_CHECKS_INTERVAL', 10) class SmokeTests(unittest.TestCase): def smoke_test_container(self, port): current_attempts = 0 - max_attempts = int(os.environ.get('GRID_STATUS_MAX_ATTEMPTS', 3)) - sleep_interval = 3 + max_attempts = int(HUB_CHECKS_MAX_ATTEMPTS) + sleep_interval = int(HUB_CHECKS_INTERVAL) status_fetched = False status_json = None + auto_scaling = SELENIUM_GRID_AUTOSCALING == 'true' + auto_scaling_min_replica = int(SELENIUM_GRID_AUTOSCALING_MIN_REPLICA) while current_attempts < max_attempts: current_attempts = current_attempts + 1 try: response = urlopen('http://%s:%s/status' % (SELENIUM_GRID_HOST, port)) status_json = json.loads(response.read()) - self.assertTrue(status_json['value']['ready'], "Container is not ready on port %s" % port) + if not auto_scaling or (auto_scaling and auto_scaling_min_replica > 0): + self.assertTrue(status_json['value']['ready'], "Container is not ready on port %s" % port) + else: + self.assertFalse(status_json['value']['ready'], "Container is autoscaling with min replica set to 0") status_fetched = True except Exception as e: time.sleep(sleep_interval) - self.assertTrue(status_fetched, "Container status was not fetched on port %s" % port) - self.assertTrue(status_json['value']['ready'], "Container is not ready on port %s" % port) + if not auto_scaling or (auto_scaling and auto_scaling_min_replica > 0): + self.assertTrue(status_fetched, "Container status was not fetched on port %s" % port) + self.assertTrue(status_json['value']['ready'], "Container is not ready on port %s" % port) + else: + self.assertFalse(status_json['value']['ready'], "Container is autoscaling with min replica set to 0") class GridTest(SmokeTests): def test_grid_is_up(self): - self.smoke_test_container(4444) + self.smoke_test_container('%s' % SELENIUM_GRID_PORT) diff --git a/tests/bootstrap.sh b/tests/bootstrap.sh index 504ca061a0..7ce7b8cf48 100755 --- a/tests/bootstrap.sh +++ b/tests/bootstrap.sh @@ -7,7 +7,7 @@ if [ "${CI:-false}" = "false" ]; then source docker-selenium-tests/bin/activate fi -python -m pip install selenium==4.12.0 \ +python -m pip install selenium==4.16.0 \ docker===6.1.3 \ | grep -v 'Requirement already satisfied' diff --git a/tests/charts/bootstrap.sh b/tests/charts/bootstrap.sh new file mode 100755 index 0000000000..d961b63ae7 --- /dev/null +++ b/tests/charts/bootstrap.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +mkdir -p tests/tests +cd tests || true + +if [ "${CI:-false}" = "false" ]; then + pip3 install virtualenv | grep -v 'Requirement already satisfied' + virtualenv docker-selenium-tests + source docker-selenium-tests/bin/activate +fi + +python -m pip install pyyaml==6.0.1 \ + | grep -v 'Requirement already satisfied' + +cd .. +helm template dummy --values tests/charts/templates/render/dummy.yaml \ + charts/selenium-grid > ./tests/tests/output_deployment.yaml + +python tests/charts/templates/test.py "./tests/tests/output_deployment.yaml" +ret_code=$? + +if [ "${CI:-false}" = "false" ]; then + deactivate +fi + +exit $ret_code diff --git a/tests/charts/ci/NodeChrome-values.yaml b/tests/charts/ci/NodeChrome-values.yaml new file mode 100644 index 0000000000..09396f42d0 --- /dev/null +++ b/tests/charts/ci/NodeChrome-values.yaml @@ -0,0 +1,13 @@ +# This is used in Helm chart testing +# Configuration for chrome nodes +chromeNode: + nameOverride: my-chrome-name + extraEnvironmentVariables: + - name: SE_OPTS + value: "--enable-managed-downloads true" +# Configuration for edge nodes +edgeNode: + enabled: false +# Configuration for firefox nodes +firefoxNode: + enabled: false diff --git a/tests/charts/ci/NodeEdge-values.yaml b/tests/charts/ci/NodeEdge-values.yaml new file mode 100644 index 0000000000..27220e2759 --- /dev/null +++ b/tests/charts/ci/NodeEdge-values.yaml @@ -0,0 +1,13 @@ +# This is used in Helm chart testing +# Configuration for chrome nodes +chromeNode: + enabled: false +# Configuration for edge nodes +edgeNode: + nameOverride: my-edge-name + extraEnvironmentVariables: + - name: SE_OPTS + value: "--enable-managed-downloads true" +# Configuration for firefox nodes +firefoxNode: + enabled: false diff --git a/tests/charts/ci/NodeFirefox-values.yaml b/tests/charts/ci/NodeFirefox-values.yaml new file mode 100644 index 0000000000..21bb6a2856 --- /dev/null +++ b/tests/charts/ci/NodeFirefox-values.yaml @@ -0,0 +1,13 @@ +# This is used in Helm chart testing +# Configuration for chrome nodes +chromeNode: + enabled: false +# Configuration for edge nodes +edgeNode: + enabled: false +# Configuration for firefox nodes +firefoxNode: + nameOverride: my-firefox-name + extraEnvironmentVariables: + - name: SE_OPTS + value: "--enable-managed-downloads true" diff --git a/tests/charts/ci/ParallelAutoscaling-values.yaml b/tests/charts/ci/ParallelAutoscaling-values.yaml new file mode 100644 index 0000000000..39ea9434c8 --- /dev/null +++ b/tests/charts/ci/ParallelAutoscaling-values.yaml @@ -0,0 +1,40 @@ +isolateComponents: false +autoscaling: + strategy: default + scaledOptions: + minReplicaCount: 0 + maxReplicaCount: 5 +chromeNode: + nameOverride: my-chrome-name + extraEnvironmentVariables: + - name: SE_OPTS + value: "--enable-managed-downloads true" +# Configuration for edge nodes +edgeNode: + nameOverride: my-edge-name + extraEnvironmentVariables: + - name: SE_OPTS + value: "--enable-managed-downloads true" +# Configuration for firefox nodes +firefoxNode: + nameOverride: my-firefox-name + extraEnvironmentVariables: + - name: SE_OPTS + value: "--enable-managed-downloads true" + +ingress: + paths: + - path: /selenium(/|$)(.*) + pathType: ImplementationSpecific + backend: + service: + name: '{{ template "seleniumGrid.hub.fullname" $ }}' + port: + number: 4444 + - path: /(/?)(session/.*/se/vnc) + pathType: ImplementationSpecific + backend: + service: + name: '{{ template "seleniumGrid.hub.fullname" $ }}' + port: + number: 4444 diff --git a/tests/charts/ci/auth-ingress-values.yaml b/tests/charts/ci/auth-ingress-values.yaml new file mode 100644 index 0000000000..e5d055ba63 --- /dev/null +++ b/tests/charts/ci/auth-ingress-values.yaml @@ -0,0 +1,34 @@ +ingress: + annotations: + nginx.ingress.kubernetes.io/use-regex: "true" + nginx.ingress.kubernetes.io/rewrite-target: /$2 + nginx.ingress.kubernetes.io/app-root: &gridAppRoot "/selenium" + nginx.ingress.kubernetes.io/proxy-connect-timeout: "360" + nginx.ingress.kubernetes.io/proxy-read-timeout: "360" + nginx.ingress.kubernetes.io/proxy-send-timeout: "360" + hostname: "" + paths: + - path: /selenium(/|$)(.*) + pathType: ImplementationSpecific + backend: + service: + name: '{{ template "seleniumGrid.router.fullname" $ }}' + port: + number: 4444 + - path: /(/?)(session/.*/se/vnc) + pathType: ImplementationSpecific + backend: + service: + name: '{{ template "seleniumGrid.router.fullname" $ }}' + port: + number: 4444 + +basicAuth: + enabled: false +isolateComponents: true + +hub: + subPath: *gridAppRoot + +components: + subPath: *gridAppRoot diff --git a/tests/charts/ci/autoscaling-values.yaml b/tests/charts/ci/autoscaling-values.yaml new file mode 100644 index 0000000000..7fa80b2bb3 --- /dev/null +++ b/tests/charts/ci/autoscaling-values.yaml @@ -0,0 +1,5 @@ +autoscaling: + enableWithExistingKEDA: true + scalingType: job + scaledOptions: + minReplicaCount: 0 diff --git a/tests/charts/ci/tracing-values.yaml b/tests/charts/ci/tracing-values.yaml new file mode 100644 index 0000000000..065b2c081a --- /dev/null +++ b/tests/charts/ci/tracing-values.yaml @@ -0,0 +1,13 @@ +hub: + extraEnvironmentVariables: + - name: SE_ENABLE_TRACING + value: "true" + - name: SE_JAVA_OPTS + value: "-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://{{ .Release.Name }}-jaeger-all-in-one-headless:14250 -Dotel.resource.attributes=service.name=selenium -Dotel.java.global-autoconfigure.enabled=true" + +components: + extraEnvironmentVariables: + - name: SE_ENABLE_TRACING + value: "true" + - name: SE_JAVA_OPTS + value: "-Dotel.traces.exporter=jaeger -Dotel.exporter.jaeger.endpoint=http://{{ .Release.Name }}-jaeger-all-in-one-headless:14250 -Dotel.resource.attributes=service.name=selenium -Dotel.java.global-autoconfigure.enabled=true" diff --git a/tests/charts/config/ct.yaml b/tests/charts/config/ct.yaml new file mode 100755 index 0000000000..7c085d076c --- /dev/null +++ b/tests/charts/config/ct.yaml @@ -0,0 +1,10 @@ +# This is config file for chart-testing tool. It is used to test Helm charts. +# https://github.com/helm/chart-testing +target-branch: trunk +chart-dirs: + - charts +chart-repos: + - kedacore=https://kedacore.github.io/charts +upgrade: false +helm-extra-args: --timeout 600s +check-version-increment: false diff --git a/tests/charts/config/kind-cluster.yaml b/tests/charts/config/kind-cluster.yaml new file mode 100755 index 0000000000..f0bcacd1be --- /dev/null +++ b/tests/charts/config/kind-cluster.yaml @@ -0,0 +1,18 @@ +# This Config is required for KIND cluster to enable ingress. Documented here https://kind.sigs.k8s.io/docs/user/ingress +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + kubeadmConfigPatches: + - | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + extraPortMappings: + - containerPort: 80 + hostPort: 80 + protocol: TCP + - containerPort: 443 + hostPort: 443 + protocol: TCP diff --git a/tests/charts/make/chart_build.sh b/tests/charts/make/chart_build.sh new file mode 100755 index 0000000000..5d57e4277a --- /dev/null +++ b/tests/charts/make/chart_build.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +CHART_PATH=${CHART_PATH:-"charts/selenium-grid"} +# Function to be executed on command failure +on_failure() { + local exit_status=$? + echo "There is step failed with exit status $exit_status" + exit $exit_status +} + +# Trap ERR signal and call on_failure function +trap 'on_failure' ERR + +cd tests || true + +if [ "${CI:-false}" = "false" ]; then + pip3 install virtualenv | grep -v 'Requirement already satisfied' + virtualenv docker-selenium-tests + source docker-selenium-tests/bin/activate +fi + +python -m pip install yamale==4.0.4 \ + yamllint==1.33.0 \ + | grep -v 'Requirement already satisfied' + +cd .. +rm -rf ${CHART_PATH}/Chart.lock +ct lint --all --config tests/charts/config/ct.yaml +# Helm dependencies build and lint is done by `ct lint` command +rm -rf ${CHART_PATH}/../*.tgz +helm package ${CHART_PATH} --version ${VERSION} --destination ${CHART_PATH}/.. + +readlink -f ${CHART_PATH}/../*.tgz > /tmp/selenium_chart_version +cat /tmp/selenium_chart_version + +if [ "${CI:-false}" = "false" ]; then + deactivate +fi diff --git a/tests/charts/make/chart_cluster_cleanup.sh b/tests/charts/make/chart_cluster_cleanup.sh new file mode 100755 index 0000000000..972a9e8b61 --- /dev/null +++ b/tests/charts/make/chart_cluster_cleanup.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +echo "Set ENV variables" +CLUSTER_NAME=${CLUSTER_NAME:-"chart-testing"} + +cleanup() { + echo "Clean up kind cluster" + kind delete clusters ${CLUSTER_NAME} +} + +cleanup diff --git a/tests/charts/make/chart_cluster_setup.sh b/tests/charts/make/chart_cluster_setup.sh new file mode 100755 index 0000000000..76b27872dc --- /dev/null +++ b/tests/charts/make/chart_cluster_setup.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +echo "Set ENV variables" +CLUSTER_NAME=${CLUSTER_NAME:-"chart-testing"} +RELEASE_NAME=${RELEASE_NAME:-"test"} +SELENIUM_NAMESPACE=${SELENIUM_NAMESPACE:-"selenium"} +KEDA_NAMESPACE=${KEDA_NAMESPACE:-"keda"} +INGRESS_NAMESPACE=${INGRESS_NAMESPACE:-"ingress-nginx"} +SUB_PATH=${SUB_PATH:-"/selenium"} +CHART_PATH=${CHART_PATH:-"charts/selenium-grid"} +TEST_VALUES_PATH=${TEST_VALUES_PATH:-"tests/charts/ci"} +SELENIUM_GRID_HOST=${SELENIUM_GRID_HOST:-"localhost"} +SELENIUM_GRID_PORT=${SELENIUM_GRID_PORT:-"80"} +WAIT_TIMEOUT=${WAIT_TIMEOUT:-"90s"} +SKIP_CLEANUP=${SKIP_CLEANUP:-"false"} # For debugging purposes, retain the cluster after the test run + +# Function to clean up for retry step on workflow +cleanup() { + if [ "${SKIP_CLEANUP}" = "false" ]; then + ./tests/charts/make/chart_cluster_cleanup.sh + fi +} + +# Function to be executed on command failure +on_failure() { + local exit_status=$? + echo "There is step failed with exit status $exit_status" + cleanup + exit $exit_status +} + +# Trap ERR signal and call on_failure function +trap 'on_failure' ERR + +echo "Create Kind cluster" +kind create cluster --wait ${WAIT_TIMEOUT} --name ${CLUSTER_NAME} --config tests/charts/config/kind-cluster.yaml + +echo "Install KEDA core on kind kubernetes cluster" +kubectl apply --server-side -f https://github.com/kedacore/keda/releases/download/v2.12.1/keda-2.12.1-core.yaml + +echo "Install ingress-nginx on kind kubernetes cluster" +kubectl apply -n ${INGRESS_NAMESPACE} -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml +kubectl wait --namespace ${INGRESS_NAMESPACE} \ + --for=condition=ready pod \ + --selector=app.kubernetes.io/component=controller \ + --timeout=${WAIT_TIMEOUT} + +echo "Load built local Docker Images into Kind Cluster" +image_list=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep ${NAMESPACE} | grep ${VERSION}) +for image in $image_list; do + kind load docker-image --name ${CLUSTER_NAME} "$image" +done diff --git a/tests/charts/make/chart_setup_env.sh b/tests/charts/make/chart_setup_env.sh new file mode 100755 index 0000000000..8c77101bfb --- /dev/null +++ b/tests/charts/make/chart_setup_env.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Function to be executed on command failure +on_failure() { + local exit_status=$? + echo "There is step failed with exit status $exit_status" + exit $exit_status +} + +# Trap ERR signal and call on_failure function +trap 'on_failure' ERR + +if [ "$(uname -m)" = "x86_64" ]; then + echo "Installing kind for AMD64 / x86_64" + curl -fsSL -o ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64 + chmod +x ./kind + sudo cp -frp ./kind /usr/local/bin/kind + sudo ln -sf /usr/local/bin/kind /usr/bin/kind + rm -rf kind + kind version + echo "===============================" + + echo "Installing kubectl for AMD64 / x86_64" + curl -fsSL -o ./kubectl "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + chmod +x ./kubectl + sudo cp -frp ./kubectl /usr/local/bin/kubectl + sudo ln -sf /usr/local/bin/kubectl /usr/bin/kubectl + rm -rf kubectl + kubectl version --client + echo "===============================" + + echo "Installing Helm for AMD64 / x86_64" + curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 + chmod 700 get_helm.sh + ./get_helm.sh + rm -rf get_helm.sh + helm version + echo "===============================" + + echo "Installing chart-testing for AMD64 / x86_64" + curl -fsSL -o ct.tar.gz https://github.com/helm/chart-testing/releases/download/v3.10.1/chart-testing_3.10.1_linux_amd64.tar.gz + sudo mkdir -p /opt/ct + sudo tar -xzf ct.tar.gz -C /opt/ct + sudo chmod +x /opt/ct/ct + sudo ln -sf /opt/ct/ct /usr/bin/ct + sudo cp -frp /opt/ct/ct /usr/local/bin/ct + sudo cp -frp /opt/ct/etc /etc/ct + rm -rf ct.tar.gz + ct version + echo "===============================" +fi diff --git a/tests/charts/make/chart_test.sh b/tests/charts/make/chart_test.sh new file mode 100755 index 0000000000..2d87c799ef --- /dev/null +++ b/tests/charts/make/chart_test.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +echo "Set ENV variables" +CLUSTER_NAME=${CLUSTER_NAME:-"chart-testing"} +RELEASE_NAME=${RELEASE_NAME:-"test"} +SELENIUM_NAMESPACE=${SELENIUM_NAMESPACE:-"selenium"} +KEDA_NAMESPACE=${KEDA_NAMESPACE:-"keda"} +INGRESS_NAMESPACE=${INGRESS_NAMESPACE:-"ingress-nginx"} +SUB_PATH=${SUB_PATH:-"/selenium"} +CHART_PATH=${CHART_PATH:-"charts/selenium-grid"} +TEST_VALUES_PATH=${TEST_VALUES_PATH:-"tests/charts/ci"} +SELENIUM_GRID_HOST=${SELENIUM_GRID_HOST:-"localhost"} +SELENIUM_GRID_PORT=${SELENIUM_GRID_PORT:-"80"} +MATRIX_BROWSER=${1:-"NodeChrome"} +SELENIUM_GRID_AUTOSCALING=${2:-"true"} +SELENIUM_GRID_AUTOSCALING_MIN_REPLICA=${3:-"0"} +WAIT_TIMEOUT=${WAIT_TIMEOUT:-"90s"} +HUB_CHECKS_INTERVAL=${HUB_CHECKS_INTERVAL:-45} +WEB_DRIVER_WAIT_TIMEOUT=${WEB_DRIVER_WAIT_TIMEOUT:-120} +SKIP_CLEANUP=${SKIP_CLEANUP:-"false"} # For debugging purposes, retain the cluster after the test run + +cleanup() { + if [ "${SKIP_CLEANUP}" = "false" ]; then + echo "Clean up chart release and namespace" + helm delete ${RELEASE_NAME} --namespace ${SELENIUM_NAMESPACE} + kubectl delete namespace ${SELENIUM_NAMESPACE} + fi +} + +# Function to be executed on command failure +on_failure() { + local exit_status=$? + echo "Describe all resources in the ${SELENIUM_NAMESPACE} namespace for debugging purposes" + kubectl describe all -n ${SELENIUM_NAMESPACE} + echo "There is step failed with exit status $exit_status" + cleanup + exit $exit_status +} + +# Trap ERR signal and call on_failure function +trap 'on_failure' ERR + +HELM_COMMAND_SET_AUTOSCALING="" +if [ "${SELENIUM_GRID_AUTOSCALING}" = "true" ]; then + HELM_COMMAND_SET_AUTOSCALING="--values ${TEST_VALUES_PATH}/autoscaling-values.yaml \ + --set autoscaling.enableWithExistingKEDA=${SELENIUM_GRID_AUTOSCALING} \ + --set autoscaling.scaledOptions.minReplicaCount=${SELENIUM_GRID_AUTOSCALING_MIN_REPLICA}" +fi + +echo "Deploy Selenium Grid Chart" +helm upgrade --install ${RELEASE_NAME} \ +--values ${TEST_VALUES_PATH}/auth-ingress-values.yaml \ +--values ${TEST_VALUES_PATH}/tracing-values.yaml \ +--values ${TEST_VALUES_PATH}/${MATRIX_BROWSER}-values.yaml \ +${HELM_COMMAND_SET_AUTOSCALING} \ +--set global.seleniumGrid.imageTag=${VERSION} --set global.seleniumGrid.imageRegistry=${NAMESPACE} \ +--set global.seleniumGrid.nodesImageTag=${VERSION} \ +${CHART_PATH} --namespace ${SELENIUM_NAMESPACE} --create-namespace + +echo "Run Tests" +export SELENIUM_GRID_HOST=${SELENIUM_GRID_HOST} +export SELENIUM_GRID_PORT=${SELENIUM_GRID_PORT}""${SUB_PATH} +export SELENIUM_GRID_AUTOSCALING=${SELENIUM_GRID_AUTOSCALING} +export SELENIUM_GRID_AUTOSCALING_MIN_REPLICA=${SELENIUM_GRID_AUTOSCALING_MIN_REPLICA} +export RUN_IN_DOCKER_COMPOSE=true +export HUB_CHECKS_INTERVAL=${HUB_CHECKS_INTERVAL} +export WEB_DRIVER_WAIT_TIMEOUT=${WEB_DRIVER_WAIT_TIMEOUT} +./tests/bootstrap.sh ${MATRIX_BROWSER} + +echo "Get pods status" +kubectl get pods -n ${SELENIUM_NAMESPACE} + +echo "Get all resources in the ${SELENIUM_NAMESPACE} namespace" +kubectl get all -n ${SELENIUM_NAMESPACE} + +cleanup diff --git a/tests/charts/templates/render/dummy.yaml b/tests/charts/templates/render/dummy.yaml new file mode 100644 index 0000000000..19ca7d6d99 --- /dev/null +++ b/tests/charts/templates/render/dummy.yaml @@ -0,0 +1,52 @@ +# This is dummy values file for chart template testing +global: + seleniumGrid: + affinity: &affinity + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - selenium + topologyKey: "kubernetes.io/hostname" +ingress: + nginx: + proxyTimeout: 360 # Set different proxy timout + proxyBuffer: + # size: 512M # Keep using sub-config default + number: # Disable sub-config + annotations: # Add you own annotations + nginx.ingress.kubernetes.io/use-regex: "true" # Add new key + nginx.ingress.kubernetes.io/rewrite-target: /$2 + nginx.ingress.kubernetes.io/app-root: &gridAppRoot "/selenium" + nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600" # Override default key + nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" # Override default key + hostname: "" + paths: + - path: /selenium(/|$)(.*) + pathType: ImplementationSpecific + backend: + service: + name: '{{ template "seleniumGrid.router.fullname" $ }}' + port: + number: 4444 + - path: /(/?)(session/.*/se/vnc) + pathType: ImplementationSpecific + backend: + service: + name: '{{ template "seleniumGrid.router.fullname" $ }}' + port: + number: 4444 + +isolateComponents: true + +chromeNode: + affinity: *affinity + +firefoxNode: + affinity: *affinity + +edgeNode: + affinity: *affinity diff --git a/tests/charts/templates/test.py b/tests/charts/templates/test.py new file mode 100644 index 0000000000..1e751f4e33 --- /dev/null +++ b/tests/charts/templates/test.py @@ -0,0 +1,61 @@ +import yaml +import unittest +import sys +import logging + +logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s") +logger = logging.getLogger(__name__) + +def load_template(yaml_file): + try: + with open(yaml_file, 'r') as file: + documents = yaml.safe_load_all(file) + list_of_documents = [doc for doc in documents] + return list_of_documents + except yaml.YAMLError as error: + print("Error in configuration file: ", error) + +class ChartTemplateTests(unittest.TestCase): + def test_set_affinity(self): + resources_name = ['selenium-chrome-node', 'selenium-distributor', 'selenium-edge-node', 'selenium-firefox-node', + 'selenium-event-bus', 'selenium-router', 'selenium-session-map', 'selenium-session-queue'] + count = 0 + logger.info(f"Assert affinity is set in global and nodes") + for doc in LIST_OF_DOCUMENTS: + if doc['metadata']['name'] in resources_name and doc['kind'] == 'Deployment': + logger.info(f"Assert affinity is set in resource {doc['metadata']['name']}") + self.assertTrue(doc['spec']['template']['spec']['affinity']['podAffinity']['requiredDuringSchedulingIgnoredDuringExecution'][0]['labelSelector']['matchExpressions'] is not None) + count += 1 + self.assertEqual(count, len(resources_name), "Not all resources have affinity set") + + def test_ingress_nginx_annotations(self): + resources_name = ['selenium-ingress'] + count = 0 + for doc in LIST_OF_DOCUMENTS: + if doc['metadata']['name'] in resources_name and doc['kind'] == 'Ingress': + logger.info(f"Assert ingress ingress annotations") + logger.info(f"Config `ingress.nginx.proxyTimeout` is able to be set a different value") + self.assertTrue(doc['metadata']['annotations']['nginx.ingress.kubernetes.io/proxy-read-timeout'] == '360') + logger.info(f"Duplicated in `ingress.annotations` take precedence to overwrite the default value") + self.assertTrue(doc['metadata']['annotations']['nginx.ingress.kubernetes.io/proxy-connect-timeout'] == '3600') + logger.info(f"Default annotation is able to be disabled by setting it to null") + self.assertTrue(doc['metadata']['annotations'].get('nginx.ingress.kubernetes.io/proxy-buffers-number') is None) + logger.info(f"Default annotation is added if no override value") + self.assertTrue(doc['metadata']['annotations']['nginx.ingress.kubernetes.io/client-body-buffer-size'] == '512M') + count += 1 + self.assertEqual(count, len(resources_name), "No ingress resources found") + +if __name__ == '__main__': + failed = False + try: + FILE_NAME = sys.argv[1] + LIST_OF_DOCUMENTS = load_template(FILE_NAME) + suite = unittest.TestLoader().loadTestsFromTestCase(ChartTemplateTests) + test_runner = unittest.TextTestRunner(verbosity=3) + failed = not test_runner.run(suite).wasSuccessful() + except Exception as e: + logger.fatal(e) + failed = True + + if failed: + exit(1) diff --git a/tests/docker-compose-v3-test-video.yml b/tests/docker-compose-v3-test-video.yml index e80c56b92c..bbfb6f6abe 100644 --- a/tests/docker-compose-v3-test-video.yml +++ b/tests/docker-compose-v3-test-video.yml @@ -12,6 +12,7 @@ services: - SE_EVENT_BUS_HOST=selenium-hub - SE_EVENT_BUS_PUBLISH_PORT=4442 - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 + - SE_OPTS=--enable-managed-downloads true ports: - "6900:5900" diff --git a/tests/test.py b/tests/test.py index ded685a97e..c94df6a428 100644 --- a/tests/test.py +++ b/tests/test.py @@ -60,9 +60,12 @@ 'NodeFirefox': 'FirefoxTests', 'StandaloneFirefox': 'FirefoxTests', - # Chrome Images + # Chromium Images 'NodeChromium': 'ChromeTests', 'StandaloneChromium': 'ChromeTests', + + # Chart Parallel Test + 'ParallelAutoscaling': 'ParallelAutoscalingTests' } FROM_IMAGE_ARGS = { @@ -144,6 +147,8 @@ def launch_container(container, **kwargs): 'SE_EVENT_BUS_PUBLISH_PORT': 4442, 'SE_EVENT_BUS_SUBSCRIBE_PORT': 4443 } + if container != 'Hub': + environment['SE_OPTS'] = "--enable-managed-downloads true" container_id = client.containers.run("%s/%s:%s" % (NAMESPACE, IMAGE_NAME_MAP[container], VERSION), detach=True, environment=environment, @@ -177,7 +182,7 @@ def standalone_browser_container_matches(container): use_random_user_id = USE_RANDOM_USER_ID == 'true' run_in_docker_compose = RUN_IN_DOCKER_COMPOSE == 'true' - random_user_id = random.randint(100000, 2147483647) + random_user_id = random.randint(2000, 65000) if use_random_user_id: logger.info("Running tests with a random user ID -> %s" % random_user_id) diff --git a/update_tag_in_docs_and_files.sh b/update_tag_in_docs_and_files.sh index 43348cc373..3783f30f51 100755 --- a/update_tag_in_docs_and_files.sh +++ b/update_tag_in_docs_and_files.sh @@ -4,20 +4,45 @@ LATEST_TAG=$1 NEXT_TAG=$2 LATEST_DATE=$(echo ${LATEST_TAG} | sed 's/.*-//') NEXT_DATE=$(echo ${NEXT_TAG} | sed 's/.*-//') +latest_chart_app_version=$(find . \( -type d -name .git -prune \) -o -type f -name 'Chart.yaml' -print0 | xargs -0 cat | grep ^appVersion | cut -d ':' -f 2 | tr -d '[:space:]') echo -e "\033[0;32m Updating tag displayed in docs and files...\033[0m" echo -e "\033[0;32m LATEST_TAG -> ${LATEST_TAG}\033[0m" echo -e "\033[0;32m NEXT_TAG -> ${NEXT_TAG}\033[0m" # If you want to test this locally and you are using macOS, do `brew install gnu-sed` and change `sed` for `gsed`. -find . \( -type d -name .git -prune \) -o -type f ! -name 'Chart.yaml' -print0 | xargs -0 sed -i "s/${LATEST_TAG}/${NEXT_TAG}/g" +find . \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s/${LATEST_TAG}/${NEXT_TAG}/g" echo -e "\033[0;32m Updating date used in some docs and files...\033[0m" echo -e "\033[0;32m LATEST_DATE -> ${LATEST_DATE}\033[0m" echo -e "\033[0;32m NEXT_DATE -> ${NEXT_DATE}\033[0m" # If you want to test this locally and you are using macOS, do `brew install gnu-sed` and change `sed` for `gsed`. -find . \( -type d -name .git -prune \) -o -type f ! -name 'Chart.yaml' -print0 | xargs -0 sed -i "s/${LATEST_DATE}/${NEXT_DATE}/g" +find . \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s/${LATEST_DATE}/${NEXT_DATE}/g" + +# Bump chart version and appVersion if next tag is different +if [ "$latest_chart_app_version" == $LATEST_TAG ] && [ "$latest_chart_app_version" != "$NEXT_TAG" ]; then + IFS='.' read -ra latest_version_parts <<< "$LATEST_TAG" + IFS='.' read -ra next_version_parts <<< "$NEXT_TAG" + latest_chart_version=$(find . \( -type d -name .git -prune \) -o -type f -name 'Chart.yaml' -print0 | xargs -0 cat | grep ^version | cut -d ':' -f 2 | tr -d '[:space:]') + IFS='.' read -ra latest_chart_version_parts <<< "$latest_chart_version" + if [ "${latest_version_parts[0]}" != "${next_version_parts[0]}" ]; then + ((latest_chart_version_parts[0]++)) + latest_chart_version_parts[1]=0 + latest_chart_version_parts[2]=0 + elif [ "${latest_version_parts[1]}" != "${next_version_parts[1]}" ]; then + ((latest_chart_version_parts[1]++)) + latest_chart_version_parts[2]=0 + elif [ "${latest_version_parts[2]}" != "${next_version_parts[2]}" ]; then + ((latest_chart_version_parts[2]++)) + fi + next_chart_version="${latest_chart_version_parts[0]}.${latest_chart_version_parts[1]}.${latest_chart_version_parts[2]}" + echo -e "\033[0;32m Updating chart version...\033[0m" + echo -e "\033[0;32m LATEST_CHART_VERSION -> ${latest_chart_version}\033[0m" + echo -e "\033[0;32m NEXT_CHART_VERSION -> ${next_chart_version}\033[0m" + # If you want to test this locally and you are using macOS, do `brew install gnu-sed` and change `sed` for `gsed`. + find . \( -type d -name .git -prune \) -o -type f -name 'Chart.yaml' -print0 | xargs -0 sed -i "s/${latest_chart_version}/${next_chart_version}/g" +fi git diff | cat