Files
rancher/package/run.sh
2023-03-27 13:50:39 -04:00

261 lines
8.8 KiB
Bash
Executable File

#!/bin/bash
set -e
# Logging helper functions
info()
{
echo "INFO:" "$@" 1>&2
}
error()
{
echo "ERROR:" "$@" 1>&2
}
warn()
{
echo "WARN:" "$@" 1>&2
}
# Print all given arguments
if [ $# -ne 0 ]; then
info "Arguments: $(echo $@ | sed -e 's/\(token\s\)\w*/\1REDACTED/')"
fi
if [ "$1" = "--" ]; then
shift 1
exec "$@"
fi
if [ "$CLUSTER_CLEANUP" = true ]; then
exec agent
fi
get_address()
{
local address=$1
# If nothing is given, return empty (it will be automatically determined later if empty)
if [ -z $address ]; then
echo ""
# If given address is a network interface on the system, retrieve configured IP on that interface (only the first configured IP is taken)
elif [ -n "$(find /sys/devices -name $address)" ]; then
echo $(ip addr show dev $address | grep -w inet | awk '{print $2}' | cut -f1 -d/ | head -1)
# Loop through cloud provider options to get IP from metadata, if not found return given value
else
case $address in
awslocal)
echo $(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)
;;
awspublic)
echo $(curl -s http://169.254.169.254/latest/meta-data/public-ipv4)
;;
doprivate)
echo $(curl -s http://169.254.169.254/metadata/v1/interfaces/private/0/ipv4/address)
;;
dopublic)
echo $(curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address)
;;
azprivate)
echo $(curl -s -H Metadata:true "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/privateIpAddress?api-version=2017-08-01&format=text")
;;
azpublic)
echo $(curl -s -H Metadata:true "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-08-01&format=text")
;;
gceinternal)
echo $(curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip)
;;
gceexternal)
echo $(curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip)
;;
packetlocal)
echo $(curl -s https://metadata.packet.net/2009-04-04/meta-data/local-ipv4)
;;
packetpublic)
echo $(curl -s https://metadata.packet.net/2009-04-04/meta-data/public-ipv4)
;;
ipify)
echo $(curl -s https://api.ipify.org)
;;
*)
echo $address
;;
esac
fi
}
check_url()
{
local url=$1
local err
err=$(curl --insecure -sS -fL -o /dev/null --stderr - $url | head -n1 ; exit ${PIPESTATUS[0]})
if [ $? -eq 0 ]
then
echo ""
else
echo ${err} | sed -e 's/^curl: ([0-9]\+) //'
fi
}
check_x509_cert()
{
local cert=$1
local err
err=$(openssl x509 -in $cert -noout 2>&1)
if [ $? -eq 0 ]
then
echo ""
else
echo ${err}
fi
}
export CATTLE_ADDRESS
export CATTLE_AGENT_CONNECT
export CATTLE_INTERNAL_ADDRESS
export CATTLE_NODE_NAME
export CATTLE_ROLE
export CATTLE_SERVER
export CATTLE_TOKEN
export CATTLE_NODE_LABEL
export CATTLE_WRITE_CERT_ONLY
export CATTLE_NODE_TAINTS
while true; do
case "$1" in
-d | --debug) DEBUG=true ;;
-s | --server) shift; CATTLE_SERVER=$1 ;;
-t | --token) shift; CATTLE_TOKEN=$1 ;;
-c | --ca-checksum) shift; CATTLE_CA_CHECKSUM=$1 ;;
-a | --all-roles) ALL=true ;;
-e | --etcd) ETCD=true ;;
-w | --worker) WORKER=true ;;
-p | --controlplane) CONTROL=true ;;
-n | --node-name) shift; CATTLE_NODE_NAME=$1 ;;
-r | --no-register) CATTLE_AGENT_CONNECT=true ;;
-a | --address) shift; CATTLE_ADDRESS=$1 ;;
-i | --internal-address) shift; CATTLE_INTERNAL_ADDRESS=$1 ;;
-l | --label) shift; CATTLE_NODE_LABEL+=",$1" ;;
-o | --only-write-certs) CATTLE_WRITE_CERT_ONLY=true ;;
--taints) shift; CATTLE_NODE_TAINTS+=",$1" ;;
*) break;
esac
shift
done
if [ "$DEBUG" = true ]; then
set -x
fi
if [ "$CATTLE_CLUSTER" != "true" ]; then
if [ ! -w /var/run/docker.sock ] || [ ! -S /var/run/docker.sock ]; then
warn "Docker socket is not available!"
warn "Please bind mount in the docker socket to /var/run/docker.sock if docker errors occur"
warn "example: docker run -v /var/run/docker.sock:/var/run/docker.sock ..."
fi
fi
if [ -z "$CATTLE_NODE_NAME" ]; then
CATTLE_NODE_NAME=$(hostname -s)
fi
export CATTLE_ADDRESS=$(get_address $CATTLE_ADDRESS)
export CATTLE_INTERNAL_ADDRESS=$(get_address $CATTLE_INTERNAL_ADDRESS)
if [ -z "$CATTLE_ADDRESS" ]; then
# Example output: '8.8.8.8 via 10.128.0.1 dev ens4 src 10.128.0.34 uid 0'
CATTLE_ADDRESS=$(ip -o route get 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p')
fi
if [ "$CATTLE_K8S_MANAGED" != "true" ]; then
if [ -z "$CATTLE_TOKEN" ]; then
error -- --token is a required option
exit 1
fi
if [ -z "$CATTLE_ADDRESS" ]; then
error -- --address is a required option
exit 1
fi
fi
if [ "$ALL" = true ]; then
CATTLE_ROLE="etcd,worker,controlplane"
else
if [ "$ETCD" = true ]; then
CATTLE_ROLE="${CATTLE_ROLE},etcd"
fi
if [ "$WORKER" = true ]; then
CATTLE_ROLE="${CATTLE_ROLE},worker"
fi
if [ "$CONTROL" = true ]; then
CATTLE_ROLE="${CATTLE_ROLE},controlplane"
fi
fi
if [ -z "$CATTLE_SERVER" ]; then
error -- --server is a required option
exit 1
fi
info "Environment: $(echo $(printenv | grep CATTLE | sort | sed -e 's/\(CATTLE_TOKEN=\).*/\1REDACTED/'))"
info "Using resolv.conf: $(echo $(cat /etc/resolv.conf | grep -v ^#))"
if grep -E -q '^nameserver 127.*.*.*|^nameserver localhost|^nameserver ::1' /etc/resolv.conf; then
warn "Loopback address found in /etc/resolv.conf, please refer to the documentation how to configure your cluster to resolve DNS properly"
fi
CATTLE_SERVER_PING="${CATTLE_SERVER}/ping"
err=$(check_url $CATTLE_SERVER_PING)
if [[ $err ]]; then
error "${CATTLE_SERVER_PING} is not accessible (${err})"
exit 1
else
info "${CATTLE_SERVER_PING} is accessible"
fi
# Extract hostname from URL
CATTLE_SERVER_HOSTNAME=$(echo $CATTLE_SERVER | sed -e 's/[^/]*\/\/\([^@]*@\)\?\([^:/]*\).*/\2/')
CATTLE_SERVER_HOSTNAME_WITH_PORT=$(echo $CATTLE_SERVER | sed -e 's/[^/]*\/\/\([^@]*@\)\?\(.*\).*/\2/')
# Resolve IPv4 address(es) from hostname
RESOLVED_ADDR=$(getent ahostsv4 $CATTLE_SERVER_HOSTNAME | sed -n 's/ *STREAM.*//p')
# If CATTLE_SERVER_HOSTNAME equals RESOLVED_ADDR, its an IP address and there is nothing to resolve
if [ "${CATTLE_SERVER_HOSTNAME}" != "${RESOLVED_ADDR}" ]; then
info "${CATTLE_SERVER_HOSTNAME} resolves to $(echo $RESOLVED_ADDR)"
fi
if [ -n "$CATTLE_CA_CHECKSUM" ]; then
temp=$(mktemp)
curl --insecure -s -fL $CATTLE_SERVER/v3/settings/cacerts | jq -r '.value | select(length > 0)' > $temp
if [ ! -s $temp ]; then
error "The environment variable CATTLE_CA_CHECKSUM is set but there is no CA certificate configured at $CATTLE_SERVER/v3/settings/cacerts"
exit 1
fi
err=$(check_x509_cert $temp)
if [[ $err ]]; then
error "Value from $CATTLE_SERVER/v3/settings/cacerts does not look like an x509 certificate (${err})"
error "Retrieved cacerts:"
cat $temp
exit 1
else
info "Value from $CATTLE_SERVER/v3/settings/cacerts is an x509 certificate"
fi
CATTLE_SERVER_CHECKSUM=$(sha256sum $temp | awk '{print $1}')
if [ $CATTLE_SERVER_CHECKSUM != $CATTLE_CA_CHECKSUM ]; then
rm -f $temp
error "Configured cacerts checksum ($CATTLE_SERVER_CHECKSUM) does not match given --ca-checksum ($CATTLE_CA_CHECKSUM)"
error "Please check if the correct certificate is configured at $CATTLE_SERVER/v3/settings/cacerts"
exit 1
else
mkdir -p /etc/kubernetes/ssl/certs
mv $temp /etc/kubernetes/ssl/certs/serverca
chmod 755 /etc/kubernetes/ssl
chmod 700 /etc/kubernetes/ssl/certs
chmod 600 /etc/kubernetes/ssl/certs/serverca
mkdir -p /etc/docker/certs.d/$CATTLE_SERVER_HOSTNAME_WITH_PORT
cp /etc/kubernetes/ssl/certs/serverca /etc/docker/certs.d/$CATTLE_SERVER_HOSTNAME_WITH_PORT/ca.crt
fi
fi
exec tini -- agent