From f3b2ced9fab4970f434f8ca61804d0eea3e09846 Mon Sep 17 00:00:00 2001 From: Daniel Davison Date: Thu, 15 Feb 2018 15:53:26 -0500 Subject: [PATCH 1/6] starting wait-for-it --- Base/Dockerfile | 11 +++ Base/wait-for-it.sh | 177 ++++++++++++++++++++++++++++++++++++++++ Hub/Dockerfile | 2 +- Hub/entry_point.sh | 2 + NodeBase/Dockerfile | 2 +- NodeBase/entry_point.sh | 4 + NodeChrome/Dockerfile | 2 +- 7 files changed, 197 insertions(+), 3 deletions(-) create mode 100755 Base/wait-for-it.sh diff --git a/Base/Dockerfile b/Base/Dockerfile index 98763d30ff..b09ccb4b86 100644 --- a/Base/Dockerfile +++ b/Base/Dockerfile @@ -46,6 +46,17 @@ RUN useradd seluser \ && echo 'ALL ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers \ && echo 'seluser:secret' | chpasswd +#======================================= +# Create shared / common bin directory +#======================================= +RUN mkdir -p /opt/bin + +#====================================== +# Add intermediate service discovery +#====================================== +COPY wait-for-it.sh \ + /opt/bin/ + #=================================================== # Run the following commands as non-privileged user #=================================================== diff --git a/Base/wait-for-it.sh b/Base/wait-for-it.sh new file mode 100755 index 0000000000..bbe404324b --- /dev/null +++ b/Base/wait-for-it.sh @@ -0,0 +1,177 @@ +#!/usr/bin/env bash +# Use this script to test if a given TCP host/port are available + +cmdname=$(basename $0) + +echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } + +usage() +{ + cat << USAGE >&2 +Usage: + $cmdname host:port [-s] [-t timeout] [-- command args] + -h HOST | --host=HOST Host or IP under test + -p PORT | --port=PORT TCP port under test + Alternatively, you specify the host and port as host:port + -s | --strict Only execute subcommand if the test succeeds + -q | --quiet Don't output any status messages + -t TIMEOUT | --timeout=TIMEOUT + Timeout in seconds, zero for no timeout + -- COMMAND ARGS Execute command with args after the test finishes +USAGE + exit 1 +} + +wait_for() +{ + if [[ $TIMEOUT -gt 0 ]]; then + echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" + else + echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" + fi + start_ts=$(date +%s) + while : + do + if [[ $ISBUSY -eq 1 ]]; then + nc -z $HOST $PORT + result=$? + else + (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 + result=$? + fi + if [[ $result -eq 0 ]]; then + end_ts=$(date +%s) + echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" + break + fi + sleep 1 + done + return $result +} + +wait_for_wrapper() +{ + # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 + if [[ $QUIET -eq 1 ]]; then + timeout $BUSYTIMEFLAG $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & + else + timeout $BUSYTIMEFLAG $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & + fi + PID=$! + trap "kill -INT -$PID" INT + wait $PID + RESULT=$? + if [[ $RESULT -ne 0 ]]; then + echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" + fi + return $RESULT +} + +# process arguments +while [[ $# -gt 0 ]] +do + case "$1" in + *:* ) + hostport=(${1//:/ }) + HOST=${hostport[0]} + PORT=${hostport[1]} + shift 1 + ;; + --child) + CHILD=1 + shift 1 + ;; + -q | --quiet) + QUIET=1 + shift 1 + ;; + -s | --strict) + STRICT=1 + shift 1 + ;; + -h) + HOST="$2" + if [[ $HOST == "" ]]; then break; fi + shift 2 + ;; + --host=*) + HOST="${1#*=}" + shift 1 + ;; + -p) + PORT="$2" + if [[ $PORT == "" ]]; then break; fi + shift 2 + ;; + --port=*) + PORT="${1#*=}" + shift 1 + ;; + -t) + TIMEOUT="$2" + if [[ $TIMEOUT == "" ]]; then break; fi + shift 2 + ;; + --timeout=*) + TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + CLI=("$@") + break + ;; + --help) + usage + ;; + *) + echoerr "Unknown argument: $1" + usage + ;; + esac +done + +if [[ "$HOST" == "" || "$PORT" == "" ]]; then + echoerr "Error: you need to provide a host and port to test." + usage +fi + +TIMEOUT=${TIMEOUT:-15} +STRICT=${STRICT:-0} +CHILD=${CHILD:-0} +QUIET=${QUIET:-0} + +# check to see if timeout is from busybox? +# check to see if timeout is from busybox? +TIMEOUT_PATH=$(realpath $(which timeout)) +if [[ $TIMEOUT_PATH =~ "busybox" ]]; then + ISBUSY=1 + BUSYTIMEFLAG="-t" +else + ISBUSY=0 + BUSYTIMEFLAG="" +fi + +if [[ $CHILD -gt 0 ]]; then + wait_for + RESULT=$? + exit $RESULT +else + if [[ $TIMEOUT -gt 0 ]]; then + wait_for_wrapper + RESULT=$? + else + wait_for + RESULT=$? + fi +fi + +if [[ $CLI != "" ]]; then + if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then + echoerr "$cmdname: strict mode, refusing to execute subprocess" + exit $RESULT + fi + exec "${CLI[@]}" +else + exit $RESULT +fi diff --git a/Hub/Dockerfile b/Hub/Dockerfile index a52ad7ebdd..18c038dea8 100644 --- a/Hub/Dockerfile +++ b/Hub/Dockerfile @@ -2,7 +2,7 @@ # NOTE: DO *NOT* EDIT THIS FILE. IT IS GENERATED. # PLEASE UPDATE Dockerfile.txt INSTEAD OF THIS FILE # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -FROM selenium/base:3.9.1-actinium +FROM selenium/base:local LABEL authors=SeleniumHQ USER seluser diff --git a/Hub/entry_point.sh b/Hub/entry_point.sh index 1da299b1e7..fcd9790f19 100755 --- a/Hub/entry_point.sh +++ b/Hub/entry_point.sh @@ -25,5 +25,7 @@ java ${JAVA_OPTS} -jar /opt/selenium/selenium-server-standalone.jar \ ${SE_OPTS} & NODE_PID=$! +/opt/bin/wait-for-it.sh -h 127.0.0.1 -p $GRID_HUB_PORT -t 30 -- echo "Hub is up and running." + trap shutdown SIGTERM SIGINT wait $NODE_PID diff --git a/NodeBase/Dockerfile b/NodeBase/Dockerfile index 3ba640cbb9..26d05b9670 100644 --- a/NodeBase/Dockerfile +++ b/NodeBase/Dockerfile @@ -2,7 +2,7 @@ # NOTE: DO *NOT* EDIT THIS FILE. IT IS GENERATED. # PLEASE UPDATE Dockerfile.txt INSTEAD OF THIS FILE # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -FROM selenium/base:3.9.1-actinium +FROM selenium/base:local LABEL authors=SeleniumHQ USER root diff --git a/NodeBase/entry_point.sh b/NodeBase/entry_point.sh index 317e4c5a85..4685aebfac 100755 --- a/NodeBase/entry_point.sh +++ b/NodeBase/entry_point.sh @@ -46,6 +46,8 @@ SERVERNUM=$(get_server_num) rm -f /tmp/.X*lock +/opt/bin/wait-for-it.sh -h $HUB_PORT_4444_TCP_ADDR -p $HUB_PORT_4444_TCP_PORT -t 30 -s -- echo "Hub is ready for connections" + xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" \ java ${JAVA_OPTS} -jar /opt/selenium/selenium-server-standalone.jar \ -role node \ @@ -55,5 +57,7 @@ xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" ${SE_OPTS} & NODE_PID=$! +/opt/bin/wait-for-it.sh -h 127.0.0.1 -p $NODE_PORT -t 30 -s -- echo "Node is up." + trap shutdown SIGTERM SIGINT wait $NODE_PID diff --git a/NodeChrome/Dockerfile b/NodeChrome/Dockerfile index 7d8f64d339..1d3f1097b8 100644 --- a/NodeChrome/Dockerfile +++ b/NodeChrome/Dockerfile @@ -2,7 +2,7 @@ # NOTE: DO *NOT* EDIT THIS FILE. IT IS GENERATED. # PLEASE UPDATE Dockerfile.txt INSTEAD OF THIS FILE # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -FROM selenium/node-base:3.9.1-actinium +FROM selenium/node-base:local LABEL authors=SeleniumHQ USER root From 7459984021402d1fb7788682c4ad1280283cf628 Mon Sep 17 00:00:00 2001 From: Daniel Davison Date: Thu, 15 Feb 2018 15:53:26 -0500 Subject: [PATCH 2/6] starting wait-for-it --- Base/Dockerfile | 11 +++ Base/wait-for-it.sh | 177 ++++++++++++++++++++++++++++++++++++++++ Hub/entry_point.sh | 2 + NodeBase/entry_point.sh | 4 + 4 files changed, 194 insertions(+) create mode 100755 Base/wait-for-it.sh diff --git a/Base/Dockerfile b/Base/Dockerfile index a8658ed557..67a46ee5e5 100644 --- a/Base/Dockerfile +++ b/Base/Dockerfile @@ -46,6 +46,17 @@ RUN useradd seluser \ && echo 'ALL ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers \ && echo 'seluser:secret' | chpasswd +#======================================= +# Create shared / common bin directory +#======================================= +RUN mkdir -p /opt/bin + +#====================================== +# Add intermediate service discovery +#====================================== +COPY wait-for-it.sh \ + /opt/bin/ + #=================================================== # Run the following commands as non-privileged user #=================================================== diff --git a/Base/wait-for-it.sh b/Base/wait-for-it.sh new file mode 100755 index 0000000000..bbe404324b --- /dev/null +++ b/Base/wait-for-it.sh @@ -0,0 +1,177 @@ +#!/usr/bin/env bash +# Use this script to test if a given TCP host/port are available + +cmdname=$(basename $0) + +echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } + +usage() +{ + cat << USAGE >&2 +Usage: + $cmdname host:port [-s] [-t timeout] [-- command args] + -h HOST | --host=HOST Host or IP under test + -p PORT | --port=PORT TCP port under test + Alternatively, you specify the host and port as host:port + -s | --strict Only execute subcommand if the test succeeds + -q | --quiet Don't output any status messages + -t TIMEOUT | --timeout=TIMEOUT + Timeout in seconds, zero for no timeout + -- COMMAND ARGS Execute command with args after the test finishes +USAGE + exit 1 +} + +wait_for() +{ + if [[ $TIMEOUT -gt 0 ]]; then + echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" + else + echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" + fi + start_ts=$(date +%s) + while : + do + if [[ $ISBUSY -eq 1 ]]; then + nc -z $HOST $PORT + result=$? + else + (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 + result=$? + fi + if [[ $result -eq 0 ]]; then + end_ts=$(date +%s) + echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" + break + fi + sleep 1 + done + return $result +} + +wait_for_wrapper() +{ + # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 + if [[ $QUIET -eq 1 ]]; then + timeout $BUSYTIMEFLAG $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & + else + timeout $BUSYTIMEFLAG $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & + fi + PID=$! + trap "kill -INT -$PID" INT + wait $PID + RESULT=$? + if [[ $RESULT -ne 0 ]]; then + echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" + fi + return $RESULT +} + +# process arguments +while [[ $# -gt 0 ]] +do + case "$1" in + *:* ) + hostport=(${1//:/ }) + HOST=${hostport[0]} + PORT=${hostport[1]} + shift 1 + ;; + --child) + CHILD=1 + shift 1 + ;; + -q | --quiet) + QUIET=1 + shift 1 + ;; + -s | --strict) + STRICT=1 + shift 1 + ;; + -h) + HOST="$2" + if [[ $HOST == "" ]]; then break; fi + shift 2 + ;; + --host=*) + HOST="${1#*=}" + shift 1 + ;; + -p) + PORT="$2" + if [[ $PORT == "" ]]; then break; fi + shift 2 + ;; + --port=*) + PORT="${1#*=}" + shift 1 + ;; + -t) + TIMEOUT="$2" + if [[ $TIMEOUT == "" ]]; then break; fi + shift 2 + ;; + --timeout=*) + TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + CLI=("$@") + break + ;; + --help) + usage + ;; + *) + echoerr "Unknown argument: $1" + usage + ;; + esac +done + +if [[ "$HOST" == "" || "$PORT" == "" ]]; then + echoerr "Error: you need to provide a host and port to test." + usage +fi + +TIMEOUT=${TIMEOUT:-15} +STRICT=${STRICT:-0} +CHILD=${CHILD:-0} +QUIET=${QUIET:-0} + +# check to see if timeout is from busybox? +# check to see if timeout is from busybox? +TIMEOUT_PATH=$(realpath $(which timeout)) +if [[ $TIMEOUT_PATH =~ "busybox" ]]; then + ISBUSY=1 + BUSYTIMEFLAG="-t" +else + ISBUSY=0 + BUSYTIMEFLAG="" +fi + +if [[ $CHILD -gt 0 ]]; then + wait_for + RESULT=$? + exit $RESULT +else + if [[ $TIMEOUT -gt 0 ]]; then + wait_for_wrapper + RESULT=$? + else + wait_for + RESULT=$? + fi +fi + +if [[ $CLI != "" ]]; then + if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then + echoerr "$cmdname: strict mode, refusing to execute subprocess" + exit $RESULT + fi + exec "${CLI[@]}" +else + exit $RESULT +fi diff --git a/Hub/entry_point.sh b/Hub/entry_point.sh index 1da299b1e7..fcd9790f19 100755 --- a/Hub/entry_point.sh +++ b/Hub/entry_point.sh @@ -25,5 +25,7 @@ java ${JAVA_OPTS} -jar /opt/selenium/selenium-server-standalone.jar \ ${SE_OPTS} & NODE_PID=$! +/opt/bin/wait-for-it.sh -h 127.0.0.1 -p $GRID_HUB_PORT -t 30 -- echo "Hub is up and running." + trap shutdown SIGTERM SIGINT wait $NODE_PID diff --git a/NodeBase/entry_point.sh b/NodeBase/entry_point.sh index 317e4c5a85..4685aebfac 100755 --- a/NodeBase/entry_point.sh +++ b/NodeBase/entry_point.sh @@ -46,6 +46,8 @@ SERVERNUM=$(get_server_num) rm -f /tmp/.X*lock +/opt/bin/wait-for-it.sh -h $HUB_PORT_4444_TCP_ADDR -p $HUB_PORT_4444_TCP_PORT -t 30 -s -- echo "Hub is ready for connections" + xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" \ java ${JAVA_OPTS} -jar /opt/selenium/selenium-server-standalone.jar \ -role node \ @@ -55,5 +57,7 @@ xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" ${SE_OPTS} & NODE_PID=$! +/opt/bin/wait-for-it.sh -h 127.0.0.1 -p $NODE_PORT -t 30 -s -- echo "Node is up." + trap shutdown SIGTERM SIGINT wait $NODE_PID From bfc15bf999ebc62921c0179afbab5fbc8d964007 Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Fri, 24 Aug 2018 18:45:06 +0200 Subject: [PATCH 3/6] Adding small script to check the Grid status, plus docs for HEALTHCHECK, fixes #691 --- .github/ISSUE_TEMPLATE.md | 13 +++ .github/PULL_REQUEST_TEMPLATE.md | 4 + Base/Dockerfile | 5 +- Base/check-grid.sh | 26 +++++ Base/wait-for-it.sh | 177 ------------------------------- Hub/Dockerfile.txt | 4 +- Hub/entry_point.sh | 2 - NodeBase/entry_point.sh | 4 - README.md | 96 +++++++++++++++++ 9 files changed, 144 insertions(+), 187 deletions(-) create mode 100644 Base/check-grid.sh delete mode 100755 Base/wait-for-it.sh diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 820c4b94b3..ebde1235a8 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,11 @@ ## Meta - + + + + + Image(s): Docker-Selenium Image Version(s): @@ -21,3 +28,9 @@ https://bugzilla.mozilla.org/buglist.cgi?product=Testing&component=Marionette ## Expected Behavior - ## Actual Behavior - + +## Steps to reproduce - + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index fc218f8f00..f578652af3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1 +1,5 @@ + + + - [ ] By placing an `X` in the preceding checkbox, I verify that I have signed the [Contributor License Agreement](https://github.com/SeleniumHQ/docker-selenium/blob/master/CONTRIBUTING.md#contributing-code-to-selenium) diff --git a/Base/Dockerfile b/Base/Dockerfile index 67a46ee5e5..4ef0b1a67f 100644 --- a/Base/Dockerfile +++ b/Base/Dockerfile @@ -25,6 +25,8 @@ RUN apt-get -qqy update \ sudo \ unzip \ wget \ + jq \ + curl \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/* \ && sed -i 's/securerandom\.source=file:\/dev\/random/securerandom\.source=file:\/dev\/urandom/' ./usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/java.security @@ -54,8 +56,9 @@ RUN mkdir -p /opt/bin #====================================== # Add intermediate service discovery #====================================== -COPY wait-for-it.sh \ +COPY check-grid.sh \ /opt/bin/ +RUN chmod +x /opt/bin/check-grid.sh #=================================================== # Run the following commands as non-privileged user diff --git a/Base/check-grid.sh b/Base/check-grid.sh new file mode 100644 index 0000000000..046fff0a26 --- /dev/null +++ b/Base/check-grid.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# check-grid.sh + +set -e + +# process arguments +while [[ $# -gt 0 ]] +do + case "$1" in + --host) + HOST="$2" + if [[ ${HOST} == "" ]]; then HOST="localhost"; fi + shift 2 + ;; + --port) + PORT="$2" + if [[ ${PORT} == "" ]]; then PORT="4444"; fi + shift 2 + ;; + *) + echoerr "Unknown argument: $1" + ;; + esac +done + +curl -sSL http://${HOST}:${PORT}/wd/hub/status | jq -r '.value.ready' | grep "true" || exit 1 diff --git a/Base/wait-for-it.sh b/Base/wait-for-it.sh deleted file mode 100755 index bbe404324b..0000000000 --- a/Base/wait-for-it.sh +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/env bash -# Use this script to test if a given TCP host/port are available - -cmdname=$(basename $0) - -echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } - -usage() -{ - cat << USAGE >&2 -Usage: - $cmdname host:port [-s] [-t timeout] [-- command args] - -h HOST | --host=HOST Host or IP under test - -p PORT | --port=PORT TCP port under test - Alternatively, you specify the host and port as host:port - -s | --strict Only execute subcommand if the test succeeds - -q | --quiet Don't output any status messages - -t TIMEOUT | --timeout=TIMEOUT - Timeout in seconds, zero for no timeout - -- COMMAND ARGS Execute command with args after the test finishes -USAGE - exit 1 -} - -wait_for() -{ - if [[ $TIMEOUT -gt 0 ]]; then - echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" - else - echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" - fi - start_ts=$(date +%s) - while : - do - if [[ $ISBUSY -eq 1 ]]; then - nc -z $HOST $PORT - result=$? - else - (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 - result=$? - fi - if [[ $result -eq 0 ]]; then - end_ts=$(date +%s) - echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" - break - fi - sleep 1 - done - return $result -} - -wait_for_wrapper() -{ - # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 - if [[ $QUIET -eq 1 ]]; then - timeout $BUSYTIMEFLAG $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & - else - timeout $BUSYTIMEFLAG $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & - fi - PID=$! - trap "kill -INT -$PID" INT - wait $PID - RESULT=$? - if [[ $RESULT -ne 0 ]]; then - echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" - fi - return $RESULT -} - -# process arguments -while [[ $# -gt 0 ]] -do - case "$1" in - *:* ) - hostport=(${1//:/ }) - HOST=${hostport[0]} - PORT=${hostport[1]} - shift 1 - ;; - --child) - CHILD=1 - shift 1 - ;; - -q | --quiet) - QUIET=1 - shift 1 - ;; - -s | --strict) - STRICT=1 - shift 1 - ;; - -h) - HOST="$2" - if [[ $HOST == "" ]]; then break; fi - shift 2 - ;; - --host=*) - HOST="${1#*=}" - shift 1 - ;; - -p) - PORT="$2" - if [[ $PORT == "" ]]; then break; fi - shift 2 - ;; - --port=*) - PORT="${1#*=}" - shift 1 - ;; - -t) - TIMEOUT="$2" - if [[ $TIMEOUT == "" ]]; then break; fi - shift 2 - ;; - --timeout=*) - TIMEOUT="${1#*=}" - shift 1 - ;; - --) - shift - CLI=("$@") - break - ;; - --help) - usage - ;; - *) - echoerr "Unknown argument: $1" - usage - ;; - esac -done - -if [[ "$HOST" == "" || "$PORT" == "" ]]; then - echoerr "Error: you need to provide a host and port to test." - usage -fi - -TIMEOUT=${TIMEOUT:-15} -STRICT=${STRICT:-0} -CHILD=${CHILD:-0} -QUIET=${QUIET:-0} - -# check to see if timeout is from busybox? -# check to see if timeout is from busybox? -TIMEOUT_PATH=$(realpath $(which timeout)) -if [[ $TIMEOUT_PATH =~ "busybox" ]]; then - ISBUSY=1 - BUSYTIMEFLAG="-t" -else - ISBUSY=0 - BUSYTIMEFLAG="" -fi - -if [[ $CHILD -gt 0 ]]; then - wait_for - RESULT=$? - exit $RESULT -else - if [[ $TIMEOUT -gt 0 ]]; then - wait_for_wrapper - RESULT=$? - else - wait_for - RESULT=$? - fi -fi - -if [[ $CLI != "" ]]; then - if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then - echoerr "$cmdname: strict mode, refusing to execute subprocess" - exit $RESULT - fi - exec "${CLI[@]}" -else - exit $RESULT -fi diff --git a/Hub/Dockerfile.txt b/Hub/Dockerfile.txt index c00d10632a..700c28c1a8 100644 --- a/Hub/Dockerfile.txt +++ b/Hub/Dockerfile.txt @@ -30,9 +30,7 @@ ENV GRID_HUB_HOST "0.0.0.0" COPY generate_config \ entry_point.sh \ /opt/bin/ -# Running this command as sudo just to avoid the message: -# To run a command as administrator (user "root"), use "sudo ". See "man sudo_root" for details. -# When logging into the container + RUN /opt/bin/generate_config > /opt/selenium/config.json CMD ["/opt/bin/entry_point.sh"] diff --git a/Hub/entry_point.sh b/Hub/entry_point.sh index fcd9790f19..1da299b1e7 100755 --- a/Hub/entry_point.sh +++ b/Hub/entry_point.sh @@ -25,7 +25,5 @@ java ${JAVA_OPTS} -jar /opt/selenium/selenium-server-standalone.jar \ ${SE_OPTS} & NODE_PID=$! -/opt/bin/wait-for-it.sh -h 127.0.0.1 -p $GRID_HUB_PORT -t 30 -- echo "Hub is up and running." - trap shutdown SIGTERM SIGINT wait $NODE_PID diff --git a/NodeBase/entry_point.sh b/NodeBase/entry_point.sh index 4685aebfac..317e4c5a85 100755 --- a/NodeBase/entry_point.sh +++ b/NodeBase/entry_point.sh @@ -46,8 +46,6 @@ SERVERNUM=$(get_server_num) rm -f /tmp/.X*lock -/opt/bin/wait-for-it.sh -h $HUB_PORT_4444_TCP_ADDR -p $HUB_PORT_4444_TCP_PORT -t 30 -s -- echo "Hub is ready for connections" - xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" \ java ${JAVA_OPTS} -jar /opt/selenium/selenium-server-standalone.jar \ -role node \ @@ -57,7 +55,5 @@ xvfb-run -n $SERVERNUM --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" ${SE_OPTS} & NODE_PID=$! -/opt/bin/wait-for-it.sh -h 127.0.0.1 -p $NODE_PORT -t 30 -s -- echo "Node is up." - trap shutdown SIGTERM SIGINT wait $NODE_PID diff --git a/README.md b/README.md index 4d775d9986..6d64ab36b9 100644 --- a/README.md +++ b/README.md @@ -269,6 +269,102 @@ $ FF=$(docker run --rm --name=fx \ _Note: Since a Docker container is not meant to preserve state and spawning a new one takes less than 3 seconds you will likely want to remove containers after each end-to-end test with_ `--rm` _command. You need to think of your Docker containers as single processes, not as running virtual machines, in case you are familiar with [Vagrant](https://www.vagrantup.com/)._ +## Waiting for the Grid to be ready + +It is a good practice to check first if the Grid is up and ready to receive requests, this can be done by checking the `/wd/hub/status` endpoint. + +A Grid that is ready, composed by a hub and a node, could look like this: + +```json +{ + "status": 0, + "value": { + "ready": true, + "message": "Hub has capacity", + "build": { + "revision": "aacccce0", + "time": "2018-08-02T20:13:22.693Z", + "version": "3.14.0" + }, + "os": { + "arch": "amd64", + "name": "Linux", + "version": "4.9.93-linuxkit-aufs" + }, + "java": { + "version": "1.8.0_181" + } + } +} +``` + +The `"ready": true` value indicates that the Grid is ready to receive requests. This status can be polled through a +script before running any test, or it can be added as a [HEALTHCHECK](https://docs.docker.com/engine/reference/run/#healthcheck) +when the docker container is started. + +### Adding a [HEALTHCHECK](https://docs.docker.com/engine/reference/run/#healthcheck) to the Grid + +The script [check-grid.sh](Base/check-grid.sh), which is included in the images, can be used to poll the Grid status. + +This example checks the status of the Grid every 15 seconds, with has a timeout of 30 seconds when the check is done, +and it retries up to 5 times until the container is marked as unhealthy. Please use values that adjust to your needs, +additionally (if needed) replace the `--host` and `--port` parameters for the ones you have in your configuration. + +``` bash +$ docker network create grid +$ docker run -d -p 4444: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:3.14.0-arsenic +$ docker run -d --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-chrome:3.14.0-arsenic +$ docker run -d --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-firefox:3.14.0-arsenic +``` +**Note:** The `\` line delimiter won't work on Windows based terminals, try either `^` or `\``. + +The container health status can be checked by doing `docker ps` and verifying the `(healthy)|(unhealthy)` status or by +inspecting it in the following way: + +```bash +$ docker inspect --format='{{json .State.Health.Status}}' selenium-hub +"healthy" +``` + +### Using a bash script to wait for the Grid + +A common problem known in docker is that a running container does not always mean that the application inside it is ready. +A simple way to tackle this is by using a "wait-for-it" script, more information can be seen [here](https://docs.docker.com/compose/startup-order/). + +The following script is an example of how this can be done using bash, but the same principle applies if you want to do this in a method implemented +in the programming language used to run the tests. + +```bash +#!/bin/bash +# wait-for-grid.sh + +set -e + +cmd="$@" + +while ! curl -sSL "http://localhost:4444/wd/hub/status" 2>&1 \ + | jq -r '.value.ready' 2>&1 | grep "true" >/dev/null; do + echo 'Waiting for the Grid' + sleep 1 +done + +>&2 echo "Selenium Grid is up - executing tests" +exec $cmd +``` +**Note:** If needed, replace `localhost` and `4444` for the correct values in your environment. Also, this script is polling indefinitely, you might want +to teak it and establish a timeout. + +Let's say that the normal command to execute your tests is `mvn clean test`. Here is a way to use the above script and execute your tests: + +```bash +$ ./wait-for-grid.sh mvn clean test +``` + +Like this, the script will poll until the Grid is ready, and then your tests will start. + ## Debugging In the event you wish to visually see what the browser is doing you will want to run the `debug` variant of node or standalone images. A VNC server will run on port 5900. You are free to map that to any free external port that you wish. Keep in mind that you will only be able to run one node per port so if you wish to include a second node, or more, you will have to use different ports, the 5900 as the internal port will have to remain the same though as thats the VNC service on the node. The second example below shows how to run multiple nodes and with different VNC ports open: From 9bda77dc7dfd0cad5170402a425f9314fe0c20a3 Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Fri, 24 Aug 2018 18:56:21 +0200 Subject: [PATCH 4/6] Fixing typos. --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6d64ab36b9..b058e2d16e 100644 --- a/README.md +++ b/README.md @@ -306,9 +306,9 @@ when the docker container is started. The script [check-grid.sh](Base/check-grid.sh), which is included in the images, can be used to poll the Grid status. -This example checks the status of the Grid every 15 seconds, with has a timeout of 30 seconds when the check is done, -and it retries up to 5 times until the container is marked as unhealthy. Please use values that adjust to your needs, -additionally (if needed) replace the `--host` and `--port` parameters for the ones you have in your configuration. +This example checks the status of the Grid every 15 seconds, it has a timeout of 30 seconds when the check is done, +and it retries up to 5 times until the container is marked as unhealthy. Please use adjusted values to fit your needs, +(if needed) replace the `--host` and `--port` parameters for the ones used in your environment. ``` bash $ docker network create grid @@ -319,7 +319,7 @@ $ docker run -d -p 4444:4444 --net grid --name selenium-hub \ $ docker run -d --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-chrome:3.14.0-arsenic $ docker run -d --net grid -e HUB_HOST=selenium-hub -v /dev/shm:/dev/shm selenium/node-firefox:3.14.0-arsenic ``` -**Note:** The `\` line delimiter won't work on Windows based terminals, try either `^` or `\``. +**Note:** The `\` line delimiter won't work on Windows based terminals, try either `^` or a backtick. The container health status can be checked by doing `docker ps` and verifying the `(healthy)|(unhealthy)` status or by inspecting it in the following way: @@ -334,8 +334,7 @@ $ docker inspect --format='{{json .State.Health.Status}}' selenium-hub A common problem known in docker is that a running container does not always mean that the application inside it is ready. A simple way to tackle this is by using a "wait-for-it" script, more information can be seen [here](https://docs.docker.com/compose/startup-order/). -The following script is an example of how this can be done using bash, but the same principle applies if you want to do this in a method implemented -in the programming language used to run the tests. +The following script is an example of how this can be done using bash, but the same principle applies if you want to do this with the programming language used to write the tests. ```bash #!/bin/bash From 8278ba0ee6093d58c528716f0f2a9e4d63a68c8f Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Sat, 25 Aug 2018 11:37:58 +0200 Subject: [PATCH 5/6] Adding default vars for script --- Base/check-grid.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Base/check-grid.sh b/Base/check-grid.sh index 046fff0a26..6c23f2441d 100644 --- a/Base/check-grid.sh +++ b/Base/check-grid.sh @@ -3,18 +3,19 @@ set -e +HOST="localhost" +PORT="4444" + # process arguments while [[ $# -gt 0 ]] do case "$1" in --host) - HOST="$2" - if [[ ${HOST} == "" ]]; then HOST="localhost"; fi + HOST=${2:-"localhost"} shift 2 ;; --port) - PORT="$2" - if [[ ${PORT} == "" ]]; then PORT="4444"; fi + PORT=${2:-"4444"} shift 2 ;; *) From 3c9a273547349068f2dd2f9cb4106e370ad25fb8 Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Sun, 26 Aug 2018 12:25:41 +0200 Subject: [PATCH 6/6] Fixing typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b058e2d16e..b8a271b2b3 100644 --- a/README.md +++ b/README.md @@ -354,7 +354,7 @@ done exec $cmd ``` **Note:** If needed, replace `localhost` and `4444` for the correct values in your environment. Also, this script is polling indefinitely, you might want -to teak it and establish a timeout. +to tweak it and establish a timeout. Let's say that the normal command to execute your tests is `mvn clean test`. Here is a way to use the above script and execute your tests: