# -*-Shell-script-*-

#
# Copyright (C) 2018 velostrata.com
# All Rights Reserved.
#

GCP_META_HOST="metadata.google.internal"
GCP_META_FALLBACK_HOST="169.254.169.254"
GCP_META_ROOT="computeMetadata/v1"

function log_err()
{
	echo -e "[`date`] MigrateForGCE: $*" >> /var/run/migrate-for-gce-aliasip.log
}

function get_meta_with_retries()
{
	local key header attempts rc
	key=$1
	header=$2
	rc=1

	attempts=$3
	[ -z "${attempts}" ] && attempts=2

	while [ "${rc}" -ne 0 ] && [ "${attempts}" -gt 0 ] ; do
		meta=$(curl -s -f -H "${header}" ${key})
		if [ "${?}" -eq 0 ] ; then
			echo ${meta}
			return
		fi

		let attempts--
		if [ "${attempts}" -gt 0 ]; then
			sleep 1
		fi
	done
}

function get_gcp_meta()
{
	get_meta_with_retries "http://${GCP_META_FALLBACK_HOST}/${GCP_META_ROOT}/$1" "Metadata-flavor: Google"
}

function get_gcp_instance_meta()
{
	get_gcp_meta instance/attributes/$1
}

function get_gcp_project_meta()
{
	get_gcp_meta project/attributes/$1
}

function get_gcp_number_of_IP_ranges()
{
        get_gcp_meta instance/network-interfaces/0/ip-aliases/
}

function get_gcp_cidr()
{
	get_gcp_meta instance/network-interfaces/0/ip-aliases/$1
}

function net_to_wildcard_netmask()
{
    prefix=$1
    shift=$(( 32 - $prefix ));

    bitmask=""
    for (( i=0; i < 32; i++ )); do
        num=0
        if [ $i -lt $prefix ]; then
            num=1
        fi

        space=
        if [ $(( i % 8 )) -eq 0 ]; then
            space=" ";
        fi

        bitmask="${bitmask}${space}${num}"
    done

    wildcard_mask=" "
    for octet in $bitmask; do
        wildcard_mask="${wildcard_mask} $(( 255 - 2#$octet ))"
    done
    echo $wildcard_mask
}

function get_gcp_ipv4s()
{
    ranges=$(get_gcp_number_of_IP_ranges)
    arr=
    for r in $ranges; do
	cidr=`get_gcp_cidr ${r}`
	if [[ -z "${cidr}" ]] ; then
		log_err "Alias range CIDR was not provided"
		return
	fi

	ip=$(echo $cidr | cut -d '/' -f 1)
	net=$(echo $cidr | cut -d '/' -f 2)
	if [[ -z "${ip}" ]] || [[ -z "${net}" ]] ; then
		log_err "Alias range CIDR is invalid - ${cidr}"
		return
	fi

	if [[ $net -lt 27 ]] ; then
		log_err "Large networks are not supported (bits: ${net})"
		return
	fi

	wildcard_mask=$(net_to_wildcard_netmask $net)
	str=
	for (( i = 1; i <= 4; i++ )); do
		range=$(echo $ip | cut -d '.' -f $i)
		mask_octet=$(echo $wildcard_mask | cut -d ' ' -f $i)
		if [ $mask_octet -gt 0 ]; then
			range="{$range..$(( $range | $mask_octet ))}"
		fi
		str="${str} $range"
	done
	ips=$(echo $str | sed "s, ,\\.,g")
	arr[$r]=$(echo $ips/$net | tr ' ' '\n')
	done

    for each in "${arr[@]}"
    do
    eval echo $each | tr ' ' '\n'
    done
}

IP_RANGES_APPLY=0
IP_RANGES_IGNORE=1
APPLY_KEY=apply-alias-ip-ranges

function gcp_should_apply_ip_ranges()
{
	local project instance
	project=`get_gcp_project_meta ${APPLY_KEY}`
	instance=`get_gcp_instance_meta ${APPLY_KEY}`

	if [[ "$instance" == "true" ]] ; then
		return $IP_RANGES_APPLY
	fi

	if [[ "$instance" == "false" ]] || [[ ! -z "$instance" ]] ; then
		return $IP_RANGES_IGNORE
	fi

	if [[ "$project" == "true" ]] ; then
		return $IP_RANGES_APPLY
	fi

	return $IP_RANGES_IGNORE
}

function is_gcp()
{
	local product
	product=$(cat /sys/devices/virtual/dmi/id/product_name)

	if [[ "$product" == "Google Compute Engine" ]] ; then
		return 0
	fi

	return 1
}

wait_for_meta()  {
  local dummy
  if is_gcp; then
    dummy=$(get_meta_with_retries "http://${GCP_META_FALLBACK_HOST}/${GCP_META_ROOT}" "Metadata-flavor: Google" 30)
  fi
}

