Skip to content

feat(chart): videoRecorder getting scripts from external files #2095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ name: Build & test

on:
push:
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'

permissions:
contents: read
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/helm-chart-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ name: Lint and Test Helm Charts

on:
push:
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
workflow_dispatch:

permissions:
Expand All @@ -15,7 +19,7 @@ jobs:
strategy:
fail-fast: false
matrix:
test-strategy: [chart_test, chart_test_parallel_autoscaling, chart_test_https_tls]
test-strategy: [chart_test, chart_test_parallel_autoscaling, chart_test_https, chart_test_parallel_autoscaling_https]
steps:
- uses: actions/checkout@v4
- name: Output Docker info
Expand Down Expand Up @@ -49,7 +53,7 @@ jobs:
- 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
run: NAME=${IMAGE_REGISTRY} VERSION=${BRANCH} BUILD_DATE=${BUILD_DATE} make build_nightly
- name: Build and lint charts
run: |
BUILD_DATE=${BUILD_DATE} make chart_build
Expand Down
10 changes: 8 additions & 2 deletions .github/workflows/nightly.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ jobs:
echo "CHART_PACKAGE_PATH=$(cat /tmp/selenium_chart_version)" >> $GITHUB_ENV
echo "CHART_FILE_NAME=$(basename $(cat /tmp/selenium_chart_version))" >> $GITHUB_ENV
- name: Delete previous nightly tag if any
uses: cb80/delrel@latest
uses: cb80/delrel@main
with:
tag: ${{ env.BASE_RELEASE }}
token: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -104,4 +104,10 @@ jobs:
generate_release_notes: true
draft: false
prerelease: true
append_body: true
append_body: false
- name: Update tag nightly
uses: richardsimko/[email protected]
with:
tag_name: ${{ env.BASE_RELEASE }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4 changes: 4 additions & 0 deletions .github/workflows/test-video.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ name: Test video files

on:
push:
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'

permissions:
contents: read
Expand Down
10 changes: 6 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,9 @@ chart_build_nightly:
chart_build:
VERSION=$(TAG_VERSION) ./tests/charts/make/chart_build.sh

chart_test_https:
SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_PORT=443 make chart_test

chart_test: chart_test_template \
chart_test_chrome \
chart_test_firefox \
Expand All @@ -443,13 +446,12 @@ chart_test_firefox:
chart_test_edge:
VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_test.sh NodeEdge

chart_test_parallel_autoscaling_https:
SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_PORT=443 make chart_test_parallel_autoscaling

chart_test_parallel_autoscaling:
VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_test.sh JobAutoscaling

chart_test_https_tls:
VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_PORT=443 \
./tests/charts/make/chart_test.sh JobAutoscaling

.PHONY: \
all \
base \
Expand Down
7 changes: 7 additions & 0 deletions charts/selenium-grid/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ This table contains the configuration parameters of the chart and their default
| `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.sidecars` | `[]` | Add a sidecars proxy in the same pod of the browser node |
| `chromeNode.initContainers` | `[]` | Add initContainers in the same pod of the browser node |
| `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 |
Expand Down Expand Up @@ -565,6 +567,8 @@ This table contains the configuration parameters of the chart and their default
| `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.sidecars` | `[]` | Add a sidecars proxy in the same pod of the browser node |
| `firefoxNode.initContainers` | `[]` | Add initContainers in the same pod of the browser node |
| `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 |
Expand Down Expand Up @@ -606,6 +610,8 @@ This table contains the configuration parameters of the chart and their default
| `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.sidecars` | `[]` | Add a sidecars proxy in the same pod of the browser node |
| `edgeNode.initContainers` | `[]` | Add initContainers in the same pod of the browser node |
| `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 |
Expand All @@ -623,6 +629,7 @@ This table contains the configuration parameters of the chart and their default
| `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.lifecycle` | `{}` | Define lifecycle events for video recorder |
| `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 |
Expand Down
7 changes: 7 additions & 0 deletions charts/selenium-grid/configs/node/nodePreStop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
if curl -sfk ${SE_SERVER_PROTOCOL}://127.0.0.1:${SE_NODE_PORT}/status; then
curl -k -X POST ${SE_SERVER_PROTOCOL}://127.0.0.1:${SE_NODE_PORT}/se/grid/node/drain --header 'X-REGISTRATION-SECRET;'
while curl -sfk ${SE_SERVER_PROTOCOL}://127.0.0.1:${SE_NODE_PORT}/status; do sleep 1; done
else
echo "Node is already drained. Shutting down gracefully!"
fi
44 changes: 44 additions & 0 deletions charts/selenium-grid/configs/uploader/s3/entry_point.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash

SE_VIDEO_FOLDER=${SE_VIDEO_FOLDER:-"/videos"}

if [[ -z "${AWS_REGION}" ]] || [[ -z "${AWS_ACCESS_KEY_ID}" ]] || [[ -z "${AWS_SECRET_ACCESS_KEY}" ]];
then
echo "AWS credentials needed to provide for configuring AWS CLI"
fi

aws configure set region ${AWS_REGION} --profile s3-profile
aws configure set aws_access_key_id ${AWS_ACCESS_KEY_ID} --profile s3-profile
aws configure set aws_secret_access_key ${AWS_SECRET_ACCESS_KEY} --profile s3-profile
aws configure --profile s3-profile

function consume_force_exit() {
rm -f ${SE_VIDEO_FOLDER}/force_exit
echo "Force exit signal consumed"
}
trap consume_force_exit EXIT

while [ ! -p ${SE_VIDEO_FOLDER}/uploadpipe ];
do
echo "Waiting for ${SE_VIDEO_FOLDER}/uploadpipe to be created"
sleep 1
done

echo "Waiting for video files put into pipe for proceeding to upload"

while read FILE DESTINATION < ${SE_VIDEO_FOLDER}/uploadpipe
do
if [ "${FILE}" = "exit" ];
then
exit
else [ "$FILE" != "" ] && [ "$DESTINATION" != "" ];
echo "Uploading ${FILE} to ${DESTINATION}"
aws s3 cp "${FILE}" "${DESTINATION}"
fi
if [ -f ${SE_VIDEO_FOLDER}/force_exit ] && [ ! -s ${SE_VIDEO_FOLDER}/uploadpipe ];
then
exit
fi
done

consume_force_exit
136 changes: 136 additions & 0 deletions charts/selenium-grid/configs/video/video.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#!/usr/bin/env bash

function create_pipe() {
if [[ "$UPLOAD_DESTINATION_PREFIX" != "false" ]];
then
echo "Create pipe if not exists for video upload stream"
if [ ! -p ${SE_VIDEO_FOLDER}/uploadpipe ];
then
mkfifo ${SE_VIDEO_FOLDER}/uploadpipe
fi
fi
}
create_pipe

function wait_util_force_exit_consume() {
if [[ "$UPLOAD_DESTINATION_PREFIX" != "false" ]];
then
while [[ -f ${SE_VIDEO_FOLDER}/force_exit ]]
do
echo "Waiting for force exit file to be consumed by uploader"
sleep 1
done
echo "Ready to shutdown the recorder"
fi
}

function add_exit_signal() {
if [[ "$UPLOAD_DESTINATION_PREFIX" != "false" ]];
then
echo "exit" > ${SE_VIDEO_FOLDER}/uploadpipe &
echo "exit" > ${SE_VIDEO_FOLDER}/force_exit
fi
}

function exit_on_max_session_reach() {
if [ $max_recorded_count -gt 0 ] && [ $recorded_count -ge $max_recorded_count ];
then
echo "Node will be drained since max sessions reached count number ($max_recorded_count)"
exit
fi
}

function finish {
add_exit_signal
wait_util_force_exit_consume
kill -INT `cat /var/run/supervisor/supervisord.pid`
}
trap finish EXIT

FRAME_RATE=${FRAME_RATE:-$SE_FRAME_RATE}
CODEC=${CODEC:-$SE_CODEC}
PRESET=${PRESET:-$SE_PRESET}
DISPLAY_CONTAINER_NAME=${DISPLAY_CONTAINER_NAME:-"localhost"}
export DISPLAY=${DISPLAY_CONTAINER_NAME}:${DISPLAY_NUM}.0

max_attempts=600
attempts=0
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
max_recorded_count=${SE_DRAIN_AFTER_SESSION_COUNT:-0}
recorded_count=0
echo Checking if node API responds
until curl -sk --request GET ${SE_SERVER_PROTOCOL}://${DISPLAY_CONTAINER_NAME}:${SE_NODE_PORT}/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 -sk --request GET ${SE_SERVER_PROTOCOL}://${DISPLAY_CONTAINER_NAME}:${SE_NODE_PORT}/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}/$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"
pkill -INT ffmpeg
recorded_count=$((recorded_count+1))
recording_started="false"
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 >> ${SE_VIDEO_FOLDER}/uploadpipe &
fi
if [ $max_recorded_count -gt 0 ] && [ $recorded_count -ge $max_recorded_count ];
then
echo "Node will be drained since max sessions reached count number ($max_recorded_count)"
exit
fi

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 "Node API is not responding, exiting."
Loading