dotfiles/overlays/itp/itp.sh

202 lines
4.5 KiB
Bash
Raw Normal View History

# -*- sh-basic-offset: 2 indent-tabs-mode: nil -*-
declare -a _positional_args
declare _dry_run=no
declare _state_file
declare _task_file
declare _org
while [[ $# -gt 0 ]]; do
case $1 in
-n|--dry-run)
_dry_run="yes"
shift # past argument
;;
-s|--state)
if [[ -z "${2:-}" ]] ; then
echo "$1 takes one argument"
exit 2
fi
_state_file="$2"
shift # past argument
shift # past value
;;
-f|--file)
if [[ -z "${2:-}" ]] ; then
echo "$1 takes one argument"
exit 2
fi
_task_file="$2"
shift # past argument
shift # past value
;;
-o|--org)
if [[ -z "${2:-}" ]] ; then
echo "$1 takes one argument"
exit 2
fi
_org="$2"
shift # past argument
shift # past value
;;
--*|-*)
echo "Unknown option $1"
exit 1
;;
*)
_positional_args+=("$1") # save positional arg
shift # past argument
;;
esac
done
set -- "${_positional_args[@]}"
if [[ -z "${_state_file:-}" ]] ; then
echo "-s|--state must be specified"
exit 2
fi
if [[ -z "${_task_file:-}" ]] ; then
echo "-f|--file must be specified"
exit 2
fi
if ! [[ -f "$_task_file" ]] ; then
echo "$_task_file must exist and be writable"
exit 2
fi
if ! [[ -w "$_state_file" ]] ; then
touch "$_state_file" || ( echo "Couldn't create state file" ; exit 2 )
echo "[]" > "$_state_file"
fi
if [[ -z "${_org:-}" ]] ; then
echo "-o|--org must be specified"
exit 2
fi
if [[ -z "${INFLUX_HOST:-}" ]] ; then
echo "INFLUX_HOST must be set"
exit 2
fi
if [[ -z "${INFLUX_TOKEN:-}" ]] ; then
echo "INFLUX_TOKEN must be set"
exit 2
fi
if ! influx task list --org "$_org" >/dev/null 2>&1 ; then
echo "Failed to establish connection to InfuxDB"
exit 2
fi
declare -a _tasks_to_remove
declare -a _tasks_to_add
declare -a _tasks_to_update
mapfile -t _tasks_to_remove < <(comm -23 <(jq -r '.[].name' < "$_state_file" | sort) <(jq -r '.[].name' < "$_task_file" | sort))
mapfile -t _tasks_to_add < <(comm -13 <(jq -r '.[].name' < "$_state_file" | sort) <(jq -r '.[].name' < "$_task_file" | sort))
mapfile -t _tasks_to_update < <(comm -12 <(jq -r '.[].name' < "$_state_file" | sort) <(jq -r '.[].name' < "$_task_file" | sort))
function task_key_by_name() {
_file="$1"
_task="$2"
_key="$3"
# shellcheck disable=SC2086 # Intended splitting of JQ_OPTS
jq ${JQ_OPTS:-} '.[] | select(.name == "'"$_task"'") | .'"$_key" < "$_file"
}
function prepend_if_not_null() {
_prepend=$1
_input=$(cat)
if [[ "$_input" != "null" ]] ; then
echo "$_prepend $_input"
fi
}
function generate_flux_file() {
_task="$1"
cat <<EOF
option task = {
name: $(task_key_by_name "$_task_file" "$task" "name")
$(task_key_by_name "$_task_file" "$task" "cron" | prepend_if_not_null ", cron: ")
$(JQ_OPTS="-r" task_key_by_name "$_task_file" "$task" "every" | prepend_if_not_null ", every: ")
}
$(cat "$(JQ_OPTS="-r" task_key_by_name "$_task_file" "$task" "flux_file")")
EOF
}
function task_delete() {
_id="$1"
influx task delete --id "$_id"
}
function task_create() {
_flux_file="$1"
influx task create --org "$_org" --file <(cat "$_flux_file")
}
function task_update() {
_task="$1"
_flux_file="$2"
influx task update --id "$(JQ_OPTS="-r" task_key_by_name "$_state_file" "$_task" "id")" --file "$_flux_file"
}
for task in "${_tasks_to_remove[@]}" ; do
if [[ "$_dry_run" == "no" ]] ; then
echo "Removing $task"
task_delete "$(JQ_OPTS="-r" task_key_by_name "$_state_file" "$task" "id")"
else
echo "Would remove $task"
fi
done
for task in "${_tasks_to_add[@]}" ; do
if [[ "$_dry_run" == "no" ]] ; then
echo "Adding $task"
_flux_file=$(generate_flux_file "$task")
task_create <(cat <<<"$_flux_file")
else
echo "Would add $task"
fi
done
for task in "${_tasks_to_update[@]}" ; do
if [[ "$_dry_run" == "no" ]] ; then
echo "Updating $task"
_flux_file=$(generate_flux_file "$task")
_output="$(task_update "$task" <(cat <<<"$_flux_file") 2>&1)"
if [[ "$?" == "1" ]] && [[ "$_output" == *"404"* ]] ; then
echo "Failed to update, creating: $_output"
task_create <(cat <<<"$_flux_file")
fi
else
echo "Would update $task"
fi
done
_current_state=$(influx task list --org "$_org" --json)
if [[ "$_dry_run" == "no" ]] ; then
echo "Saving new state"
cat "$_task_file" <(cat <<<"$_current_state") | jq -s '[.[0] as $new | .[1] as $old | $old[] | select(.name | IN($new[].name))]' > "$_state_file"
fi