netbox-community / netbox

The premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/free-netbox-cloud/
http://netboxlabs.com/oss/netbox/
Apache License 2.0
15.77k stars 2.54k forks source link

Custom validator for tags works for single edits but breaks bulk edits #17277

Open Azmodeszer opened 2 weeks ago

Azmodeszer commented 2 weeks ago

Deployment Type

Self-hosted

NetBox Version

v.4.0.9

Python Version

3.11

Steps to Reproduce

  1. Create a custom validator as described here https://github.com/netbox-community/netbox/discussions/16198#discussioncomment-10463695
  2. Bulk edit affected objects. (VMs or devices, in my case)

Expected Behavior

Edit works as it does for single edits.

Observed Behavior

<class 'KeyError'>

'tags'
jeremystretch commented 2 weeks ago
  1. Create a custom validator as described here

Please replicate the exact reproduction steps in your initial post above.

Azmodeszer commented 2 weeks ago

@jeremystretch

  1. Create a script for the validator checking for the presence of either of two tags and the lack of a third. self.fail if the condition is met:
from extras.validators import CustomValidator

class webmintagging(CustomValidator):

    def validate(self, instance, request):
        if ("webmin-autoupdates".upper() in [tag.slug.upper() for tag in instance._m2m_values['tags']] or "webmin-autosecupdates".upper() in [tag.slug.upper() for tag in instance._m2m_values['tags']]) and not "webmin".upper() in [tag.slug.upper() for tag in instance._m2m_values['tags']]:
            self.fail("Can't add specific Webmin tag without basic Webmin tag!", field='tags')
  1. Add a custom validator pointing to the script to configuration.py, applying it to devices and VMs:
CUSTOM_VALIDATORS = {
    'dcim.device': (
        'scripts.custom_validators.webmintagging.webmintagging',
    ),
    'virtualization.virtualmachine': (
        'scripts.custom_validators.webmintagging.webmintagging',
    ),
}
  1. sudo systemctl restart netbox
  2. Try to edit a single device or VM. (validation works)
  3. Try to bulk edit two or more devices or VMs. (does not work and results in the error above)

Maybe something to do with the fact that for bulk edits the field splits into "Add tags" and "Remove tags"?

atownson commented 2 weeks ago

Just an FYI, I can replicate this issue and confirm the custom validator breaks bulk editing regardless of whether or not tags are added or removed in the bulk edit request (i.e. just changing the description field). Here's the validator we have in place:

class GroupValidator(CustomValidator):
    def validate(self, instance):
        # Group is required unless the instance is tagged with 'Exception'
        if not instance.group and 'exception' not in [tag.name.lower() for tag in instance._m2m_values['tags']]:
            self.fail('Custom validation: Group is required.', field='group')

image

The issue appears to be that the _m2m_values dictionary is empty.