Running Custom Script via API with ObjectVar Parameter - getting AttributeError

877 views
Skip to first unread message

Chris Rowat

unread,
Jun 15, 2020, 6:11:14 PM6/15/20
to NetBox
I have a custom script defined like this (I shortened the run function to eliminate as much of my code as possible as the source of the problem):



class ProbeDevice(Script):

    class Meta:
        name = "Probe Device"
        description = "Populate basic device information"
        field_order = ['device']

    device = ObjectVar(
        description = "Device to probe",
        queryset = Device.objects.all()
    )

    def run(self, data, commit):
        device = data['device']
        self.log_success("Starting script for device [{}]({})".format(device, reverse('dcim:device', kwargs={'pk': device.pk})))





When I attempt to call it via the API I get the following:

$ curl -X POST "http://netbox.example.com/api/extras/scripts/devices.SerializeDevice/" -H "accept: application/json" -H "Authorization: Token <token goes here>" -H "Content-Type: application/json" --data '{"commit":true,"data":{"device":519}}'

{"log":[{"status":"failure","message":"An exception occurred: `AttributeError: 'int' object has no attribute '_meta'`\n```\nTraceback (most recent call last):\n  File \"/opt/netbox/netbox/extras/scripts.py\", line 408, in run_script\n    output = script.run(**kwargs)\n  File \"/etc/netbox/scripts/devices.py\", line 42, in run\n    return serializers.serialize('json', [device])\n  File \"/usr/local/lib/python3.7/site-packages/django/core/serializers/__init__.py\", line 128, in serialize\n    s.serialize(queryset, **options)\n  File \"/usr/local/lib/python3.7/site-packages/django/core/serializers/base.py\", line 94, in serialize\n    concrete_model = obj._meta.concrete_model\nAttributeError: 'int' object has no attribute '_meta'\n\n```"},{"status":"info","message":"Database changes have been reverted automatically."}],"output":null}


Which seems to indicate that my data object is not the type it is expecting?   How is one supposed to feed in values for an ObjectVar parameter type when executing a custom script via the API?



To sanity check my work, I have another script that takes only a string as input:

class FindDevice(Script):

    class Meta:
        name = "Find Device"
        description = "Find a device by IP and populate basic device information"
        field_order = ['ip_address']

    ip_address = StringVar(
        description = "IPv4 address of the device to probe",
        min_length = 8,
        max_length = 16
    )
    
    def run(self, data, commit):
        self.log_success("Starting script for IP address: {}".format(data['ip_address']))


And when I call it like this:

$ curl -X POST "http://netbox.example.com/api/extras/scripts/devices.FindDevice/" -H "accept: application/json" -H "Authorization: Token <token goes here>" -H "Content-Type: application/json" --data '{"commit":true,"data":{"ip_address":"192.168.1.1/32"}}'

I get a JSON object representing the response as expected 

Chris Rowat

unread,
Jun 15, 2020, 6:12:12 PM6/15/20
to NetBox
I should also mention, I am running netbox 2.8.5 (as 2.8.6 only released today and the docker image isn't available yet)

mahomed...@brokertech.co.uk

unread,
Jun 17, 2020, 4:41:52 AM6/17/20
to NetBox
I haven't used custom scripts via the API, but does your script work through the Web UI? It may help to work out if the error is in your script or in what you are sending. Also try passing the device name rather than id for "device" or use "device_id"

Chris Rowat

unread,
Jun 17, 2020, 10:18:52 AM6/17/20
to NetBox
The script works fine through the UI.  

I just tried using the device name and sending it as a string (which is an unusual suggestion given that device name not guaranteed to be unique) and it produces a similar error (except 'string' instead of 'int' in the lowest level of the traceback).
Renaming the parameter to "device_id" just causes a missing parameter error for the "device" field.

Also, I tried updating to 2.8.6 yesterday and it did not fix this problem (though it did fix a few others I was encountering).  I'm going to start digging through the netbox source and looking into the relevant django functions to see if something jumps out at me.
Reply all
Reply to author
Forward
0 new messages