Skip to content
59 changes: 44 additions & 15 deletions parts/linux/cloud-init/artifacts/localdns.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,35 @@ CURL_COMMAND="curl -s http://${LOCALDNS_NODE_LISTENER_IP}:8181/ready"
NETWORKCTL_RELOAD_CMD="networkctl reload"

START_LOCALDNS_TIMEOUT=10
LOCALDNS_PID_POLL_INTERVAL_SECONDS=0.1
LOCALDNS_READY_POLL_INTERVAL_SECONDS=0.1
LOCALDNS_READY_TIMEOUT_SECONDS=60

# DNS health check timeout.
DNS_HEALTH_CHECK_TIMEOUT=2
DNS_HEALTH_CHECK_TRIES=2

# Convert a wall-clock timeout budget into a poll count for the configured interval.
calculate_max_poll_attempts() {
local timeout_duration=$1
local poll_interval_seconds=$2

awk -v timeout="${timeout_duration}" -v interval="${poll_interval_seconds}" '
BEGIN {
if (timeout < 0 || interval <= 0) {
exit 1
}
Comment thread
jingwenw15 marked this conversation as resolved.
Comment thread
jingwenw15 marked this conversation as resolved.

if (timeout == 0) {
print 0
exit 0
}

printf "%d\n", int((timeout / interval) + 0.999999)
}
'
}

