Fix false-positive "config changed" on every alert, every run
The previous fix compared the whole live 'config' object against the whole desired one - but Graylog's GET response fills in extra defaults (query_parameters, filters, use_cron_scheduling, cron_expression, cron_timezone, ...) that never appear in our alert JSON files. That made every single alert compare as "different" on every single run, not just the one actually edited - confirmed live: a re-run PUT-updated all 7 alerts when only alert7's query had changed. Fixed by comparing only the keys our own files actually author (project the live config down to just those keys before comparing), and switched from interpolating JSON into python -c string literals to writing to temp files and reading them - the former is fragile the moment a value contains a quote or backslash. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
c1361f16c9
commit
19643a74dd
1 changed files with 46 additions and 14 deletions
|
|
@ -498,39 +498,71 @@ step_alerts() {
|
|||
# Same "compare content, PUT-update if changed" fix as step_pipeline_rules()/
|
||||
# step_pipelines() - an alert's title never changes when its query/threshold
|
||||
# does, so a plain title-exists check would silently skip the update
|
||||
# forever. Confirmed live this session: alert7's query was fixed in git
|
||||
# (vendor:accel-ppp -> vendor:accel-ppp AND event_type:*) but a re-run
|
||||
# kept reporting "already exists" with the old, buggy query still live.
|
||||
local existing_defs
|
||||
existing_defs="$(gcurl GET /events/definitions)"
|
||||
local f title id body current_config desired_config
|
||||
# forever.
|
||||
#
|
||||
# Uses files instead of interpolating JSON into python -c strings (fragile
|
||||
# with quotes/backslashes), and compares only the keys OUR file authors in
|
||||
# "config" - not the whole object. Confirmed live this is necessary:
|
||||
# Graylog's GET response fills in extra defaults (query_parameters, filters,
|
||||
# use_cron_scheduling, cron_expression, cron_timezone, ...) that never
|
||||
# appear in our alert JSON files, so a naive whole-object comparison always
|
||||
# reports "changed" and PUTs every single alert on every single run, not
|
||||
# just the one actually edited.
|
||||
local existing_defs_file
|
||||
existing_defs_file="$(mktemp)"
|
||||
gcurl GET /events/definitions > "$existing_defs_file"
|
||||
|
||||
local f title id body_file
|
||||
for f in "$SCRIPT_DIR"/alerts/alert*.json; do
|
||||
[ -f "$f" ] || continue
|
||||
title="$(python3 -c "import json;print(json.load(open('$f'))['title'])")"
|
||||
body="$(sed \
|
||||
body_file="$(mktemp)"
|
||||
sed \
|
||||
-e "s/__NETWORK_STREAM_ID__/$NETWORK_STREAM_ID/" \
|
||||
-e "s/__SERVERS_STREAM_ID__/$SERVERS_STREAM_ID/" \
|
||||
-e "s/__DISCORD_NOTIFICATION_ID__/$notif_id/" \
|
||||
"$f")"
|
||||
id="$(echo "$existing_defs" | python3 -c "import json,sys;d=json.load(sys.stdin);print(next((e['id'] for e in d['event_definitions'] if e['title']=='$title'),''))")"
|
||||
"$f" > "$body_file"
|
||||
|
||||
id="$(python3 -c "
|
||||
import json
|
||||
d = json.load(open('$existing_defs_file'))
|
||||
print(next((e['id'] for e in d['event_definitions'] if e['title'] == '$title'), ''))
|
||||
")"
|
||||
|
||||
if [ -n "$id" ]; then
|
||||
current_config="$(echo "$existing_defs" | python3 -c "import json,sys;d=json.load(sys.stdin);print(json.dumps(next(e['config'] for e in d['event_definitions'] if e['id']=='$id'),sort_keys=True))")"
|
||||
desired_config="$(echo "$body" | python3 -c "import json,sys;print(json.dumps(json.load(sys.stdin)['config'],sort_keys=True))")"
|
||||
if [ "$current_config" = "$desired_config" ]; then
|
||||
if python3 -c "
|
||||
import json, sys
|
||||
existing = json.load(open('$existing_defs_file'))
|
||||
current_full = next(e['config'] for e in existing['event_definitions'] if e['id'] == '$id')
|
||||
desired = json.load(open('$body_file'))['config']
|
||||
filtered_current = {k: current_full.get(k) for k in desired}
|
||||
sys.exit(0 if filtered_current == desired else 1)
|
||||
"; then
|
||||
skip "alert '$title' already up to date ($id)"
|
||||
rm -f "$body_file"
|
||||
continue
|
||||
fi
|
||||
gcurl PUT "/events/definitions/$id" "$(echo "$body" | python3 -c "import json,sys;d=json.load(sys.stdin);d['id']='$id';print(json.dumps(d))")" >/dev/null
|
||||
python3 -c "
|
||||
import json
|
||||
d = json.load(open('$body_file'))
|
||||
d['id'] = '$id'
|
||||
print(json.dumps(d))
|
||||
" > "${body_file}.put"
|
||||
gcurl PUT "/events/definitions/$id" "$(cat "${body_file}.put")" >/dev/null
|
||||
gcurl PUT "/events/definitions/$id/schedule" "" >/dev/null
|
||||
ok "updated alert '$title' ($id) - config changed"
|
||||
rm -f "$body_file" "${body_file}.put"
|
||||
continue
|
||||
fi
|
||||
id="$(gcurl POST /events/definitions "{\"entity\": ${body}, \"share_request\": {\"selected_grantee_capabilities\": {}}}" \
|
||||
|
||||
id="$(gcurl POST /events/definitions "{\"entity\": $(cat "$body_file"), \"share_request\": {\"selected_grantee_capabilities\": {}}}" \
|
||||
| python3 -c "import json,sys;print(json.load(sys.stdin).get('id',''))")"
|
||||
[ -n "$id" ] || die "alert '$title' failed to create"
|
||||
gcurl PUT "/events/definitions/$id/schedule" "" >/dev/null
|
||||
ok "created and enabled alert '$title' ($id)"
|
||||
rm -f "$body_file"
|
||||
done
|
||||
rm -f "$existing_defs_file"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue