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()/
|
# Same "compare content, PUT-update if changed" fix as step_pipeline_rules()/
|
||||||
# step_pipelines() - an alert's title never changes when its query/threshold
|
# step_pipelines() - an alert's title never changes when its query/threshold
|
||||||
# does, so a plain title-exists check would silently skip the update
|
# does, so a plain title-exists check would silently skip the update
|
||||||
# forever. Confirmed live this session: alert7's query was fixed in git
|
# forever.
|
||||||
# (vendor:accel-ppp -> vendor:accel-ppp AND event_type:*) but a re-run
|
#
|
||||||
# kept reporting "already exists" with the old, buggy query still live.
|
# Uses files instead of interpolating JSON into python -c strings (fragile
|
||||||
local existing_defs
|
# with quotes/backslashes), and compares only the keys OUR file authors in
|
||||||
existing_defs="$(gcurl GET /events/definitions)"
|
# "config" - not the whole object. Confirmed live this is necessary:
|
||||||
local f title id body current_config desired_config
|
# 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
|
for f in "$SCRIPT_DIR"/alerts/alert*.json; do
|
||||||
[ -f "$f" ] || continue
|
[ -f "$f" ] || continue
|
||||||
title="$(python3 -c "import json;print(json.load(open('$f'))['title'])")"
|
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/__NETWORK_STREAM_ID__/$NETWORK_STREAM_ID/" \
|
||||||
-e "s/__SERVERS_STREAM_ID__/$SERVERS_STREAM_ID/" \
|
-e "s/__SERVERS_STREAM_ID__/$SERVERS_STREAM_ID/" \
|
||||||
-e "s/__DISCORD_NOTIFICATION_ID__/$notif_id/" \
|
-e "s/__DISCORD_NOTIFICATION_ID__/$notif_id/" \
|
||||||
"$f")"
|
"$f" > "$body_file"
|
||||||
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'),''))")"
|
|
||||||
|
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
|
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))")"
|
if python3 -c "
|
||||||
desired_config="$(echo "$body" | python3 -c "import json,sys;print(json.dumps(json.load(sys.stdin)['config'],sort_keys=True))")"
|
import json, sys
|
||||||
if [ "$current_config" = "$desired_config" ]; then
|
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)"
|
skip "alert '$title' already up to date ($id)"
|
||||||
|
rm -f "$body_file"
|
||||||
continue
|
continue
|
||||||
fi
|
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
|
gcurl PUT "/events/definitions/$id/schedule" "" >/dev/null
|
||||||
ok "updated alert '$title' ($id) - config changed"
|
ok "updated alert '$title' ($id) - config changed"
|
||||||
|
rm -f "$body_file" "${body_file}.put"
|
||||||
continue
|
continue
|
||||||
fi
|
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',''))")"
|
| python3 -c "import json,sys;print(json.load(sys.stdin).get('id',''))")"
|
||||||
[ -n "$id" ] || die "alert '$title' failed to create"
|
[ -n "$id" ] || die "alert '$title' failed to create"
|
||||||
gcurl PUT "/events/definitions/$id/schedule" "" >/dev/null
|
gcurl PUT "/events/definitions/$id/schedule" "" >/dev/null
|
||||||
ok "created and enabled alert '$title' ($id)"
|
ok "created and enabled alert '$title' ($id)"
|
||||||
|
rm -f "$body_file"
|
||||||
done
|
done
|
||||||
|
rm -f "$existing_defs_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue