Custom Script API Access seems to cache data #9120

Closed
opened 2025-12-29 20:45:52 +01:00 by adam · 7 comments
Owner

Originally created by @mmackay21724 on GitHub (Jan 20, 2024).

Deployment Type

Self-hosted

NetBox Version

v3.7.0

Python Version

3.8

Steps to Reproduce

I have a custom script - when I use it via the GUI and log the data I see the correct info.
I pass in site and vlan.
Via API (postman or curl) I always get the result of the last GUI run.

Abbreviated script::


class Netbox_lookup(Script):

    class Meta:
        name = "netbox_lookup"
        description = "Pulls the data about a vlan and its tenants, backdoor ips etc"
    site_name = StringVar(
        description="Name of the site"
    )
    vlan = IntegerVar(
        description="vlan to pull from"
    )
   
    def run(self, data, commit):
                
        try:
            ## Check site 
            self.log_success(f"data= {data}")

Expected Behavior

Each execution should be using the new data.

Observed Behavior

Via GUI I see::

if I pass in usw1, 222 I get

Success | data= {'site_name': 'usw1', 'vlan': 222}

if I pass in usw1, 1411

Success | data= {'site_name': 'usw1', 'vlan': 1411}

If I now connect via API:

curl --location 'http://netbox-dev.usw1.production.devnetsandbox.local/api/extras/scripts/netbox_lookup.Netbox_lookup' \
--header 'Authorization: Token f4f6bcc0b5b19233533774630cd4cfe9795b6a37' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json; indent=4' \
--data '{
    "data": {
        "site": "usw1",
        "vlan": "500"
    }
}'

result is
"message": "data= {'site_name': 'usw1', 'vlan': 1411}"

If I execute the GUI again::
usw1, 333
result =. data= {'site_name': 'usw1', 'vlan': 333}

rerun the above cutl I get
result =. data= {'site_name': 'usw1', 'vlan': 333}

Originally created by @mmackay21724 on GitHub (Jan 20, 2024). ### Deployment Type Self-hosted ### NetBox Version v3.7.0 ### Python Version 3.8 ### Steps to Reproduce I have a custom script - when I use it via the GUI and log the data I see the correct info. I pass in site and vlan. Via API (postman or curl) I always get the result of the last GUI run. Abbreviated script:: ```python class Netbox_lookup(Script): class Meta: name = "netbox_lookup" description = "Pulls the data about a vlan and its tenants, backdoor ips etc" site_name = StringVar( description="Name of the site" ) vlan = IntegerVar( description="vlan to pull from" ) def run(self, data, commit): try: ## Check site self.log_success(f"data= {data}") ``` ### Expected Behavior Each execution should be using the new data. ### Observed Behavior Via GUI I see:: if I pass in usw1, 222 I get *Success | data= {'site_name': 'usw1', 'vlan': 222}* if I pass in usw1, 1411 *Success | data= {'site_name': 'usw1', 'vlan': 1411}* If I now connect via API: ```bash curl --location 'http://netbox-dev.usw1.production.devnetsandbox.local/api/extras/scripts/netbox_lookup.Netbox_lookup' \ --header 'Authorization: Token f4f6bcc0b5b19233533774630cd4cfe9795b6a37' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json; indent=4' \ --data '{ "data": { "site": "usw1", "vlan": "500" } }' ``` result is "message": "data= {'site_name': 'usw1', 'vlan': 1411}" If I execute the GUI again:: usw1, 333 result =. *data= {'site_name': 'usw1', 'vlan': 333}* rerun the above cutl I get result =. *data= {'site_name': 'usw1', 'vlan': 333}*
adam added the type: bugstatus: revisions needed labels 2025-12-29 20:45:52 +01:00
adam closed this issue 2025-12-29 20:45:52 +01:00
Author
Owner

@jeremystretch commented on GitHub (Jan 22, 2024):

You seem to be either omitting a large portion of your workflow, or have indicated an incorrect NetBox version. Executing a script via the REST API on NetBox v3.7 does not return the output of the script, but rather the pending result of the background job created to effect its execution. As such, the reported behavior is not reproducible.

@jeremystretch commented on GitHub (Jan 22, 2024): You seem to be either omitting a large portion of your workflow, or have indicated an incorrect NetBox version. Executing a script via the REST API on NetBox v3.7 does not return the output of the script, but rather the pending result of the background job created to effect its execution. As such, the reported behavior is not reproducible.
Author
Owner

@mmackay21724 commented on GitHub (Jan 22, 2024):

Hey @jeremystretch ,

Not sure I follow "does not return the output of the script" - I see a field called "Output" that has the result of the the return statement.

I omitted the majority of the script because it's mostly moot. The script executes as expected, based on values of the data it is using.

