CLI script invocation is broken in NetBox 4.3.1 #11195

Closed
opened 2025-12-29 21:41:46 +01:00 by adam · 7 comments
Owner

Originally created by @peteeckel on GitHub (May 18, 2025).

Originally assigned to: @arthanson, @jnovinger on GitHub.

Deployment Type

Self-hosted

NetBox Version

v4.3.1

Python Version

3.11

Steps to Reproduce

  1. Set SCRIPTS_ROOT = '/opt/netbox/netbox/scripts' in configuration.py
  2. Create a custom script and save it as dummy.py:
from extras.scripts import Script

name = "Dummy"


class Dummy(Script):

    class Meta:
        name = "Dummy Script"
        commit_default = True

    def run(self, data, commit):
        self.log_info(f"Script was executed")
  1. Add the script to NetBox using "Customization/Scripts/Add"
  2. Try to run the script using the GUI
  3. Verify that the script gets executed properly
    Image
  4. Now try to run the script using the API:
# /opt/netbox/netbox/manage.py runscript dummy.Dummy

Expected Behavior

The script gets executed from the command line, like in NetBox 4.2.9:

# /opt/netbox/netbox/manage.py runscript dummy.Dummy
[2025-05-18 09:40:21,967][INFO] - Running script (commit=False)
[2025-05-18 09:40:21,967][INFO] - Script was executed
[2025-05-18 09:40:21,968][INFO] - Database changes have been reverted automatically.
[2025-05-18 09:40:21,973][INFO] - Script completed in 0 minutes, 0.01 seconds

Observed Behavior

Script execution failed with an exception:

