#!/usr/bin/bash
#----------------------------------------------------------------------

CT_DIR=${CT_DIR:=/etc/pve/lxc/}



#----------------------------------------------------------------------
# XXX this is quite generic, might be a good idea to move this to a 
# 		seporate lib/file...

# Execute (optionally) and print a command.
#
#QUIET=
#DRY_RUN=
ECHO_PREFIX="### "
@(){
	if [ -z $DRY_RUN ] ; then
		! [ $QUIET ] \
			&& echo "${ECHO_PREFIX}$@"
		$@
	else
		echo $@
	fi
	return $?
}



#----------------------------------------------------------------------
# Fill section...
#
# XXX this is quite generic -- move to a more logical place...

fillsection(){ (
	usage(){
		echo "Usage:"
		echo "    ${FUNCNAME[0]} [-h]"
		echo "    ${FUNCNAME[0]} [-r] NAME FILE [CONTENT]"
		echo
	}
	while true ; do
		case $1 in
			-h|--help)
				usage
				echo "Options:"
				#	  .	  .					.
				echo "    -h | --help       print this help message and exit."
				echo "    -r | --return     replace section markers with CONTENT."
				echo
				return 0
				;;
			-r|--replace)
				local replace=1
				shift
				;;

			*)
				break
				;;
		esac
	done
	if [[ $# < 2 ]] ; then
		usage
		return 1
	fi

	name=$1
	file=$2
	content=$3
	content=${content:=/dev/stdin}

	# print file upto section marker...
	if [ $replace ] ; then
		sed "/${name^^} BEGIN/q" "$file" | sed '$d'
	else
		sed "/${name^^} BEGIN/q" "$file"
	fi
	# print content...
	cat $content
	# print file from section end marker...
	if [ $replace ] ; then
		sed -ne "/${name^^} END/,$ p" "$file" | sed '1d' 
	else
		sed -ne "/${name^^} END/,$ p" "$file"
	fi
) }



#----------------------------------------------------------------------
# CT hostname <-> CT id...

ct2hostname(){
	local ct=${CT_DIR}/${1}.conf
	local host=$(cat $ct | grep hostname | head -1)
	echo ${host/hostname: /}
}