When I use the GUI, it correctly returns the data entered into GUI form fields. When I execute via the API it shows me that data as last entered when executed via the GUI, from that point on it generates the correct, from the perspective of the script, data.

Super abbreviated script for brevity.


from extras.scripts import *
from django.utils.text import slugify

from dcim.choices import DeviceStatusChoices, SiteStatusChoices
from dcim.models import Device, Site, ConsolePort, PowerPort
from ipam.models import Prefix, VLAN, Role
from virtualization.models import VirtualMachine
from utilities.exceptions import AbortScript
import json

class Netbox_lookup(Script):

    class Meta:
        name = "netbox_lookup"
        description = "Pulls the data about a vlan and its tenants, backdoor ips etc"

    site_name = StringVar(
        description="Name of the site"
    )
    vlan = IntegerVar(
        description="vlan to pull from"
    )
   
    def run(self, data, commit):   
        try:
            return json.dumps(data)
        
        except Exception as e:
            raise AbortScript(f"Got an error {e}")
            

executed via GUI::

Output
{"site_name": "usw1", "vlan": 1411}

But from the API notice that the values in the Output are the ones I executed in the GUI, not the ones provide in the API call.


mmackay~ $curl --location 'http://netbox-dev.usw1.production.devnetsandbox.local/api/extras/scripts/netbox_lookup.Netbox_lookup' \
--header 'Authorization: Token f4f6bcc0b5b19233533774630cd4cfe9795b6a37' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json; indent=4' \
--data '{
    "data": {
        "site": "usw1",
        "vlan": "500"
    }
}'
{
    "url": "http://netbox-dev.usw1.production.devnetsandbox.local/api/extras/scripts/netbox_lookup.Netbox_lookup/",
    "id": "netbox_lookup.Netbox_lookup",
    "module": "netbox_lookup",
    "name": "netbox_lookup",
    "description": "Pulls the data about a vlan and its tenants, backdoor ips etc",
    "vars": {
        "site_name": "StringVar",
        "vlan": "IntegerVar"
    },
    "result": {
        "id": 233,
        "url": "http://netbox-dev.usw1.production.devnetsandbox.local/api/core/jobs/233/",
        "display": "5d285720-67c7-4dd5-a2df-725005552ad7",
        "object_type": "extras.scriptmodule",
        "object_id": 79,
        "name": "Netbox_lookup",
        "status": {
            "value": "completed",
            "label": "Completed"
        },
        "created": "2024-01-22T20:14:39.885463Z",
        "scheduled": null,
        "interval": null,
        "started": "2024-01-22T20:14:39.901339Z",
        "completed": "2024-01-22T20:14:39.936114Z",
        "user": {
            "id": 16,
            "url": "http://netbox-dev.usw1.production.devnetsandbox.local/api/users/users/16/",
            "display": "****",
            "username": "****"
        },
        "data": {
            "log": [],
            "output": "{\"site_name\": \"usw1\", \"vlan\": 1411}"
        },
        "error": "",
        "job_id": "5d285720-67c7-4dd5-a2df-725005552ad7"
    },
    "display": "netbox_lookup (netbox_lookup)"
}%    

