311 lines
7.7 KiB
Plaintext
311 lines
7.7 KiB
Plaintext
CHAT_OUTPUT_BEGIN
|
|
COMMAND_ID=CLUSTER-REFERENCE-STATE-AUDIT-149
|
|
STATUS=OK
|
|
RC=0
|
|
HOST=pve01
|
|
MODE=read-only
|
|
COMPONENT=cluster-audit
|
|
REFERENCE_REGISTER_CHECK=OK
|
|
REFERENCE_SHA256=5763f2f8edc75fcf6f3951f8c95896d1cc112ceccb6cf5b64a383f540a4deb8e
|
|
ERROR_REGISTER_CHECK=OK
|
|
ERROR_REGISTER_SHA256=08b3a769b8e38eaa1acec915352fb328180d70caa7ff6cd9d1ec0da426262752
|
|
COMMAND_SHA256=2af6ffbc1ab71f8fd13302a48794faa713dfcde5a4c90652ace8ab2355e3c2e4
|
|
DUPLICATE_FAILED_COMMAND_BLOCKED=false
|
|
EXECUTION_STARTED=true
|
|
CHANGES_MADE=false
|
|
SANITIZED=yes
|
|
SECRETS_INCLUDED=no
|
|
PRIVATE_ADDRESSES_INCLUDED=no
|
|
RAW_EVIDENCE_SHA256=8fda57d15c1339215b841cef0152a9d2ff5e74b8ecb22d0a7b22050900061148
|
|
SANITIZED_OUTPUT_SHA256=c5ff5c4350fa2306f6847ecfe42105b46c49aa92a065610327cb1a9f0e9498bc
|
|
OUTPUT_BEGIN
|
|
=== IMMUTABLE_COMMAND_RESULTS ===
|
|
--- COMMAND_ID=CLUSTER-REFERENCE-MODE-CONFIRM-145 ---
|
|
JSON_COMMIT=072668fbc56c580756f0ad7a6a30e4a6af953794
|
|
STATUS=OK
|
|
RC=0
|
|
REASON=None
|
|
EXECUTION_STARTED=True
|
|
DUPLICATE_BLOCKED=False
|
|
TXT_COMMIT=072668fbc56c580756f0ad7a6a30e4a6af953794
|
|
VALID_MODES=change,read-only,transport-test,verify
|
|
SAFE_WRITE_MODE=UNRESOLVED
|
|
CLUSTER_REFERENCE_MODE_CONFIRM=COMPLETE
|
|
ERROR_REGISTERED=no
|
|
--- COMMAND_ID=CLUSTER-REFERENCE-FRAMEWORK-146 ---
|
|
JSON_HISTORY=MISSING
|
|
TXT_HISTORY=MISSING
|
|
ERROR_REGISTERED=no
|
|
--- COMMAND_ID=CLUSTER-REFERENCE-SOURCE-AUDIT-147 ---
|
|
JSON_COMMIT=4ef5989856165ac24b02ba54455d3782e16a7cae
|
|
STATUS=FAIL
|
|
RC=22
|
|
REASON=None
|
|
EXECUTION_STARTED=True
|
|
DUPLICATE_BLOCKED=False
|
|
TXT_COMMIT=4ef5989856165ac24b02ba54455d3782e16a7cae
|
|
ERROR_REGISTERED=no
|
|
--- COMMAND_ID=CLUSTER-REFERENCE-FOUNDATION-148 ---
|
|
JSON_HISTORY=MISSING
|
|
TXT_HISTORY=MISSING
|
|
ERROR_REGISTERED=no
|
|
=== RUNNER_MODE_RULES ===
|
|
3-umask 077
|
|
4-
|
|
5-usage() {
|
|
6- cat >&2 <<'USAGE'
|
|
7-Usage:
|
|
8- homelab-chat-run COMMAND_ID MODE COMPONENT -- command [arguments...]
|
|
9-
|
|
10-MODE:
|
|
11: read-only
|
|
12- verify
|
|
13: change
|
|
14- transport-test
|
|
15-
|
|
16-Environment:
|
|
17- HOMELAB_ALLOW_REPEAT=1 Allow exact repeat of a previously failed command.
|
|
18- HOMELAB_TIMEOUT=SECONDS Optional command timeout.
|
|
19-USAGE
|
|
20- exit 64
|
|
21-}
|
|
22-
|
|
23-[ "$#" -ge 5 ] || usage
|
|
24-
|
|
25-COMMAND_ID="$1"
|
|
26-MODE="$2"
|
|
27-COMPONENT="$3"
|
|
28-shift 3
|
|
29-
|
|
30-[ "${1:-}" = '--' ] || usage
|
|
31-shift
|
|
32-[ "$#" -ge 1 ] || usage
|
|
33-
|
|
--
|
|
43- ''|*[!A-Za-z0-9._-]*)
|
|
44- echo 'RESULT=FAIL'
|
|
45- echo 'REASON=INVALID_COMPONENT'
|
|
46- exit 66
|
|
47- ;;
|
|
48-esac
|
|
49-
|
|
50-case "$MODE" in
|
|
51: read-only|verify|change|transport-test)
|
|
52- ;;
|
|
53- *)
|
|
54- echo 'RESULT=FAIL'
|
|
55: echo 'REASON=INVALID_MODE'
|
|
56- exit 67
|
|
57- ;;
|
|
58-esac
|
|
59-
|
|
60-for TOOL in \
|
|
61- awk \
|
|
62- curl \
|
|
63- flock \
|
|
64- python3 \
|
|
65- scp \
|
|
66- sha256sum \
|
|
67- ssh
|
|
68-do
|
|
69- command -v "$TOOL" >/dev/null 2>&1 || {
|
|
70- echo 'RESULT=FAIL'
|
|
71- echo "REASON=REQUIRED_TOOL_MISSING:$TOOL"
|
|
72- exit 68
|
|
73- }
|
|
74-done
|
|
75-
|
|
--
|
|
139- print value
|
|
140- }
|
|
141- ' "$LEDGER"
|
|
142-)"
|
|
143-
|
|
144-RUN_STARTED=true
|
|
145-REPEAT_BLOCKED=false
|
|
146-BLOCK_REASON=''
|
|
147:CHANGES_MADE=false
|
|
148-
|
|
149-case "$MODE" in
|
|
150: change)
|
|
151: CHANGES_MADE=true
|
|
152- ;;
|
|
153-esac
|
|
154-
|
|
155-if [ -n "$PREVIOUS_FAILED_RC" ] &&
|
|
156- [ "${HOMELAB_ALLOW_REPEAT:-0}" != 1 ]; then
|
|
157-
|
|
158- RUN_STARTED=false
|
|
159- REPEAT_BLOCKED=true
|
|
160- BLOCK_REASON='EXACT_FAILED_COMMAND_REPEAT'
|
|
161- RC=73
|
|
162- STATUS='BLOCKED'
|
|
163-
|
|
164- {
|
|
165- echo 'COMMAND_EXECUTION_BLOCKED=yes'
|
|
166- echo 'REASON=EXACT_FAILED_COMMAND_REPEAT'
|
|
167- echo "PREVIOUS_RC=$PREVIOUS_FAILED_RC"
|
|
168- echo "COMMAND_SHA256=$COMMAND_SHA256"
|
|
169- echo
|
|
170- echo 'Set HOMELAB_ALLOW_REPEAT=1 only after reviewing the previous failure.'
|
|
171- } >"$RAW_FILE"
|
|
--
|
|
298- text = (
|
|
299- first
|
|
300- + "\n\n"
|
|
301- + "===== PUBLIC OUTPUT TRUNCATED; FULL RAW LOG RETAINED LOCALLY ====="
|
|
302- + "\n\n"
|
|
303- + last
|
|
304- )
|
|
305-
|
|
306:target.write_text(text, encoding="utf-8")
|
|
307-PY
|
|
308-
|
|
309-SANITIZED_SHA256="$(
|
|
310- sha256sum "$SANITIZED_FILE" |
|
|
311- awk '{print $1}'
|
|
312-)"
|
|
313-
|
|
314-python3 - \
|
|
315- "$JSON_FILE" \
|
|
316- "$SANITIZED_FILE" \
|
|
317- "$COMMAND_ID" \
|
|
318- "$STATUS" \
|
|
319- "$RC" \
|
|
320- "$HOST_SHORT" \
|
|
321- "$MODE" \
|
|
322- "$COMPONENT" \
|
|
323- "$STARTED_AT" \
|
|
324- "$FINISHED_AT" \
|
|
325- "$REFERENCE_SHA256" \
|
|
326- "$ERROR_REGISTER_SHA256" \
|
|
327- "$COMMAND_SHA256" \
|
|
328- "$RAW_SHA256" \
|
|
329- "$SANITIZED_SHA256" \
|
|
330- "$RUN_STARTED" \
|
|
331- "$REPEAT_BLOCKED" \
|
|
332- "$BLOCK_REASON" \
|
|
333: "$CHANGES_MADE" <<'PY'
|
|
334-import json
|
|
335-import sys
|
|
336-from pathlib import Path
|
|
337-
|
|
338-(
|
|
339- json_path,
|
|
340- output_path,
|
|
341- command_id,
|
|
342- status,
|
|
343- rc,
|
|
344- host,
|
|
345- mode,
|
|
346- component,
|
|
347- started,
|
|
348- finished,
|
|
349- reference_sha,
|
|
350- error_sha,
|
|
351- command_sha,
|
|
352- raw_sha,
|
|
353- sanitized_sha,
|
|
354- run_started,
|
|
355- repeat_blocked,
|
|
356- block_reason,
|
|
357: changes_made,
|
|
358-) = sys.argv[1:]
|
|
359-
|
|
360-output = Path(output_path).read_text(
|
|
361- encoding="utf-8",
|
|
362- errors="replace",
|
|
363-)
|
|
364-
|
|
365-encoded = output.encode("utf-8")
|
|
366-json_limit = 300_000
|
|
367-output_truncated = len(encoded) > json_limit
|
|
368-
|
|
369-if output_truncated:
|
|
370- output_preview = encoded[:json_limit].decode(
|
|
371- "utf-8",
|
|
372- errors="ignore",
|
|
373- )
|
|
374-else:
|
|
375- output_preview = output
|
|
376-
|
|
377-document = {
|
|
--
|
|
388- "reference_register_checked": True,
|
|
389- "reference_sha256": reference_sha,
|
|
390- "error_register_checked": True,
|
|
391- "error_register_sha256": error_sha,
|
|
392- "command_sha256": command_sha,
|
|
393- "duplicate_failed_command_blocked": repeat_blocked == "true",
|
|
394- "block_reason": block_reason or None,
|
|
395- "execution_started": run_started == "true",
|
|
396: "changes_made": changes_made == "true",
|
|
397- "sanitized": True,
|
|
398- "secrets_included": False,
|
|
399- "private_addresses_included": False,
|
|
400- "raw_evidence_retained_locally": True,
|
|
401- "raw_evidence_sha256": raw_sha,
|
|
402- "sanitized_output_sha256": sanitized_sha,
|
|
403- "output_truncated_in_json": output_truncated,
|
|
404- "full_sanitized_output_url": (
|
|
405- "https://git.gram1.ru/.well-known/"
|
|
406- "homelab-runtime/latest.txt"
|
|
407- ),
|
|
408- "output": output_preview,
|
|
409-}
|
|
410-
|
|
411:Path(json_path).write_text(
|
|
412- json.dumps(
|
|
413- document,
|
|
414- ensure_ascii=False,
|
|
415- indent=2,
|
|
416- )
|
|
417- + "\n",
|
|
418- encoding="utf-8",
|
|
419-)
|
|
420-PY
|
|
421-
|
|
422-{
|
|
423- echo 'CHAT_OUTPUT_BEGIN'
|
|
424- echo "COMMAND_ID=$COMMAND_ID"
|
|
425- echo "STATUS=$STATUS"
|
|
426- echo "RC=$RC"
|
|
427- echo "HOST=$HOST_SHORT"
|
|
428- echo "MODE=$MODE"
|
|
429- echo "COMPONENT=$COMPONENT"
|
|
430- echo 'REFERENCE_REGISTER_CHECK=OK'
|
|
431- echo "REFERENCE_SHA256=$REFERENCE_SHA256"
|
|
432- echo 'ERROR_REGISTER_CHECK=OK'
|
|
433- echo "ERROR_REGISTER_SHA256=$ERROR_REGISTER_SHA256"
|
|
434- echo "COMMAND_SHA256=$COMMAND_SHA256"
|
|
435- echo "DUPLICATE_FAILED_COMMAND_BLOCKED=$REPEAT_BLOCKED"
|
|
436- echo "EXECUTION_STARTED=$RUN_STARTED"
|
|
437: echo "CHANGES_MADE=$CHANGES_MADE"
|
|
438- echo 'SANITIZED=yes'
|
|
439- echo 'SECRETS_INCLUDED=no'
|
|
440- echo 'PRIVATE_ADDRESSES_INCLUDED=no'
|
|
441- echo "RAW_EVIDENCE_SHA256=$RAW_SHA256"
|
|
442- echo "SANITIZED_OUTPUT_SHA256=$SANITIZED_SHA256"
|
|
443- echo 'OUTPUT_BEGIN'
|
|
444- cat "$SANITIZED_FILE"
|
|
445- echo
|
|
446- echo 'OUTPUT_END'
|
|
447- echo 'CHAT_OUTPUT_END'
|
|
448-} >"$TXT_FILE"
|
|
449-
|
|
450-chmod 0600 \
|
|
451- "$RAW_FILE" \
|
|
452- "$SANITIZED_FILE" \
|
|
453- "$JSON_FILE" \
|
|
454- "$TXT_FILE"
|
|
455-
|
|
456-TARGET=debian@[PRIVATE_IP]
|
|
457-REMOTE_PREFIX="/tmp/homelab-runtime-${COMMAND_ID}-$$"
|
|
=== PARTIAL_REFERENCE_STATE ===
|
|
REFERENCE_ROOT=ABSENT
|
|
REFERENCE_CLI=ABSENT
|
|
CLUSTER_REFERENCE_STATE_AUDIT=COMPLETE
|
|
|
|
OUTPUT_END
|
|
CHAT_OUTPUT_END
|