From 51de968acbcd4d8837de6447dd6a91cdebfc51ea Mon Sep 17 00:00:00 2001 From: Marko Klemetti Date: Sat, 6 May 2017 15:48:18 +0300 Subject: [PATCH 01/16] Move travis build and status under Eficode --- .travis.yml | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 90bc111..392b52e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,5 +6,5 @@ services: - docker before_install: - - docker build -t mrako/wait-for . - - docker run mrako/wait-for + - docker build -t eficode/wait-for . + - docker run eficode/wait-for diff --git a/README.md b/README.md index b6c83e4..a31be9b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ When using this tool, you only need to pick the `wait-for` file as part of your project. -[![Build Status](https://travis-ci.org/mrako/wait-for.svg?branch=master)](https://travis-ci.org/mrako/wait-for) +[![Build Status](https://travis-ci.org/Eficode/wait-for.svg?branch=master)](https://travis-ci.org/Eficode/wait-for) ## Usage From a8511d0630388d00a865b34847a03e532e53c74b Mon Sep 17 00:00:00 2001 From: JeremyCraigMartinez Date: Fri, 4 Aug 2017 11:36:14 -0700 Subject: [PATCH 02/16] add name and version so it can be installed with npm --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 6d167cc..977ac4a 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,6 @@ { + "name": "wait-for", + "version": "0.1.0", "scripts": { "test": "./node_modules/.bin/bats wait-for.bats" }, From f71f8199a0dd95953752fb5d3f76f79ced16d47d Mon Sep 17 00:00:00 2001 From: Manabu Matsui Date: Fri, 25 Aug 2017 09:50:42 +0900 Subject: [PATCH 03/16] use 'exec "$@"' --- wait-for | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/wait-for b/wait-for index 077a8d3..ddfc39e 100755 --- a/wait-for +++ b/wait-for @@ -20,14 +20,13 @@ USAGE } wait_for() { - command="$*" for i in `seq $TIMEOUT` ; do nc -z "$HOST" "$PORT" > /dev/null 2>&1 result=$? if [ $result -eq 0 ] ; then - if [ -n "$command" ] ; then - exec $command + if [ $# -gt 0 ] ; then + exec "$@" fi exit 0 fi From be1c7bd5820044f2cc11b39ea624ed961af8f524 Mon Sep 17 00:00:00 2001 From: szTheory Date: Sun, 8 Apr 2018 20:09:46 -0400 Subject: [PATCH 04/16] Update README.md fix Travis CI build badge URL --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a31be9b..7fbcaed 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ When using this tool, you only need to pick the `wait-for` file as part of your project. -[![Build Status](https://travis-ci.org/Eficode/wait-for.svg?branch=master)](https://travis-ci.org/Eficode/wait-for) +[![Build Status](https://travis-ci.org/eficode/wait-for.svg?branch=master)](https://travis-ci.org/Eficode/wait-for) ## Usage @@ -48,4 +48,4 @@ services: 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)). docker build -t wait-for . - docker run -t wait-for \ No newline at end of file + docker run -t wait-for From 541a5d61d7faaf87af01dad757a7c4b01ca65cf2 Mon Sep 17 00:00:00 2001 From: Markus Suonto Date: Mon, 9 Apr 2018 10:08:54 +0200 Subject: [PATCH 05/16] Fix also the other url that had capital E --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7fbcaed..f1956f7 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ When using this tool, you only need to pick the `wait-for` file as part of your project. -[![Build Status](https://travis-ci.org/eficode/wait-for.svg?branch=master)](https://travis-ci.org/Eficode/wait-for) +[![Build Status](https://travis-ci.org/eficode/wait-for.svg?branch=master)](https://travis-ci.org/eficode/wait-for) ## Usage From d62fcc3960450399a2f41f50ec84a490956b1e87 Mon Sep 17 00:00:00 2001 From: Omar Bouzoumita Date: Thu, 6 Sep 2018 14:38:48 +0100 Subject: [PATCH 06/16] add a backup for the environment variables named `TIMEOUT`, `QUIT`, `PORT`, `HOST` --- wait-for | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wait-for b/wait-for index ddfc39e..aa8188d 100755 --- a/wait-for +++ b/wait-for @@ -1,5 +1,10 @@ #!/bin/sh +OLD_TIMEOUT=$TIMEOUT +OLD_QUIET=$QUIET +OLD_PORT=$PORT +OLD_HOST=$HOST + TIMEOUT=15 QUIET=0 @@ -26,7 +31,7 @@ wait_for() { result=$? if [ $result -eq 0 ] ; then if [ $# -gt 0 ] ; then - exec "$@" + TIMEOUT=$OLD_TIMEOUT QUIET=$OLD_QUIET PORT=$OLD_PORT HOST=$OLD_HOST exec "$@" fi exit 0 fi From ae37d72731b9141fb5bb2cb48d790e4a489a1d8d Mon Sep 17 00:00:00 2001 From: Rahmat Budiharso Date: Wed, 11 Oct 2017 11:32:27 +0700 Subject: [PATCH 07/16] preserve existing environment variable --- wait-for.bats | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/wait-for.bats b/wait-for.bats index cbea6a4..c720419 100644 --- a/wait-for.bats +++ b/wait-for.bats @@ -2,7 +2,7 @@ @test "google should be immediately found" { run ./wait-for google.com:80 -- echo 'success' - + [ "$output" = "success" ] } @@ -12,3 +12,12 @@ [ "$status" -ne 0 ] [ "$output" != "success" ] } + +@test "preserve existing environment variable" { + HOST=myweb.com + PORT=8080 + run ./wait-for google.com:80 -- echo 'success' + + [ "$(echo $HOST)" = 'myweb.com' ] + [ "$(echo $PORT)" = '8080' ] +} From 1e47fb8ae35e95ef3683d3cc1e9b183b048a32c7 Mon Sep 17 00:00:00 2001 From: Wilson Silva Date: Wed, 7 Feb 2018 12:48:49 +0000 Subject: [PATCH 08/16] Fix the silent timeout error when netcat is not installed --- wait-for | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wait-for b/wait-for index aa8188d..6949f3f 100755 --- a/wait-for +++ b/wait-for @@ -8,6 +8,11 @@ OLD_HOST=$HOST TIMEOUT=15 QUIET=0 +if ! which nc >/dev/null; then + echo "Netcat is not installed. This script requires netcat to work correctly." + exit 1 +fi + echoerr() { if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi } From 65664639c80c181e897ceb6e22809b20d4f8aea8 Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 7 May 2018 13:15:51 -0300 Subject: [PATCH 09/16] Add strict option --- wait-for | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/wait-for b/wait-for index 6949f3f..d9a9b99 100755 --- a/wait-for +++ b/wait-for @@ -23,6 +23,7 @@ usage() { Usage: $cmdname host:port [-t timeout] [-- command args] -q | --quiet Do not output any status messages + -s | --strict Only execute subcommand if the test succeeds -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout -- COMMAND ARGS Execute command with args after the test finishes USAGE @@ -43,6 +44,12 @@ wait_for() { sleep 1 done echo "Operation timed out" >&2 + if [ $result -ne 0 ] && [ $STRICT -ne 1 ] ; then + if [ $# -gt 0 ] ; then + exec "$@" + fi + exit 0 + fi exit 1 } @@ -58,6 +65,10 @@ do QUIET=1 shift 1 ;; + -s | --strict) + STRICT=1 + shift 1 + ;; -t) TIMEOUT="$2" if [ "$TIMEOUT" = "" ]; then break; fi @@ -86,4 +97,6 @@ if [ "$HOST" = "" -o "$PORT" = "" ]; then usage 2 fi +STRICT=${STRICT:-0} + wait_for "$@" From 40f22acd975f58dede50884b04782e80e144f162 Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 7 May 2018 13:41:28 -0300 Subject: [PATCH 10/16] Update README.md --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index f1956f7..f169999 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ When using this tool, you only need to pick the `wait-for` file as part of your ``` ./wait-for host:port [-t timeout] [-- command args] -q | --quiet Do not output any status messages + -s | --strict Only execute subcommand if the test succeeds -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout -- COMMAND ARGS Execute command with args after the test finishes ``` @@ -26,6 +27,15 @@ Connection to www.eficode.com port 80 [tcp/http] succeeded! Eficode site is up ``` +The subcommand will be executed regardless if the service is up or not. If you wish to execute the subcommand only if the service is up, add the --strict argument. In this example, we will test port 81 on www.google.com which will fail: + +``` +$ ./wait-for www.eficode.com:80 -- echo "Eficode site is up" +$ ./wait-for www.google.com:81 --timeout=1 --strict -- echo "google is up" +Operation timed out +google is up +``` + To wait for database container to become available: From 4a309ccd13e03f32517f28ce9df595abfc8d9082 Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Thu, 25 Oct 2018 09:15:03 -0400 Subject: [PATCH 11/16] fix representation of cmd name in usage()/help --- wait-for | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wait-for b/wait-for index d9a9b99..6c892cf 100755 --- a/wait-for +++ b/wait-for @@ -21,7 +21,7 @@ usage() { exitcode="$1" cat << USAGE >&2 Usage: - $cmdname host:port [-t timeout] [-- command args] + $(basename $0) host:port [-t timeout] [-- command args] -q | --quiet Do not output any status messages -s | --strict Only execute subcommand if the test succeeds -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout From d101d613f0f56b2b15bf250e52f008b9c6b94d9d Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Thu, 25 Oct 2018 09:18:18 -0400 Subject: [PATCH 12/16] Make nc time out in a known amount of time instead of hanging --- wait-for | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wait-for b/wait-for index 6c892cf..c93c054 100755 --- a/wait-for +++ b/wait-for @@ -32,7 +32,8 @@ USAGE wait_for() { for i in `seq $TIMEOUT` ; do - nc -z "$HOST" "$PORT" > /dev/null 2>&1 + # use a 1-second timeout + nc -w 1 -z "$HOST" "$PORT" > /dev/null 2>&1 result=$? if [ $result -eq 0 ] ; then From 5a7a56e6e5d6ab1d00dc932abdedaeffecb8ceda Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Thu, 25 Oct 2018 09:57:06 -0400 Subject: [PATCH 13/16] when on OSX, use all relevant nc timeout options --- wait-for | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/wait-for b/wait-for index c93c054..5748a0e 100755 --- a/wait-for +++ b/wait-for @@ -30,11 +30,20 @@ USAGE exit "$exitcode" } +test_connection() { + # force a 1-second timeout on darwin (https://stackoverflow.com/a/20460402/2063546) + if [ -z "${OSTYPE##*darwin*}" ] ; then + nc -z -w 1 -G 1 "$1" "$2" > /dev/null 2>&1 + else + nc -z -w 1 "$1" "$2" > /dev/null 2>&1 + fi +} + wait_for() { for i in `seq $TIMEOUT` ; do - # use a 1-second timeout - nc -w 1 -z "$HOST" "$PORT" > /dev/null 2>&1 - + # use a 1-second timeout, but still sleep 0.1 seconds after just to be safe + test_connection "$HOST" "$PORT" + result=$? if [ $result -eq 0 ] ; then if [ $# -gt 0 ] ; then From 442f8fb80be34368d623145d436b361eb54f79e4 Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Thu, 25 Oct 2018 10:44:00 -0400 Subject: [PATCH 14/16] Change strict option to loose option to avoid breaking existing behavior --- README.md | 13 ++++++------- wait-for | 30 +++++++++++------------------- wait-for.bats | 26 +++++++++++++++++++++----- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index f169999..ca2d3a9 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ When using this tool, you only need to pick the `wait-for` file as part of your ## Usage ``` -./wait-for host:port [-t timeout] [-- command args] +wait-for host:port [-t timeout] [-- command args] -q | --quiet Do not output any status messages - -s | --strict Only execute subcommand if the test succeeds + -l | --loose Execute subcommand even if the test times out -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout -- COMMAND ARGS Execute command with args after the test finishes ``` @@ -22,18 +22,17 @@ To check if [eficode.com](https://eficode.com) is available: ``` $ ./wait-for www.eficode.com:80 -- echo "Eficode site is up" - -Connection to www.eficode.com port 80 [tcp/http] succeeded! Eficode site is up ``` The subcommand will be executed regardless if the service is up or not. If you wish to execute the subcommand only if the service is up, add the --strict argument. In this example, we will test port 81 on www.google.com which will fail: ``` -$ ./wait-for www.eficode.com:80 -- echo "Eficode site is up" -$ ./wait-for www.google.com:81 --timeout=1 --strict -- echo "google is up" +$ ./wait-for www.google.com:81 --timeout=1 -- echo "google is up" +Operation timed out +$ ./wait-for www.google.com:81 --timeout=1 --loose -- echo "waited for google" Operation timed out -google is up +waited for google ``` To wait for database container to become available: diff --git a/wait-for b/wait-for index 5748a0e..c9f5b86 100755 --- a/wait-for +++ b/wait-for @@ -4,9 +4,11 @@ OLD_TIMEOUT=$TIMEOUT OLD_QUIET=$QUIET OLD_PORT=$PORT OLD_HOST=$HOST +OLD_LOOSE=$LOOSE TIMEOUT=15 QUIET=0 +LOOSE=0 if ! which nc >/dev/null; then echo "Netcat is not installed. This script requires netcat to work correctly." @@ -23,7 +25,7 @@ usage() { Usage: $(basename $0) host:port [-t timeout] [-- command args] -q | --quiet Do not output any status messages - -s | --strict Only execute subcommand if the test succeeds + -l | --loose Execute subcommand even if the test times out -t TIMEOUT | --timeout=timeout Timeout in seconds, zero for no timeout -- COMMAND ARGS Execute command with args after the test finishes USAGE @@ -40,27 +42,19 @@ test_connection() { } wait_for() { + local result for i in `seq $TIMEOUT` ; do # use a 1-second timeout, but still sleep 0.1 seconds after just to be safe test_connection "$HOST" "$PORT" - result=$? - if [ $result -eq 0 ] ; then - if [ $# -gt 0 ] ; then - TIMEOUT=$OLD_TIMEOUT QUIET=$OLD_QUIET PORT=$OLD_PORT HOST=$OLD_HOST exec "$@" - fi - exit 0 - fi + if [ $result -eq 0 ] ; then break ; fi sleep 1 done - echo "Operation timed out" >&2 - if [ $result -ne 0 ] && [ $STRICT -ne 1 ] ; then - if [ $# -gt 0 ] ; then - exec "$@" - fi - exit 0 + [ $result -ne 0 ] && echo "Operation timed out" >&2 + if [ $result -eq 0 -o $LOOSE -eq 1 -a $# -gt 0 ] ; then + TIMEOUT=$OLD_TIMEOUT QUIET=$OLD_QUIET PORT=$OLD_PORT HOST=$OLD_HOST LOOSE=$OLD_LOOSE exec "$@" fi - exit 1 + exit $result } while [ $# -gt 0 ] @@ -75,8 +69,8 @@ do QUIET=1 shift 1 ;; - -s | --strict) - STRICT=1 + -l | --loose) + LOOSE=1 shift 1 ;; -t) @@ -107,6 +101,4 @@ if [ "$HOST" = "" -o "$PORT" = "" ]; then usage 2 fi -STRICT=${STRICT:-0} - wait_for "$@" diff --git a/wait-for.bats b/wait-for.bats index c720419..fa873ac 100644 --- a/wait-for.bats +++ b/wait-for.bats @@ -13,11 +13,27 @@ [ "$output" != "success" ] } -@test "preserve existing environment variable" { - HOST=myweb.com - PORT=8080 +@test "nonexistent server should start command if loose option is specified" { + run ./wait-for -t 1 -l noserver:9999 -- echo 'passable' 2>&1 + + [ "$status" -eq 0 ] + + [ "${lines[0]}" = "Operation timed out" ] + [ "${lines[1]}" = "passable" ] +} + +@test "preserve existing environment variables" { + TIMEOUT=mytimeout + QUIET=myquiet + HOST=myhost + PORT=myport + LOOSE=myloose + run ./wait-for google.com:80 -- echo 'success' - [ "$(echo $HOST)" = 'myweb.com' ] - [ "$(echo $PORT)" = '8080' ] + [ "$(echo $TIMEOUT)" = 'mytimeout' ] + [ "$(echo $QUIET)" = 'myquiet' ] + [ "$(echo $HOST)" = 'myhost' ] + [ "$(echo $PORT)" = 'myport' ] + [ "$(echo $LOOSE)" = 'myloose' ] } From 7ff9b124a28eda5f4bc8c888ef301071063b7c90 Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Thu, 25 Oct 2018 11:37:08 -0400 Subject: [PATCH 15/16] use npm to test via node --- .travis.yml | 4 ++++ Dockerfile | 3 ++- package.json | 2 +- run_tests.sh | 8 ++++++++ wait-for | 2 +- 5 files changed, 16 insertions(+), 3 deletions(-) create mode 100755 run_tests.sh diff --git a/.travis.yml b/.travis.yml index 392b52e..e8a4731 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,8 @@ services: before_install: - docker build -t eficode/wait-for . + +script: + - npm install + - ./run_tests.sh - docker run eficode/wait-for diff --git a/Dockerfile b/Dockerfile index 412d8e1..f636844 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,4 +8,5 @@ WORKDIR /app COPY . /app RUN npm install -CMD ./node_modules/.bin/bats wait-for.bats +# On launch, run the test suite via npm +CMD npm test diff --git a/package.json b/package.json index 977ac4a..7aea0e7 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "wait-for", "version": "0.1.0", "scripts": { - "test": "./node_modules/.bin/bats wait-for.bats" + "test": "./run_tests.sh" }, "dependencies": { "bats": "^0.4.2" diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 0000000..13bf63a --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# Although it would be possible to just call this directly from the Dockerfile, +# centralizing tests in this file allows both the docker container and the +# CI machine to run the same set of tests for an additional datapoint -- +# which gives a better chance of turning up POSIX noncompliance + +./node_modules/.bin/bats wait-for.bats \ No newline at end of file diff --git a/wait-for b/wait-for index c9f5b86..53b5041 100755 --- a/wait-for +++ b/wait-for @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash OLD_TIMEOUT=$TIMEOUT OLD_QUIET=$QUIET From 72f20b20647c6e3408e7e8329d26c931d5728f60 Mon Sep 17 00:00:00 2001 From: Ian Katz Date: Wed, 31 Oct 2018 14:37:52 -0400 Subject: [PATCH 16/16] add more verbosity if not in quiet mode, enforce it if we are --- wait-for | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/wait-for b/wait-for index 53b5041..cc168b0 100755 --- a/wait-for +++ b/wait-for @@ -19,6 +19,14 @@ echoerr() { if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi } +conditionally_output() { + if [ "$QUIET" -ne 1 ]; then + "$@" + else + "$@" > /dev/null 2>&1 + fi +} + usage() { exitcode="$1" cat << USAGE >&2 @@ -33,11 +41,13 @@ USAGE } test_connection() { + conditionally_output echo "Testing connection to $1:$2..." + # force a 1-second timeout on darwin (https://stackoverflow.com/a/20460402/2063546) if [ -z "${OSTYPE##*darwin*}" ] ; then - nc -z -w 1 -G 1 "$1" "$2" > /dev/null 2>&1 + conditionally_output nc -z -w 1 -G 1 "$1" "$2" else - nc -z -w 1 "$1" "$2" > /dev/null 2>&1 + conditionally_output nc -z -w 1 "$1" "$2" > /dev/null 2>&1 fi } @@ -50,7 +60,7 @@ wait_for() { if [ $result -eq 0 ] ; then break ; fi sleep 1 done - [ $result -ne 0 ] && echo "Operation timed out" >&2 + [ $result -ne 0 ] && echoerr "Operation timed out" if [ $result -eq 0 -o $LOOSE -eq 1 -a $# -gt 0 ] ; then TIMEOUT=$OLD_TIMEOUT QUIET=$OLD_QUIET PORT=$OLD_PORT HOST=$OLD_HOST LOOSE=$OLD_LOOSE exec "$@" fi