@mmackay21724 commented on GitHub (Jan 22, 2024): Hey @jeremystretch , Not sure I follow "does not return the output of the script" - I see a field called "Output" that has the result of the the return statement. I omitted the majority of the script because it's mostly moot. The script executes as expected, based on values of the data it is using. When I use the GUI, it correctly returns the data entered into GUI form fields. When I execute via the API it shows me that data as last entered when executed via the GUI, from that point on it generates the correct, from the perspective of the script, data. Super abbreviated script for brevity. ```python from extras.scripts import * from django.utils.text import slugify from dcim.choices import DeviceStatusChoices, SiteStatusChoices from dcim.models import Device, Site, ConsolePort, PowerPort from ipam.models import Prefix, VLAN, Role from virtualization.models import VirtualMachine from utilities.exceptions import AbortScript import json class Netbox_lookup(Script): class Meta: name = "netbox_lookup" description = "Pulls the data about a vlan and its tenants, backdoor ips etc" site_name = StringVar( description="Name of the site" ) vlan = IntegerVar( description="vlan to pull from" ) def run(self, data, commit): try: return json.dumps(data) except Exception as e: raise AbortScript(f"Got an error {e}") ``` executed via GUI:: >Output {"site_name": "usw1", "vlan": 1411} But from the API notice that the values in the Output are the ones I executed in the GUI, not the ones provide in the API call. ```bash mmackay~ $curl --location 'http://netbox-dev.usw1.production.devnetsandbox.local/api/extras/scripts/netbox_lookup.Netbox_lookup' \ --header 'Authorization: Token f4f6bcc0b5b19233533774630cd4cfe9795b6a37' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json; indent=4' \ --data '{ "data": { "site": "usw1", "vlan": "500" } }' { "url": "http://netbox-dev.usw1.production.devnetsandbox.local/api/extras/scripts/netbox_lookup.Netbox_lookup/", "id": "netbox_lookup.Netbox_lookup", "module": "netbox_lookup", "name": "netbox_lookup", "description": "Pulls the data about a vlan and its tenants, backdoor ips etc", "vars": { "site_name": "StringVar", "vlan": "IntegerVar" }, "result": { "id": 233, "url": "http://netbox-dev.usw1.production.devnetsandbox.local/api/core/jobs/233/", "display": "5d285720-67c7-4dd5-a2df-725005552ad7", "object_type": "extras.scriptmodule", "object_id": 79, "name": "Netbox_lookup", "status": { "value": "completed", "label": "Completed" }, "created": "2024-01-22T20:14:39.885463Z", "scheduled": null, "interval": null, "started": "2024-01-22T20:14:39.901339Z", "completed": "2024-01-22T20:14:39.936114Z", "user": { "id": 16, "url": "http://netbox-dev.usw1.production.devnetsandbox.local/api/users/users/16/", "display": "****", "username": "****" }, "data": { "log": [], "output": "{\"site_name\": \"usw1\", \"vlan\": 1411}" }, "error": "", "job_id": "5d285720-67c7-4dd5-a2df-725005552ad7" }, "display": "netbox_lookup (netbox_lookup)" }% ```
Author
Owner

@markkuleinio commented on GitHub (Jan 22, 2024):

Note that you are providing "site" in the API call, while the script takes "site_name"

@markkuleinio commented on GitHub (Jan 22, 2024): Note that you are providing "site" in the API call, while the script takes "site_name"
Author
Owner

@mmackay21724 commented on GitHub (Jan 22, 2024):

Actually, as dumb as that mistake on my side , it actually highlights that the data being used via the API is not whats provided.
Just in case it was some weird result of it not receiving correct data I tried with site_name, same result.

@mmackay21724 commented on GitHub (Jan 22, 2024): Actually, as dumb as that mistake on my side , it actually highlights that the data being used via the API is not whats provided. Just in case it was some weird result of it not receiving correct data I tried with site_name, same result.
Author
Owner

@markkuleinio commented on GitHub (Jan 23, 2024):

Works here with NetBox 3.7.1, Test.py:

from extras.scripts import *

class Test(Script):
    device_name = StringVar(
        label="Device name",
    )

    def run(self, data, commit):
        return data["device_name"]

I run this via GUI with device name "Test from GUI": I get result "Test from GUI".

Then from API:

$ curl -s -H "Authorization: token 5052364b816bb45fbd1a983f63dfb9be7ee8c423" \
-H "Content-Type: application/json" \
-H "Accept: application/json; indent=4" \
https://mynetbox.example.com/api/extras/scripts/Test.Test/ \
--data '{"data": {"device_name":"Test from API"}, "commit":true}'
{
    "url": "https://mynetbox.example.com/api/extras/scripts/Test.Test/",
    "id": "Test.Test",
    "module": "Test",
    "name": "Test",
    "description": "",
    "vars": {
        "device_name": "StringVar"
    },
    "result": {
        "id": 53,
        "url": "https://mynetbox.example.com/api/core/jobs/53/",
        "display": "4c4af1c4-4881-4c6a-baec-e78e3db13cdb",
        "object_type": "extras.scriptmodule",
        "object_id": 7,
        "name": "Test",
        "status": {
            "value": "pending",
            "label": "Pending"
        },
        "created": "2024-01-23T09:56:53.162009+02:00",
        "scheduled": null,
        "interval": null,
        "started": null,
        "completed": null,
        "user": {
            "id": 66,
            "url": "https://mynetbox.example.com/api/users/users/66/",
            "display": "markku",
            "username": "markku"
        },
        "data": null,
        "error": "",
        "job_id": "4c4af1c4-4881-4c6a-baec-e78e3db13cdb"
    },
    "display": "Test (Test)"
}

= I get the pending job with the POST call.

Then with GET:

$ curl -s -H "Authorization: token 5052364b816bb45fbd1a983f63dfb9be7ee8c423" \
-H "Content-Type: application/json" \
-H "Accept: application/json; indent=4" \
https://mynetbox.example.com/api/extras/scripts/Test.Test/
{
    "url": "https://mynetbox.example.com/api/extras/scripts/Test.Test/",
    "id": "Test.Test",
    "module": "Test",
    "name": "Test",
    "description": "",
    "vars": {
        "device_name": "StringVar"
    },
    "result": {
        "id": 53,
        "url": "https://mynetbox.example.com/api/core/jobs/53/",
        "display": "4c4af1c4-4881-4c6a-baec-e78e3db13cdb",
        "object_type": "extras.scriptmodule",
        "object_id": 7,
        "name": "Test",
        "status": {
            "value": "completed",
            "label": "Completed"
        },
        "created": "2024-01-23T09:56:53.162009+02:00",
        "scheduled": null,
        "interval": null,
        "started": "2024-01-23T09:56:53.208167+02:00",
        "completed": "2024-01-23T09:56:53.259858+02:00",
        "user": {
            "id": 66,
            "url": "https://mynetbox.example.com/api/users/users/66/",
            "display": "markku",
            "username": "markku"
        },
        "data": {
            "log": [],
            "output": "Test from API"
        },
        "error": "",
        "job_id": "4c4af1c4-4881-4c6a-baec-e78e3db13cdb"
    },
    "display": "Test (Test)"
}

output = "Test from API" = works fine

@markkuleinio commented on GitHub (Jan 23, 2024): Works here with NetBox 3.7.1, `Test.py`: ``` from extras.scripts import * class Test(Script): device_name = StringVar( label="Device name", ) def run(self, data, commit): return data["device_name"] ``` I run this via GUI with device name "Test from GUI": I get result "Test from GUI". Then from API: ``` $ curl -s -H "Authorization: token 5052364b816bb45fbd1a983f63dfb9be7ee8c423" \ -H "Content-Type: application/json" \ -H "Accept: application/json; indent=4" \ https://mynetbox.example.com/api/extras/scripts/Test.Test/ \ --data '{"data": {"device_name":"Test from API"}, "commit":true}' { "url": "https://mynetbox.example.com/api/extras/scripts/Test.Test/", "id": "Test.Test", "module": "Test", "name": "Test", "description": "", "vars": { "device_name": "StringVar" }, "result": { "id": 53, "url": "https://mynetbox.example.com/api/core/jobs/53/", "display": "4c4af1c4-4881-4c6a-baec-e78e3db13cdb", "object_type": "extras.scriptmodule", "object_id": 7, "name": "Test", "status": { "value": "pending", "label": "Pending" }, "created": "2024-01-23T09:56:53.162009+02:00", "scheduled": null, "interval": null, "started": null, "completed": null, "user": { "id": 66, "url": "https://mynetbox.example.com/api/users/users/66/", "display": "markku", "username": "markku" }, "data": null, "error": "", "job_id": "4c4af1c4-4881-4c6a-baec-e78e3db13cdb" }, "display": "Test (Test)" } ``` = I get the pending job with the POST call. Then with GET: ``` $ curl -s -H "Authorization: token 5052364b816bb45fbd1a983f63dfb9be7ee8c423" \ -H "Content-Type: application/json" \ -H "Accept: application/json; indent=4" \ https://mynetbox.example.com/api/extras/scripts/Test.Test/ { "url": "https://mynetbox.example.com/api/extras/scripts/Test.Test/", "id": "Test.Test", "module": "Test", "name": "Test", "description": "", "vars": { "device_name": "StringVar" }, "result": { "id": 53, "url": "https://mynetbox.example.com/api/core/jobs/53/", "display": "4c4af1c4-4881-4c6a-baec-e78e3db13cdb", "object_type": "extras.scriptmodule", "object_id": 7, "name": "Test", "status": { "value": "completed", "label": "Completed" }, "created": "2024-01-23T09:56:53.162009+02:00", "scheduled": null, "interval": null, "started": "2024-01-23T09:56:53.208167+02:00", "completed": "2024-01-23T09:56:53.259858+02:00", "user": { "id": 66, "url": "https://mynetbox.example.com/api/users/users/66/", "display": "markku", "username": "markku" }, "data": { "log": [], "output": "Test from API" }, "error": "", "job_id": "4c4af1c4-4881-4c6a-baec-e78e3db13cdb" }, "display": "Test (Test)" } ``` output = "Test from API" = works fine
Author
Owner

@markkuleinio commented on GitHub (Jan 23, 2024):

If I try POST without commit field, API responds:

{
    "commit": [
        "This field is required."
    ]
}
@markkuleinio commented on GitHub (Jan 23, 2024): If I try POST without `commit` field, API responds: ``` { "commit": [ "This field is required." ] } ```
Author
Owner

@jeremystretch commented on GitHub (Feb 20, 2024):

Closing this out as we've been unable to reproduce the reported behavior.

@jeremystretch commented on GitHub (Feb 20, 2024): Closing this out as we've been unable to reproduce the reported behavior.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#9120