mirror of
https://git.sr.ht/~magic_rb/dotfiles
synced 2024-12-12 01:42:02 +01:00
202 lines
4.5 KiB
Bash
202 lines
4.5 KiB
Bash
|
# -*- 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
|