Skip to content
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

Add --reverse flag to wait until the port is no longer available #102

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ wait-for-it.sh 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
-r | --reverse Perform the reverse test, wait until a port is
no longer available
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don't output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Expand Down Expand Up @@ -36,6 +38,15 @@ wait-for-it.sh: www.google.com:80 is available after 0 seconds
google is up
```

You can perform the reverse test with the `-r` or `--reverse` option. Setting the reverse flag will check if the port is unavailable and if it is, echo the message `port is unavailable`.

```
$ ./wait-for-it.sh localhost:0 --reverse -- echo "port is unavailable"
wait-for-it.sh: waiting 15 seconds for localhost:0
wait-for-it.sh: localhost:0 is unavailable after 0 seconds
port is unavailable
```

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:

```
Expand Down
13 changes: 12 additions & 1 deletion test/wait-for-it.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ def test_host_port(self):
)
soc.close()

def test_reverse_host_port(self):
""" Check that --reverse args work correctly """
soc, port = self.open_local_port()
soc.close()
self.check_args(
"--host=localhost --port={0} --timeout=1 --reverse".format(port),
"",
".*wait-for-it.sh: localhost:{0} is unavailable after 0 seconds".format(port),
True
)

def test_combined_host_port(self):
"""
Tests that wait-for-it.sh returns correctly after establishing a
Expand All @@ -130,7 +141,7 @@ def test_combined_host_port(self):

def test_port_failure_with_timeout(self):
"""
Note exit status of 124 is exected, passed from the timeout command
Note exit status of 124 is expected, passed from the timeout command
"""
self.check_args(
"localhost:8929 --timeout=1",
Expand Down
28 changes: 18 additions & 10 deletions wait-for-it.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ usage()
{
cat << USAGE >&2
Usage:
$WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
$WAITFORIT_cmdname host:port [-r] [-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
-r | --reverse Perform the reverse test, wait until a port is
no longer available
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don't output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Expand All @@ -32,31 +34,32 @@ wait_for()
WAITFORIT_start_ts=$(date +%s)
while :
do
WAITFORIT_test_success=$([[ $WAITFORIT_REVERSE -eq 0 ]] && echo 0 || echo 1)
if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
nc -z $WAITFORIT_HOST $WAITFORIT_PORT
WAITFORIT_result=$?
else
(echo > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
WAITFORIT_result=$?
fi
if [[ $WAITFORIT_result -eq 0 ]]; then
if [[ $WAITFORIT_result -eq $WAITFORIT_test_success ]]; then
WAITFORIT_end_ts=$(date +%s)
echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
WAITFORIT_availability=$([[ $WAITFORIT_REVERSE -eq 0 ]] && echo "available" || echo "unavailable")
echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is $WAITFORIT_availability after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
break
fi
sleep 1
done
return $WAITFORIT_result
return $([[ $WAITFORIT_result -eq $WAITFORIT_test_success ]] && echo 0 || echo 1)
}

wait_for_wrapper()
{
WAITFORIT_QUIETFLAG=$([[ $WAITFORIT_QUIET -eq 1 ]] && echo "--quiet")
WAITFORIT_REVERSEFLAG=$([[ $WAITFORIT_REVERSE -eq 1 ]] && echo "--reverse")

# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
if [[ $WAITFORIT_QUIET -eq 1 ]]; then
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
else
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
fi
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT $WAITFORIT_REVERSEFLAG $WAITFORIT_REVERSEFLAG --timeout=$WAITFORIT_TIMEOUT &
WAITFORIT_PID=$!
trap "kill -INT -$WAITFORIT_PID" INT
wait $WAITFORIT_PID
Expand Down Expand Up @@ -85,6 +88,10 @@ do
WAITFORIT_QUIET=1
shift 1
;;
-r | --reverse)
WAITFORIT_REVERSE=1
shift 1
;;
-s | --strict)
WAITFORIT_STRICT=1
shift 1
Expand Down Expand Up @@ -137,9 +144,10 @@ if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then
fi

WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
WAITFORIT_QUIET=${WAITFORIT_QUIET:-0}
WAITFORIT_REVERSE=${WAITFORIT_REVERSE:-0}
WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}

# Check to see if timeout is from busybox?
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
Expand Down