#!/bin/bash
#  apt - Debian/Ubuntu apt command support

set -e

lib_load 'net/remote'
lib_load 'sys/tool/chroot'

######
# Settings

sys_tool_apt_config_init() {
	# $aptbin - Name of program to execute (e.g. 'apt' or 'apt-get').
	# Default: ``apt-get``
	lib_setting_vars aptbin

	lib_setting_vars apt_pretend

	lib_setting_arrays \
		apt_update_opts apt_install_opts apt_upgrade_opts
}

# sys_tool_apt_config_check - scans libraries and script for package settings
sys_tool_apt_config_check() {
	aptbin=${aptbin:-apt-get}

	apt_pretend=${apt_pretend:-false}

	for_each_lib _sys_tool_apt_config_check
	_sys_tool_apt_config_check "$script_name"
}

# scans one library/script for apt package settings
_sys_tool_apt_config_check() {
	local name=$1
	for ext in client server; do
		local var="$(lib_symbol $name)_${ext}_packages"
		if eval "[ \"\${${var}[*]}\" ]"; then
			settings_add_arrays "apt" "$var"
		fi
	done
}


######
# Internal functions

apt_deps_append() {
	has_args 3 "$@"
	local var=$1
	local class=$2
	local prefix=$3

	local sym
	sym=$(lib_symbol $prefix)
	local name="${sym}_${class}_packages"

	local -a packages
	eval "packages=( \"\${$name[@]}\" )"
	if [ "${packages[*]}" ]; then
		info "$prefix: adding $class packages: ${packages[*]}"
		list_append $var "${packages[@]}"
	else
		debug "$prefix: no $class packages"
	fi
}


######
# Public interface

# apt_run() - Run the APT package management tool
apt_run() {
	local -a opts
	opts+=( --yes )
	opts+=( --quiet )
	$verbose || opts+=( --quiet )
	! $apt_pretend || opts+=( --dry-run )
	run_sudo $aptbin "${opts[@]}" "$@"
}

# apt_install() - Installs packages
apt_install() { apt_run install "$@"; }

# apt_upgrade() - Upgrades all of the native package dependencies
apt_upgrade() {
	apt_run update
	apt_run dist-upgrade
	apt_run autoremove
}


######
# Package class support

#  apt_class_usage - Prints common command usage for client/server CLI
apt_class_usage() {
	has_args 1 "$@"
	local class=$1
	cat <<USAGE
<cmd> ...
Package Commands:
	deps				List $class packages
	install				Install $class packages
USAGE
}

_apt_class_deps() {
	has_args 2 "$@"
	local var=$1
	local class=$2

	for_each_lib apt_deps_append $var $class
	apt_deps_append $var $class $script_name
}

apt_class_deps() {
	has_args 1 "$@"
	local class=$1

	lib_load 'sys/packages'
	tool_packages "$class" | sort -u
}

apt_class_install() {
	has_args 1 "$@"
	local class=$1

	local -a deps
	deps=( $(apt_class_deps "$class") )
	apt_install "${deps[@]}"
}

# apt_install_remote() - Installs packages ($@) on a remote host ($1)
apt_install_remote() {
	min_args 2 "$@"
	local pkg_host=$1
	shift
	remote_sudo $pkg_host apt install "$@"
}

# apt_install_remote_class() - Installs a class ($2) of packages ($@) on a
# remote host ($1)
apt_install_remote_class() {
	local host=$1
	local class=$2
	local -a deps
	deps=( $(tool_class_deps $class) )
	apt_install_remote "$host" "${deps[@]}"
}

# apt_install_tool_class() - Installs all of the tool dependencies
#  $1 - library name
apt_install_tool_class() {
	local class=$1
	local -a deps
	deps=( $(tool_class_deps $class) )
	apt_install "${deps[@]}"
}


######
# Cloud package management

# apt_install_cloud_class() - Installs a class of deps ($2) on the named
# cloud ($1)
#  $1 - cloud name
#  $2 - package class name
apt_install_cloud_class() {
	min_args 2 "$@"
	local cloud=$1
	for_each_cloud_host "$cloud" apt_install_cloud_class_host "$@"
}

# apt_install_cloud_class_host() - Installs a class of deps ($2) on the
# name host ($3) in the given cloud ($2)
#  $1 - cloud name
#  $2 - package class name
#  $@ - host name
apt_install_cloud_class_host() {
	min_args 3 "$@"
	local cloud=$1
	local class=$2
	shift 2

	local args=( "$@" )
	local name
	name=$(list_pop args)

	app_echo "$cloud: $name: cloud host $class install: starting..."

	if is_localhost $name; then
		apt_install_tool_class $class "${args[@]}"
	else
		remote_class_install $name $class "${args[@]}"
	fi
	app_echo "$cloud: $name: cloud host $class install: ... done!"
}

# apt_upgrade_cloud() - Upgrades all hosts in the named cloud ($1)
#  $1 - cloud name
apt_upgrade_cloud() {
	has_args 1 "$@"
	local cloud=$1
	cloud_required "$cloud"
	for_each_cloud_host "$cloud" apt_upgrade_cloud_host "$cloud"
}

# apt_upgrade_cloud_host() - Upgrades a single host ($2) in a cloud ($1)
#  $1 - cloud name
#  $2 - host name
apt_upgrade_cloud_host() {
	has_args 2 "$@"
	local cloud=$1
	local name=$2

	app_echo "$cloud: $name: cloud host upgrade: starting..."
	if is_localhost "$name"; then
		apt_upgrade
	else
		local -a opts=( --yes --quiet )
		$verbose || opts+=( --quiet )
		local tmp
		file_capture tmp <<EOF
$aptbin update ${opts[*]}
$aptbin dist-upgrade ${opts[*]}
$aptbin autoremove ${opts[*]}
EOF
		local installer="cloud_upgrade.sh"
		remote_copy_to "$name" "$tmp" "$installer"
		remote_sudo $name bash "$installer"
		remote_run $name rm -f "$installer"
	fi
	app_echo "$cloud: $name: cloud host upgrade: ... done!"
}


######
# Apt inside chroots

apt_chroot() {
	local action=$1
	local name=$2
	shift 2
	local -a cmd
	list_append cmd env "DEBIAN_FRONTEND=noninteractive"
	list_append cmd apt "$action" --yes
#	list_append cmd -o 'Dpkg::Options::="--force-confdef"'
#	list_append cmd -o 'Dpkg::Options::="--force-confold"'
	local var="apt_${action}_opts"
	eval "list_append cmd \"\${$var[@]}\""
	run_chroot "$name" "${cmd[@]}" "$@"
}

apt_chroot_update() { apt_chroot update "$@"; }
apt_chroot_install() { apt_chroot install "$@"; }
apt_chroot_upgrade() { apt_chroot upgrade "$@"; }

View the Developer Guide Index

View the Reference Manual Index


Generated on Tue Jul 4 17:01:02 PDT 2017 by mcsh d14 v0.21.0.