# Function definitions used in this file.
# functions defined until "${__SOURCED__:+return}" are sourced and tested in -
# spec/parts/linux/cloud-init/artifacts/localdns_spec.sh.
Expand Down Expand Up @@ -419,14 +443,21 @@ start_localdns() {
${COREDNS_COMMAND} &

# Wait until the PID file is created.
local elapsed=0
local attempts=0
local max_attempts
max_attempts=$(calculate_max_poll_attempts "${START_LOCALDNS_TIMEOUT}" "${LOCALDNS_PID_POLL_INTERVAL_SECONDS}") || {
echo "Invalid localdns PID poll interval configuration."
Comment thread
jingwenw15 marked this conversation as resolved.
Outdated
return 1
}

while [ ! -f "${LOCALDNS_PID_FILE}" ]; do
sleep 1
elapsed=$((elapsed + 1))
if [ "$elapsed" -ge "$START_LOCALDNS_TIMEOUT" ]; then
if [ "$attempts" -ge "$max_attempts" ]; then
echo "Timed out waiting for CoreDNS to create PID file at ${LOCALDNS_PID_FILE}."
return 1
fi

sleep "${LOCALDNS_PID_POLL_INTERVAL_SECONDS}"
attempts=$((attempts + 1))
done

COREDNS_PID="$(cat ${LOCALDNS_PID_FILE})"
Expand All @@ -436,26 +467,24 @@ start_localdns() {

# Wait for localdns to be ready to serve traffic.
wait_for_localdns_ready() {
local maxattempts=$1
local timeout_duration=$2
declare -i attempts=0
local starttime=$(date +%s)
local timeout_duration=$1
local starttime
local currenttime
local elapsedtime

starttime=$(date +%s)

echo "Waiting for localdns to start and be able to serve traffic."
until [ "$($CURL_COMMAND)" = "OK" ]; do
if [ $attempts -ge $maxattempts ]; then
echo "Localdns failed to come online after $maxattempts attempts."
return 1
fi
# Check for timeout based on elapsed time.
currenttime=$(date +%s)
elapsedtime=$((currenttime - starttime))
if [ $elapsedtime -ge $timeout_duration ]; then
echo "Localdns failed to come online after $timeout_duration seconds (timeout)."
return 1
fi
sleep 1
((attempts++))

sleep "${LOCALDNS_READY_POLL_INTERVAL_SECONDS}"
done
Comment thread
jingwenw15 marked this conversation as resolved.
echo "Localdns is online and ready to serve traffic."
return 0
Expand Down Expand Up @@ -1059,7 +1088,7 @@ fi
start_localdns || exit $ERR_LOCALDNS_FAIL

# Wait to direct traffic to localdns until it's ready.
wait_for_localdns_ready 60 60 || exit $ERR_LOCALDNS_FAIL
wait_for_localdns_ready "${LOCALDNS_READY_TIMEOUT_SECONDS}" || exit $ERR_LOCALDNS_FAIL

# Disable DNS from DHCP and point the system at localdns.
# --------------------------------------------------------------------------------------------------------------------
Expand Down
60 changes: 46 additions & 14 deletions spec/parts/linux/cloud-init/artifacts/localdns_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,23 @@ EOF
The status should be failure
The output should include "Timed out waiting for CoreDNS to create PID file"
End

It 'should poll for the PID file every 0.1 seconds'
MOCK_SCRIPT="./mock-coredns.sh"
cat > "$MOCK_SCRIPT" <<EOF
#!/bin/bash
exit 0
EOF
chmod +x "$MOCK_SCRIPT"
COREDNS_COMMAND="$MOCK_SCRIPT"
START_LOCALDNS_TIMEOUT=1
sleep() {
echo "sleep called with: $1"
}
When call start_localdns
The status should be failure
The output should include "sleep called with: 0.1"
End
End


Expand All @@ -716,35 +733,50 @@ EOF
Describe 'wait_for_localdns_ready'
setup() {
Include "./parts/linux/cloud-init/artifacts/localdns.sh"
DATE_SEQUENCE_FILE="/tmp/localdns-date-sequence-$$"
SLEEP_LOG_FILE="/tmp/localdns-sleep-log-$$"
}
cleanup() {
rm -f "$DATE_SEQUENCE_FILE" "${DATE_SEQUENCE_FILE}.next" "$SLEEP_LOG_FILE"
}
BeforeEach 'setup'
AfterEach 'cleanup'
#------------------------- wait_for_localdns_ready -----------------------------------------------------------
It 'should return success if localdns is ready'
CURL_COMMAND="echo OK"
MAX_ATTEMPTS=100
TIMEOUT=5
When call wait_for_localdns_ready $MAX_ATTEMPTS $TIMEOUT
When call wait_for_localdns_ready $TIMEOUT
The status should be success
The output should include "Waiting for localdns to start and be able to serve traffic."
The output should include "Localdns is online and ready to serve traffic."
End

It 'should return failure if localdns is not ready, after timeout'
It 'should return failure if localdns is not ready after the wall-clock timeout'
CURL_COMMAND="echo NOTOK"
MAX_ATTEMPTS=1000
TIMEOUT=2
When call wait_for_localdns_ready $MAX_ATTEMPTS $TIMEOUT
The status should be failure
The output should include "Localdns failed to come online after ${TIMEOUT} seconds (timeout)."
End
EXPECTED_SLEEP_LOG=$(printf '0.1\n0.1\n')
cat > "$DATE_SEQUENCE_FILE" <<EOF
100
100
101
102
EOF
date() {
local current_time

It 'should return failure if localdns is not ready, after max attempts'
CURL_COMMAND="echo NOTOK"
MAX_ATTEMPTS=2
TIMEOUT=50
When call wait_for_localdns_ready $MAX_ATTEMPTS $TIMEOUT
current_time=$(head -n 1 "$DATE_SEQUENCE_FILE")
tail -n +2 "$DATE_SEQUENCE_FILE" > "${DATE_SEQUENCE_FILE}.next"
mv "${DATE_SEQUENCE_FILE}.next" "$DATE_SEQUENCE_FILE"

echo "$current_time"
}
sleep() {
echo "$1" >> "$SLEEP_LOG_FILE"
}
When call wait_for_localdns_ready $TIMEOUT
The status should be failure
The output should include "Localdns failed to come online after ${MAX_ATTEMPTS} attempts."
The output should include "Localdns failed to come online after ${TIMEOUT} seconds (timeout)."
The contents of file "$SLEEP_LOG_FILE" should eq "$EXPECTED_SLEEP_LOG"
End
End

Expand Down
Loading