#!/bin/bash
#
# Copyright 2013 Red Hat
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

set -e  # exit on the first non-zero status
set -u  # exit on unset variables

SCRIPT_NAME=$(basename $0)


function show_options() {
    echo "Usage: $SCRIPT_NAME LOOPS_NUMBER SLEEP_TIME ARGS"
    echo
    echo "ARGS are read and concatenated together into a single command."
    echo "Execute the command in a loop until it succeeds or the number"
    echo "of attempts exceeds LOOPS_NUMBER value. After each failure"
    echo "pause for SLEEP_TIME seconds."
    echo
    echo "An optional FAIL_MATCH_OUTPUT variable may also be set to control "
    echo "if the loop exits early if the commands stdout/stderr matches the "
    echo "supplied regex string."
    echo
    echo "Examples:"
    echo "    wait_for 30 10 ping -c 1 192.0.2.2"
    echo "    wait_for 10 1 ls file_we_are_waiting_for"
    echo "    wait_for 10 3 date \| grep 8"
    echo "    FAIL_MATCH_OUTPUT=CREATE_FAILED wait_for 30 10 heat stack-show undercloud"
    echo "    SUCCESSFUL_MATCH_OUTPUT=CREATE_COMPLETE wait_for 30 10 heat stack-show undercloud"
    exit 1
}


LOOPS=${1:-""}
SLEEPTIME=${2:-""}
FAIL_MATCH_OUTPUT=${FAIL_MATCH_OUTPUT:-""}
SUCCESSFUL_MATCH_OUTPUT=${SUCCESSFUL_MATCH_OUTPUT:-""}
shift 2 || true
COMMAND="$@"

if [ -z "$LOOPS" -o -z "$SLEEPTIME" -o -z "$COMMAND" ]; then
    show_options
fi


i=0
while [ $i -lt $LOOPS ]; do
    i=$((i + 1))
    STATUS=0
    OUTPUT=$(eval $COMMAND 2>&1) || STATUS=$?
    if [[ -n "$SUCCESSFUL_MATCH_OUTPUT" ]] \
        && [[ $OUTPUT =~ $SUCCESSFUL_MATCH_OUTPUT ]]; then
        exit 0
    elif [[ -n "$FAIL_MATCH_OUTPUT" ]] \
        && [[ $OUTPUT =~ $FAIL_MATCH_OUTPUT ]]; then
        echo "Command output matched '$FAIL_MATCH_OUTPUT'. Exiting..."
        exit 1
    elif [[ -z "$SUCCESSFUL_MATCH_OUTPUT" ]] && [[ $STATUS -eq 0 ]]; then
        # The command successfully completed and we aren't testing against
        # it's output so we have finished waiting.
        exit 0
    fi

    sleep $SLEEPTIME
done
SECONDS=$((LOOPS * SLEEPTIME))
printf 'Timing out after %d seconds:\nCOMMAND=%s\nOUTPUT=%s\n' \
    "$SECONDS" "$COMMAND" "$OUTPUT"
exit 1
