#!/bin/bash
# Readiness of kube-proxy = the process LISTENS: its healthz port accepts a TCP
# connection (pattern of the other units in this package: port, not quorum).
#
# The address comes from the configuration, in kube-proxy's own order:
# --healthz-bind-address in DAEMON_ARGS, otherwise healthzBindAddress in the
# file named by --config (Puppet: profiles::kubernetes::kube_proxy renders
# 0.0.0.0:10256), otherwise the upstream default 0.0.0.0:10256. A wildcard
# host is checked on 127.0.0.1.
#
# Not /healthz: kube-proxy reports unhealthy while its rules are not synced
# with the API server; that is a statement about the cluster, not about this
# process, and must not hold a node's boot transition or the s6-rc lock.
#
# The flags come from /etc/default/kube-proxy (DAEMON_ARGS), the same file
# run-script-daemon sources. Source it before "set -u": it may reference
# variables that are unset here.
DAEMON_ARGS=
[ -r /etc/default/kube-proxy ] && . /etc/default/kube-proxy 2>/dev/null
set -u
flag() { printf '%s\n' $DAEMON_ARGS | sed -n "s/^$1=//p" | tail -n 1; }
# "--config <file>" may also come as two words
config() { printf '%s\n' $DAEMON_ARGS | awk '/^--config=/{sub(/^--config=/,""); c=$0} p{c=$0; p=0} /^--config$/{p=1} END{print c}'; }
addr=$(flag --healthz-bind-address)
if [ -z "$addr" ]; then
  conf=$(config)
  if [ -n "$conf" ] && [ -r "$conf" ]; then
    addr=$(sed -n 's/^healthzBindAddress:[[:space:]]*//p' "$conf" | tr -d "\"' " | tail -n 1)
  fi
fi
addr=${addr:-0.0.0.0:10256}
port=${addr##*:}
host=${addr%:*}
host=${host#[}; host=${host%]}
case "$host" in ''|0.0.0.0|'::') host=127.0.0.1 ;; esac
case "$port" in ''|*[!0-9]*) echo "no usable healthz port in '$addr'"; exit 1 ;; esac
if ! { exec 3<>"/dev/tcp/$host/$port"; } 2>/dev/null; then
  echo "port $host:$port does not accept connections"
  exit 1
fi
exec 3<&- 3>&-
exit 0
