forked from bonzo81/netbox-librenms-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
Refactor/import utils package #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
63 commits
Select commit
Hold shift + click to select a range
64ede34
feat: serial number matching and device conflict resolution
marcinpsk 9439ce8
Merge origin/develop into feat/serial-matching-and-conflict-resolution
marcinpsk 603bbf1
feat: devcontainer proxy/codespaces support, auto-create librenms_id …
marcinpsk 7c5f5bc
Update devcontainer.json
marcinpsk 6023a08
feat: serial number matching, conflict resolution, and device sync im…
marcinpsk b3e0550
feat: devcontainer proxy/codespaces support, auto-create librenms_id …
marcinpsk 6595502
Update devcontainer.json
marcinpsk 2272ef6
fix: address code review findings across views, templates, and forms
marcinpsk dffd573
fix: cables tab ignoring interface_name_field user preference
marcinpsk 3b3acba
feat: add Modules tab to LibreNMS Sync page
marcinpsk e198de1
feat: add Install Module button and fix countdown timer
marcinpsk d07ce9c
feat: show sub-components and fix install redirect
marcinpsk d090560
Add DeviceTypeMapping model with full CRUD stack
marcinpsk a181d84
Add ModuleTypeMapping model, fix ordering, add contrib examples
marcinpsk 7c50f2d
Add ModuleBayMapping model with CRUD stack, replace bay matching heur…
marcinpsk 816b9a0
Add chassis inventory fallback for device type matching
marcinpsk 2c7d899
Add {module_path} compatibility guard for module installation
marcinpsk 56b1e4f
Add nested module branch installation and fix URL naming
marcinpsk 4175af7
Add transceiver API integration for modules tab
marcinpsk 8a3e6ec
Add Nokia vendor support and improve module bay matching
marcinpsk 7895ec7
Scope module bay matching to parent module and fix install scroll
marcinpsk 22ee52a
Update Nokia contrib mappings for corrected module types
marcinpsk 3193210
Fix nested module bay matching and expression template evaluation
marcinpsk 0ab6981
Add NormalizationRule: generic regex-based string normalization for m…
marcinpsk a47e8f8
Add manufacturer scope to NormalizationRule, transceiver mappings
marcinpsk 739ea19
Add UfiSpace device type mappings to contrib examples
marcinpsk 6133452
Fix device import validation: always set 'found' key on device_type r…
marcinpsk f4c880a
Fix Arcos inventory display and X2 slot resolution
marcinpsk 49224f3
Fix duplicate items and ancestor chain check in module sync
marcinpsk 5ed1e63
Fix Actions column layout: nowrap + shorter Branch button text
marcinpsk 87a532a
Add description-based bay matching and device_type scope for install …
marcinpsk f64e050
Add Juniper, Arcos, and Finisar mappings to contrib YAML
marcinpsk 1ec2930
Add regex bay mappings, bulk selection, collapsible help, module_path…
marcinpsk 48050d4
Add bulk module install, breakout interface rules, and description ma…
marcinpsk 8237a41
refactor: remove redundant post-install interface renaming logic
marcinpsk 2aa523c
refactor: remove NormalizationRule, add InterfaceNameRule, clean up m…
marcinpsk 16f89e7
refactor: remove InterfaceNameRule (moved to separate plugin), keep i…
marcinpsk b8ff5bf
Fix import cache staleness and module bay matching
marcinpsk 4bf6346
Fix child bay scoping and branch install error handling
marcinpsk 2f54930
Add e2e Playwright tests for module install workflow
marcinpsk 7b99189
Add name conflict detection for nested modules using {module} token
marcinpsk 5b88922
feat: detect {module_path} support via import instead of version string
marcinpsk 49fb5af
feat: include port class in module sync inventory
marcinpsk edee517
feat: add Ciena 180-3530-900 to module type mappings
marcinpsk daa2e4e
fix: walk ancestor chain to filter nested port items
marcinpsk 4d4243b
feat: add container class support and dedup transceiver entries
marcinpsk ee0e0d9
feat: expand module mappings for Juniper and multi-vendor SFPs
marcinpsk 7a0634b
feat: use ifName for synthetic transceiver naming and add Nokia mappings
marcinpsk b7dfd97
fix: skip empty-model containers in ENTITY-MIB hierarchy
marcinpsk 72c5d4a
feat: restore NormalizationRule CRUD stack and integrate into module …
marcinpsk b41d4c5
feat: Juniper MX SFP bay matching + vendor module types
marcinpsk f9110a6
Fix duplicate interface error and cross-FPC bay mismatch
marcinpsk e1381e2
refactor: address PR review feedback for user preferences
marcinpsk 75628bf
fix: removed BulkInstallModulesView - unused
marcinpsk a676d6e
fix: ruff
marcinpsk b466553
Code review fixes: bugs, cleanup, and hardening
marcinpsk 4b2533e
fix: devcontainer script hardening and cleanup
marcinpsk 1fbc4f9
Code review fixes: safety, scoping, and cleanup (round 2)
marcinpsk bf3ad64
fix: gate MAC sync on exclude_columns
marcinpsk f09628c
fix: correct plugin-config.py path in diagnose.sh
marcinpsk 12860a2
refactor: split import_utils.py into a package
marcinpsk 04e4cc3
fix: update mock.patch paths for import_utils package refactor
marcinpsk 27ed0a6
refactor: remove redundant inline Cluster import in device_operations
marcinpsk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,67 +1,225 @@ | ||
| #!/bin/bash | ||
| # netbox-librenms-plugin devcontainer script | ||
| # Quick alias loader for current session | ||
| # Usage: source .devcontainer/scripts/load-aliases.sh | ||
|
|
||
| export PATH="/opt/netbox/venv/bin:$PATH" | ||
| export DEBUG="${DEBUG:-True}" | ||
| PLUGIN_DIR="/workspaces/netbox-librenms-plugin" | ||
| PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" | ||
|
|
||
| alias netbox-run-bg="$PLUGIN_DIR/.devcontainer/scripts/start-netbox.sh --background" | ||
| alias netbox-run="$PLUGIN_DIR/.devcontainer/scripts/start-netbox.sh" | ||
| # Clean up empty CA bundle vars (Compose/devcontainer inject "" when host var is | ||
| # unset, which breaks requests/curl). When setup.sh has installed custom CAs | ||
| # into the system trust store, point to it instead. | ||
| for _ca_var in REQUESTS_CA_BUNDLE SSL_CERT_FILE CURL_CA_BUNDLE; do | ||
| _val="${!_ca_var}" | ||
| if [ -z "$_val" ]; then | ||
| if [ -f /etc/ssl/certs/ca-certificates.crt ]; then | ||
| declare -x "$_ca_var=/etc/ssl/certs/ca-certificates.crt" | ||
| else | ||
| unset "$_ca_var" | ||
| fi | ||
| fi | ||
| done | ||
| unset _ca_var _val | ||
|
|
||
| # Load shared process management helpers | ||
| if ! source "$PLUGIN_DIR/.devcontainer/scripts/process-helpers.sh"; then | ||
| printf '%s\n' "Failed to load process-helpers.sh" >&2 | ||
| return 1 | ||
| fi | ||
|
|
||
| netbox-run-bg() { "$PLUGIN_DIR/.devcontainer/scripts/start-netbox.sh" --background; } | ||
| netbox-run() { "$PLUGIN_DIR/.devcontainer/scripts/start-netbox.sh"; } | ||
|
|
||
| # Robust stop command that kills both tracked and orphaned processes | ||
| alias netbox-stop='echo "🛑 Stopping NetBox and RQ workers..."; \ | ||
| if [ -f /tmp/netbox.pid ]; then \ | ||
| PID=$(cat /tmp/netbox.pid 2>/dev/null); \ | ||
| if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then \ | ||
| kill "$PID" 2>/dev/null || kill -9 "$PID" 2>/dev/null; \ | ||
| echo " Stopped NetBox (PID: $PID)"; \ | ||
| fi; \ | ||
| rm -f /tmp/netbox.pid; \ | ||
| fi; \ | ||
| if [ -f /tmp/rqworker.pid ]; then \ | ||
| PID=$(cat /tmp/rqworker.pid 2>/dev/null); \ | ||
| if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then \ | ||
| kill "$PID" 2>/dev/null || kill -9 "$PID" 2>/dev/null; \ | ||
| echo " Stopped RQ worker (PID: $PID)"; \ | ||
| fi; \ | ||
| rm -f /tmp/rqworker.pid; \ | ||
| fi; \ | ||
| if pgrep -f "python.*rqworker" >/dev/null 2>&1; then \ | ||
| ORPHAN_COUNT=$(pgrep -cf "python.*rqworker" 2>/dev/null || echo 0); \ | ||
| pkill -9 -f "python.*rqworker" 2>/dev/null; \ | ||
| echo " Killed $ORPHAN_COUNT orphaned RQ worker(s)"; \ | ||
| fi; \ | ||
| if pgrep -f "python.*runserver.*8000" >/dev/null 2>&1; then \ | ||
| pkill -9 -f "python.*runserver.*8000" 2>/dev/null; \ | ||
| echo " Killed orphaned NetBox server(s)"; \ | ||
| fi; \ | ||
| echo "✅ All processes stopped"' | ||
|
|
||
| alias netbox-restart="netbox-stop && sleep 1 && netbox-run-bg" | ||
| alias netbox-reload="cd $PLUGIN_DIR && (command -v uv >/dev/null 2>&1 && uv pip install -e . || pip install -e .) && netbox-restart" | ||
| netbox-stop() { | ||
| echo "🛑 Stopping NetBox and RQ workers..." | ||
| if [ -f /tmp/netbox.pid ]; then | ||
| local PID | ||
| PID=$(cat /tmp/netbox.pid 2>/dev/null) | ||
| if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then | ||
| if is_expected_pid "$PID" "python.*runserver.*8000"; then | ||
| graceful_kill_pid "$PID" | ||
| echo " Stopped NetBox (PID: $PID)" | ||
| else | ||
| echo " Skipping stale /tmp/netbox.pid (PID $PID is not NetBox runserver)" | ||
| fi | ||
| fi | ||
| rm -f /tmp/netbox.pid | ||
| fi | ||
| if [ -f /tmp/rqworker.pid ]; then | ||
| local PID | ||
| PID=$(cat /tmp/rqworker.pid 2>/dev/null) | ||
| if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then | ||
| if is_expected_pid "$PID" "python.*rqworker"; then | ||
| graceful_kill_pid "$PID" | ||
| echo " Stopped RQ worker (PID: $PID)" | ||
| else | ||
| echo " Skipping stale /tmp/rqworker.pid (PID $PID is not rqworker)" | ||
| fi | ||
| fi | ||
| rm -f /tmp/rqworker.pid | ||
| fi | ||
| if pgrep -f "python.*rqworker" >/dev/null 2>&1; then | ||
| local ORPHAN_COUNT | ||
| ORPHAN_COUNT=$(pgrep -cf "python.*rqworker" 2>/dev/null || echo 0) | ||
| graceful_kill_pattern "python.*rqworker" | ||
| echo " Killed $ORPHAN_COUNT orphaned RQ worker(s)" | ||
| fi | ||
| if pgrep -f "python.*runserver.*8000" >/dev/null 2>&1; then | ||
| graceful_kill_pattern "python.*runserver.*8000" | ||
| echo " Killed orphaned NetBox server(s)" | ||
| fi | ||
| echo "✅ All processes stopped" | ||
| } | ||
|
|
||
| netbox-restart() { | ||
| netbox-stop && sleep 1 && netbox-run-bg | ||
| } | ||
|
|
||
| netbox-reload() { | ||
| cd "$PLUGIN_DIR" || return 1 | ||
| if command -v uv >/dev/null 2>&1; then | ||
| uv pip install -e . || return 1 | ||
| else | ||
| pip install -e . || return 1 | ||
| fi | ||
| netbox-restart | ||
| } | ||
|
|
||
| alias netbox-logs="tail -f /tmp/netbox.log" | ||
| alias netbox-status="[ -f /tmp/netbox.pid ] && kill -0 \$(cat /tmp/netbox.pid) 2>/dev/null && echo 'NetBox is running (PID: '\$(cat /tmp/netbox.pid)')' || echo 'NetBox is not running'; [ -f /tmp/rqworker.pid ] && kill -0 \$(cat /tmp/rqworker.pid) 2>/dev/null && echo 'RQ worker is running (PID: '\$(cat /tmp/rqworker.pid)')' || echo 'RQ worker is not running'" | ||
| alias rq-logs="tail -f /tmp/rqworker.log" | ||
| alias rq-status="[ -f /tmp/rqworker.pid ] && kill -0 \$(cat /tmp/rqworker.pid) 2>/dev/null && echo 'RQ worker is running (PID: '\$(cat /tmp/rqworker.pid)')' || echo 'RQ worker is not running'" | ||
| alias netbox-shell="cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell" | ||
| alias netbox-test="cd $PLUGIN_DIR && source /opt/netbox/venv/bin/activate && python -m pytest" | ||
| alias netbox-manage="cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py" | ||
| alias plugin-install="cd $PLUGIN_DIR && (command -v uv >/dev/null 2>&1 && uv pip install -e . || pip install -e .)" | ||
| alias ruff-check="cd $PLUGIN_DIR && ruff check ." | ||
| alias ruff-format="cd $PLUGIN_DIR && ruff format ." | ||
| alias ruff-fix="cd $PLUGIN_DIR && ruff check --fix ." | ||
| alias diagnose="$PLUGIN_DIR/.devcontainer/scripts/diagnose.sh" | ||
| alias plugins-install='if [ -f "$PLUGIN_DIR/.devcontainer/extra-requirements.txt" ]; then source /opt/netbox/venv/bin/activate && pip install -r "$PLUGIN_DIR/.devcontainer/extra-requirements.txt"; else echo "No .devcontainer/extra-requirements.txt found"; fi' | ||
|
|
||
| netbox-status() { | ||
| local PID | ||
| if [ -f /tmp/netbox.pid ]; then | ||
| PID=$(cat /tmp/netbox.pid 2>/dev/null) | ||
| if [ -n "$PID" ] && is_expected_pid "$PID" "python.*runserver.*8000"; then | ||
| echo "NetBox is running (PID: $PID)" | ||
| else | ||
| echo "NetBox is not running" | ||
| fi | ||
| else | ||
| echo "NetBox is not running" | ||
| fi | ||
| if [ -f /tmp/rqworker.pid ]; then | ||
| PID=$(cat /tmp/rqworker.pid 2>/dev/null) | ||
| if [ -n "$PID" ] && is_expected_pid "$PID" "python.*rqworker"; then | ||
| echo "RQ worker is running (PID: $PID)" | ||
| else | ||
| echo "RQ worker is not running" | ||
| fi | ||
| else | ||
| echo "RQ worker is not running" | ||
| fi | ||
| } | ||
|
|
||
| rq-status() { | ||
| local PID | ||
| if [ -f /tmp/rqworker.pid ]; then | ||
| PID=$(cat /tmp/rqworker.pid 2>/dev/null) | ||
| if [ -n "$PID" ] && is_expected_pid "$PID" "python.*rqworker"; then | ||
| echo "RQ worker is running (PID: $PID)" | ||
| else | ||
| echo "RQ worker is not running" | ||
| fi | ||
| else | ||
| echo "RQ worker is not running" | ||
| fi | ||
| } | ||
|
|
||
| netbox-shell() { | ||
| cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell | ||
| } | ||
|
|
||
| netbox-test() { | ||
| cd "$PLUGIN_DIR" && source /opt/netbox/venv/bin/activate && python -m pytest "$@" | ||
| } | ||
|
|
||
| netbox-manage() { | ||
| cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py "$@" | ||
| } | ||
|
|
||
| plugin-install() { | ||
| cd "$PLUGIN_DIR" || return 1 | ||
| if command -v uv >/dev/null 2>&1; then | ||
| uv pip install -e . | ||
| else | ||
| pip install -e . | ||
| fi | ||
| } | ||
|
|
||
| plugins-install() { | ||
| if [ -f "$PLUGIN_DIR/.devcontainer/extra-requirements.txt" ]; then | ||
| source /opt/netbox/venv/bin/activate && pip install -r "$PLUGIN_DIR/.devcontainer/extra-requirements.txt" | ||
| else | ||
| echo "No .devcontainer/extra-requirements.txt found" | ||
| fi | ||
| } | ||
|
|
||
| ruff-check() { cd "$PLUGIN_DIR" && command ruff check .; } | ||
| ruff-format() { cd "$PLUGIN_DIR" && command ruff format .; } | ||
| ruff-fix() { cd "$PLUGIN_DIR" && command ruff check --fix .; } | ||
|
|
||
| diagnose() { "$PLUGIN_DIR/.devcontainer/scripts/diagnose.sh"; } | ||
|
|
||
| # RQ job inspection commands | ||
| alias rq-stats="cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py rqstats" | ||
| alias rq-jobs="cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \"from django_rq import get_queue; q = get_queue('default'); print(f'Jobs in queue: {len(q)}'); [print(f' {job.id[:8]}: {job.func_name} - {job.get_status()}') for job in q.jobs[:10]]\"" | ||
| alias rq-failed="cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \"from django_rq import get_failed_queue; q = get_failed_queue(); print(f'Failed jobs: {len(q)}'); [print(f' {job.id[:8]}: {job.func_name}') for job in q.jobs[:10]]\"" | ||
| alias rq-recent="cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \"from core.models import Job; jobs = Job.objects.all().order_by('-created')[:10]; [print(f'{j.id}: {j.name[:50]} - {getattr(j.status, \\\"value\\\", j.status)} ({j.user})') for j in jobs]\"" | ||
| rq-stats() { | ||
| cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py rqstats | ||
| } | ||
|
|
||
| rq-jobs() { | ||
| cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \ | ||
| "from django_rq import get_queue; q = get_queue('default'); print(f'Jobs in queue: {len(q)}'); [print(f' {job.id[:8]}: {job.func_name} - {job.get_status()}') for job in q.jobs[:10]]" | ||
| } | ||
|
|
||
| rq-failed() { | ||
| cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \ | ||
| "from django_rq import get_failed_queue; q = get_failed_queue(); print(f'Failed jobs: {len(q)}'); [print(f' {job.id[:8]}: {job.func_name}') for job in q.jobs[:10]]" | ||
| } | ||
|
|
||
| rq-recent() { | ||
| cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \ | ||
| "from core.models import Job; jobs = Job.objects.all().order_by('-created')[:10]; [print(f'{j.id}: {j.name[:50]} - {getattr(j.status, \"value\", j.status)} ({j.user})') for j in jobs]" | ||
| } | ||
|
|
||
| # Help | ||
| alias dev-help='echo "🎯 NetBox LibreNMS Plugin Development Commands:"; echo ""; echo "📊 NetBox Server Management:"; echo " netbox-run-bg : Start NetBox in background"; echo " netbox-run : Start NetBox in foreground (for debugging)"; echo " netbox-stop : Stop NetBox and RQ worker"; echo " netbox-restart : Restart NetBox and RQ worker"; echo " netbox-reload : Reinstall plugin and restart NetBox"; echo " netbox-status : Check if NetBox and RQ worker are running"; echo " netbox-logs : View NetBox server logs"; echo ""; echo "⚙️ Background Jobs (RQ Worker):"; echo " rq-status : Check if RQ worker is running"; echo " rq-logs : View RQ worker logs"; echo " rq-stats : Show RQ queue statistics"; echo " rq-jobs : List jobs in default queue"; echo " rq-failed : List failed jobs"; echo " rq-recent : Show recent NetBox jobs"; echo ""; echo "🛠️ Development Tools:"; echo " netbox-shell : Open NetBox Django shell"; echo " netbox-test : Run plugin tests"; echo " netbox-manage : Run Django management commands"; echo " plugin-install : Reinstall plugin in development mode"; echo ""; echo "🧹 Code Quality:"; echo " ruff-check : Check code with Ruff"; echo " ruff-format : Format code with Ruff"; echo " ruff-fix : Auto-fix code issues with Ruff"; echo ""; echo "🔎 Diagnostics:"; echo " diagnose : Run startup diagnostics"; echo " dev-help : Show this help message"; echo ""; echo "📖 NetBox available at: http://localhost:8000 (admin/admin)"; echo ""' | ||
| dev-help() { | ||
| echo "🎯 NetBox LibreNMS Plugin Development Commands:" | ||
| echo "" | ||
| echo "📊 NetBox Server Management:" | ||
| echo " netbox-run-bg : Start NetBox in background" | ||
| echo " netbox-run : Start NetBox in foreground (for debugging)" | ||
| echo " netbox-stop : Stop NetBox and RQ worker" | ||
| echo " netbox-restart : Restart NetBox and RQ worker" | ||
| echo " netbox-reload : Reinstall plugin and restart NetBox" | ||
| echo " netbox-status : Check if NetBox and RQ worker are running" | ||
| echo " netbox-logs : View NetBox server logs" | ||
| echo "" | ||
| echo "⚙️ Background Jobs (RQ Worker):" | ||
| echo " rq-status : Check if RQ worker is running" | ||
| echo " rq-logs : View RQ worker logs" | ||
| echo " rq-stats : Show RQ queue statistics" | ||
| echo " rq-jobs : List jobs in default queue" | ||
| echo " rq-failed : List failed jobs" | ||
| echo " rq-recent : Show recent NetBox jobs" | ||
| echo "" | ||
| echo "🛠️ Development Tools:" | ||
| echo " netbox-shell : Open NetBox Django shell" | ||
| echo " netbox-test : Run plugin tests" | ||
| echo " netbox-manage : Run Django management commands" | ||
| echo " plugin-install : Reinstall plugin in development mode" | ||
| echo "" | ||
| echo "🧹 Code Quality:" | ||
| echo " ruff-check : Check code with Ruff" | ||
| echo " ruff-format : Format code with Ruff" | ||
| echo " ruff-fix : Auto-fix code issues with Ruff" | ||
| echo "" | ||
| echo "🔎 Diagnostics:" | ||
| echo " diagnose : Run startup diagnostics" | ||
| echo " dev-help : Show this help message" | ||
| echo "" | ||
| echo "📖 NetBox available at: http://localhost:8000 (admin/admin)" | ||
| } | ||
|
|
||
| echo "✅ Aliases loaded! Try: rq-status, rq-stats, rq-recent, dev-help" |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #!/bin/bash | ||
| # Shared process management helpers. | ||
| # Sourced by load-aliases.sh and start-netbox.sh. | ||
|
|
||
| # Graceful termination: SIGTERM, wait, then SIGKILL if still alive. | ||
| graceful_kill_pid() { | ||
| local pid="$1" | ||
| kill -15 "$pid" 2>/dev/null | ||
| sleep 2 | ||
| kill -0 "$pid" 2>/dev/null && kill -9 "$pid" 2>/dev/null | ||
| } | ||
|
|
||
| graceful_kill_pattern() { | ||
| local pattern="$1" | ||
| pkill -15 -f "$pattern" 2>/dev/null | ||
| sleep 2 | ||
| pgrep -f "$pattern" >/dev/null 2>&1 && pkill -9 -f "$pattern" 2>/dev/null | ||
| } | ||
|
|
||
| # Verify a PID matches the expected process before killing it | ||
| is_expected_pid() { | ||
| local pid="$1" pattern="$2" | ||
| ps -p "$pid" -o args= 2>/dev/null | grep -Eq "$pattern" | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider returning an exit status for callers that need it.
Currently
graceful_kill_piddoesn't indicate success/failure. While not critical for current usage, a return value could be useful for future callers that need to know if the process was successfully terminated.♻️ Optional: Add return status
graceful_kill_pid() { local pid="$1" kill -15 "$pid" 2>/dev/null sleep 2 - kill -0 "$pid" 2>/dev/null && kill -9 "$pid" 2>/dev/null + if kill -0 "$pid" 2>/dev/null; then + kill -9 "$pid" 2>/dev/null + fi + ! kill -0 "$pid" 2>/dev/null # return 0 if process is gone }📝 Committable suggestion
🤖 Prompt for AI Agents