diff --git a/README.md b/README.md index f1207c4..2d20deb 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Download the `wait-for` file, either the latest from [`master`](https://raw.gith With the file locally on your file system, you can directly invoke it. ``` -./wait-for host:port [-t timeout] [-- command args] +./wait-for host:port|url [-t timeout] [-- command args] -q | --quiet Do not 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 @@ -69,8 +69,8 @@ Eficode site is up To wait for database container to become available: -``` -version: '2' +```yml +version: '3' services: db: @@ -83,6 +83,30 @@ services: - db ``` +To check if [https://www.eficode.com](https://www.eficode.com) is available over HTTPS: +``` +$ ./wait-for https://www.eficode.com -- echo "Eficode is accessible over HTTPS" +Eficode is accessible over HTTPS +``` + +To wait for your API service to become available: + + +```yml +version: '3' + +services: + api: + image: nginx + + tests: + build: . + command: sh -c './wait-for http://api -- echo "The api is up! Let's use it"' + depends_on: + - api + +``` + ## Testing Ironically testing is done using [bats](https://github.com/sstephenson/bats), which on the other hand is depending on [bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)). @@ -100,9 +124,11 @@ Also, please include or update the test cases whenever possible by extending `wa ## Note -Make sure netcat is installed in your Dockerfile before running the command. +Make sure netcat is installed in your Dockerfile before running the command if you test over plain TCP. ``` RUN apt-get -q update && apt-get -qy install netcat ``` https://stackoverflow.com/questions/44663180/docker-why-does-wait-for-always-time-out +If you are connecting over HTTP, then you will need to have wget available. + \ No newline at end of file diff --git a/wait-for b/wait-for index 4ec5263..43ed61b 100755 --- a/wait-for +++ b/wait-for @@ -22,9 +22,11 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -set -- "$@" -- "$TIMEOUT" "$QUIET" "$HOST" "$PORT" "$result" +set -- "$@" -- "$TIMEOUT" "$QUIET" "$PROTOCOL" "$HOST" "$PORT" "$result" TIMEOUT=15 QUIET=0 +# The protocol to make the request with, either "tcp" or "http" +PROTOCOL="tcp" echoerr() { if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi @@ -34,7 +36,7 @@ usage() { exitcode="$1" cat << USAGE >&2 Usage: - $cmdname host:port [-t timeout] [-- command args] + $cmdname host:port|url [-t timeout] [-- command args] -q | --quiet Do not 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 @@ -43,25 +45,47 @@ USAGE } wait_for() { - if ! command -v nc >/dev/null; then - echoerr 'nc command is missing!' - exit 1 - fi + case "$PROTOCOL" in + tcp) + if ! command -v nc >/dev/null; then + echoerr 'nc command is missing!' + exit 1 + fi + ;; + wget) + if ! command -v wget >/dev/null; then + echoerr 'nc command is missing!' + exit 1 + fi + ;; + esac while :; do - nc -z "$HOST" "$PORT" > /dev/null 2>&1 - + case "$PROTOCOL" in + tcp) + nc -z "$HOST" "$PORT" > /dev/null 2>&1 + ;; + http) + wget --timeout=1 -q "$HOST" -O /dev/null > /dev/null 2>&1 + ;; + *) + echoerr "Unknown protocol '$PROTOCOL'" + exit 1 + ;; + esac + result=$? + if [ $result -eq 0 ] ; then - if [ $# -gt 6 ] ; then - for result in $(seq $(($# - 6))); do + if [ $# -gt 7 ] ; then + for result in $(seq $(($# - 7))); do result=$1 shift set -- "$@" "$result" done - TIMEOUT=$2 QUIET=$3 HOST=$4 PORT=$5 result=$6 - shift 6 + TIMEOUT=$2 QUIET=$3 PROTOCOL=$4 HOST=$5 PORT=$6 result=$7 + shift 7 exec "$@" fi exit 0 @@ -80,6 +104,11 @@ wait_for() { while :; do case "$1" in + http://*|https://*) + HOST="$1" + PROTOCOL="http" + shift 1 + ;; *:* ) HOST=$(printf "%s\n" "$1"| cut -d : -f 1) PORT=$(printf "%s\n" "$1"| cut -d : -f 2) @@ -137,9 +166,19 @@ if ! [ "$TIMEOUT" -ge 0 ] 2>/dev/null; then usage 3 fi -if [ "$HOST" = "" -o "$PORT" = "" ]; then - echoerr "Error: you need to provide a host and port to test." - usage 2 -fi +case "$PROTOCOL" in + tcp) + if [ "$HOST" = "" -o "$PORT" = "" ]; then + echoerr "Error: you need to provide a host and port to test." + usage 2 + fi + ;; + http) + if [ "$HOST" = "" ]; then + echoerr "Error: you need to provide a host to test." + usage 2 + fi + ;; +esac wait_for "$@" diff --git a/wait-for.bats b/wait-for.bats index d75f0cc..758e086 100644 --- a/wait-for.bats +++ b/wait-for.bats @@ -33,15 +33,54 @@ [ "$output" != "success" ] } -@test "environment variables should be restored for command invocation" { +@test "environment variable HOST should be restored for command invocation" { HOST=success run ./wait-for -t 1 google.com:80 -- sh -c 'echo "$HOST"' [ "$output" = "success" ] } -@test "unset environment variables should be restored as unset for command invocation" { +@test "unset environment variable HOST should be restored as unset for command invocation" { run ./wait-for -t 1 google.com:80 -- sh -uc 'echo "$HOST"' [ "$status" -ne 0 ] [ "$output" != "google.com" ] } + +@test "environment variable PROTOCOL should be restored for command invocation" { + PROTOCOL=success run ./wait-for -t 1 google.com:80 -- sh -c 'echo "$PROTOCOL"' + + [ "$output" = "success" ] +} + +@test "unset environment variables PROTOCOL should be restored as unset for command invocation" { + run ./wait-for -t 1 google.com:80 -- sh -uc 'echo "$PROTOCOL"' + + [ "$status" -ne 0 ] + [ "$output" != "google.com" ] +} + +@test "http://duckduckgo.com should be immediately found" { + run ./wait-for http://duckduckgo.com -- echo 'success' + + [ "$output" = "success" ] +} + +@test "https://duckduckgo.com should be immediately found" { + run ./wait-for https://duckduckgo.com -- echo 'success' + + [ "$output" = "success" ] +} + +@test "connection error in HTTP test should not start command" { + run ./wait-for -t 1 http://google.com:8080 -- echo 'success' + + [ "$status" -ne 0 ] + [ "$output" != "success" ] +} + +@test "not found HTTP status should not start command" { + run ./wait-for -t 1 http://google.com/ping -- echo 'success' + + [ "$status" -ne 0 ] + [ "$output" != "success" ] +}