fix(arkime): un-shadow db.pl, and make #3346's translation actually run (#3343) - #3392
Merged
Merged
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
…3343) into composable ones, and left the refusal it could not get past open: Elasticsearch refuses to create a legacy template whose patterns match an existing composable one, and single-node-replica-default matches "*", so db.pl could never install or refresh any of Arkime's templates again. On an Arkime version bump that needed a template upgrade, arkime-init's db.pl would fail under `set -e`, the done-marker would not be written, and capture and viewer would wait on it forever. It was worse than that. arkime-init's command is a YAML `>` folded block scalar, and a folded scalar joins every run of adjacent non-empty lines with a single space. The node invocation sat directly under its comment with no blank line between, so the whole thing rendered as one `fi` line with a trailing comment: fi # #3343: translate ... See arkime/composable-templates.js. /opt/arkime/bin/node /opt/arkime/composable-templates.js composable-templates.js had therefore never once run, and #3346's fix was inert while still reading as correct in the YAML. bash -n accepts the result either way and nothing else exercised the rendering. composable-templates.js gains a `shadow` subcommand, run before db.pl and restored after: it deletes every composable template that covers an Arkime index family, stashing each body first, so db.pl has nothing to collide with. Coverage is decided by Elasticsearch's own simpleMatch glob semantics rather than by name, so a renamed or second catch-all is shadowed too -- the previous approach of testing one invented probe name missed even arkime_sessions3-2*, which overlaps arkime_sessions3-* just as hard. The restore runs in a `finally`, because the shadowed set includes the replicas catch-all for every template-less index family in the stack and leaving it deleted would turn one failure into a yellow cluster. compose.yml wraps db.pl in a bounded three-attempt retry, which covers the one race a shadow cannot: a template created *while* db.pl runs, by elasticsearch-setup's catch-all landing mid-run. Both db.pl verbs are safe to re-run, and the loop exits non-zero without writing the done marker rather than wedging the deploy permanently. elasticsearch-setup.sh's comment claimed the catch-all "explicitly excluded" Arkime, which was never true -- composable templates have no exclusion syntax, so the "-arkime_..." entries were literal index names matching nothing. The inert entries are gone and the comment now names the mechanism that actually works. Its 60s wait for Arkime's legacy template is kept: it is the common case and needs no shadow/restore cycle, but it is no longer load-bearing. Refs #3343
CodeQL flagged js/insecure-temp-file on the shadow file: it was written to a fixed path directly in /tmp, so anything on the host could have pre-created it as a symlink or read the stash. The stash holds the full body of every Arkime template this script deletes from the cluster, so that is worth closing. The path stays fixed because the shadow and generate passes are separate processes that must share it -- a fresh mkdtemp per process would hand each one its own empty stash and the generate pass would have nothing to restore. The fix is the permissions instead: the parent directory is created 0700 and the file 0600, and neither is widened on rewrite. os.tmpdir() honours TMPDIR and SHADOW_FILE still overrides the location outright. Asserted in tests/docs/test_3343_fix.py so a later change cannot quietly drop the modes back to the mkdir/write defaults.
Conflict resolution follow-up for the rebase onto main. #3391 (the #3283 retention work) landed in composable-templates.js between this branch being cut and the rebase, and it widened the contract generate() has with Elasticsearch: it now installs _ilm/policy/arkime-sessions-30d immediately before the template that names it, verifies index.lifecycle.name through _simulate_index, and adopts the arkime_sessions3-* indices already on disk. The #3343 suite drives the real script against a stub Elasticsearch, so two of its tests failed on the rebase with an AssertionError naming an "unexpected" PUT /_ilm/policy/arkime-sessions-30d. No assertion changed -- the stub is what was stale, and it is what had to learn the new routes. Its _simulate_index answer changes from a canned {"number_of_replicas": "0"} to a composition of the templates the script really PUT, which is what Elasticsearch does and what the script's own post-install verification depends on. That is strictly stronger than what it replaces: the canned reply reported 0 replicas whatever the script installed, so a generated template that dropped number_of_replicas would still have passed. Composed, it fails. Dropping the retention line from build() now fails 18 tests across both suites rather than passing silently. The adoption routes answer with an empty index list, so the #3343 assertions stay about templates and the shadow; the adoption contract itself remains asserted in tests/docs/test_3283_fix.py, which owns it. Refs #3343, #3283
Xore
force-pushed
the
oc/3343-arkime-index-templates
branch
from
September 27, 2026 10:18
4ab43c9 to
7a80c9c
Compare
… ordering Follow-up to 7a80c9c, which taught this stub the routes #3283 added. That commit answered them, but answered _cat/indices with an empty list and _settings with a constant, so the adoption branch was never actually entered from this suite -- the routes were registered and dead. tests/docs/ test_3283_fix.py owns the adoption contract and pins it properly; this change is about the *combined* run, which is what this suite owns. The stub now models the one field the script reads: a name maps to whatever index.lifecycle.name it carries, or None for unmanaged. _stubbed() seeds one unmanaged sessions index, so the functional tests drive the real path, and put_ilm_policies records the body so the ordering can be asserted rather than assumed. New test: the run that restores the catch-all is the same run that installs arkime-sessions-30d and adopts what predates it, and the policy is installed before the template that names it. That ordering is the part that breaks silently -- an index template naming an ILM policy that does not exist yet fails index creation outright, and Elasticsearch validates it at index creation rather than here, so nothing upstream would report it. Non-vacuous, checked by mutating the script and reverting: * moving ensurePolicy after the template PUT fails the new test ("the policy was installed after the template naming it") * deleting the adoption loop fails it ("arkime_sessions3-2026.09.01 was not adopted onto the policy: None") Local: pytest tests/docs/ 521 passed, 1 xfailed (main: 497 passed, same xfail); test_3343 + test_3283 together 46 passed. scripts/tests unchanged from main: the same 2 pre-existing test_compose_drift_watch_sweep failures that fail on a pristine main checkout on this host.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note on issue state
This issue is already closed (as fixed by #3346), so this PR is a judgement call I would like reviewed rather than assumed: the subject of the issue -- Arkime's own index templates never apply -- is still literally true in the deployed stack, because #3346's translation step never ran. The residual
db.plrefusal was also left open in a comment on the issue. Happy to close this if you read the scope differently.The finding
arkime-init'scommand:is a YAML>folded block scalar. A folded scalar joins every run of adjacent non-empty lines with a single space. #3346 put the node invocation directly under its comment with no blank line between, so the whole thing rendered as one line:The invocation is entirely inside the comment.
composable-templates.jshad never once run.Nothing caught it:
bash -naccepts the folded line either way, the YAML reads as correct, and there was no test over the rendering. The other 90 lines of that command fold harmlessly (the shell bodies are more indented, so they stay literal).What this changes
composable-templates.js— ashadowsubcommand, run beforedb.pland restored after. It deletes every composable template covering an Arkime index family, stashing each body first, sodb.plhas nothing to collide with. This is the residual refusal from the issue's comment, implemented as a variant of the option offered there.Coverage is decided by Elasticsearch's
simpleMatchglob semantics, not by name, so a renamed or second catch-all is covered too. Worth noting how the obvious implementation is wrong: testing one invented probe name (arkime_sessions3-shadow-probe) missesarkime_sessions3-2*andarkime_history_v1-?, both of which overlapdb.pl's patterns just as hard as a bare*. The matcher asks whether a pattern can match some index of the family.compose.yml— a bounded three-attempt retry arounddb.pl. This covers the one race a shadow cannot: a template created whiledb.plruns, byelasticsearch-setup's catch-all landing mid-run. It exits non-zero without writing the done marker rather than wedging the deploy, sincearkime-captureandarkime-viewerboth block on it.elasticsearch-setup.sh— the false claim removed. The comment asserted the catch-all "explicitly excluded"arkime_sessions3-*/arkime_history_v1-*. Composable templates have no exclusion syntax, so those entries were literal index names matching nothing. The inert entries are gone and the comment names the mechanism that actually works. The 60s wait is kept -- it is the common case and needs no shadow/restore cycle -- but is no longer load-bearing.Verification
tests/docs/test_3343_fix.py, 22 tests:docker compose config-clean,bash -nandshellcheck --severity=errorclean;dionaea-*,ml-anomalies, ...) survives, stashed bodies come back, the generated templates and the ip-fix fragment are not resurrected, the stash ends empty, and the catch-all is restored even whengenerate()throws;firstPacketdate,nodekeyword,source.ip/destination.iptypedip,number_of_replicas: 0, anddynamic_templatesin the order*Ip, *Tokens, strings_as_keyword-- reversed, every IP is a keyword again.python -m pytest tests/docs/ -v→ 469 passed, 1 xfailed. Againstmainthe same file fails 15 of them, including the headline fold test.Not done here
arkime-capturerunsdb.pl upgradenoprompt --ifneededafter the marker. That is a template update with unchanged patterns, which Elasticsearch only warns about, so it is not the create-path failure above -- but it is not shadowed either, and a future Arkime bump that changes a legacy pattern would surface there.Refs #3343