|
|
|
|
@@ -0,0 +1,306 @@
|
|
|
|
|
#!/usr/bin/env zsh
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
local debug=${DEBUG}
|
|
|
|
|
local playbook_filename="main.yml"
|
|
|
|
|
local playbook_dir=
|
|
|
|
|
local inventory=
|
|
|
|
|
local template_dir=
|
|
|
|
|
local template_repo=
|
|
|
|
|
local template_repo_version=
|
|
|
|
|
local quiet=
|
|
|
|
|
|
|
|
|
|
# Bold Colors
|
|
|
|
|
local BLUE='\x1b[34;1m'
|
|
|
|
|
local GREEN='\x1b[32;1m'
|
|
|
|
|
local RED='\x1b[31;1m'
|
|
|
|
|
local NOCOLOR='\033[0m'
|
|
|
|
|
|
|
|
|
|
########################## UTILS #########################
|
|
|
|
|
|
|
|
|
|
function print_color {
|
|
|
|
|
local color=$1
|
|
|
|
|
local string=$2
|
|
|
|
|
shift;shift;
|
|
|
|
|
printf "%s$color$string$NOCOLOR$@"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function debug_print() {
|
|
|
|
|
local label=$1
|
|
|
|
|
shift
|
|
|
|
|
local rest="$@"
|
|
|
|
|
[ ! "$debug" = "" ] && print_color $BLUE "$label " && print_color $NOCOLOR "$rest\n"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fail() {
|
|
|
|
|
print_color $RED "ERROR: " && print_color $NOCOLOR "$1\n" && exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function set_verbose() {
|
|
|
|
|
if [ ! "$1" = "" ]; then
|
|
|
|
|
debug="1"
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function set_quiet() {
|
|
|
|
|
if [ ! "$1" = "" ]; then
|
|
|
|
|
debug=
|
|
|
|
|
quiet="1"
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function load_config() {
|
|
|
|
|
local configs=(
|
|
|
|
|
"$HOME/.hparc"
|
|
|
|
|
$(find "$XDG_CONFIG_HOME/hpa-playbook/" -type f -maxdepth 1 -mindepth 1 -print0)
|
|
|
|
|
"${HPA_CONFIG_DIR}"
|
|
|
|
|
"$PWD/.hparc"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
for f in ${configs[@]}; do
|
|
|
|
|
[ -f "$f" ] && source "$f" && debug_print "Load Config:" "sourced config: $f"
|
|
|
|
|
done
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# NOTE: Assumes you've already called load_config.
|
|
|
|
|
function ensure_playbook_dir_from_env_or_fail() {
|
|
|
|
|
local dir=${HPA_PLAYBOOK_DIR}
|
|
|
|
|
|
|
|
|
|
if [ "$dir" = "" ] || [ ! -d "$dir" ]; then
|
|
|
|
|
fail "Env Playbook Dir: Failed to find playbook directory"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
[ ! -f "$dir/$playbook_filename" ] && fail "Env Playbook Dir: could not find playbook file."
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# NOTE: Assumes playbook_dir and inventory have been setup.
|
|
|
|
|
function run_playbook() {
|
|
|
|
|
if [ "$quiet" = "" ]; then
|
|
|
|
|
ansible-playbook "$playbook_dir/$playbook_filename" \
|
|
|
|
|
--inventory "$inventory" \
|
|
|
|
|
"${HPA_DEFAULT_PLAYBOOK_ARGS}" \
|
|
|
|
|
"$@"
|
|
|
|
|
else
|
|
|
|
|
ansible-playbook "$playbook_dir/$playbook_filename" \
|
|
|
|
|
--inventory "$inventory" \
|
|
|
|
|
"${HPA_DEFAULT_PLAYBOOK_ARGS}" \
|
|
|
|
|
"$@" 2>&1 1>/dev/null
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function parse_playbook_dir_or_fail() {
|
|
|
|
|
local opt=$1
|
|
|
|
|
local env=${HPA_PLAYBOOK_DIR}
|
|
|
|
|
|
|
|
|
|
if [ ! "$opt" = "" ]; then
|
|
|
|
|
if [ -f "$opt" ]; then
|
|
|
|
|
debug_print "Parse Playbook:" "using option."
|
|
|
|
|
playbook_dir=$(dirname "$opt")
|
|
|
|
|
return 0
|
|
|
|
|
elif [ -d "$opt" ]; then
|
|
|
|
|
debug_print "Parse Playbook:" "using option."
|
|
|
|
|
playbook_dir=$opt
|
|
|
|
|
return 0
|
|
|
|
|
else
|
|
|
|
|
fail "Parse Playbook Dir: Playbook was not file or directory: $opt"
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
ensure_playbook_dir_from_env_or_fail
|
|
|
|
|
playbook_dir="$env"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function parse_opt_or_env_var {
|
|
|
|
|
local opt=$1
|
|
|
|
|
local env=$2
|
|
|
|
|
|
|
|
|
|
if [ ! "$opt" = "" ]; then
|
|
|
|
|
echo $opt
|
|
|
|
|
elif [ ! "$env" = "" ]; then
|
|
|
|
|
echo $env
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# NOTE: assumes playbook_dir has been set.
|
|
|
|
|
function parse_inventory_or_fail() {
|
|
|
|
|
local label="Parse Inventory:"
|
|
|
|
|
|
|
|
|
|
debug_print $label "opt: '$1'"
|
|
|
|
|
|
|
|
|
|
local output=$(parse_opt_or_env_var $1 ${HPA_DEFAULT_INVENTORY})
|
|
|
|
|
|
|
|
|
|
debug_print $label "parsed opt or env: '$output'"
|
|
|
|
|
|
|
|
|
|
if [ ! "$output" = "" ]; then
|
|
|
|
|
[ ! -f "$output" ] && fail "$label inventory is not a file."
|
|
|
|
|
debug_print $label "using parsed inventory."
|
|
|
|
|
inventory=$output
|
|
|
|
|
elif [ -f "$playbook_dir/inventory.ini" ]; then
|
|
|
|
|
debug_print $label "using default playbook option."
|
|
|
|
|
inventory="$playbook_dir/inventory.ini"
|
|
|
|
|
else
|
|
|
|
|
fail "$label failed to find inventory file."
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# NOTE: assumes load_config has been called.
|
|
|
|
|
function parse_template_dir() {
|
|
|
|
|
template_dir=$(parse_opt_or_env_var $1 ${HPA_TEMPLATE_DIR})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# NOTE: assumes load_config has been called.
|
|
|
|
|
function parse_repo_or_fail() {
|
|
|
|
|
local label="Parse Repo:"
|
|
|
|
|
template_repo=$(parse_opt_or_env_var $1 ${HPA_TEMPLATE_REPO})
|
|
|
|
|
|
|
|
|
|
if [ "$template_repo" = "" ]; then
|
|
|
|
|
fail "$label failed to find template repo."
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# NOTE: assumes load_config has been called.
|
|
|
|
|
function parse_repo_version_or_fail() {
|
|
|
|
|
local label="Parse Repo Version:"
|
|
|
|
|
template_repo_version=$(parse_opt_or_env_var $1 ${HPA_TEMPLATE_VERSION})
|
|
|
|
|
|
|
|
|
|
if [ "$template_repo_version" = "" ]; then
|
|
|
|
|
fail "$label failed to find template repo version."
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
########################## SUBCOMMANDS #########################
|
|
|
|
|
|
|
|
|
|
function setup_project() {
|
|
|
|
|
function usage() {
|
|
|
|
|
cat <<EOF
|
|
|
|
|
|
|
|
|
|
Setup a project from a template or repo.
|
|
|
|
|
|
|
|
|
|
This script calls the ansible-hpa-playbook that sets up a new project from the supplied template or repo.
|
|
|
|
|
Or will read from a configuration file what defaults to use.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Usage: hpa setup-project [Options [GlobalOptions]] <project-dir> [playbook-args...]
|
|
|
|
|
|
|
|
|
|
Where:
|
|
|
|
|
project-dir : The directory to generate the project in (required).
|
|
|
|
|
playbook-args : Extra arguments passed after the project directory get passed directly to the ansible-playbook command.
|
|
|
|
|
|
|
|
|
|
Options:
|
|
|
|
|
|
|
|
|
|
-b | --branch : The repo branch to clone (ignored if the -t option is used).
|
|
|
|
|
-r | --repo : A template repo to use and clone into the project (ignored if the -t option is used).
|
|
|
|
|
-t | --template : A local template / repo to use without cloning.
|
|
|
|
|
-v | --version : The version of the repo to clone (ignored if the -t option is used).
|
|
|
|
|
|
|
|
|
|
Flags:
|
|
|
|
|
-h | --help : Show this help page.
|
|
|
|
|
-l | --local-template-dir : Force using local template dir, generally used when config holds the information for where to
|
|
|
|
|
locate the template directory on the system.
|
|
|
|
|
|
|
|
|
|
Global Options:
|
|
|
|
|
|
|
|
|
|
-i | --inventory : A custom ansible inventory file to use (optional if calling this script from the playbook directory).
|
|
|
|
|
-p | --playbook : Path to the ansible-hpa-playbook (optional if calling this script from the playbook directory).
|
|
|
|
|
-q | --quiet : Surpress ansible output to only errors and warnings.
|
|
|
|
|
|
|
|
|
|
Global Flags:
|
|
|
|
|
--verbose : Increase log output.
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
|
|
|
|
|
# Setup a project for super-customer using a local template directory.
|
|
|
|
|
$ hpa setup-project --template ~/projects/my-template ~/consults/super-customer --ask-vault-pass
|
|
|
|
|
|
|
|
|
|
# Setup a project for super-customer using a template repo.
|
|
|
|
|
$ hpa setup-project --repo "https://git.example.com/my-template.git" --branch "main" ~/consults/super-customer --ask-vault-pass
|
|
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local label="Setup Project:"
|
|
|
|
|
|
|
|
|
|
zparseopts -D -E - \
|
|
|
|
|
p:=playbookOpt -playbook:=playbookOpt \
|
|
|
|
|
i:=inventoryOpt -inventory:=inventoryOpt \
|
|
|
|
|
t:=template -template-dir:=template \
|
|
|
|
|
r:=repo -repo:=repo \
|
|
|
|
|
v:=version -version:=version \
|
|
|
|
|
b:=version -branch:=version \
|
|
|
|
|
h=help -help=help \
|
|
|
|
|
l=localTemplateDir -local-template-dir=localTemplateDir \
|
|
|
|
|
-verbose=verbose \
|
|
|
|
|
q=quietOpt -quiet=quietOpt
|
|
|
|
|
|
|
|
|
|
# exit early and show help
|
|
|
|
|
[ ! "$help" = "" ] && usage && exit 0
|
|
|
|
|
|
|
|
|
|
set_verbose $verbose
|
|
|
|
|
set_quiet $quietOpt
|
|
|
|
|
|
|
|
|
|
debug_print "$label" "begin args: $@"
|
|
|
|
|
|
|
|
|
|
parse_playbook_dir_or_fail "${playbookOpt[-1]}"
|
|
|
|
|
parse_inventory_or_fail "${inventoryOpt[-1]}"
|
|
|
|
|
debug_print "$label" "playbook dir: $playbook_dir"
|
|
|
|
|
debug_print "$label" "inventory: $inventory"
|
|
|
|
|
|
|
|
|
|
local project_dir="$1"
|
|
|
|
|
[ "$project_dir" = "" ] && fail "Setup Project: project directory not supplied"
|
|
|
|
|
shift;
|
|
|
|
|
|
|
|
|
|
parse_template_dir "${template[-1]}"
|
|
|
|
|
local json=
|
|
|
|
|
|
|
|
|
|
if [ ! "$localTemplateDir" = "" ]; then
|
|
|
|
|
debug_print $label "parsed template dir: '$template_dir'"
|
|
|
|
|
if [ "$template_dir" = "" ]; then
|
|
|
|
|
fail "$label failed to find template directory."
|
|
|
|
|
fi
|
|
|
|
|
json="{'template': {'path': '"$template_dir"'}}"
|
|
|
|
|
else
|
|
|
|
|
parse_repo_or_fail ${repo[-1]}
|
|
|
|
|
parse_repo_version_or_fail ${version[-1]}
|
|
|
|
|
debug_print $label "parsed repo: '$template_repo'"
|
|
|
|
|
debug_print $label "parsed repo version: '$template_repo_version'"
|
|
|
|
|
json="{'template': {'repo': {'url': '"$template_repo"', 'version': '"$template_repo_version"' }}}"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
debug_print "$label" "json: $json"
|
|
|
|
|
|
|
|
|
|
run_playbook \
|
|
|
|
|
--tags setup-project \
|
|
|
|
|
--extra-vars "$json" \
|
|
|
|
|
--extra-vars "project_dir=$project_dir" \
|
|
|
|
|
"$@"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
########################## MAIN #########################
|
|
|
|
|
|
|
|
|
|
function main() {
|
|
|
|
|
|
|
|
|
|
zparseopts -D -E - \
|
|
|
|
|
p:=playbookOpt -playbook:=playbookOpt \
|
|
|
|
|
i:=inventoryOpt -inventory:=inventoryOpt \
|
|
|
|
|
-verbose=verbose \
|
|
|
|
|
q=quietOpt -quiet=quietOpt
|
|
|
|
|
|
|
|
|
|
set_verbose $verbose
|
|
|
|
|
set_quiet $quietOpt
|
|
|
|
|
|
|
|
|
|
debug_print "MAIN:" "Begin main: $@"
|
|
|
|
|
load_config
|
|
|
|
|
debug_print "MAIN:" "Loaded configuration."
|
|
|
|
|
|
|
|
|
|
case $1 in
|
|
|
|
|
setup-project)
|
|
|
|
|
shift
|
|
|
|
|
setup_project $playbookOpt $inventoryOpt $verbose $quietOpt $@
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
fail "Fix me!"
|
|
|
|
|
esac
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug_print "GLOBAL:" "${@}"
|
|
|
|
|
main "${@}"
|