Skip to content

Commit

Permalink
feat: adds support for http using wget
Browse files Browse the repository at this point in the history
Implements eficode#14
  • Loading branch information
Addono committed Feb 27, 2021
1 parent 2e4e8de commit ff0d29d
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 22 deletions.
34 changes: 30 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -69,8 +69,8 @@ Eficode site is up
To wait for database container to become available:


```
version: '2'
```yml
version: '3'

services:
db:
Expand All @@ -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)).
Expand All @@ -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.

71 changes: 55 additions & 16 deletions wait-for
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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 "$@"
43 changes: 41 additions & 2 deletions wait-for.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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" ]
}

0 comments on commit ff0d29d

Please sign in to comment.