pynetbox
pynetbox copied to clipboard
Permission Constraints are handled as Records
Follow up to #398, as this issue still persists with current pynetbox:
2022-05-20T16:31:32Z DEBUG Type of permission.constraints: <class 'list'>
2022-05-20T16:31:32Z DEBUG Type of first item in permission.constraints: <class 'pynetbox.core.response.Record'>
Traceback (most recent call last):
(...)
File "/home/jg/.local/lib/python3.10/site-packages/pynetbox/core/response.py", line 484, in _diff
{fmt_dict(k, v) for k, v in self.serialize(init=True).items()}
File "/home/jg/.local/lib/python3.10/site-packages/pynetbox/core/response.py", line 463, in serialize
current_val = [
File "/home/jg/.local/lib/python3.10/site-packages/pynetbox/core/response.py", line 464, in <listcomp>
v.id if isinstance(v, Record) else v for v in current_val
File "/home/jg/.local/lib/python3.10/site-packages/pynetbox/core/response.py", line 298, in __getattr__
raise AttributeError('object has no attribute "{}"'.format(k))
AttributeError: object has no attribute "id"
I think this bit of code has to be reworked for it to work: https://github.com/netbox-community/pynetbox/blob/v6.6.2/pynetbox/core/response.py#L369
As NetBox returns constraints as a list, isinstance(v, dict)
will never be true, but isinstance(v, list)
will:
https://github.com/netbox-community/pynetbox/blob/v6.6.2/pynetbox/core/response.py#L384
Then each item will be converted to a Record, as Permissions.constraints
is not a list, but JsonField:
https://github.com/netbox-community/pynetbox/blob/v6.6.2/pynetbox/core/response.py#L360
https://github.com/netbox-community/pynetbox/blob/v6.6.2/pynetbox/models/users.py#L26
As JsonField
does not take any arguments, the solution of users is not usable without further changes:
https://github.com/netbox-community/pynetbox/blob/v6.6.2/pynetbox/models/users.py#L25
https://github.com/netbox-community/pynetbox/blob/v6.6.2/pynetbox/core/response.py#L366
Please provide a minimum reproducable example of the situation (what did you try to do with what kind of input etc), that will hugely help someone to start tackling the problem. Thanks! 👍
Here you go, based on documented examples by NetBox maintainers: https://docs.netbox.dev/en/stable/administration/permissions/#constraints
import pynetbox
def ensure_permission(api, permission):
nb_permission = api.users.permissions.get(name=permission['name'])
if nb_permission is None:
print(f'Creating permission {permission["name"]}')
return api.users.permissions.create(permission)
# for the sake of a simple example, only constraint updating is implemented
nb_permission.constraints = permission['constraints']
print(f'Saving permission {permission["name"]}')
nb_permission.save()
return nb_permission
def delete_permission(api, permission):
nb_permission = api.users.permissions.get(name=permission['name'])
if nb_permission is not None:
print(f'Deleting permission {permission["name"]}')
nb_permission.delete()
api = pynetbox.api(
'https://netbox.domain.tld',
token='<token>'
)
permissions = [
{
'name': 'nb_example_constraint_1',
'enabled': False,
'object_types': [
'dcim.site'
],
'actions': [
'add',
'change',
'delete'
],
'constraints': {
"status": "active",
"region__name": "Americas"
}
},
{
'name': 'nb_example_constraint_2',
'enabled': False,
'object_types': [
'ipam.vlan'
],
'actions': [
'add',
'change',
'delete'
],
'constraints': [
{
"vid__gte": 100,
"vid__lt": 200
},
{
"status": "reserved"
}
]
}
]
print('Cleaning up permissions from previous runs')
for permission in permissions:
delete_permission(api, permission)
print('Creating permissions')
for permission in permissions:
ensure_permission(api, permission)
# do the same again - it should be idempotent (Hint: its not for nb_example_constraint_2)
print('Doing an idempotency check')
for permission in permissions:
ensure_permission(api, permission)
# now change constraints on both with other NetBox documentation examples:
permissions[0]['constraints']['name__startswith'] = 'Foo'
permissions[1]['constraints'].append({
'role': 'testing'
})
print('Updating permissions')
for permission in permissions:
ensure_permission(api, permission)
Hi! I just checked and sadly have to confirm that the issue still exists. Any chance this will get a fix?
Regards, j.