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

More details

Full run details