hostname2ct(){
	if [ -e "${CT_DIR}/${1}.conf" ] ; then
		echo $1
	fi
	local running=$2
	running=${running:=any}
	local ct
	local host
	for ct in "${CT_DIR}"/*.conf ; do
		host=$(cat $ct | grep hostname | head -1)
		host=${host/hostname: /}
		if [ "$host" = $1 ] ; then
			ct=${ct#${CT_DIR}}
			ct=${ct%.conf}
			ct=${ct#\/}
			# filter results if needed...
			if [ $running = "any" ] ; then
				echo $ct
			else
				local status=`pct status $ct`
				if [ "$running" = "${status/status: /}" ] ; then
					echo $ct
				fi
			fi
		fi
	done
}


#----------------------------------------------------------------------

normpath(){
	echo $1 \
		| sed \
			-e 's/\/\+/\//g' \
			-e 's/\/.\//\//g' \
			-e 's/[^\/]\+\/\.\.//g' \
			-e 's/\/\+/\//g' \
			-e 's/\/\.$/\//g'
}


#----------------------------------------------------------------------

#
#	xread [-n] MSG VAR
#
xread(){
	local non_empty=
	if [[ $1 == '-n' ]] ; then
		shift
		local non_empty=1
	fi
	[ -z ${!2} ] \
		&& eval 'read -ep "'$1'" -i "$DFL_'$2'" '${2}''
	if [ -z $non_empty ] ; then
		eval ''$2'=${'$2':=$DFL_'$2'}'
	fi
	[ $SCRIPTING ] \
		&& echo "$2=${!2}"
}


#
#	readVars
#
# Variables this handles:
#	EMAIL
#	DOMAIN
#	ID
#	CTHOSTNAME
#	WAN_BRIDGE
#	LAN_BRIDGE
#	ADMIN_BRIDGE
#	WAN_IP
#	WAN_GATE
#	LAN_IP
#	LAN_GATE
#	ADMIN_IP
#	ADMIN_GATE
#	ROOTPASS
#	PCT_EXTRA
#
# Variables this sets:
#	PASS
#
# Variables used:
# 	TMP_PASS_LEN
# 	ROOTPASS
#
readVars(){
	xread -n "Email: " EMAIL
	xread -n "Domain: " DOMAIN
	xread "ID: " ID
	xread "Hostname: " CTHOSTNAME

	# bridge config...
	xread "WAN bridge: vmbr" WAN_BRIDGE
	xread "LAN bridge: vmbr" LAN_BRIDGE
	xread "ADMIN bridge: vmbr" ADMIN_BRIDGE

	# gateway...
	# IPs can be:
	#	<empty>
	#	<IP>/<mask>
	#	dhcp
	# Gateways can be:
	#	<empty>
	#	<IP>
	xread "WAN ip: " WAN_IP
	xread "WAN gateway: " WAN_GATE
	xread "LAN ip: " LAN_IP
	xread "LAN gateway: " LAN_GATE
	xread "ADMIN ip: " ADMIN_IP
	xread "ADMIN gateway: " ADMIN_GATE

	# root password...
	if [ -z $ROOTPASS ] ; then
		read -sep "root password (Enter to skip): " PASS1
		echo
		if [ $PASS1 ] ; then
			read -sep "retype root password: " PASS2
			echo
			if [[ $PASS1 != $PASS2 ]] ; then
				echo "ERR: passwords do not match."
				exit 1
			fi
			PASS=$PASS1
		fi
	else
		PASS=$ROOTPASS
	fi

	# extra stuff...
	xread "pct extra options: " PCT_EXTRA
}


#
#	buildAssets [TEMPLATES [ASSETS]]
#
buildAssets(){
	local TEMPLATE_DIR=$1
	TEMPLATE_DIR=${TEMPLATE_DIR:=templates}
	local ASSETS_DIR=$2
	ASSETS_DIR=${ASSETS_DIR:=assets}

	local TEMPLATES=($(find "$TEMPLATE_DIR" -type f))
	for file in "${TEMPLATES[@]}" ; do
		file=${file#${TEMPLATE_DIR}}
		echo Generating: ${file}...
		[ $DRY_RUN ] \
			&& continue
		# ensure the directory exists...
		mkdir -p "$(dirname "${ASSETS_DIR}/${file}")"
		cat "${TEMPLATE_DIR}/${file}" \
			| sed \
				-e 's/\${EMAIL}/'${EMAIL/\//\\/}'/g' \
				-e 's/\${DOMAIN}/'${DOMAIN/\//\\/}'/g' \
				-e 's/\${CTHOSTNAME}/'${CTHOSTNAME/\//\\/}'/g' \
				-e 's/\${WAN_IP}/'${WAN_IP/\//\\/}'/g' \
				-e 's/\${WAN_GATE}/'${WAN_GATE/\//\\/}'/g' \
				-e 's/\${LAN_IP}/'${LAN_IP/\//\\/}'/g' \
				-e 's/\${LAN_GATE}/'${LAN_GATE/\//\\/}'/' \
				-e 's/\${ADMIN_IP}/'${ADMIN_IP/\//\\/}'/g' \
				-e 's/\${ADMIN_GATE}/'${ADMIN_GATE/\//\\/}'/g' \
			> "${ASSETS_DIR}/${file}"
	done
}


#
#	pctCreate ID TEMPLATE ARGS [PASS]
#
pctCreate(){
	local TMP_PASS=$(cat /dev/urandom | base64 | head -c ${TMP_PASS_LEN:=32})
	# NOTE: we are not setting the password here to avoid printing it to the terminal...
	@ pct create $1 \
		${2} \
		${3} \
		--password="$TMP_PASS" \
		--start 1 \
	|| exit 1
	# set actual root password...
	if [ "$4" ] ; then
		echo "root:$4" \
			| @ lxc-attach $1 chpasswd
	fi
}

#
#	pctCreate ID ARGS [PASS]
#
pctCreateAlpine(){
	if [ $DRY_RUN ] ; then
		local TEMPLATE=(/var/lib/vz/template/cache/alpine-3.18\*.tar.xz)
	else
		local TEMPLATE=($(ls /var/lib/vz/template/cache/alpine-3.18*.tar.xz))
	fi

	pctCreate $1 "${TEMPLATE[-1]}" "$2" "$3"

	@ lxc-attach $1 apk update
	@ lxc-attach $1 apk upgrade
}


#
#	pctSet ID [ARGS [REBOOT]]
#
pctSet(){
	[ "$2" ] \
		&& @ pct set $1 \
			${2}
	[ "$3" ] \
		&& @ pct reboot $1
}



#----------------------------------------------------------------------
# vim:set ts=4 sw=4 nowrap :
