New Upstream Snapshot - wait-for-it
Ready changes
Summary
Merged new upstream version: 0.0~git20200822 (was: 0.0~git20180723).
Resulting package
Built on 2022-10-30T19:05 (took 3m57s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-snapshots wait-for-it
Lintian Result
Diff
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 3e7e969..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-**/*.pyc
-.pydevproject
-
diff --git a/README.md b/README.md
index fb67821..d08d5a2 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,13 @@
-## wait-for-it
+# wait-for-it
-`wait-for-it.sh` is a pure bash script that will wait on the availability of a host and TCP port. It is useful for synchronizing the spin-up of interdependent services, such as linked docker containers. Since it is a pure bash script, it does not have any external dependencies.
+`wait-for-it.sh` is a pure bash script that will wait on the availability of a
+host and TCP port. It is useful for synchronizing the spin-up of
+interdependent services, such as linked docker containers. Since it is a pure
+bash script, it does not have any external dependencies.
## Usage
-```
+```text
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
@@ -18,36 +21,43 @@ wait-for-it.sh host:port [-s] [-t timeout] [-- command args]
## Examples
-For example, let's test to see if we can access port 80 on www.google.com, and if it is available, echo the message `google is up`.
+For example, let's test to see if we can access port 80 on `www.google.com`,
+and if it is available, echo the message `google is up`.
-```
+```text
$ ./wait-for-it.sh www.google.com:80 -- echo "google is up"
wait-for-it.sh: waiting 15 seconds for www.google.com:80
wait-for-it.sh: www.google.com:80 is available after 0 seconds
google is up
```
-You can set your own timeout with the `-t` or `--timeout=` option. Setting the timeout value to 0 will disable the timeout:
+You can set your own timeout with the `-t` or `--timeout=` option. Setting
+the timeout value to 0 will disable the timeout:
-```
+```text
$ ./wait-for-it.sh -t 0 www.google.com:80 -- echo "google is up"
wait-for-it.sh: waiting for www.google.com:80 without a timeout
wait-for-it.sh: www.google.com:80 is available after 0 seconds
google 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:
+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:
-```
+```text
$ ./wait-for-it.sh www.google.com:81 --timeout=1 --strict -- echo "google is up"
wait-for-it.sh: waiting 1 seconds for www.google.com:81
wait-for-it.sh: timeout occurred after waiting 1 seconds for www.google.com:81
wait-for-it.sh: strict mode, refusing to execute subprocess
```
-If you don't want to execute a subcommand, leave off the `--` argument. This way, you can test the exit condition of `wait-for-it.sh` in your own scripts, and determine how to proceed:
+If you don't want to execute a subcommand, leave off the `--` argument. This
+way, you can test the exit condition of `wait-for-it.sh` in your own scripts,
+and determine how to proceed:
-```
+```text
$ ./wait-for-it.sh www.google.com:80
wait-for-it.sh: waiting 15 seconds for www.google.com:80
wait-for-it.sh: www.google.com:80 is available after 0 seconds
@@ -60,3 +70,6 @@ $ echo $?
124
```
+## Community
+
+*Debian*: There is a [Debian package](https://tracker.debian.org/pkg/wait-for-it).
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..ea892d7
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,7 @@
+{
+ "name": "vishnubob/wait-for-it",
+ "description": "Pure bash script to test and wait on the availability of a TCP host and port",
+ "type": "library",
+ "license": "MIT",
+ "bin": ["wait-for-it.sh"]
+}
diff --git a/debian/changelog b/debian/changelog
index 3a7a387..25145a3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,10 @@
-wait-for-it (0.0~git20180723-2) UNRELEASED; urgency=medium
+wait-for-it (0.0~git20200822-1) UNRELEASED; urgency=medium
* Apply multi-arch hints.
+ wait-for-it: Add Multi-Arch: foreign.
+ * New upstream snapshot.
- -- Debian Janitor <janitor@jelmer.uk> Fri, 03 Sep 2021 04:09:37 -0000
+ -- Debian Janitor <janitor@jelmer.uk> Sun, 30 Oct 2022 19:03:13 -0000
wait-for-it (0.0~git20180723-1) unstable; urgency=medium
diff --git a/test/README.md b/test/README.md
new file mode 100644
index 0000000..59cd8db
--- /dev/null
+++ b/test/README.md
@@ -0,0 +1,18 @@
+# Tests for wait-for-it
+
+* wait-for-it.py - pytests for wait-for-it.sh
+* container-runners.py - Runs wait-for-it.py tests in multiple containers
+* requirements.txt - pip requirements for container-runners.py
+
+To run the basic tests:
+
+```
+python wait-for-it.py
+```
+
+Many of the issues encountered have been related to differences between operating system versions. The container-runners.py script provides an easy way to run the python wait-for-it.py tests against multiple system configurations:
+
+```
+pip install -r requirements.txt
+python container-runners.py
+```
diff --git a/test/container-runners.py b/test/container-runners.py
new file mode 100755
index 0000000..3f8f358
--- /dev/null
+++ b/test/container-runners.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+# Unit tests to run wait-for-it.py unit tests in several different docker images
+
+import unittest
+import os
+import docker
+from parameterized import parameterized
+
+client = docker.from_env()
+app_path = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..'))
+volumes = {app_path: {'bind': '/app', 'mode': 'ro'}}
+
+class TestContainers(unittest.TestCase):
+ """
+ Test multiple container types with the test cases in wait-for-it.py
+ """
+
+ @parameterized.expand([
+ "python:3.5-buster",
+ "python:3.5-stretch",
+ "dougg/alpine-busybox:alpine-3.11.3_busybox-1.30.1",
+ "dougg/alpine-busybox:alpine-3.11.3_busybox-1.31.1"
+ ])
+ def test_image(self, image):
+ print(image)
+ command="/app/test/wait-for-it.py"
+ container = client.containers.run(image, command=command, volumes=volumes, detach=True)
+ result = container.wait()
+ logs = container.logs()
+ container.remove()
+ self.assertEqual(result["StatusCode"], 0)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/requirements.txt b/test/requirements.txt
new file mode 100644
index 0000000..9ba1e52
--- /dev/null
+++ b/test/requirements.txt
@@ -0,0 +1,2 @@
+docker>=4.0.0
+parameterized>=0.7.0
diff --git a/test/wait-for-it.py b/test/wait-for-it.py
old mode 100644
new mode 100755
index e06fb8c..de7530e
--- a/test/wait-for-it.py
+++ b/test/wait-for-it.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python
+
import unittest
import shlex
from subprocess import Popen, PIPE
@@ -24,17 +26,17 @@ class TestWaitForIt(unittest.TestCase):
proc = Popen(args, stdout=PIPE, stderr=PIPE)
out, err = proc.communicate()
exitcode = proc.returncode
- return exitcode, out, err
+ return exitcode, out.decode('utf-8'), err.decode('utf-8')
- def open_local_port(self, host="localhost", port=8929, timeout=5):
+ def open_local_port(self, timeout=5):
s = socket.socket()
- s.bind((host, port))
+ s.bind(('', 0))
s.listen(timeout)
- return s
+ return s, s.getsockname()[1]
- def check_args(self, args, stdout_regex, stderr_regex, exitcode):
+ def check_args(self, args, stdout_regex, stderr_regex, should_succeed):
command = self.wait_script + " " + args
- actual_exitcode, out, err = self.execute(command)
+ exitcode, out, err = self.execute(command)
# Check stderr
msg = ("Failed check that STDERR:\n" +
@@ -51,7 +53,7 @@ class TestWaitForIt(unittest.TestCase):
self.assertIsNotNone(re.match(stdout_regex, out, re.DOTALL), msg)
# Check exit code
- self.assertEqual(actual_exitcode, exitcode)
+ self.assertEqual(should_succeed, exitcode == 0)
def setUp(self):
script_path = os.path.dirname(sys.argv[0])
@@ -67,7 +69,7 @@ class TestWaitForIt(unittest.TestCase):
"",
"^$",
MISSING_ARGS_TEXT,
- 1
+ False
)
# Return code should be 1 when called with no args
exitcode, out, err = self.execute(self.wait_script)
@@ -79,7 +81,7 @@ class TestWaitForIt(unittest.TestCase):
"--help",
"",
HELP_TEXT,
- 1
+ False
)
def test_no_port(self):
@@ -88,7 +90,7 @@ class TestWaitForIt(unittest.TestCase):
"--host=localhost",
"",
MISSING_ARGS_TEXT,
- 1
+ False
)
def test_no_host(self):
@@ -97,17 +99,17 @@ class TestWaitForIt(unittest.TestCase):
"--port=80",
"",
MISSING_ARGS_TEXT,
- 1
+ False
)
def test_host_port(self):
""" Check that --host and --port args work correctly """
- soc = self.open_local_port(port=8929)
+ soc, port = self.open_local_port()
self.check_args(
- "--host=localhost --port=8929 --timeout=1",
+ "--host=localhost --port={0} --timeout=1".format(port),
"",
- "wait-for-it.sh: waiting 1 seconds for localhost:8929",
- 0
+ "wait-for-it.sh: waiting 1 seconds for localhost:{0}".format(port),
+ True
)
soc.close()
@@ -116,15 +118,16 @@ class TestWaitForIt(unittest.TestCase):
Tests that wait-for-it.sh returns correctly after establishing a
connectionm using combined host and ports
"""
- soc = self.open_local_port(port=8929)
+ soc, port = self.open_local_port()
self.check_args(
- "localhost:8929 --timeout=1",
+ "localhost:{0} --timeout=1".format(port),
"",
- "wait-for-it.sh: waiting 1 seconds for localhost:8929",
- 0
+ "wait-for-it.sh: waiting 1 seconds for localhost:{0}".format(port),
+ True
)
soc.close()
+
def test_port_failure_with_timeout(self):
"""
Note exit status of 124 is exected, passed from the timeout command
@@ -133,19 +136,19 @@ class TestWaitForIt(unittest.TestCase):
"localhost:8929 --timeout=1",
"",
".*timeout occurred after waiting 1 seconds for localhost:8929",
- 124
+ False
)
def test_command_execution(self):
"""
Checks that a command executes correctly after a port test passes
"""
- soc = self.open_local_port(port=8929)
+ soc, port = self.open_local_port()
self.check_args(
- "localhost:8929 -- echo \"CMD OUTPUT\"",
+ "localhost:{0} -- echo \"CMD OUTPUT\"".format(port),
"CMD OUTPUT",
- ".*wait-for-it.sh: localhost:8929 is available after 0 seconds",
- 0
+ ".*wait-for-it.sh: localhost:{0} is available after 0 seconds".format(port),
+ True
)
soc.close()
@@ -154,12 +157,12 @@ class TestWaitForIt(unittest.TestCase):
Check command failure. The command in question outputs STDERR and
an exit code of 2
"""
- soc = self.open_local_port(port=8929)
+ soc, port = self.open_local_port()
self.check_args(
- "localhost:8929 -- ls not_real_file",
+ "localhost:{0} -- ls not_real_file".format(port),
"",
".*No such file or directory\n",
- 2
+ False
)
soc.close()
@@ -172,7 +175,7 @@ class TestWaitForIt(unittest.TestCase):
"localhost:8929 --timeout=1 -- echo \"CMD OUTPUT\"",
"CMD OUTPUT",
".*timeout occurred after waiting 1 seconds for localhost:8929",
- 0
+ True
)
if __name__ == '__main__':
diff --git a/wait-for-it.sh b/wait-for-it.sh
index bbe4043..d990e0d 100755
--- a/wait-for-it.sh
+++ b/wait-for-it.sh
@@ -1,15 +1,15 @@
#!/usr/bin/env bash
-# Use this script to test if a given TCP host/port are available
+# Use this script to test if a given TCP host/port are available
-cmdname=$(basename $0)
+WAITFORIT_cmdname=${0##*/}
-echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
+echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
usage()
{
cat << USAGE >&2
Usage:
- $cmdname host:port [-s] [-t timeout] [-- command args]
+ $WAITFORIT_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
@@ -24,47 +24,47 @@ USAGE
wait_for()
{
- if [[ $TIMEOUT -gt 0 ]]; then
- echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT"
+ if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
+ echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
else
- echoerr "$cmdname: waiting for $HOST:$PORT without a timeout"
+ echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
fi
- start_ts=$(date +%s)
+ WAITFORIT_start_ts=$(date +%s)
while :
do
- if [[ $ISBUSY -eq 1 ]]; then
- nc -z $HOST $PORT
- result=$?
+ if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
+ nc -z $WAITFORIT_HOST $WAITFORIT_PORT
+ WAITFORIT_result=$?
else
- (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1
- result=$?
+ (echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
+ WAITFORIT_result=$?
fi
- if [[ $result -eq 0 ]]; then
- end_ts=$(date +%s)
- echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds"
+ if [[ $WAITFORIT_result -eq 0 ]]; then
+ WAITFORIT_end_ts=$(date +%s)
+ echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
break
fi
sleep 1
done
- return $result
+ return $WAITFORIT_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 &
+ 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 $BUSYTIMEFLAG $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
+ timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_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"
+ WAITFORIT_PID=$!
+ trap "kill -INT -$WAITFORIT_PID" INT
+ wait $WAITFORIT_PID
+ WAITFORIT_RESULT=$?
+ if [[ $WAITFORIT_RESULT -ne 0 ]]; then
+ echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
fi
- return $RESULT
+ return $WAITFORIT_RESULT
}
# process arguments
@@ -72,53 +72,53 @@ while [[ $# -gt 0 ]]
do
case "$1" in
*:* )
- hostport=(${1//:/ })
- HOST=${hostport[0]}
- PORT=${hostport[1]}
+ WAITFORIT_hostport=(${1//:/ })
+ WAITFORIT_HOST=${WAITFORIT_hostport[0]}
+ WAITFORIT_PORT=${WAITFORIT_hostport[1]}
shift 1
;;
--child)
- CHILD=1
+ WAITFORIT_CHILD=1
shift 1
;;
-q | --quiet)
- QUIET=1
+ WAITFORIT_QUIET=1
shift 1
;;
-s | --strict)
- STRICT=1
+ WAITFORIT_STRICT=1
shift 1
;;
-h)
- HOST="$2"
- if [[ $HOST == "" ]]; then break; fi
+ WAITFORIT_HOST="$2"
+ if [[ $WAITFORIT_HOST == "" ]]; then break; fi
shift 2
;;
--host=*)
- HOST="${1#*=}"
+ WAITFORIT_HOST="${1#*=}"
shift 1
;;
-p)
- PORT="$2"
- if [[ $PORT == "" ]]; then break; fi
+ WAITFORIT_PORT="$2"
+ if [[ $WAITFORIT_PORT == "" ]]; then break; fi
shift 2
;;
--port=*)
- PORT="${1#*=}"
+ WAITFORIT_PORT="${1#*=}"
shift 1
;;
-t)
- TIMEOUT="$2"
- if [[ $TIMEOUT == "" ]]; then break; fi
+ WAITFORIT_TIMEOUT="$2"
+ if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi
shift 2
;;
--timeout=*)
- TIMEOUT="${1#*=}"
+ WAITFORIT_TIMEOUT="${1#*=}"
shift 1
;;
--)
shift
- CLI=("$@")
+ WAITFORIT_CLI=("$@")
break
;;
--help)
@@ -131,47 +131,52 @@ do
esac
done
-if [[ "$HOST" == "" || "$PORT" == "" ]]; then
+if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_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}
+WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
+WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
+WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
+WAITFORIT_QUIET=${WAITFORIT_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"
+# Check to see if timeout is from busybox?
+WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
+WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)
+
+WAITFORIT_BUSYTIMEFLAG=""
+if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
+ WAITFORIT_ISBUSY=1
+ # Check if busybox timeout uses -t flag
+ # (recent Alpine versions don't support -t anymore)
+ if timeout &>/dev/stdout | grep -q -e '-t '; then
+ WAITFORIT_BUSYTIMEFLAG="-t"
+ fi
else
- ISBUSY=0
- BUSYTIMEFLAG=""
+ WAITFORIT_ISBUSY=0
fi
-if [[ $CHILD -gt 0 ]]; then
+if [[ $WAITFORIT_CHILD -gt 0 ]]; then
wait_for
- RESULT=$?
- exit $RESULT
+ WAITFORIT_RESULT=$?
+ exit $WAITFORIT_RESULT
else
- if [[ $TIMEOUT -gt 0 ]]; then
+ if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
wait_for_wrapper
- RESULT=$?
+ WAITFORIT_RESULT=$?
else
wait_for
- RESULT=$?
+ WAITFORIT_RESULT=$?
fi
fi
-if [[ $CLI != "" ]]; then
- if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then
- echoerr "$cmdname: strict mode, refusing to execute subprocess"
- exit $RESULT
+if [[ $WAITFORIT_CLI != "" ]]; then
+ if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
+ echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"
+ exit $WAITFORIT_RESULT
fi
- exec "${CLI[@]}"
+ exec "${WAITFORIT_CLI[@]}"
else
- exit $RESULT
+ exit $WAITFORIT_RESULT
fi
Debdiff
File lists identical (after any substitutions)
No differences were encountered in the control files