|
6 | 6 |
|
7 | 7 | export PATH="/opt/netbox/venv/bin:$PATH" |
8 | 8 | export DEBUG="${DEBUG:-True}" |
9 | | -PLUGIN_DIR="/workspaces/netbox-InterfaceNameRules-plugin" |
| 9 | +PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" |
10 | 10 |
|
11 | | -netbox-run-bg() { |
12 | | - "$PLUGIN_DIR/.devcontainer/scripts/start-netbox.sh" --background |
13 | | -} |
| 11 | +# Unset CA bundle vars when empty (Compose/devcontainer inject "" when the |
| 12 | +# host var is unset, which breaks requests/curl). |
| 13 | +for _ca_var in REQUESTS_CA_BUNDLE SSL_CERT_FILE CURL_CA_BUNDLE; do |
| 14 | + if [ -z "${!_ca_var}" ]; then |
| 15 | + unset "$_ca_var" |
| 16 | + fi |
| 17 | +done |
| 18 | +unset _ca_var |
14 | 19 |
|
15 | | -netbox-run() { |
16 | | - "$PLUGIN_DIR/.devcontainer/scripts/start-netbox.sh" |
17 | | -} |
| 20 | +# Load shared process management helpers |
| 21 | +if ! source "$PLUGIN_DIR/.devcontainer/scripts/process-helpers.sh"; then |
| 22 | + printf '%s\n' "Failed to load process-helpers.sh" >&2 |
| 23 | + return 1 |
| 24 | +fi |
| 25 | + |
| 26 | +netbox-run-bg() { "$PLUGIN_DIR/.devcontainer/scripts/start-netbox.sh" --background; } |
| 27 | +netbox-run() { "$PLUGIN_DIR/.devcontainer/scripts/start-netbox.sh"; } |
18 | 28 |
|
| 29 | +# Robust stop command that kills both tracked and orphaned processes |
19 | 30 | netbox-stop() { |
20 | | - echo "🛑 Stopping NetBox..." |
| 31 | + echo "🛑 Stopping NetBox and RQ workers..." |
21 | 32 | if [ -f /tmp/netbox.pid ]; then |
22 | | - local pid |
23 | | - pid=$(cat /tmp/netbox.pid 2>/dev/null) |
24 | | - if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then |
25 | | - kill "$pid" 2>/dev/null || kill -9 "$pid" 2>/dev/null |
26 | | - echo " Stopped NetBox (PID: $pid)" |
| 33 | + local PID |
| 34 | + PID=$(cat /tmp/netbox.pid 2>/dev/null) |
| 35 | + if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then |
| 36 | + graceful_kill_pid "$PID" |
| 37 | + echo " Stopped NetBox (PID: $PID)" |
27 | 38 | fi |
28 | 39 | rm -f /tmp/netbox.pid |
29 | 40 | fi |
| 41 | + if [ -f /tmp/rqworker.pid ]; then |
| 42 | + local PID |
| 43 | + PID=$(cat /tmp/rqworker.pid 2>/dev/null) |
| 44 | + if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then |
| 45 | + graceful_kill_pid "$PID" |
| 46 | + echo " Stopped RQ worker (PID: $PID)" |
| 47 | + fi |
| 48 | + rm -f /tmp/rqworker.pid |
| 49 | + fi |
| 50 | + if pgrep -f "python.*rqworker" >/dev/null 2>&1; then |
| 51 | + local ORPHAN_COUNT |
| 52 | + ORPHAN_COUNT=$(pgrep -cf "python.*rqworker" 2>/dev/null || echo 0) |
| 53 | + graceful_kill_pattern "python.*rqworker" |
| 54 | + echo " Killed $ORPHAN_COUNT orphaned RQ worker(s)" |
| 55 | + fi |
30 | 56 | if pgrep -f "python.*runserver.*8000" >/dev/null 2>&1; then |
31 | | - pkill -9 -f "python.*runserver.*8000" 2>/dev/null |
| 57 | + graceful_kill_pattern "python.*runserver.*8000" |
32 | 58 | echo " Killed orphaned NetBox server(s)" |
33 | 59 | fi |
34 | 60 | echo "✅ All processes stopped" |
35 | 61 | } |
36 | 62 |
|
37 | 63 | netbox-restart() { |
38 | | - netbox-stop |
39 | | - sleep 1 |
40 | | - netbox-run-bg |
| 64 | + netbox-stop && sleep 1 && netbox-run-bg |
41 | 65 | } |
42 | 66 |
|
43 | 67 | netbox-reload() { |
44 | | - cd "$PLUGIN_DIR" && uv pip install -e . && netbox-restart |
| 68 | + cd "$PLUGIN_DIR" || return 1 |
| 69 | + if command -v uv >/dev/null 2>&1; then |
| 70 | + uv pip install -e . || return 1 |
| 71 | + else |
| 72 | + pip install -e . || return 1 |
| 73 | + fi |
| 74 | + netbox-restart |
45 | 75 | } |
46 | 76 |
|
47 | | -netbox-logs() { |
48 | | - tail -f /tmp/netbox.log |
49 | | -} |
| 77 | +alias netbox-logs="tail -f /tmp/netbox.log" |
| 78 | +alias rq-logs="tail -f /tmp/rqworker.log" |
50 | 79 |
|
51 | 80 | netbox-status() { |
52 | | - if [ -f /tmp/netbox.pid ] && kill -0 "$(cat /tmp/netbox.pid)" 2>/dev/null; then |
53 | | - echo "NetBox is running (PID: $(cat /tmp/netbox.pid))" |
| 81 | + local PID |
| 82 | + if [ -f /tmp/netbox.pid ]; then |
| 83 | + PID=$(cat /tmp/netbox.pid 2>/dev/null) |
| 84 | + if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then |
| 85 | + echo "NetBox is running (PID: $PID)" |
| 86 | + else |
| 87 | + echo "NetBox is not running" |
| 88 | + fi |
54 | 89 | else |
55 | 90 | echo "NetBox is not running" |
56 | 91 | fi |
| 92 | + if [ -f /tmp/rqworker.pid ]; then |
| 93 | + PID=$(cat /tmp/rqworker.pid 2>/dev/null) |
| 94 | + if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then |
| 95 | + echo "RQ worker is running (PID: $PID)" |
| 96 | + else |
| 97 | + echo "RQ worker is not running" |
| 98 | + fi |
| 99 | + else |
| 100 | + echo "RQ worker is not running" |
| 101 | + fi |
| 102 | +} |
| 103 | + |
| 104 | +rq-status() { |
| 105 | + local PID |
| 106 | + if [ -f /tmp/rqworker.pid ]; then |
| 107 | + PID=$(cat /tmp/rqworker.pid 2>/dev/null) |
| 108 | + if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then |
| 109 | + echo "RQ worker is running (PID: $PID)" |
| 110 | + else |
| 111 | + echo "RQ worker is not running" |
| 112 | + fi |
| 113 | + else |
| 114 | + echo "RQ worker is not running" |
| 115 | + fi |
57 | 116 | } |
58 | 117 |
|
59 | 118 | netbox-shell() { |
60 | | - (cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell) |
| 119 | + cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell |
61 | 120 | } |
62 | 121 |
|
63 | 122 | netbox-test() { |
64 | | - (cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py test netbox_interface_name_rules "$@") |
| 123 | + cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py test netbox_interface_name_rules "$@" |
65 | 124 | } |
66 | 125 |
|
67 | 126 | netbox-manage() { |
68 | | - (cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py "$@") |
| 127 | + cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py "$@" |
69 | 128 | } |
70 | 129 |
|
71 | 130 | plugin-install() { |
72 | | - (cd "$PLUGIN_DIR" && uv pip install -e .) |
| 131 | + cd "$PLUGIN_DIR" || return 1 |
| 132 | + if command -v uv >/dev/null 2>&1; then |
| 133 | + uv pip install -e . |
| 134 | + else |
| 135 | + pip install -e . |
| 136 | + fi |
73 | 137 | } |
74 | 138 |
|
75 | | -ruff-check() { |
76 | | - (cd "$PLUGIN_DIR" && ruff check .) |
| 139 | +plugins-install() { |
| 140 | + if [ -f "$PLUGIN_DIR/.devcontainer/extra-requirements.txt" ]; then |
| 141 | + source /opt/netbox/venv/bin/activate |
| 142 | + if command -v uv >/dev/null 2>&1; then |
| 143 | + uv pip install -r "$PLUGIN_DIR/.devcontainer/extra-requirements.txt" |
| 144 | + else |
| 145 | + pip install -r "$PLUGIN_DIR/.devcontainer/extra-requirements.txt" |
| 146 | + fi |
| 147 | + else |
| 148 | + echo "No .devcontainer/extra-requirements.txt found" |
| 149 | + fi |
77 | 150 | } |
78 | 151 |
|
79 | | -ruff-format() { |
80 | | - (cd "$PLUGIN_DIR" && ruff format .) |
| 152 | +ruff-check() { cd "$PLUGIN_DIR" && command ruff check .; } |
| 153 | +ruff-format() { cd "$PLUGIN_DIR" && command ruff format .; } |
| 154 | +ruff-fix() { cd "$PLUGIN_DIR" && command ruff check --fix .; } |
| 155 | + |
| 156 | +diagnose() { "$PLUGIN_DIR/.devcontainer/scripts/diagnose.sh"; } |
| 157 | + |
| 158 | +# RQ job inspection commands |
| 159 | +rq-stats() { |
| 160 | + cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py rqstats |
81 | 161 | } |
82 | 162 |
|
83 | | -ruff-fix() { |
84 | | - (cd "$PLUGIN_DIR" && ruff check --fix .) |
| 163 | +rq-jobs() { |
| 164 | + cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \ |
| 165 | + "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]]" |
85 | 166 | } |
86 | 167 |
|
87 | | -diagnose() { |
88 | | - "$PLUGIN_DIR/.devcontainer/scripts/diagnose.sh" |
| 168 | +rq-failed() { |
| 169 | + cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \ |
| 170 | + "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]]" |
89 | 171 | } |
90 | 172 |
|
| 173 | +rq-recent() { |
| 174 | + cd /opt/netbox/netbox && source /opt/netbox/venv/bin/activate && python manage.py shell -c \ |
| 175 | + "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]" |
| 176 | +} |
| 177 | + |
| 178 | +# Help |
91 | 179 | dev-help() { |
92 | 180 | echo "🎯 NetBox Interface Name Rules Plugin Development Commands:" |
93 | 181 | echo "" |
94 | 182 | echo "📊 NetBox Server Management:" |
95 | | - echo " netbox-run-bg Start NetBox in background" |
96 | | - echo " netbox-run Start NetBox in foreground" |
97 | | - echo " netbox-stop Stop NetBox" |
98 | | - echo " netbox-restart Restart NetBox" |
99 | | - echo " netbox-reload Reinstall plugin and restart" |
100 | | - echo " netbox-status Check if NetBox is running" |
101 | | - echo " netbox-logs View NetBox server logs" |
| 183 | + echo " netbox-run-bg : Start NetBox in background" |
| 184 | + echo " netbox-run : Start NetBox in foreground (for debugging)" |
| 185 | + echo " netbox-stop : Stop NetBox and RQ worker" |
| 186 | + echo " netbox-restart : Restart NetBox and RQ worker" |
| 187 | + echo " netbox-reload : Reinstall plugin and restart NetBox" |
| 188 | + echo " netbox-status : Check if NetBox and RQ worker are running" |
| 189 | + echo " netbox-logs : View NetBox server logs" |
| 190 | + echo "" |
| 191 | + echo "⚙️ Background Jobs (RQ Worker):" |
| 192 | + echo " rq-status : Check if RQ worker is running" |
| 193 | + echo " rq-logs : View RQ worker logs" |
| 194 | + echo " rq-stats : Show RQ queue statistics" |
| 195 | + echo " rq-jobs : List jobs in default queue" |
| 196 | + echo " rq-failed : List failed jobs" |
| 197 | + echo " rq-recent : Show recent NetBox jobs" |
102 | 198 | echo "" |
103 | 199 | echo "🛠️ Development Tools:" |
104 | | - echo " netbox-shell Open NetBox Django shell" |
105 | | - echo " netbox-test Run plugin tests" |
106 | | - echo " netbox-manage CMD Run Django management commands" |
107 | | - echo " plugin-install Reinstall plugin in dev mode" |
| 200 | + echo " netbox-shell : Open NetBox Django shell" |
| 201 | + echo " netbox-test : Run plugin tests" |
| 202 | + echo " netbox-manage : Run Django management commands" |
| 203 | + echo " plugin-install : Reinstall plugin in development mode" |
108 | 204 | echo "" |
109 | 205 | echo "🧹 Code Quality:" |
110 | | - echo " ruff-check Check code with Ruff" |
111 | | - echo " ruff-format Format code with Ruff" |
112 | | - echo " ruff-fix Auto-fix code issues" |
| 206 | + echo " ruff-check : Check code with Ruff" |
| 207 | + echo " ruff-format : Format code with Ruff" |
| 208 | + echo " ruff-fix : Auto-fix code issues with Ruff" |
113 | 209 | echo "" |
114 | 210 | echo "🔎 Diagnostics:" |
115 | | - echo " diagnose Run startup diagnostics" |
116 | | - echo " dev-help Show this help message" |
| 211 | + echo " diagnose : Run startup diagnostics" |
| 212 | + echo " dev-help : Show this help message" |
117 | 213 | echo "" |
118 | | - echo "📖 NetBox at: http://localhost:8000 (admin/admin)" |
| 214 | + echo "📖 NetBox available at: http://localhost:8000 (${SUPERUSER_NAME:-admin}/${SUPERUSER_PASSWORD:-admin})" |
119 | 215 | } |
120 | 216 |
|
121 | | -echo "✅ Functions loaded! Type 'dev-help' for available commands." |
| 217 | +echo "✅ Dev helpers loaded! Try: rq-status, rq-stats, rq-recent, dev-help" |
0 commit comments