# /opt/netbox/netbox/manage.py runscript dummy.Dummy
Traceback (most recent call last):
  File "/opt/netbox/netbox/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/opt/netbox/lib64/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/opt/netbox/lib64/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/netbox/lib64/python3.11/site-packages/django/core/management/base.py", line 416, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/opt/netbox/lib64/python3.11/site-packages/django/core/management/base.py", line 460, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/netbox/extras/management/commands/runscript.py", line 41, in handle
    script_obj = get_module_and_script(module_name, script_name)[1]
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/netbox/extras/scripts.py", line 649, in get_module_and_script
    module = ScriptModule.objects.get(file_path=f'{module_name}.py')
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/lib64/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/netbox/lib64/python3.11/site-packages/django/db/models/query.py", line 633, in get
    raise self.model.DoesNotExist(
extras.models.scripts.ScriptModule.DoesNotExist: ScriptModule matching query does not exist.

The script can be made to run in NetBox 4.3.1 with a modified invocation (which is definitely not how it's supposed to work):

# /opt/netbox/netbox/manage.py runscript /opt/netbox/netbox/scripts/dummy.Dummy
[2025-05-18 09:36:02,840][INFO] - Running script (commit=False)
[2025-05-18 09:36:02,840][INFO] - Script was executed
[2025-05-18 09:36:02,840][INFO] - Database changes have been reverted automatically.
[2025-05-18 09:36:02,847][INFO] - Script completed in 0 minutes, 0.01 seconds
Originally created by @peteeckel on GitHub (May 18, 2025). Originally assigned to: @arthanson, @jnovinger on GitHub. ### Deployment Type Self-hosted ### NetBox Version v4.3.1 ### Python Version 3.11 ### Steps to Reproduce 1. Set `SCRIPTS_ROOT = '/opt/netbox/netbox/scripts'` in `configuration.py` 1. Create a custom script and save it as `dummy.py`: ```python from extras.scripts import Script name = "Dummy" class Dummy(Script): class Meta: name = "Dummy Script" commit_default = True def run(self, data, commit): self.log_info(f"Script was executed") ``` 3. Add the script to NetBox using "Customization/Scripts/Add" 4. Try to run the script using the GUI 5. Verify that the script gets executed properly <img width="855" alt="Image" src="https://github.com/user-attachments/assets/b3601dcf-bc0d-41e7-af6a-8e5292d475d1" /> 6. Now try to run the script using the API: ```bash # /opt/netbox/netbox/manage.py runscript dummy.Dummy ``` ### Expected Behavior The script gets executed from the command line, like in NetBox 4.2.9: ``` # /opt/netbox/netbox/manage.py runscript dummy.Dummy [2025-05-18 09:40:21,967][INFO] - Running script (commit=False) [2025-05-18 09:40:21,967][INFO] - Script was executed [2025-05-18 09:40:21,968][INFO] - Database changes have been reverted automatically. [2025-05-18 09:40:21,973][INFO] - Script completed in 0 minutes, 0.01 seconds ``` ### Observed Behavior Script execution failed with an exception: ``` # /opt/netbox/netbox/manage.py runscript dummy.Dummy Traceback (most recent call last): File "/opt/netbox/netbox/manage.py", line 10, in <module> execute_from_command_line(sys.argv) File "/opt/netbox/lib64/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line utility.execute() File "/opt/netbox/lib64/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/opt/netbox/lib64/python3.11/site-packages/django/core/management/base.py", line 416, in run_from_argv self.execute(*args, **cmd_options) File "/opt/netbox/lib64/python3.11/site-packages/django/core/management/base.py", line 460, in execute output = self.handle(*args, **options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/netbox/extras/management/commands/runscript.py", line 41, in handle script_obj = get_module_and_script(module_name, script_name)[1] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/netbox/extras/scripts.py", line 649, in get_module_and_script module = ScriptModule.objects.get(file_path=f'{module_name}.py') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/lib64/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/netbox/lib64/python3.11/site-packages/django/db/models/query.py", line 633, in get raise self.model.DoesNotExist( extras.models.scripts.ScriptModule.DoesNotExist: ScriptModule matching query does not exist. ``` The script can be made to run in NetBox 4.3.1 with a modified invocation (which is definitely **not** how it's supposed to work): ``` # /opt/netbox/netbox/manage.py runscript /opt/netbox/netbox/scripts/dummy.Dummy [2025-05-18 09:36:02,840][INFO] - Running script (commit=False) [2025-05-18 09:36:02,840][INFO] - Script was executed [2025-05-18 09:36:02,840][INFO] - Database changes have been reverted automatically. [2025-05-18 09:36:02,847][INFO] - Script completed in 0 minutes, 0.01 seconds ```
adam added the type: bugstatus: acceptedseverity: low labels 2025-12-29 21:41:46 +01:00
adam closed this issue 2025-12-29 21:41:47 +01:00
Author
Owner

@jnovinger commented on GitHub (May 19, 2025):

Hrm, the workaround is not working for me, at least in my dev environment.

@jnovinger commented on GitHub (May 19, 2025): Hrm, the workaround is not working for me, at least in my dev environment.
Author
Owner

@peteeckel commented on GitHub (May 19, 2025):

Hrm, the workaround is not working for me, at least in my dev environment.

Permissions issue perhaps? It worked for me in two environments.

Anyway, it's just a side note.

@peteeckel commented on GitHub (May 19, 2025): > Hrm, the workaround is not working for me, at least in my dev environment. Permissions issue perhaps? It worked for me in two environments. Anyway, it's just a side note.
Author
Owner

@jnovinger commented on GitHub (May 20, 2025):

Permissions issue perhaps? It worked for me in two environments.

Anyway, it's just a side note.

Turns out I was invoking the workaround incorrectly, my bad. Your workaround does work for me.

@jnovinger commented on GitHub (May 20, 2025): > Permissions issue perhaps? It worked for me in two environments. > > Anyway, it's just a side note. Turns out I was invoking the workaround incorrectly, my bad. Your workaround does work for me.
Author
Owner

@jnovinger commented on GitHub (May 20, 2025):

This also affects Event Rule bulk import as it also relies on extras.scripts.get_module_and_script, which is where the issue is. Will have a fix up shortly.

@jnovinger commented on GitHub (May 20, 2025): This also affects Event Rule bulk import as it also relies on `extras.scripts.get_module_and_script`, which is where the issue is. Will have a fix up shortly.
Author
Owner

@ninabel commented on GitHub (May 28, 2025):

This also affects invocation scripts through API.
After upgrade old scripts are still working. But a new or recreated script can't by found by the name.
Also in browser you can find a new scrip instance by id:
/api/extras/scripts/
but not by name
/api/extras/scripts/.

@ninabel commented on GitHub (May 28, 2025): This also affects invocation scripts through API. After upgrade old scripts are still working. But a new or recreated script can't by found by the name. Also in browser you can find a new scrip instance by id: /api/extras/scripts/<id> but not by name /api/extras/scripts/<module>.<ScriptName>
Author
Owner

@ninabel commented on GitHub (May 28, 2025):

@jnovinger your fix doesn't help me.
Really, old scripts in the same directory works fine.
It seems that netbox looks in some cash and don't go farther if doesn't find the script there.

@ninabel commented on GitHub (May 28, 2025): @jnovinger your fix doesn't help me. Really, old scripts in the same directory works fine. It seems that netbox looks in some cash and don't go farther if doesn't find the script there.
Author
Owner

@ninabel commented on GitHub (May 29, 2025):

It seems that I've found the problem. New scripts was stored in database with full path.

netbox=# select id, file_path from core_managedfile;
 id |               file_path
----+----------------------------------------
  3 | old_script.py
 13 | /opt/netbox/netbox/scripts/test.py
(4 rows)

Was it change done intentionally?

@ninabel commented on GitHub (May 29, 2025): It seems that I've found the problem. New scripts was stored in database with full path. ``` netbox=# select id, file_path from core_managedfile; id | file_path ----+---------------------------------------- 3 | old_script.py 13 | /opt/netbox/netbox/scripts/test.py (4 rows) ``` Was it change done intentionally?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#11195