From c93eff55345769a3db1471e3963dd095a5609bd4 Mon Sep 17 00:00:00 2001 From: Viet Nguyen Duc Date: Tue, 19 Nov 2024 00:31:02 +0700 Subject: [PATCH] Build FFmpeg and optimize video container Signed-off-by: Viet Nguyen Duc --- .github/workflows/deploy.yml | 9 +- .github/workflows/docker-test.yml | 16 +-- .github/workflows/helm-chart-test.yml | 2 +- .github/workflows/nightly.yml | 9 +- Base/Dockerfile | 25 ++-- Makefile | 53 +++++--- NodeBase/Dockerfile | 12 +- NodeChrome/Dockerfile | 3 +- NodeChromium/Dockerfile | 3 +- NodeEdge/Dockerfile | 3 +- NodeFirefox/Dockerfile | 3 +- RecorderBase/Dockerfile | 110 ++++++++++++++++ RecorderBase/recorder.conf | 28 +++++ {Video => RecorderBase}/upload.sh | 5 +- RecorderBase/uploader.conf | 14 +++ {Video => RecorderBase}/validate_endpoint.sh | 0 {Video => RecorderBase}/video.sh | 0 {Video => RecorderBase}/video_graphQLQuery.sh | 0 {Video => RecorderBase}/video_gridUrl.sh | 0 {Video => RecorderBase}/video_ready.py | 0 Video/Dockerfile | 118 ++---------------- Video/supervisord.conf | 56 --------- Video/upload.conf | 0 charts/selenium-grid/CONFIGURATION.md | 2 +- charts/selenium-grid/values.yaml | 2 +- tests/charts/make/chart_setup_env.sh | 10 +- tests/charts/templates/test.py | 2 +- 27 files changed, 245 insertions(+), 240 deletions(-) create mode 100644 RecorderBase/Dockerfile create mode 100755 RecorderBase/recorder.conf rename {Video => RecorderBase}/upload.sh (94%) create mode 100644 RecorderBase/uploader.conf rename {Video => RecorderBase}/validate_endpoint.sh (100%) rename {Video => RecorderBase}/video.sh (100%) rename {Video => RecorderBase}/video_graphQLQuery.sh (100%) rename {Video => RecorderBase}/video_gridUrl.sh (100%) rename {Video => RecorderBase}/video_ready.py (100%) delete mode 100755 Video/supervisord.conf delete mode 100755 Video/upload.conf diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8ecb7fe70..6e21f78e4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -83,11 +83,10 @@ jobs: AUTHORS: ${{ vars.AUTHORS || 'SeleniumHQ' }} - name: Sets prerelease to false by default run: echo "PRERELEASE=false" >> $GITHUB_ENV - - name: Build base image to get Grid version - run: VERSION="local" BUILD_DATE=${BUILD_DATE} make base - name: Get Grid version - # sed used to remove last comma of Selenium version output - run: echo "GRID_VERSION=$(docker run --rm ${NAME}/base:local-${BUILD_DATE} java -jar /opt/selenium/selenium-server.jar hub --version | awk '{print $3}' | sed 's/\(.*\),/\1 /')" | awk '{$1=$1;print}' >> $GITHUB_ENV + run: | + echo ${BASE_VERSION} + echo "GRID_VERSION=${BASE_VERSION}" >> $GITHUB_ENV - name: Is it a prerelease? run: echo "GRID_VERSION=${GRID_VERSION}-prerelease" >> $GITHUB_ENV && echo "PRERELEASE=true" >> $GITHUB_ENV if: contains(toJson(github.event.commits), '[prerelease]') == true @@ -121,7 +120,7 @@ jobs: if: github.event.inputs.skip-build-push-image != 'true' uses: nick-invision/retry@master with: - timeout_minutes: 90 + timeout_minutes: 240 max_attempts: 3 retry_wait_seconds: 60 command: PLATFORMS="${PLATFORMS}" VERSION="${GRID_VERSION}" BUILD_DATE=${BUILD_DATE} make build diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index 935588482..b74bbe586 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -128,23 +128,11 @@ jobs: uses: nick-invision/retry@master if: matrix.build-all == true with: - timeout_minutes: 20 + timeout_minutes: 60 max_attempts: 3 retry_wait_seconds: 60 command: | VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make build - - name: Pre-build to reduce logs in test phase - uses: nick-invision/retry@master - if: matrix.build-all != true - with: - timeout_minutes: 30 - max_attempts: 3 - retry_wait_seconds: 60 - command: | - VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make hub - VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make chrome - VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make firefox - VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make edge - name: Set test parameters if: (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') run: | @@ -158,7 +146,7 @@ jobs: - name: Run Docker Compose to ${{ matrix.test-strategy }} uses: nick-invision/retry@master with: - timeout_minutes: 40 + timeout_minutes: 120 max_attempts: 2 retry_wait_seconds: 60 command: | diff --git a/.github/workflows/helm-chart-test.yml b/.github/workflows/helm-chart-test.yml index 58448ba43..b3524ada6 100644 --- a/.github/workflows/helm-chart-test.yml +++ b/.github/workflows/helm-chart-test.yml @@ -154,7 +154,7 @@ jobs: - name: Build Docker images uses: nick-invision/retry@master with: - timeout_minutes: 12 + timeout_minutes: 60 max_attempts: 3 retry_wait_seconds: 60 command: NAME=${IMAGE_REGISTRY} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make build diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a1ae4cf54..39d734da6 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -63,16 +63,13 @@ jobs: env: NAMESPACE: ${{ vars.DOCKER_NAMESPACE || 'selenium' }} AUTHORS: ${{ vars.AUTHORS || 'SeleniumHQ' }} - - name: Build base image to get Grid version - run: VERSION="local" BUILD_DATE=${BUILD_DATE} make base - name: Get Grid version - # sed used to remove last comma of Selenium version output run: | - echo "GRID_VERSION=$(docker run --rm ${NAME}/base:local-${BUILD_DATE} java -jar /opt/selenium/selenium-server.jar hub --version | awk '{print $3}' | sed 's/\(.*\),/\1 /')" | awk '{$1=$1;print}' >> $GITHUB_ENV + echo ${BASE_VERSION} + echo "GRID_VERSION=${BASE_VERSION}" >> $GITHUB_ENV - name: Display Grid version and set Base version run: | echo ${GRID_VERSION} - echo "BASE_VERSION=$(echo ${GRID_VERSION})" >> $GITHUB_ENV echo "BASE_RELEASE=nightly" >> $GITHUB_ENV - name: Update tag nightly uses: richardsimko/update-tag@v1.0.11 @@ -83,7 +80,7 @@ jobs: - name: Build images uses: nick-invision/retry@master with: - timeout_minutes: 90 + timeout_minutes: 240 max_attempts: 3 retry_wait_seconds: 60 command: PLATFORMS="${PLATFORMS}" VERSION="${GRID_VERSION}" BUILD_DATE=${BUILD_DATE} make build diff --git a/Base/Dockerfile b/Base/Dockerfile index 3fefce765..44953bb03 100644 --- a/Base/Dockerfile +++ b/Base/Dockerfile @@ -33,14 +33,14 @@ ENV DEBIAN_FRONTEND=noninteractive \ SEL_GID=${GID} \ HOME=${HOME} \ TZ=${TZ} \ - SEL_DOWNLOAD_DIR=${HOME}/Downloads + SEL_DOWNLOAD_DIR=${HOME}/Downloads \ + VIDEO_FOLDER="/videos" #======================== # Miscellaneous packages # Includes minimal runtime used for executing non GUI Java programs #======================== -RUN --mount=type=secret,id=SEL_PASSWD \ - if [ "$(dpkg --print-architecture)" = "amd64" ]; then \ +RUN if [ "$(dpkg --print-architecture)" = "amd64" ]; then \ echo "deb http://archive.ubuntu.com/ubuntu noble main universe\n" > /etc/apt/sources.list \ && echo "deb http://archive.ubuntu.com/ubuntu noble-updates main universe\n" >> /etc/apt/sources.list \ && echo "deb http://security.ubuntu.com/ubuntu noble-security main universe\n" >> /etc/apt/sources.list ; \ @@ -61,8 +61,11 @@ RUN --mount=type=secret,id=SEL_PASSWD \ gnupg2 \ libnss3-tools \ python3-pip \ + python3-psutil \ openjdk-${JRE_VERSION}-jre-headless \ - && if [ "${TARGETARCH}" = "arm" ] && [ "${TARGETVARIANT}" = "v7" ]; then \ + && pip install --no-cache-dir --upgrade --break-system-packages setuptools +RUN --mount=type=secret,id=SEL_PASSWD \ + if [ "${TARGETARCH}" = "arm" ] && [ "${TARGETVARIANT}" = "v7" ]; then \ export ARCH=armhf ; \ else \ export ARCH=$(dpkg --print-architecture) ; \ @@ -93,18 +96,18 @@ RUN --mount=type=secret,id=SEL_PASSWD \ # Selenium & relaxing permissions for OpenShift and other non-sudo environments #========== && mkdir -p /opt/selenium /opt/selenium/assets /opt/selenium/secrets /var/run/supervisor /var/log/supervisor ${SEL_DOWNLOAD_DIR} \ - ${HOME}/.mozilla ${HOME}/.vnc ${HOME}/.pki/nssdb \ + ${HOME}/.mozilla ${HOME}/.vnc ${HOME}/.pki/nssdb ${VIDEO_FOLDER} \ # NSSDB initialization with an empty password && certutil -d sql:${HOME}/.pki/nssdb -N --empty-password \ && touch /opt/selenium/config.toml \ - && chown -R ${SEL_USER}:${SEL_GROUP} /opt/selenium /var/run/supervisor /var/log/supervisor /etc/passwd ${HOME} \ - && chmod -R 775 /opt/selenium /var/run/supervisor /var/log/supervisor /etc/passwd ${HOME} \ + && chown -R ${SEL_USER}:${SEL_GROUP} /opt/selenium /var/run/supervisor /var/log/supervisor /etc/passwd ${HOME} ${VIDEO_FOLDER} \ + && chmod -R 775 /opt/selenium /var/run/supervisor /var/log/supervisor /etc/passwd ${HOME} ${VIDEO_FOLDER} \ && wget --no-verbose https://github.com/${AUTHORS}/selenium/releases/download/${RELEASE}/selenium-server-${VERSION}.jar \ -O /opt/selenium/selenium-server.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:${SEL_USER}:rwx /opt /opt/selenium ${HOME} /opt/selenium/assets /var/run/supervisor /var/log/supervisor \ - && setfacl -Rm g:${SEL_GROUP}:rwx /opt /opt/selenium ${HOME} /opt/selenium/assets /var/run/supervisor /var/log/supervisor \ + && chgrp -R 0 /opt/selenium ${HOME} ${VIDEO_FOLDER} /opt/selenium/assets /var/run/supervisor /var/log/supervisor \ + && chmod -R g=u /opt/selenium ${HOME} ${VIDEO_FOLDER} /opt/selenium/assets /var/run/supervisor /var/log/supervisor \ + && setfacl -Rm u:${SEL_USER}:rwx /opt /opt/selenium ${HOME} ${VIDEO_FOLDER} /opt/selenium/assets /var/run/supervisor /var/log/supervisor \ + && setfacl -Rm g:${SEL_GROUP}:rwx /opt /opt/selenium ${HOME} ${VIDEO_FOLDER} /opt/selenium/assets /var/run/supervisor /var/log/supervisor \ #===== # Download observability related OpenTelemetry jars and make them available in a separate directory # so that the container can skip downloading them everytime it comes up diff --git a/Makefile b/Makefile index f1851ef3a..e7e0559b9 100644 --- a/Makefile +++ b/Makefile @@ -142,6 +142,9 @@ sessionqueue: base event_bus: base cd ./EventBus && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/event-bus:$(TAG_VERSION) . +recorder_base: base + cd ./RecorderBase && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/recorder-base:$(TAG_VERSION) . + node_base: base cd ./NodeBase && SEL_PASSWD=$(SEL_PASSWD) docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --secret id=SEL_PASSWD -t $(NAME)/node-base:$(TAG_VERSION) . @@ -243,8 +246,8 @@ standalone_edge_dev: edge_dev standalone_edge_beta: edge_beta cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --build-arg NAMESPACE=$(NAME) --build-arg VERSION=beta --build-arg BASE=node-edge -t $(NAME)/standalone-edge:beta . -video: - cd ./Video && SEL_PASSWD=$(SEL_PASSWD) docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --build-arg NAMESPACE=$(FFMPEG_BASED_NAME) --build-arg BASED_TAG=$(FFMPEG_BASED_TAG) --secret id=SEL_PASSWD --sbom=true --attest type=provenance,mode=max -t $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) . +video: recorder_base + cd ./Video && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/video:$(TAG_VERSION) . fetch_grid_scaler_resources: mkdir -p ./.keda/scalers \ @@ -292,7 +295,8 @@ count_image_layers: docker history $(NAME)/standalone-edge:$(TAG_VERSION) -q | wc -l docker history $(NAME)/standalone-firefox:$(TAG_VERSION) -q | wc -l docker history $(NAME)/standalone-docker:$(TAG_VERSION) -q | wc -l - docker history $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) -q | wc -l + docker history $(NAME)/recorder-base:$(TAG_VERSION) -q | wc -l + docker history $(NAME)/video:$(TAG_VERSION) -q | wc -l chrome_upgrade_version: cd ./NodeChrome && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --build-arg NAMESPACE=$(NAMESPACE) --build-arg VERSION=$(VERSION) --build-arg AUTHORS=$(AUTHORS) -t $(NAME)/node-chrome:$(TAG_VERSION) . @@ -350,7 +354,8 @@ tag_latest: docker tag $(NAME)/standalone-edge:$(TAG_VERSION) $(NAME)/standalone-edge:latest docker tag $(NAME)/standalone-firefox:$(TAG_VERSION) $(NAME)/standalone-firefox:latest docker tag $(NAME)/standalone-docker:$(TAG_VERSION) $(NAME)/standalone-docker:latest - docker tag $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) $(NAME)/video:latest + docker tag $(NAME)/recorder-base:$(TAG_VERSION) $(NAME)/recorder-base:latest + docker tag $(NAME)/video:$(TAG_VERSION) $(NAME)/video:latest release_latest: docker push $(NAME)/base:latest @@ -371,6 +376,7 @@ release_latest: docker push $(NAME)/standalone-edge:latest docker push $(NAME)/standalone-firefox:latest docker push $(NAME)/standalone-docker:latest + docker push $(NAME)/recorder-base:latest docker push $(NAME)/video:latest generate_latest_sbom: @@ -395,7 +401,8 @@ tag_nightly: docker tag $(NAME)/standalone-edge:$(TAG_VERSION) $(NAME)/standalone-edge:nightly docker tag $(NAME)/standalone-firefox:$(TAG_VERSION) $(NAME)/standalone-firefox:nightly docker tag $(NAME)/standalone-docker:$(TAG_VERSION) $(NAME)/standalone-docker:nightly - docker tag $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) $(NAME)/video:nightly + docker tag $(NAME)/recorder-base:$(TAG_VERSION) $(NAME)/recorder-base:nightly + docker tag $(NAME)/video:$(TAG_VERSION) $(NAME)/video:nightly release_nightly: docker push $(NAME)/base:nightly @@ -416,6 +423,7 @@ release_nightly: docker push $(NAME)/standalone-edge:nightly docker push $(NAME)/standalone-firefox:nightly docker push $(NAME)/standalone-docker:nightly + docker push $(NAME)/recorder-base:nightly docker push $(NAME)/video:nightly generate_nightly_sbom: @@ -514,6 +522,8 @@ release: tag_major_minor docker push $(NAME)/standalone-edge:$(TAG_VERSION) docker push $(NAME)/standalone-firefox:$(TAG_VERSION) docker push $(NAME)/standalone-docker:$(TAG_VERSION) + docker push $(NAME)/recorder-base:$(TAG_VERSION) + docker push $(NAME)/video:$(TAG_VERSION) docker push $(NAME)/base:$(MAJOR) docker push $(NAME)/hub:$(MAJOR) docker push $(NAME)/distributor:$(MAJOR) @@ -532,6 +542,8 @@ release: tag_major_minor docker push $(NAME)/standalone-edge:$(MAJOR) docker push $(NAME)/standalone-firefox:$(MAJOR) docker push $(NAME)/standalone-docker:$(MAJOR) + docker push $(NAME)/recorder-base:$(MAJOR) + docker push $(NAME)/video:$(MAJOR) docker push $(NAME)/base:$(MAJOR).$(MINOR) docker push $(NAME)/hub:$(MAJOR).$(MINOR) docker push $(NAME)/distributor:$(MAJOR).$(MINOR) @@ -550,6 +562,8 @@ release: tag_major_minor docker push $(NAME)/standalone-edge:$(MAJOR).$(MINOR) docker push $(NAME)/standalone-firefox:$(MAJOR).$(MINOR) docker push $(NAME)/standalone-docker:$(MAJOR).$(MINOR) + docker push $(NAME)/recorder-base:$(MAJOR).$(MINOR) + docker push $(NAME)/video:$(MAJOR).$(MINOR) docker push $(NAME)/base:$(MAJOR_MINOR_PATCH) docker push $(NAME)/hub:$(MAJOR_MINOR_PATCH) docker push $(NAME)/distributor:$(MAJOR_MINOR_PATCH) @@ -568,7 +582,8 @@ release: tag_major_minor docker push $(NAME)/standalone-edge:$(MAJOR_MINOR_PATCH) docker push $(NAME)/standalone-firefox:$(MAJOR_MINOR_PATCH) docker push $(NAME)/standalone-docker:$(MAJOR_MINOR_PATCH) - docker push $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) + docker push $(NAME)/recorder-base:$(MAJOR_MINOR_PATCH) + docker push $(NAME)/video:$(MAJOR_MINOR_PATCH) test: test_chrome \ test_chrome_standalone \ @@ -647,7 +662,7 @@ test_parallel: hub chrome firefox edge chromium video for node in DeploymentAutoscaling JobAutoscaling ; do \ cd ./tests || true ; \ echo TAG=$(TAG_VERSION) > .env ; \ - echo VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) >> .env ; \ + echo VIDEO_TAG=$(TAG_VERSION) >> .env ; \ echo TEST_DELAY_AFTER_TEST=$(or $(TEST_DELAY_AFTER_TEST), 2) >> .env ; \ echo TEST_DRAIN_AFTER_SESSION_COUNT=$(or $(TEST_DRAIN_AFTER_SESSION_COUNT), 2) >> .env ; \ echo TEST_PARALLEL_HARDENING=$(or $(TEST_PARALLEL_HARDENING), "true") >> .env ; \ @@ -701,7 +716,7 @@ test_video: video hub chrome firefox edge chromium fi; \ for node in $${list_nodes}; do \ cd ./tests || true ; \ - echo VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) > .env ; \ + echo VIDEO_TAG=$(TAG_VERSION) > .env ; \ echo TAG=$(TAG_VERSION) >> .env ; \ echo NODE=$$node >> .env ; \ echo UID=$$(id -u) >> .env ; \ @@ -815,7 +830,7 @@ test_node_docker: hub standalone_docker standalone_chrome standalone_firefox sta sudo rm -rf $$DOWNLOADS_DIR/* ; \ echo NAMESPACE=$(NAME) > .env ; \ echo TAG=$(TAG_VERSION) >> .env ; \ - echo VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) >> .env ; \ + echo VIDEO_TAG=$(TAG_VERSION) >> .env ; \ echo TEST_DRAIN_AFTER_SESSION_COUNT=$(or $(TEST_DRAIN_AFTER_SESSION_COUNT), 0) >> .env ; \ echo TEST_PARALLEL_HARDENING=$(or $(TEST_PARALLEL_HARDENING), "false") >> .env ; \ echo LOG_LEVEL=$(or $(LOG_LEVEL), "INFO") >> .env ; \ @@ -890,7 +905,7 @@ test_video_integrity: fi; \ for file in $$list_files; do \ echo "Checking video file: $$file"; \ - docker run -u $$(id -u) -v $$(pwd):$$(pwd) -w $$(pwd) --entrypoint="" $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) ffmpeg -v error -i "$$file" -f null - ; \ + docker run -u $$(id -u) -v $$(pwd):$$(pwd) -w $$(pwd) --entrypoint="" $(NAME)/video:$(TAG_VERSION) ffmpeg -v error -i "$$file" -f null - ; \ if [ $$? -ne 0 ]; then \ echo "Video file $$file is corrupted"; \ number_corrupted_files=$$((number_corrupted_files+1)); \ @@ -911,7 +926,7 @@ chart_render_template: chart_test_autoscaling_disabled: PLATFORMS=$(PLATFORMS) TEST_CHROMIUM=true RELEASE_NAME=selenium SELENIUM_GRID_AUTOSCALING=false CHART_ENABLE_TRACING=true \ SECURE_INGRESS_ONLY_GENERATE=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=$$(hostname -i) SELENIUM_GRID_PORT=443 EXTERNAL_UPLOADER_CONFIG=true \ - VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ + VERSION=$(TAG_VERSION) VIDEO_TAG=$(TAG_VERSION) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ TEMPLATE_OUTPUT_FILENAME="k8s_nodeChromium_enableTracing_secureIngress_generateCerts_ingressPublicIP_subPath.yaml" \ ./tests/charts/make/chart_test.sh NoAutoscaling @@ -919,7 +934,7 @@ chart_test_autoscaling_deployment_https: PLATFORMS=$(PLATFORMS) CHART_FULL_DISTRIBUTED_MODE=true CHART_ENABLE_BASIC_AUTH=true \ SECURE_INGRESS_ONLY_DEFAULT=true INGRESS_DISABLE_USE_HTTP2=true SELENIUM_GRID_PROTOCOL=https CHART_ENABLE_INGRESS_HOSTNAME=true SELENIUM_GRID_PORT=443 \ SELENIUM_GRID_AUTOSCALING_MIN_REPLICA=0 MAX_SESSIONS_FIREFOX=1 MAX_SESSIONS_EDGE=1 MAX_SESSIONS_CHROME=1 TEST_NAME_OVERRIDE=true \ - VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ + VERSION=$(TAG_VERSION) VIDEO_TAG=$(TAG_VERSION) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ TEMPLATE_OUTPUT_FILENAME="k8s_fullDistributed_basicAuth_secureIngress_defaultCerts_ingressHostName_disableHttp2_autoScaling_patchKEDA_scaledObject_subPath.yaml" \ ./tests/charts/make/chart_test.sh DeploymentAutoscaling @@ -927,37 +942,37 @@ chart_test_autoscaling_deployment: PLATFORMS=$(PLATFORMS) TEST_EXISTING_KEDA=true RELEASE_NAME=selenium CHART_ENABLE_TRACING=true TEST_PATCHED_KEDA=false \ SECURE_CONNECTION_SERVER=true SECURE_USE_EXTERNAL_CERT=true SERVICE_TYPE_NODEPORT=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=$$(hostname -i) SELENIUM_GRID_PORT=31444 \ SELENIUM_GRID_AUTOSCALING_MIN_REPLICA=1 SET_MAX_REPLICAS=3 TEST_DELAY_AFTER_TEST=2 SELENIUM_GRID_MONITORING=false \ - VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ + VERSION=$(TAG_VERSION) VIDEO_TAG=$(TAG_VERSION) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ TEMPLATE_OUTPUT_FILENAME="k8s_prefixSelenium_enableTracing_secureServer_externalCerts_nodePort_autoScaling_scaledObject_existingKEDA_subPath.yaml" \ ./tests/charts/make/chart_test.sh DeploymentAutoscaling chart_test_autoscaling_job_https: - PLATFORMS=$(PLATFORMS) TEST_EXISTING_KEDA=true RELEASE_NAME=selenium CHART_ENABLE_BASIC_AUTH=true SELENIUM_GRID_MONITORING=false SCALING_STRATEGY=accurate \ + PLATFORMS=$(PLATFORMS) TEST_EXISTING_KEDA=true RELEASE_NAME=selenium CHART_ENABLE_BASIC_AUTH=true SELENIUM_GRID_MONITORING=false \ SECURE_CONNECTION_SERVER=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_PORT=443 SUB_PATH=/ \ MAX_SESSIONS_FIREFOX=1 MAX_SESSIONS_EDGE=2 MAX_SESSIONS_CHROME=3 TEST_NAME_OVERRIDE=true \ - VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) EXTERNAL_UPLOADER_CONFIG=true \ + VERSION=$(TAG_VERSION) VIDEO_TAG=$(TAG_VERSION) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) EXTERNAL_UPLOADER_CONFIG=true \ TEMPLATE_OUTPUT_FILENAME="k8s_prefixSelenium_basicAuth_secureServer_autoScaling_scaledJob_existingKEDA.yaml" \ ./tests/charts/make/chart_test.sh JobAutoscaling chart_test_autoscaling_job_hostname: PLATFORMS=$(PLATFORMS) CHART_ENABLE_TRACING=true CHART_ENABLE_BASIC_AUTH=true BASIC_AUTH_EMBEDDED_URL=true TEST_PATCHED_KEDA=false \ SECURE_INGRESS_ONLY_DEFAULT=true SECURE_USE_EXTERNAL_CERT=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=$$(hostname -i) SELENIUM_GRID_PORT=443 \ - VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ + VERSION=$(TAG_VERSION) VIDEO_TAG=$(TAG_VERSION) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ TEMPLATE_OUTPUT_FILENAME="k8s_enableTracing_basicAuth_secureIngress_externalCerts_ingressPublicIP_autoScaling_originKEDA_scaledJob_subPath.yaml" \ ./tests/charts/make/chart_test.sh JobAutoscaling chart_test_autoscaling_job: PLATFORMS=$(PLATFORMS) TEST_EXISTING_KEDA=true TEST_CHROMIUM=true RELEASE_NAME=selenium CHART_ENABLE_TRACING=true CHART_FULL_DISTRIBUTED_MODE=true SELENIUM_GRID_MONITORING=false \ SECURE_INGRESS_ONLY_CONFIG_INLINE=true SECURE_USE_EXTERNAL_CERT=true CHART_ENABLE_INGRESS_HOSTNAME=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=selenium-grid.prod SUB_PATH=/ SELENIUM_GRID_PORT=443 \ - VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ + VERSION=$(TAG_VERSION) VIDEO_TAG=$(TAG_VERSION) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ TEMPLATE_OUTPUT_FILENAME="k8s_fullDistributed_secureIngress_externalCerts_ingressHostName_ingressTLSInline_autoScaling_scaledJob_existingKEDA_prefixSelenium_nodeChromium_enableTracing.yaml" \ ./tests/charts/make/chart_test.sh JobAutoscaling chart_test_autoscaling_playwright_connect_grid: - PLATFORMS=$(PLATFORMS) CHART_ENABLE_TRACING=true CHART_ENABLE_BASIC_AUTH=true MATRIX_TESTS=CDPTests SCALING_STRATEGY=accurate \ + PLATFORMS=$(PLATFORMS) CHART_ENABLE_TRACING=true CHART_ENABLE_BASIC_AUTH=true MATRIX_TESTS=CDPTests \ BASIC_AUTH_USERNAME=docker-selenium BASIC_AUTH_PASSWORD=2NMI4jdBi6k7bENoeUfV25295VvzwAE9chM24a+2VL95uOHozo \ SECURE_INGRESS_ONLY_DEFAULT=true SECURE_USE_EXTERNAL_CERT=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=$$(hostname -i) SELENIUM_GRID_PORT=443 \ - VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ + VERSION=$(TAG_VERSION) VIDEO_TAG=$(TAG_VERSION) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \ TEMPLATE_OUTPUT_FILENAME="k8s_playwright_connect_grid_basicAuth_secureIngress_ingressPublicIP_autoScaling_patchKEDA.yaml" \ ./tests/charts/make/chart_test.sh JobAutoscaling diff --git a/NodeBase/Dockerfile b/NodeBase/Dockerfile index 7cf22070c..4f9bcaaac 100644 --- a/NodeBase/Dockerfile +++ b/NodeBase/Dockerfile @@ -1,6 +1,7 @@ ARG NAMESPACE=selenium ARG VERSION=latest -FROM ${NAMESPACE}/base:${VERSION} +ARG BASE=base +FROM ${NAMESPACE}/${BASE}:${VERSION} ARG AUTHORS LABEL authors=${AUTHORS} @@ -66,8 +67,7 @@ ENV LANG_WHICH=${LANG_WHICH} \ # Following line fixes https://github.com/SeleniumHQ/docker-selenium/issues/87 DBUS_SESSION_BUS_ADDRESS=/dev/null -RUN --mount=type=secret,id=SEL_PASSWD \ - apt-get update -qqy \ +RUN apt-get update -qqy \ && apt-get -qqy --no-install-recommends install \ #============== # Xvfb @@ -103,12 +103,12 @@ RUN --mount=type=secret,id=SEL_PASSWD \ && dpkg-reconfigure --frontend noninteractive locales \ && apt-get -qyy autoremove \ && rm -rf /var/lib/apt/lists/* \ - && apt-get -qyy clean \ - && pip install --no-cache-dir --upgrade --break-system-packages setuptools \ + && apt-get -qyy clean ######################################## # noVNC exposes VNC through a web page # ######################################## - && wget -nv -O noVNC.zip \ +RUN --mount=type=secret,id=SEL_PASSWD \ + wget -nv -O noVNC.zip \ "https://github.com/novnc/noVNC/archive/refs/${NOVNC_SOURCE}/${NOVNC_VERSION}.zip" \ && unzip -x noVNC.zip \ && mv noVNC-${NOVNC_VERSION} /opt/bin/noVNC \ diff --git a/NodeChrome/Dockerfile b/NodeChrome/Dockerfile index f91981e49..e2b9b413d 100644 --- a/NodeChrome/Dockerfile +++ b/NodeChrome/Dockerfile @@ -1,6 +1,7 @@ ARG NAMESPACE=selenium ARG VERSION=latest -FROM ${NAMESPACE}/node-base:${VERSION} +ARG BASE=node-base +FROM ${NAMESPACE}/${BASE}:${VERSION} ARG AUTHORS LABEL authors=${AUTHORS} diff --git a/NodeChromium/Dockerfile b/NodeChromium/Dockerfile index 0bba4f2dc..57b471862 100644 --- a/NodeChromium/Dockerfile +++ b/NodeChromium/Dockerfile @@ -1,6 +1,7 @@ ARG NAMESPACE=selenium ARG VERSION=latest -FROM ${NAMESPACE}/node-base:${VERSION} +ARG BASE=node-base +FROM ${NAMESPACE}/${BASE}:${VERSION} ARG AUTHORS LABEL authors=${AUTHORS} diff --git a/NodeEdge/Dockerfile b/NodeEdge/Dockerfile index 177b6b481..0428a5cf6 100644 --- a/NodeEdge/Dockerfile +++ b/NodeEdge/Dockerfile @@ -1,6 +1,7 @@ ARG NAMESPACE=selenium ARG VERSION=latest -FROM ${NAMESPACE}/node-base:${VERSION} +ARG BASE=node-base +FROM ${NAMESPACE}/${BASE}:${VERSION} ARG AUTHORS LABEL authors=${AUTHORS} diff --git a/NodeFirefox/Dockerfile b/NodeFirefox/Dockerfile index 0271e790a..8a4296e3e 100644 --- a/NodeFirefox/Dockerfile +++ b/NodeFirefox/Dockerfile @@ -1,6 +1,7 @@ ARG NAMESPACE=selenium ARG VERSION=latest -FROM ${NAMESPACE}/node-base:${VERSION} +ARG BASE=node-base +FROM ${NAMESPACE}/${BASE}:${VERSION} ARG AUTHORS LABEL authors=${AUTHORS} diff --git a/RecorderBase/Dockerfile b/RecorderBase/Dockerfile new file mode 100644 index 000000000..ba9aa406e --- /dev/null +++ b/RecorderBase/Dockerfile @@ -0,0 +1,110 @@ +ARG NAMESPACE=selenium +ARG VERSION=latest +FROM ${NAMESPACE}/base:${VERSION} AS builder +ARG VERSION_FFMPEG="7.1" +ARG VERSION_RCLONE="v1.68.2" +ARG VERSION_GO="1.23.3" + +USER root + +#====================================== +# Install build tools +#====================================== +ARG TOOLS_DEPS="autoconf automake cmake libfreetype6 gcc build-essential libtool make nasm pkg-config zlib1g-dev numactl \ +libnuma-dev libx11-6 libxcb1 libxcb1-dev yasm git" + +RUN apt-get update -qqy \ + && apt-get -qqy --no-install-recommends install ${TOOLS_DEPS} \ + && apt-get -qyy clean \ + && mkdir -p /usr/local/src + +RUN curl -sLO https://go.dev/dl/go$VERSION_GO.linux-$(dpkg --print-architecture).tar.gz \ + && tar -xf go$VERSION_GO.linux-$(dpkg --print-architecture).tar.gz -C /usr/local \ + && rm -rf go$VERSION_GO.linux-$(dpkg --print-architecture).tar.gz* \ + && ln -sf /usr/local/go/bin/go /usr/bin/go \ + && go version + +RUN cd /usr/local/src \ + && git clone https://github.com/rclone/rclone.git \ + && cd rclone \ + && git checkout $VERSION_RCLONE \ + && make \ + && mv ~/go/bin/rclone /usr/local/bin/ \ + && rclone version + +#====================================== +# Install x264 from source +#====================================== +RUN cd /usr/local/src \ + && git clone https://code.videolan.org/videolan/x264.git \ + && cd x264 \ + && ./configure --prefix="/usr/local" --enable-static \ + && make \ + && make install + +#====================================== +# Install FFmpeg from source +#====================================== +RUN cd /usr/local/src \ + && git clone https://github.com/FFmpeg/FFmpeg.git \ + && git checkout release/$VERSION_FFMPEG \ + && PKG_CONFIG_PATH="/usr/local/lib/pkgconfig" ./configure \ + --prefix="/usr/local" \ + --extra-cflags="-I/usr/local/include" \ + --extra-ldflags="-L/usr/local/lib" \ + --pkg-config-flags="--static" \ + --enable-gpl \ + --enable-nonfree \ + --enable-libx264 \ + --enable-libxcb \ + && make \ + && make install + +RUN rm -rf /usr/local/src/* \ + && rm -rf /usr/local/go \ + && apt-get remove -y ${TOOLS_DEPS} \ + && apt-get -qyy autoremove + +# Final stage +FROM ${NAMESPACE}/base:${VERSION} +ARG AUTHORS +LABEL authors=${AUTHORS} + +USER root + +COPY --from=builder /usr/local /usr/local + +RUN apt-get -qqy update \ + && apt-get -qqy --no-install-recommends install \ + libx11-6 libxcb1 libxcb-shm0 \ + x11-xserver-utils x11-utils \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/* + +COPY *.conf /etc/supervisor/conf.d/ +COPY --chown="${SEL_UID}:${SEL_GID}" *.sh video_ready.py /opt/bin/ + +USER ${SEL_UID} + +RUN ldd /usr/local/bin/ffmpeg \ + && /usr/local/bin/ffmpeg -version \ + && rclone --version \ + && touch /opt/selenium/upload.conf + +ENV DISPLAY_NUM=99 \ + DISPLAY_CONTAINER_NAME="selenium" \ + SE_SERVER_PROTOCOL="http" \ + SE_VIDEO_ENABLED=false \ + SE_VIDEO_POLL_INTERVAL=1 \ + SE_SCREEN_WIDTH=1920 \ + SE_SCREEN_HEIGHT=1080 \ + SE_FRAME_RATE=15 \ + SE_CODEC="libx264" \ + SE_PRESET="-preset ultrafast" \ + VIDEO_FOLDER="/videos" \ + SE_VIDEO_FILE_NAME=video.mp4 \ + SE_VIDEO_FILE_NAME_TRIM_REGEX="[:alnum:]-_" \ + # Environment variables for the uploader + RCLONE_CONFIG="/opt/selenium/upload.conf" \ + SE_VIDEO_UPLOAD_ENABLED=false \ + SE_VIDEO_INTERNAL_UPLOAD=true \ + SE_UPLOAD_DESTINATION_PREFIX="" diff --git a/RecorderBase/recorder.conf b/RecorderBase/recorder.conf new file mode 100755 index 000000000..991dd075d --- /dev/null +++ b/RecorderBase/recorder.conf @@ -0,0 +1,28 @@ +[program:video-recording] +priority=10 +command=/opt/bin/video.sh +killasgroup=true +autostart=%(ENV_SE_VIDEO_ENABLED)s +startsecs=0 +autorestart=%(ENV_SE_VIDEO_ENABLED)s +stopsignal=TERM +stopwaitsecs=30 + +;Logs (all activity redirected to stdout so it can be seen through "docker logs" +redirect_stderr=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 + +[program:video-ready] +priority=0 +command=python3 /opt/bin/video_ready.py +killasgroup=true +autostart=%(ENV_SE_VIDEO_ENABLED)s +startsecs=0 +autorestart=%(ENV_SE_VIDEO_ENABLED)s +stopsignal=KILL + +;Logs (all activity redirected to stdout so it can be seen through "docker logs" +redirect_stderr=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 diff --git a/Video/upload.sh b/RecorderBase/upload.sh similarity index 94% rename from Video/upload.sh rename to RecorderBase/upload.sh index 3d5c7adde..1ea39dddb 100755 --- a/Video/upload.sh +++ b/RecorderBase/upload.sh @@ -1,8 +1,7 @@ #!/usr/bin/env bash VIDEO_FOLDER=${VIDEO_FOLDER} -UPLOAD_CONFIG_DIRECTORY=${SE_UPLOAD_CONFIG_DIRECTORY:-"/opt/bin"} -UPLOAD_CONFIG_FILE_NAME=${SE_UPLOAD_CONFIG_FILE_NAME:-"upload.conf"} +RCLONE_CONFIG=${RCLONE_CONFIG:-${SE_RCLONE_CONFIG}} UPLOAD_COMMAND=${SE_UPLOAD_COMMAND:-"copy"} UPLOAD_OPTS=${SE_UPLOAD_OPTS:-"-P --cutoff-mode SOFT --metadata --inplace"} UPLOAD_RETAIN_LOCAL_FILE=${SE_UPLOAD_RETAIN_LOCAL_FILE:-"false"} @@ -57,7 +56,7 @@ function rclone_upload() { local source=$1 local target=$2 echo "$(date -u +"${ts_format}") [${process_name}] - Uploading ${source} to ${target}" - rclone --config ${UPLOAD_CONFIG_DIRECTORY}/${UPLOAD_CONFIG_FILE_NAME} ${UPLOAD_COMMAND} ${UPLOAD_OPTS} "${source}" "${target}" & + rclone --config ${RCLONE_CONFIG} ${UPLOAD_COMMAND} ${UPLOAD_OPTS} "${source}" "${target}" & list_rclone_pid+=($!) check_and_clear_background } diff --git a/RecorderBase/uploader.conf b/RecorderBase/uploader.conf new file mode 100644 index 000000000..f92969be4 --- /dev/null +++ b/RecorderBase/uploader.conf @@ -0,0 +1,14 @@ +[program:video-upload] +priority=5 +command=/opt/bin/upload.sh +killasgroup=true +autostart=%(ENV_SE_VIDEO_INTERNAL_UPLOAD)s +startsecs=0 +autorestart=%(ENV_SE_VIDEO_INTERNAL_UPLOAD)s +stopsignal=TERM +stopwaitsecs=30 + +;Logs (all activity redirected to stdout so it can be seen through "docker logs" +redirect_stderr=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 diff --git a/Video/validate_endpoint.sh b/RecorderBase/validate_endpoint.sh similarity index 100% rename from Video/validate_endpoint.sh rename to RecorderBase/validate_endpoint.sh diff --git a/Video/video.sh b/RecorderBase/video.sh similarity index 100% rename from Video/video.sh rename to RecorderBase/video.sh diff --git a/Video/video_graphQLQuery.sh b/RecorderBase/video_graphQLQuery.sh similarity index 100% rename from Video/video_graphQLQuery.sh rename to RecorderBase/video_graphQLQuery.sh diff --git a/Video/video_gridUrl.sh b/RecorderBase/video_gridUrl.sh similarity index 100% rename from Video/video_gridUrl.sh rename to RecorderBase/video_gridUrl.sh diff --git a/Video/video_ready.py b/RecorderBase/video_ready.py similarity index 100% rename from Video/video_ready.py rename to RecorderBase/video_ready.py diff --git a/Video/Dockerfile b/Video/Dockerfile index f223d1038..5e9231571 100755 --- a/Video/Dockerfile +++ b/Video/Dockerfile @@ -1,121 +1,21 @@ -ARG NAMESPACE=linuxserver -ARG BASED_TAG=latest -FROM $NAMESPACE/ffmpeg:$BASED_TAG -ARG AUTHORS=SeleniumHQ -LABEL authors="${AUTHORS} " -LABEL org.opencontainers.image.source="https://github.com/${AUTHORS}/docker-selenium" - -ARG RCLONE_VERSION=current -#Arguments to define the user running the container -ARG SEL_USER=seluser -ARG SEL_GROUP=${SEL_USER} -ARG HOME=/home/${SEL_USER} -ARG UID=1200 -ARG GID=1201 -ARG VIDEO_FOLDER=/videos +ARG NAMESPACE=selenium +ARG VERSION=latest +FROM ${NAMESPACE}/recorder-base:${VERSION} +ARG AUTHORS +LABEL authors=${AUTHORS} USER root -#================================================ -# Customize sources for apt-get -#================================================ -RUN if [ "$(dpkg --print-architecture)" = "amd64" ]; then \ - echo "deb http://archive.ubuntu.com/ubuntu noble main universe\n" > /etc/apt/sources.list \ - && echo "deb http://archive.ubuntu.com/ubuntu noble-updates main universe\n" >> /etc/apt/sources.list \ - && echo "deb http://security.ubuntu.com/ubuntu noble-security main universe\n" >> /etc/apt/sources.list ; \ - fi - -# No interactive frontend during docker build -ENV DEBIAN_FRONTEND=noninteractive \ - DEBCONF_NONINTERACTIVE_SEEN=true \ - PIP_ROOT_USER_ACTION=ignore - -#======================== -# Supervisor -#======================== -RUN apt-get -qqy update \ - && apt-get upgrade -yq \ - && apt-get -qqy --no-install-recommends install \ - supervisor x11-xserver-utils x11-utils libxcb1-dev curl jq python3-pip tzdata acl unzip python3-psutil \ - && pip install --no-cache-dir --upgrade --break-system-packages setuptools \ - && rm -rf /var/lib/apt/lists/* /var/cache/apt/* - -#=================== -# Timezone settings -# Possible alternative: https://github.com/docker/docker/issues/3359#issuecomment-32150214 -#=================== -ENV TZ="UTC" -RUN ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime && \ - dpkg-reconfigure -f noninteractive tzdata && \ - cat /etc/timezone - -#====================================== -# Configure environement -#====================================== -ENV SEL_USER=${SEL_USER} \ - SEL_UID=${UID} \ - SEL_GID=${GID} \ - HOME=${HOME} - -#======================================== -# Add normal user and group with passwordless sudo -#======================================== -RUN --mount=type=secret,id=SEL_PASSWD \ - groupadd ${SEL_GROUP} \ - --gid ${SEL_GID} \ - && useradd ${SEL_USER} \ - --create-home \ - --gid ${SEL_GID} \ - --shell /bin/bash \ - --uid ${SEL_UID} \ - && usermod -a -G sudo ${SEL_USER} \ - && echo 'ALL ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers \ - && echo "${SEL_USER}:$(cat /run/secrets/SEL_PASSWD)" | chpasswd - -#====================================== -# Add Supervisor configuration files -#====================================== -COPY supervisord.conf /etc -COPY --chown="${SEL_UID}:${SEL_GID}" entry_point.sh validate_endpoint.sh video.sh video_ready.py video_graphQLQuery.sh video_gridUrl.sh /opt/bin/ #====================================== -# Add RCLONE for uploading videos +# Add entrypoint script #====================================== -RUN curl -fLo /tmp/rclone.zip https://downloads.rclone.org/rclone-${RCLONE_VERSION}-linux-$(dpkg --print-architecture).zip \ - && unzip -a /tmp/rclone.zip -d /tmp \ - && mv /tmp/rclone-*-linux-*/rclone /usr/local/bin/ \ - && rm -rf /tmp/rclone-* -COPY --chown="${SEL_UID}:${SEL_GID}" upload.sh upload.conf /opt/bin/ -ENV SE_VIDEO_UPLOAD_ENABLED=false \ - SE_VIDEO_INTERNAL_UPLOAD=true \ - SE_UPLOAD_DESTINATION_PREFIX="" - -RUN mkdir -p /var/run/supervisor /var/log/supervisor ${VIDEO_FOLDER} \ - && chown -R ${SEL_USER}:${SEL_GROUP} /var/run/supervisor /var/log/supervisor ${VIDEO_FOLDER} ${HOME} \ - && chmod -R 775 /var/run/supervisor /var/log/supervisor ${VIDEO_FOLDER} ${HOME} \ - && chgrp -R 0 /var/run/supervisor /var/log/supervisor ${VIDEO_FOLDER} ${HOME} \ - && chmod -R g=u /var/run/supervisor /var/log/supervisor ${VIDEO_FOLDER} ${HOME} \ - && setfacl -Rdm u:${SEL_USER}:rwx,g:${SEL_GROUP}:rwx /var/run/supervisor /var/log/supervisor ${VIDEO_FOLDER} ${HOME} +COPY --chown="${SEL_UID}:${SEL_GID}" entry_point.sh /opt/bin/ USER ${SEL_UID} +ENV SE_VIDEO_ENABLED=true + ENTRYPOINT ["/opt/bin/entry_point.sh"] CMD ["/opt/bin/entry_point.sh"] -ENV DISPLAY_NUM=99 \ - DISPLAY_CONTAINER_NAME=selenium \ - SE_SERVER_PROTOCOL="http" \ - SE_VIDEO_POLL_INTERVAL=1 \ - SE_SCREEN_WIDTH=1920 \ - SE_SCREEN_HEIGHT=1080 \ - SE_FRAME_RATE=15 \ - SE_CODEC=libx264 \ - SE_PRESET="-preset ultrafast" \ - VIDEO_FOLDER=${VIDEO_FOLDER} \ - SE_VIDEO_FILE_NAME=video.mp4 \ - SE_VIDEO_FILE_NAME_TRIM_REGEX="[:alnum:]-_" \ - SE_SUPERVISORD_LOG_LEVEL="info" \ - SE_SUPERVISORD_CHILD_LOG_DIR="/tmp" \ - SE_SUPERVISORD_LOG_FILE="/tmp/supervisord.log" \ - SE_SUPERVISORD_PID_FILE="/tmp/supervisord.pid" - EXPOSE 9000 diff --git a/Video/supervisord.conf b/Video/supervisord.conf deleted file mode 100755 index fa9c4596a..000000000 --- a/Video/supervisord.conf +++ /dev/null @@ -1,56 +0,0 @@ -; Documentation of this file format -> http://supervisord.org/configuration.html - -[supervisord] -childlogdir=%(ENV_SE_SUPERVISORD_CHILD_LOG_DIR)s ; ('AUTO' child log dir, default $TEMP) -logfile=%(ENV_SE_SUPERVISORD_LOG_FILE)s ; (main log file;default $CWD/supervisord.log) -logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB) -logfile_backups=10 ; (num of main logfile rotation backups;default 10) -loglevel=%(ENV_SE_SUPERVISORD_LOG_LEVEL)s ; (log level;default info; others: debug,warn,trace) http://supervisord.org/logging.html -pidfile=%(ENV_SE_SUPERVISORD_PID_FILE)s ; (supervisord pidfile;default supervisord.pid) -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) - -[program:video-recording] -priority=10 -command=/opt/bin/video.sh -killasgroup=true -autostart=true -startsecs=0 -autorestart=true -stopsignal=TERM -stopwaitsecs=30 - -;Logs (all activity redirected to stdout so it can be seen through "docker logs" -redirect_stderr=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 - -[program:video-ready] -priority=0 -command=python3 /opt/bin/video_ready.py -killasgroup=true -autostart=true -startsecs=0 -autorestart=true -stopsignal=KILL - -;Logs (all activity redirected to stdout so it can be seen through "docker logs" -redirect_stderr=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 - -[program:video-upload] -priority=5 -command=/opt/bin/upload.sh -killasgroup=true -autostart=%(ENV_SE_VIDEO_INTERNAL_UPLOAD)s -startsecs=0 -autorestart=%(ENV_SE_VIDEO_INTERNAL_UPLOAD)s -stopsignal=TERM -stopwaitsecs=30 - -;Logs (all activity redirected to stdout so it can be seen through "docker logs" -redirect_stderr=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 diff --git a/Video/upload.conf b/Video/upload.conf deleted file mode 100755 index e69de29bb..000000000 diff --git a/charts/selenium-grid/CONFIGURATION.md b/charts/selenium-grid/CONFIGURATION.md index ff986b3f9..6f8eb1833 100644 --- a/charts/selenium-grid/CONFIGURATION.md +++ b/charts/selenium-grid/CONFIGURATION.md @@ -148,7 +148,7 @@ A Helm chart for creating a Selenium Grid Server in Kubernetes | uploaderConfigMap.nameOverride | string | `nil` | Override the name of the uploader configMap | | uploaderConfigMap.defaultMode | int | `493` | Default mode for ConfigMap is mounted as file | | uploaderConfigMap.extraScriptsImportFrom | string | `"configs/uploader/**"` | Directory where the extra scripts are imported to ConfigMap by default (if given a relative path, it should be in chart's directory) | -| uploaderConfigMap.extraScriptsDirectory | string | `"/opt/bin"` | Directory where the extra scripts are mounted to | +| uploaderConfigMap.extraScriptsDirectory | string | `"/opt/selenium"` | Directory where the extra scripts are mounted to | | uploaderConfigMap.extraScripts | object | `{"upload.sh":""}` | List of extra scripts to be mounted to the container. Format as `filename: content` | | uploaderConfigMap.secretFiles | object | `{"upload.conf":"[sample]"}` | Extra files stored in Secret to be mounted to the container. | | uploaderConfigMap.scriptVolumeMountName | string | `nil` | Name of volume mount is used to mount scripts in the ConfigMap | diff --git a/charts/selenium-grid/values.yaml b/charts/selenium-grid/values.yaml index 42d89cf06..9fe466f00 100644 --- a/charts/selenium-grid/values.yaml +++ b/charts/selenium-grid/values.yaml @@ -330,7 +330,7 @@ uploaderConfigMap: # -- Directory where the extra scripts are imported to ConfigMap by default (if given a relative path, it should be in chart's directory) extraScriptsImportFrom: "configs/uploader/**" # -- Directory where the extra scripts are mounted to - extraScriptsDirectory: "/opt/bin" + extraScriptsDirectory: "/opt/selenium" # -- List of extra scripts to be mounted to the container. Format as `filename: content` extraScripts: upload.sh: "" diff --git a/tests/charts/make/chart_setup_env.sh b/tests/charts/make/chart_setup_env.sh index 3f543a793..a319e50db 100755 --- a/tests/charts/make/chart_setup_env.sh +++ b/tests/charts/make/chart_setup_env.sh @@ -83,11 +83,15 @@ elif [ "${CLUSTER}" = "minikube" ]; then rm -rf minikube-linux-$(dpkg --print-architecture) echo "===============================" echo "Installing Go" - GO_VERSION="1.23.2" + GO_VERSION="1.23.3" curl -sLO https://go.dev/dl/go$GO_VERSION.linux-$(dpkg --print-architecture).tar.gz - sudo tar -xf go$GO_VERSION.linux-$(dpkg --print-architecture).tar.gz -C /usr/local + tar -xvf go$GO_VERSION.linux-$(dpkg --print-architecture).tar.gz -C /tmp rm -rf go$GO_VERSION.linux-$(dpkg --print-architecture).tar.gz* - sudo ln -sf /usr/local/go/bin/go /usr/bin/go + sudo mv /tmp/go /usr/local + export GOROOT=/usr/local/go + export GOPATH=$HOME/go + export PATH=$GOPATH/bin:$GOROOT/bin:$PATH + source $HOME/.profile || source $HOME/.bashrc go version echo "===============================" echo "Installing CRI-CTL (CLI for CRI-compatible container runtimes)" diff --git a/tests/charts/templates/test.py b/tests/charts/templates/test.py index 4d68ddf47..213c0828f 100644 --- a/tests/charts/templates/test.py +++ b/tests/charts/templates/test.py @@ -217,7 +217,7 @@ def test_upload_conf_mount_to_video_container(self): else: list_volume_mounts = video_container['volumeMounts'] for volume in list_volume_mounts: - if volume['mountPath'] == '/opt/bin/upload.conf': + if volume['mountPath'] == '/opt/selenium/upload.conf': is_present = True self.assertTrue(is_present, "Volume mount for upload config is not present in the container")