nautobot 2.3.11__py3-none-any.whl → 2.3.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/core/api/serializers.py +1 -0
- nautobot/core/celery/log.py +4 -4
- nautobot/core/models/tree_queries.py +5 -2
- nautobot/core/settings.py +26 -0
- nautobot/core/settings.yaml +31 -0
- nautobot/core/tables.py +60 -10
- nautobot/core/templates/generic/object_notes.html +1 -1
- nautobot/core/templates/generic/object_retrieve.html +1 -1
- nautobot/core/templatetags/helpers.py +7 -1
- nautobot/core/testing/api.py +5 -1
- nautobot/core/testing/views.py +15 -4
- nautobot/core/tests/test_api.py +20 -0
- nautobot/core/tests/test_csv.py +25 -3
- nautobot/core/tests/test_utils.py +8 -0
- nautobot/core/utils/lookup.py +11 -8
- nautobot/dcim/api/views.py +3 -0
- nautobot/dcim/choices.py +6 -0
- nautobot/dcim/filters/__init__.py +26 -1
- nautobot/dcim/forms.py +4 -0
- nautobot/dcim/tables/devices.py +2 -6
- nautobot/dcim/templates/dcim/controller_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/device/base.html +1 -1
- nautobot/dcim/tests/test_filters.py +33 -0
- nautobot/dcim/tests/test_views.py +6 -0
- nautobot/extras/api/serializers.py +1 -0
- nautobot/extras/api/views.py +2 -0
- nautobot/extras/forms/forms.py +2 -0
- nautobot/extras/group_sync.py +42 -0
- nautobot/extras/models/metadata.py +1 -0
- nautobot/extras/models/models.py +1 -1
- nautobot/extras/plugins/__init__.py +15 -3
- nautobot/extras/tables.py +1 -0
- nautobot/extras/templates/extras/inc/job_table.html +1 -1
- nautobot/extras/tests/test_views.py +2 -2
- nautobot/extras/views.py +0 -2
- nautobot/ipam/lookups.py +101 -62
- nautobot/ipam/tables.py +22 -15
- nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -1
- nautobot/ipam/tests/test_querysets.py +49 -1
- nautobot/ipam/utils/__init__.py +24 -0
- nautobot/ipam/views.py +61 -68
- nautobot/project-static/docs/404.html +10 -10
- nautobot/project-static/docs/additional-features/caching.html +1 -2
- nautobot/project-static/docs/additional-features/change-logging.html +1 -2
- nautobot/project-static/docs/additional-features/config-contexts.html +1 -2
- nautobot/project-static/docs/additional-features/healthcheck.html +1 -2
- nautobot/project-static/docs/additional-features/jobs.html +1 -2
- nautobot/project-static/docs/additional-features/prometheus-metrics.html +1 -2
- nautobot/project-static/docs/administration/celery-queues.html +1 -2
- nautobot/project-static/docs/administration/nautobot-server.html +1 -2
- nautobot/project-static/docs/administration/nautobot-shell.html +1 -2
- nautobot/project-static/docs/administration/permissions.html +1 -2
- nautobot/project-static/docs/administration/replicating-nautobot.html +1 -2
- nautobot/project-static/docs/apps/index.html +10 -10
- nautobot/project-static/docs/apps/migrating-jobs-from-nautobot-v1.html +1 -2
- nautobot/project-static/docs/apps/nautobot-apps.html +10 -10
- nautobot/project-static/docs/assets/stylesheets/main.6f8fc17f.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/main.6f8fc17f.min.css.map +1 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +206 -14
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +25 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +10 -10
- nautobot/project-static/docs/configuration/authentication/ldap.html +1 -2
- nautobot/project-static/docs/configuration/authentication/remote.html +1 -2
- nautobot/project-static/docs/configuration/authentication/sso.html +1 -2
- nautobot/project-static/docs/configuration/index.html +1 -2
- nautobot/project-static/docs/configuration/optional-settings.html +1 -2
- nautobot/project-static/docs/configuration/required-settings.html +1 -2
- nautobot/project-static/docs/core-functionality/circuits.html +1 -2
- nautobot/project-static/docs/core-functionality/device-types.html +1 -2
- nautobot/project-static/docs/core-functionality/devices.html +1 -2
- nautobot/project-static/docs/core-functionality/ipam.html +1 -2
- nautobot/project-static/docs/core-functionality/power.html +1 -2
- nautobot/project-static/docs/core-functionality/secrets.html +1 -2
- nautobot/project-static/docs/core-functionality/services.html +1 -2
- nautobot/project-static/docs/core-functionality/sites-and-racks.html +1 -2
- nautobot/project-static/docs/core-functionality/tenancy.html +1 -2
- nautobot/project-static/docs/core-functionality/virtualization.html +1 -2
- nautobot/project-static/docs/core-functionality/vlans.html +1 -2
- nautobot/project-static/docs/development/application-registry.html +1 -2
- nautobot/project-static/docs/development/apps/api/configuration-view.html +10 -10
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +10 -10
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +10 -10
- nautobot/project-static/docs/development/apps/api/models/global-search.html +10 -10
- nautobot/project-static/docs/development/apps/api/models/graphql.html +10 -10
- nautobot/project-static/docs/development/apps/api/models/index.html +10 -10
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +32 -13
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +10 -10
- nautobot/project-static/docs/development/apps/api/prometheus.html +10 -10
- nautobot/project-static/docs/development/apps/api/setup.html +10 -10
- nautobot/project-static/docs/development/apps/api/testing.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-detail-views.html +1 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/tabs.html +1 -2
- nautobot/project-static/docs/development/apps/api/views/base-template.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/index.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/notes.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/urls.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/view-overrides.html +1 -2
- nautobot/project-static/docs/development/apps/index.html +10 -10
- nautobot/project-static/docs/development/apps/migration/code-updates.html +10 -10
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +10 -10
- nautobot/project-static/docs/development/apps/migration/from-v1.html +10 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +10 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +10 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +10 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +10 -10
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +10 -10
- nautobot/project-static/docs/development/best-practices.html +1 -2
- nautobot/project-static/docs/development/core/application-registry.html +10 -10
- nautobot/project-static/docs/development/core/best-practices.html +10 -10
- nautobot/project-static/docs/development/core/bootstrap-ui.html +10 -10
- nautobot/project-static/docs/development/core/caching.html +10 -10
- nautobot/project-static/docs/development/core/controllers.html +10 -10
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +10 -10
- nautobot/project-static/docs/development/core/extending-models.html +1 -2
- nautobot/project-static/docs/development/core/generic-views.html +10 -10
- nautobot/project-static/docs/development/core/getting-started.html +10 -10
- nautobot/project-static/docs/development/core/homepage.html +10 -10
- nautobot/project-static/docs/development/core/index.html +10 -10
- nautobot/project-static/docs/development/core/model-checklist.html +10 -10
- nautobot/project-static/docs/development/core/model-features.html +10 -10
- nautobot/project-static/docs/development/core/natural-keys.html +10 -10
- nautobot/project-static/docs/development/core/navigation-menu.html +10 -10
- nautobot/project-static/docs/development/core/react-ui.html +1 -2
- nautobot/project-static/docs/development/core/release-checklist.html +10 -10
- nautobot/project-static/docs/development/core/role-internals.html +10 -10
- nautobot/project-static/docs/development/core/settings.html +10 -10
- nautobot/project-static/docs/development/core/style-guide.html +10 -10
- nautobot/project-static/docs/development/core/templates.html +10 -10
- nautobot/project-static/docs/development/core/testing.html +12 -12
- nautobot/project-static/docs/development/core/user-preferences.html +10 -10
- nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1 -2
- nautobot/project-static/docs/development/extending-models.html +1 -2
- nautobot/project-static/docs/development/generic-views.html +1 -2
- nautobot/project-static/docs/development/getting-started.html +1 -2
- nautobot/project-static/docs/development/homepage.html +1 -2
- nautobot/project-static/docs/development/index.html +10 -10
- nautobot/project-static/docs/development/jobs/index.html +10 -10
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +10 -10
- nautobot/project-static/docs/development/model-features.html +1 -2
- nautobot/project-static/docs/development/natural-keys.html +1 -2
- nautobot/project-static/docs/development/navigation-menu.html +1 -2
- nautobot/project-static/docs/development/react-ui.html +1 -2
- nautobot/project-static/docs/development/release-checklist.html +1 -2
- nautobot/project-static/docs/development/role-internals.html +1 -2
- nautobot/project-static/docs/development/style-guide.html +1 -2
- nautobot/project-static/docs/development/templates.html +1 -2
- nautobot/project-static/docs/development/testing.html +1 -2
- nautobot/project-static/docs/development/user-preferences.html +1 -2
- nautobot/project-static/docs/docker/index.html +1 -2
- nautobot/project-static/docs/index.html +10 -10
- nautobot/project-static/docs/installation/centos.html +1 -2
- nautobot/project-static/docs/installation/external-authentication.html +1 -2
- nautobot/project-static/docs/installation/http-server.html +1 -2
- nautobot/project-static/docs/installation/index.html +1 -2
- nautobot/project-static/docs/installation/migrating-from-netbox.html +1 -2
- nautobot/project-static/docs/installation/migrating-from-postgresql.html +1 -2
- nautobot/project-static/docs/installation/nautobot.html +1 -2
- nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1 -2
- nautobot/project-static/docs/installation/selinux-troubleshooting.html +1 -2
- nautobot/project-static/docs/installation/services.html +1 -2
- nautobot/project-static/docs/installation/ubuntu.html +1 -2
- nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +1 -2
- nautobot/project-static/docs/installation/upgrading.html +1 -2
- nautobot/project-static/docs/models/circuits/circuit.html +1 -2
- nautobot/project-static/docs/models/circuits/circuittermination.html +1 -2
- nautobot/project-static/docs/models/circuits/circuittype.html +1 -2
- nautobot/project-static/docs/models/circuits/provider.html +1 -2
- nautobot/project-static/docs/models/circuits/providernetwork.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudaccount.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudnetwork.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudresourcetype.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudservice.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +1 -2
- nautobot/project-static/docs/models/dcim/cable.html +1 -2
- nautobot/project-static/docs/models/dcim/consoleport.html +1 -2
- nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/consoleserverport.html +1 -2
- nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/controller.html +1 -2
- nautobot/project-static/docs/models/dcim/controllermanageddevicegroup.html +1 -2
- nautobot/project-static/docs/models/dcim/device.html +1 -2
- nautobot/project-static/docs/models/dcim/devicebay.html +1 -2
- nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/devicefamily.html +1 -2
- nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1 -2
- nautobot/project-static/docs/models/dcim/devicetype.html +1 -2
- nautobot/project-static/docs/models/dcim/frontport.html +1 -2
- nautobot/project-static/docs/models/dcim/frontporttemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/interface.html +1 -2
- nautobot/project-static/docs/models/dcim/interfacetemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/inventoryitem.html +1 -2
- nautobot/project-static/docs/models/dcim/location.html +1 -2
- nautobot/project-static/docs/models/dcim/locationtype.html +1 -2
- nautobot/project-static/docs/models/dcim/manufacturer.html +1 -2
- nautobot/project-static/docs/models/dcim/module.html +1 -2
- nautobot/project-static/docs/models/dcim/modulebay.html +1 -2
- nautobot/project-static/docs/models/dcim/modulebaytemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/moduletype.html +1 -2
- nautobot/project-static/docs/models/dcim/platform.html +1 -2
- nautobot/project-static/docs/models/dcim/powerfeed.html +1 -2
- nautobot/project-static/docs/models/dcim/poweroutlet.html +1 -2
- nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/powerpanel.html +1 -2
- nautobot/project-static/docs/models/dcim/powerport.html +1 -2
- nautobot/project-static/docs/models/dcim/powerporttemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/rack.html +1 -2
- nautobot/project-static/docs/models/dcim/rackgroup.html +1 -2
- nautobot/project-static/docs/models/dcim/rackreservation.html +1 -2
- nautobot/project-static/docs/models/dcim/rearport.html +1 -2
- nautobot/project-static/docs/models/dcim/rearporttemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/softwareimagefile.html +1 -2
- nautobot/project-static/docs/models/dcim/softwareversion.html +1 -2
- nautobot/project-static/docs/models/dcim/virtualchassis.html +1 -2
- nautobot/project-static/docs/models/extras/computedfield.html +1 -2
- nautobot/project-static/docs/models/extras/configcontext.html +1 -2
- nautobot/project-static/docs/models/extras/configcontextschema.html +1 -2
- nautobot/project-static/docs/models/extras/contact.html +1 -2
- nautobot/project-static/docs/models/extras/customfield.html +1 -2
- nautobot/project-static/docs/models/extras/customlink.html +1 -2
- nautobot/project-static/docs/models/extras/dynamicgroup.html +1 -2
- nautobot/project-static/docs/models/extras/exporttemplate.html +1 -2
- nautobot/project-static/docs/models/extras/gitrepository.html +1 -2
- nautobot/project-static/docs/models/extras/jobhook.html +1 -2
- nautobot/project-static/docs/models/extras/joblogentry.html +1 -2
- nautobot/project-static/docs/models/extras/jobresult.html +1 -2
- nautobot/project-static/docs/models/extras/metadatachoice.html +1 -2
- nautobot/project-static/docs/models/extras/metadatatype.html +1 -2
- nautobot/project-static/docs/models/extras/objectmetadata.html +1 -2
- nautobot/project-static/docs/models/extras/role.html +1 -2
- nautobot/project-static/docs/models/extras/savedview.html +1 -2
- nautobot/project-static/docs/models/extras/secret.html +1 -2
- nautobot/project-static/docs/models/extras/secretsgroup.html +1 -2
- nautobot/project-static/docs/models/extras/staticgroupassociation.html +1 -2
- nautobot/project-static/docs/models/extras/status.html +1 -2
- nautobot/project-static/docs/models/extras/team.html +1 -2
- nautobot/project-static/docs/models/ipam/ipaddress.html +1 -2
- nautobot/project-static/docs/models/ipam/prefix.html +1 -2
- nautobot/project-static/docs/models/ipam/rir.html +1 -2
- nautobot/project-static/docs/models/ipam/routetarget.html +1 -2
- nautobot/project-static/docs/models/ipam/service.html +1 -2
- nautobot/project-static/docs/models/ipam/vlan.html +1 -2
- nautobot/project-static/docs/models/ipam/vlangroup.html +1 -2
- nautobot/project-static/docs/models/ipam/vrf.html +1 -2
- nautobot/project-static/docs/models/tenancy/tenant.html +1 -2
- nautobot/project-static/docs/models/tenancy/tenantgroup.html +1 -2
- nautobot/project-static/docs/models/virtualization/cluster.html +1 -2
- nautobot/project-static/docs/models/virtualization/clustergroup.html +1 -2
- nautobot/project-static/docs/models/virtualization/clustertype.html +1 -2
- nautobot/project-static/docs/models/virtualization/virtualmachine.html +1 -2
- nautobot/project-static/docs/models/virtualization/vminterface.html +1 -2
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +10 -10
- nautobot/project-static/docs/overview/design_philosophy.html +10 -10
- nautobot/project-static/docs/overview/index.html +1 -2
- nautobot/project-static/docs/plugins/development.html +1 -2
- nautobot/project-static/docs/plugins/index.html +1 -2
- nautobot/project-static/docs/plugins/porting-from-netbox.html +1 -2
- nautobot/project-static/docs/release-notes/index.html +15 -15
- nautobot/project-static/docs/release-notes/version-1.0.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.1.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.2.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.3.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.4.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.5.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.6.html +623 -188
- nautobot/project-static/docs/release-notes/version-2.0.html +10 -10
- nautobot/project-static/docs/release-notes/version-2.1.html +10 -10
- nautobot/project-static/docs/release-notes/version-2.2.html +10 -10
- nautobot/project-static/docs/release-notes/version-2.3.html +548 -192
- nautobot/project-static/docs/requirements.txt +2 -2
- nautobot/project-static/docs/rest-api/overview.html +1 -2
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +270 -270
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +10 -10
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +10 -10
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +65 -12
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +10 -10
- nautobot/project-static/docs/user-guide/administration/configuration/node-configuration.html +1 -2
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +1 -2
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +10 -10
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +1 -2
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +122 -10
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +1 -2
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +1 -2
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/docker.html +1 -2
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +1 -2
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/index.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +1 -2
- nautobot/project-static/docs/user-guide/administration/installation/services.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +1 -2
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +1 -2
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +1 -2
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +10 -10
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +10 -10
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +10 -10
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +10 -10
- nautobot/project-static/docs/user-guide/index.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +10 -10
- nautobot/project-static/docs/user-guides/custom-fields.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/index.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/ipam.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/platforms.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/tenants.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1 -2
- nautobot/project-static/docs/user-guides/git-data-source.html +1 -2
- nautobot/project-static/docs/user-guides/graphql.html +1 -2
- nautobot/project-static/docs/user-guides/ip-address-merge-tool.html +1 -2
- nautobot/project-static/docs/user-guides/relationships.html +1 -2
- nautobot/project-static/docs/user-guides/s3-django-storage.html +1 -2
- nautobot/project-static/js/forms.js +10 -0
- nautobot/users/api/serializers.py +1 -0
- nautobot/virtualization/filters.py +19 -2
- nautobot/virtualization/forms.py +3 -3
- nautobot/virtualization/templates/virtualization/vminterface.html +4 -0
- nautobot/virtualization/tests/test_filters.py +9 -0
- {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/METADATA +4 -4
- {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/RECORD +514 -513
- nautobot/project-static/docs/assets/stylesheets/main.0253249f.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.0253249f.min.css.map +0 -1
- {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/NOTICE +0 -0
- {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/WHEEL +0 -0
- {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/entry_points.txt +0 -0
nautobot/core/api/serializers.py
CHANGED
|
@@ -134,6 +134,7 @@ class BaseModelSerializer(OptInFieldsMixin, serializers.HyperlinkedModelSerializ
|
|
|
134
134
|
|
|
135
135
|
serializer_related_field = NautobotHyperlinkedRelatedField
|
|
136
136
|
|
|
137
|
+
id = serializers.UUIDField(read_only=False, default=serializers.CreateOnlyDefault(uuid.uuid4))
|
|
137
138
|
display = serializers.SerializerMethodField(read_only=True, help_text="Human friendly display value")
|
|
138
139
|
object_type = ObjectTypeField()
|
|
139
140
|
# composite_key = serializers.SerializerMethodField() # TODO: Revisit if we reintroduce composite keys
|
nautobot/core/celery/log.py
CHANGED
|
@@ -11,6 +11,10 @@ class NautobotDatabaseHandler(logging.Handler):
|
|
|
11
11
|
if current_task is None:
|
|
12
12
|
return
|
|
13
13
|
|
|
14
|
+
# Skip recording the log entry if it has been marked as such
|
|
15
|
+
if getattr(record, "skip_db_logging", False):
|
|
16
|
+
return
|
|
17
|
+
|
|
14
18
|
from nautobot.extras.models.jobs import JobResult
|
|
15
19
|
|
|
16
20
|
try:
|
|
@@ -24,10 +28,6 @@ class NautobotDatabaseHandler(logging.Handler):
|
|
|
24
28
|
# JobResult.DoesNotExist - because we might not have a JobResult with that ID
|
|
25
29
|
return
|
|
26
30
|
|
|
27
|
-
# Skip recording the log entry if it has been marked as such
|
|
28
|
-
if getattr(record, "skip_db_logging", False):
|
|
29
|
-
return
|
|
30
|
-
|
|
31
31
|
job_result.log(
|
|
32
32
|
message=record.message,
|
|
33
33
|
level_choice=record.levelname.lower(),
|
|
@@ -111,8 +111,11 @@ class TreeModel(TreeNode):
|
|
|
111
111
|
if display_str:
|
|
112
112
|
return display_str
|
|
113
113
|
try:
|
|
114
|
-
if self.
|
|
115
|
-
|
|
114
|
+
if self.parent_id is not None:
|
|
115
|
+
parent_display_str = cache.get(cache_key.replace(str(self.id), str(self.parent_id)), "")
|
|
116
|
+
if not parent_display_str:
|
|
117
|
+
parent_display_str = self.parent.display
|
|
118
|
+
display_str = parent_display_str + " → "
|
|
116
119
|
except self.DoesNotExist:
|
|
117
120
|
# Expected to occur at times during bulk-delete operations
|
|
118
121
|
pass
|
nautobot/core/settings.py
CHANGED
|
@@ -212,6 +212,32 @@ SOCIAL_AUTH_POSTGRES_JSONFIELD = False
|
|
|
212
212
|
# Nautobot related - May be overridden if using custom social auth backend
|
|
213
213
|
SOCIAL_AUTH_BACKEND_PREFIX = "social_core.backends"
|
|
214
214
|
|
|
215
|
+
# Enables adding the OAuth2/OIDC group sync module to the authentication pipeline
|
|
216
|
+
SSO_ENABLE_GROUP_SYNC = is_truthy(os.getenv("NAUTOBOT_SSO_ENABLE_GROUP_SYNC", "false"))
|
|
217
|
+
if SSO_ENABLE_GROUP_SYNC:
|
|
218
|
+
SOCIAL_AUTH_PIPELINE = (
|
|
219
|
+
"social_core.pipeline.social_auth.social_details",
|
|
220
|
+
"social_core.pipeline.social_auth.social_uid",
|
|
221
|
+
"social_core.pipeline.social_auth.auth_allowed",
|
|
222
|
+
"social_core.pipeline.social_auth.social_user",
|
|
223
|
+
"social_core.pipeline.user.get_username",
|
|
224
|
+
"social_core.pipeline.user.create_user",
|
|
225
|
+
"social_core.pipeline.social_auth.associate_user",
|
|
226
|
+
"social_core.pipeline.social_auth.load_extra_data",
|
|
227
|
+
"social_core.pipeline.user.user_details",
|
|
228
|
+
"nautobot.extras.group_sync.group_sync",
|
|
229
|
+
)
|
|
230
|
+
# OAuth2/OIDC claim where the list of groups the authenticating user is a part of
|
|
231
|
+
SSO_CLAIMS_GROUP = os.getenv("NAUTOBOT_SSO_CLAIMS_GROUP", "groups")
|
|
232
|
+
# list of groups that an authenticating user can be a part of to get the Django staff permission
|
|
233
|
+
SSO_STAFF_GROUPS = [
|
|
234
|
+
group for group in os.getenv("NAUTOBOT_SSO_STAFF_GROUPS", "").split(_CONFIG_SETTING_SEPARATOR) if group != ""
|
|
235
|
+
]
|
|
236
|
+
# list of groups that an authenticating user can be a part of to be a Django super user
|
|
237
|
+
SSO_SUPERUSER_GROUPS = [
|
|
238
|
+
group for group in os.getenv("NAUTOBOT_SSO_SUPERUSER_GROUPS", "").split(_CONFIG_SETTING_SEPARATOR) if group != ""
|
|
239
|
+
]
|
|
240
|
+
|
|
215
241
|
# Job log entry sanitization and similar
|
|
216
242
|
SANITIZER_PATTERNS = [
|
|
217
243
|
# General removal of username-like and password-like tokens
|
nautobot/core/settings.yaml
CHANGED
|
@@ -1705,6 +1705,37 @@ properties:
|
|
|
1705
1705
|
"Single Sign On": "./authentication/sso.md"
|
|
1706
1706
|
"`social-auth-app-django`": "https://python-social-auth.readthedocs.io/en/latest/configuration/django.html"
|
|
1707
1707
|
type: "string"
|
|
1708
|
+
SSO_CLAIMS_GROUP:
|
|
1709
|
+
default: "groups"
|
|
1710
|
+
description: "OAuth2/OIDC claim which will contain the groups which the authenticated user is a member of."
|
|
1711
|
+
environment_variable: "NAUTOBOT_SSO_CLAIMS_GROUP"
|
|
1712
|
+
see_also:
|
|
1713
|
+
"Single Sign On": "./authentication/sso.md"
|
|
1714
|
+
SSO_ENABLE_GROUP_SYNC:
|
|
1715
|
+
default: false
|
|
1716
|
+
type: "boolean"
|
|
1717
|
+
description: "Enables the group syncing authentication module."
|
|
1718
|
+
environment_variable: "NAUTOBOT_SSO_ENABLE_GROUP_SYNC"
|
|
1719
|
+
see_also:
|
|
1720
|
+
"Single Sign On": "./authentication/sso.md"
|
|
1721
|
+
SSO_STAFF_GROUPS:
|
|
1722
|
+
default: []
|
|
1723
|
+
description: "List of groups that a user can be a member of to get the Django Staff permission."
|
|
1724
|
+
environment_variable: "NAUTOBOT_SSO_STAFF_GROUPS"
|
|
1725
|
+
see_also:
|
|
1726
|
+
"Single Sign On": "./authentication/sso.md"
|
|
1727
|
+
items:
|
|
1728
|
+
type: "string"
|
|
1729
|
+
type: "array"
|
|
1730
|
+
SSO_SUPERUSER_GROUPS:
|
|
1731
|
+
default: []
|
|
1732
|
+
description: "List of groups that a user can be a member of to be a Django Super User."
|
|
1733
|
+
environment_variable: "NAUTOBOT_SSO_SUPERUSER_GROUPS"
|
|
1734
|
+
see_also:
|
|
1735
|
+
"Single Sign On": "./authentication/sso.md"
|
|
1736
|
+
items:
|
|
1737
|
+
type: "string"
|
|
1738
|
+
type: "array"
|
|
1708
1739
|
STATIC_ROOT:
|
|
1709
1740
|
"$ref": "#/definitions/absolute_path"
|
|
1710
1741
|
default: "~/.nautobot/static"
|
nautobot/core/tables.py
CHANGED
|
@@ -14,7 +14,8 @@ from django.utils.http import urlencode
|
|
|
14
14
|
from django.utils.safestring import mark_safe
|
|
15
15
|
from django.utils.text import Truncator
|
|
16
16
|
import django_tables2
|
|
17
|
-
from django_tables2.data import TableQuerysetData
|
|
17
|
+
from django_tables2.data import TableData, TableQuerysetData
|
|
18
|
+
from django_tables2.rows import BoundRows
|
|
18
19
|
from django_tables2.utils import Accessor, OrderBy, OrderByTuple
|
|
19
20
|
from tree_queries.models import TreeNode
|
|
20
21
|
|
|
@@ -46,8 +47,24 @@ class BaseTable(django_tables2.Table):
|
|
|
46
47
|
user=None,
|
|
47
48
|
hide_hierarchy_ui=False,
|
|
48
49
|
order_by=None,
|
|
50
|
+
data_transform_callback=None,
|
|
49
51
|
**kwargs,
|
|
50
52
|
):
|
|
53
|
+
"""
|
|
54
|
+
Instantiate a BaseTable.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
*args (list, optional): Passed through to django_tables2.Table
|
|
58
|
+
table_changes_pending (bool): TODO
|
|
59
|
+
saved_view (SavedView, optional): TODO
|
|
60
|
+
user (User, optional): TODO
|
|
61
|
+
hide_hierarchy_ui (bool): Whether to display or hide hierarchy indentation of nested objects.
|
|
62
|
+
order_by (list, optional): Field(s) to sort by
|
|
63
|
+
data_transform_callback (function, optional): A function that takes the given `data` as an input and
|
|
64
|
+
returns new data. Runs after all of the queryset auto-optimization performed by this class.
|
|
65
|
+
Used for example in IPAM views to inject "fake" records for "available" Prefixes, IPAddresses, or VLANs.
|
|
66
|
+
**kwargs (dict, optional): Passed through to django_tables2.Table
|
|
67
|
+
"""
|
|
51
68
|
# Add custom field columns
|
|
52
69
|
model = self._meta.model
|
|
53
70
|
|
|
@@ -89,6 +106,14 @@ class BaseTable(django_tables2.Table):
|
|
|
89
106
|
# Init table
|
|
90
107
|
super().__init__(*args, order_by=order_by, **kwargs)
|
|
91
108
|
|
|
109
|
+
if not isinstance(self.data, TableQuerysetData):
|
|
110
|
+
# LinkedCountColumns don't work properly if the data is a list of dicts instead of a queryset,
|
|
111
|
+
# as they rely on a `queryset.annotate()` call to gather the data.
|
|
112
|
+
self.exclude = [
|
|
113
|
+
*self.exclude,
|
|
114
|
+
*[column.name for column in self.columns if isinstance(column.column, LinkedCountColumn)],
|
|
115
|
+
]
|
|
116
|
+
|
|
92
117
|
# Don't show hierarchy if we're sorted
|
|
93
118
|
if order_by is not None and hide_hierarchy_ui is None:
|
|
94
119
|
hide_hierarchy_ui = True
|
|
@@ -122,7 +147,7 @@ class BaseTable(django_tables2.Table):
|
|
|
122
147
|
columns = user.get_config(f"tables.{self.__class__.__name__}.columns")
|
|
123
148
|
if columns:
|
|
124
149
|
for name, column in self.base_columns.items():
|
|
125
|
-
if name in columns:
|
|
150
|
+
if name in columns and name not in self.exclude:
|
|
126
151
|
self.columns.show(name)
|
|
127
152
|
else:
|
|
128
153
|
self.columns.hide(name)
|
|
@@ -161,7 +186,8 @@ class BaseTable(django_tables2.Table):
|
|
|
161
186
|
logger.error("Couldn't find model for %s", column.column.viewname)
|
|
162
187
|
continue
|
|
163
188
|
reverse_lookup = column.column.reverse_lookup or next(iter(column.column.url_params.keys()))
|
|
164
|
-
|
|
189
|
+
distinct = column.column.distinct
|
|
190
|
+
count_fields.append((column.name, column_model, reverse_lookup, distinct))
|
|
165
191
|
try:
|
|
166
192
|
lookup = column.column.lookup or get_related_field_for_models(model, column_model).name
|
|
167
193
|
# For some reason get_related_field_for_models(Tag, DynamicGroup) gives a M2M with the name
|
|
@@ -173,7 +199,8 @@ class BaseTable(django_tables2.Table):
|
|
|
173
199
|
if lookup is not None:
|
|
174
200
|
# Also attempt to prefetch the first matching record for display - see LinkedCountColumn
|
|
175
201
|
prefetch_fields.append(
|
|
176
|
-
|
|
202
|
+
# Use order_by() because we don't care about ordering here and it's potentially expensive
|
|
203
|
+
Prefetch(lookup, column_model.objects.order_by()[:1], to_attr=f"{lookup}_list")
|
|
177
204
|
)
|
|
178
205
|
continue
|
|
179
206
|
|
|
@@ -256,24 +283,34 @@ class BaseTable(django_tables2.Table):
|
|
|
256
283
|
)
|
|
257
284
|
|
|
258
285
|
if count_fields:
|
|
259
|
-
for column_name, column_model, lookup_name in count_fields:
|
|
286
|
+
for column_name, column_model, lookup_name, distinct in count_fields:
|
|
260
287
|
if hasattr(queryset.first(), column_name):
|
|
261
288
|
continue
|
|
262
289
|
try:
|
|
263
290
|
logger.debug(
|
|
264
|
-
"Applying .annotate(%s=count_related(%s, %r) to %s QuerySet",
|
|
291
|
+
"Applying .annotate(%s=count_related(%s, %r, distinct=%s) to %s QuerySet",
|
|
265
292
|
column_name,
|
|
266
293
|
column_model.__name__,
|
|
267
294
|
lookup_name,
|
|
295
|
+
distinct,
|
|
268
296
|
model.__name__,
|
|
269
297
|
)
|
|
270
|
-
queryset = queryset.annotate(
|
|
298
|
+
queryset = queryset.annotate(
|
|
299
|
+
**{column_name: count_related(column_model, lookup_name, distinct=distinct)}
|
|
300
|
+
)
|
|
271
301
|
except FieldError:
|
|
272
302
|
# No error message logged here as the above is *very much* best-effort
|
|
273
303
|
pass
|
|
274
304
|
|
|
275
305
|
self.data.data = queryset
|
|
276
306
|
|
|
307
|
+
# TODO: it would be better if we could apply this transformation and the above queryset optimizations
|
|
308
|
+
# **before** calling super().__init__(), but the current implementation works for now, though inelegant.
|
|
309
|
+
if data_transform_callback is not None:
|
|
310
|
+
self.data = TableData.from_data(data_transform_callback(self.data.data))
|
|
311
|
+
self.data.set_table(self)
|
|
312
|
+
self.rows = BoundRows(data=self.data, table=self, pinned_data=self.pinned_data)
|
|
313
|
+
|
|
277
314
|
@property
|
|
278
315
|
def configurable_columns(self):
|
|
279
316
|
selected_columns = [
|
|
@@ -288,7 +325,7 @@ class BaseTable(django_tables2.Table):
|
|
|
288
325
|
|
|
289
326
|
@property
|
|
290
327
|
def visible_columns(self):
|
|
291
|
-
return [name for name in self.sequence if self.columns[name].visible]
|
|
328
|
+
return [name for name in self.sequence if self.columns[name].visible and name not in self.exclude]
|
|
292
329
|
|
|
293
330
|
@property
|
|
294
331
|
def order_by(self):
|
|
@@ -490,6 +527,7 @@ class LinkedCountColumn(django_tables2.Column):
|
|
|
490
527
|
TODO: this currently does *not* support nested lookups via `__`. That may be solvable in the future.
|
|
491
528
|
reverse_lookup (str, optional): The reverse lookup parameter to use to derive the count.
|
|
492
529
|
If not specified, the first key in `url_params` will be implicitly used as the `reverse_lookup` value.
|
|
530
|
+
distinct (bool, optional): Parameter passed through to `count_related()`.
|
|
493
531
|
**kwargs (dict, optional): As the parent Column class.
|
|
494
532
|
|
|
495
533
|
Examples:
|
|
@@ -514,21 +552,33 @@ class LinkedCountColumn(django_tables2.Column):
|
|
|
514
552
|
# We'd like to do the below but this module isn't currently smart enough to build the right Prefetch()
|
|
515
553
|
# for a nested lookup:
|
|
516
554
|
# lookup="circuit_terminations__circuit",
|
|
517
|
-
# For the count,
|
|
555
|
+
# For the count,
|
|
556
|
+
# .annotate(circuit_count=count_related(Circuit, "circuit_terminations__cloud_network", distinct=True))
|
|
518
557
|
reverse_lookup="circuit_terminations__cloud_network",
|
|
558
|
+
distinct=True,
|
|
519
559
|
verbose_name="Circuits",
|
|
520
560
|
)
|
|
521
561
|
```
|
|
522
562
|
"""
|
|
523
563
|
|
|
524
564
|
def __init__(
|
|
525
|
-
self,
|
|
565
|
+
self,
|
|
566
|
+
viewname,
|
|
567
|
+
*args,
|
|
568
|
+
view_kwargs=None,
|
|
569
|
+
url_params=None,
|
|
570
|
+
lookup=None,
|
|
571
|
+
reverse_lookup=None,
|
|
572
|
+
distinct=False,
|
|
573
|
+
default=None,
|
|
574
|
+
**kwargs,
|
|
526
575
|
):
|
|
527
576
|
self.viewname = viewname
|
|
528
577
|
self.lookup = lookup
|
|
529
578
|
self.view_kwargs = view_kwargs or {}
|
|
530
579
|
self.url_params = url_params
|
|
531
580
|
self.reverse_lookup = reverse_lookup or next(iter(url_params.keys()))
|
|
581
|
+
self.distinct = distinct
|
|
532
582
|
self.model = get_model_for_view_name(self.viewname)
|
|
533
583
|
super().__init__(*args, default=default, **kwargs)
|
|
534
584
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
</div>
|
|
22
22
|
</div>
|
|
23
23
|
<div class="col-md-6 col-md-offset-3 text-right" style="margin-bottom: 20px;">
|
|
24
|
-
<button type="submit" class="btn btn-primary">Create</button>
|
|
24
|
+
<button id="createNote" type="submit" class="btn btn-primary">Create</button>
|
|
25
25
|
<a href="{{ object.get_absolute_url }}" class="btn btn-default">Cancel</a>
|
|
26
26
|
</div>
|
|
27
27
|
</div>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
<h1>
|
|
55
55
|
<span class="hover_copy">
|
|
56
56
|
<span id="copy_title">{% block title %}{{object.display|default:object}}{% endblock %}</span>
|
|
57
|
-
<button type="button" class="btn btn-inline btn-default hover_copy_button" data-clipboard-
|
|
57
|
+
<button type="button" class="btn btn-inline btn-default hover_copy_button" data-clipboard-text="{{ object.display | default:object }}">
|
|
58
58
|
<span class="mdi mdi-content-copy"></span>
|
|
59
59
|
</button>
|
|
60
60
|
</span>
|
|
@@ -795,7 +795,13 @@ def saved_view_modal(
|
|
|
795
795
|
"clear_view",
|
|
796
796
|
]
|
|
797
797
|
|
|
798
|
-
|
|
798
|
+
view_class = lookup.get_view_for_model(model, "List")
|
|
799
|
+
table_name = None
|
|
800
|
+
if hasattr(view_class, "table"):
|
|
801
|
+
table_name = view_class.table.__name__
|
|
802
|
+
if hasattr(view_class, "table_class"):
|
|
803
|
+
table_name = view_class.table_class.__name__
|
|
804
|
+
|
|
799
805
|
for param in non_filter_params:
|
|
800
806
|
if param == "saved_view":
|
|
801
807
|
current_saved_view_pk = filters_applied.pop(param, None)
|
nautobot/core/testing/api.py
CHANGED
|
@@ -707,7 +707,11 @@ class APIViewTestCases:
|
|
|
707
707
|
self.assertHttpStatus(response, status.HTTP_201_CREATED, csv_data)
|
|
708
708
|
# Note that create via CSV is always treated as a bulk-create, and so the response is always a list of dicts
|
|
709
709
|
new_instance = self._get_queryset().get(pk=response.data[0]["id"])
|
|
710
|
-
|
|
710
|
+
if isinstance(orig_pk, int):
|
|
711
|
+
self.assertNotEqual(new_instance.pk, orig_pk)
|
|
712
|
+
else:
|
|
713
|
+
# for our non-integer PKs, we're expecting the creation to respect the requested PK
|
|
714
|
+
self.assertEqual(new_instance.pk, orig_pk)
|
|
711
715
|
|
|
712
716
|
new_serializer = serializer_class(new_instance, context={"request": None})
|
|
713
717
|
new_data = new_serializer.data
|
nautobot/core/testing/views.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import contextlib
|
|
1
2
|
import re
|
|
2
3
|
from typing import Optional, Sequence
|
|
3
4
|
from unittest import skipIf
|
|
@@ -792,11 +793,16 @@ class ViewTestCases:
|
|
|
792
793
|
response = self.client.get(f"{self._get_url('list')}?id={instance1.pk}")
|
|
793
794
|
self.assertHttpStatus(response, 200)
|
|
794
795
|
content = utils.extract_page_body(response.content.decode(response.charset))
|
|
796
|
+
# There should be only one row in the table
|
|
797
|
+
self.assertIn('<tr class="even', content)
|
|
798
|
+
self.assertNotIn('<tr class="odd', content)
|
|
795
799
|
if hasattr(self.model, "name"):
|
|
796
800
|
self.assertRegex(content, r">\s*" + re.escape(escape(instance1.name)) + r"\s*<", msg=content)
|
|
797
801
|
self.assertNotRegex(content, r">\s*" + re.escape(escape(instance2.name)) + r"\s*<", msg=content)
|
|
798
|
-
|
|
799
|
-
|
|
802
|
+
with contextlib.suppress(AttributeError):
|
|
803
|
+
# Some models, such as ObjectMetadata, don't have a detail URL
|
|
804
|
+
if instance1.get_absolute_url() in content:
|
|
805
|
+
self.assertNotIn(instance2.get_absolute_url(), content, msg=content)
|
|
800
806
|
|
|
801
807
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"], STRICT_FILTERING=True)
|
|
802
808
|
def test_list_objects_unknown_filter_strict_filtering(self):
|
|
@@ -833,11 +839,16 @@ class ViewTestCases:
|
|
|
833
839
|
content = utils.extract_page_body(response.content.decode(response.charset))
|
|
834
840
|
self.assertNotIn("Unknown filter field", content, msg=content)
|
|
835
841
|
self.assertIn("None", content, msg=content)
|
|
842
|
+
# There should be at least two rows in the table
|
|
843
|
+
self.assertIn('<tr class="even', content)
|
|
844
|
+
self.assertIn('<tr class="odd', content)
|
|
836
845
|
if hasattr(self.model, "name"):
|
|
837
846
|
self.assertRegex(content, r">\s*" + re.escape(escape(instance1.name)) + r"\s*<", msg=content)
|
|
838
847
|
self.assertRegex(content, r">\s*" + re.escape(escape(instance2.name)) + r"\s*<", msg=content)
|
|
839
|
-
|
|
840
|
-
|
|
848
|
+
with contextlib.suppress(AttributeError):
|
|
849
|
+
# Some models, such as ObjectMetadata, don't have a detail URL
|
|
850
|
+
if instance1.get_absolute_url() in content:
|
|
851
|
+
self.assertIn(instance2.get_absolute_url(), content, msg=content)
|
|
841
852
|
|
|
842
853
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=[])
|
|
843
854
|
def test_list_objects_without_permission(self):
|
nautobot/core/tests/test_api.py
CHANGED
|
@@ -3,6 +3,7 @@ from io import BytesIO, StringIO
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
from unittest import skip
|
|
6
|
+
import uuid
|
|
6
7
|
|
|
7
8
|
from constance import config
|
|
8
9
|
from constance.test import override_config
|
|
@@ -754,6 +755,25 @@ class WritableNestedSerializerTest(testing.APITestCase):
|
|
|
754
755
|
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
|
|
755
756
|
self.assertEqual(ipam_models.VLAN.objects.filter(name="Test VLAN 100").count(), 0)
|
|
756
757
|
|
|
758
|
+
def test_create_with_specified_id(self):
|
|
759
|
+
data = {
|
|
760
|
+
"id": str(uuid.uuid4()),
|
|
761
|
+
"vid": 400,
|
|
762
|
+
"name": "Test VLAN 400",
|
|
763
|
+
"status": self.statuses.first().pk,
|
|
764
|
+
"vlan_group": self.vlan_group1.pk,
|
|
765
|
+
}
|
|
766
|
+
url = reverse("ipam-api:vlan-list")
|
|
767
|
+
self.add_permissions("ipam.add_vlan")
|
|
768
|
+
|
|
769
|
+
response = self.client.post(url, data, format="json", **self.header)
|
|
770
|
+
self.assertHttpStatus(response, status.HTTP_201_CREATED)
|
|
771
|
+
self.assertEqual(str(response.data["vlan_group"]["url"]), self.absolute_api_url(self.vlan_group1))
|
|
772
|
+
self.assertEqual(str(response.data["id"]), data["id"])
|
|
773
|
+
vlan = ipam_models.VLAN.objects.get(pk=response.data["id"])
|
|
774
|
+
self.assertEqual(vlan.status, self.statuses.first())
|
|
775
|
+
self.assertEqual(vlan.vlan_group, self.vlan_group1)
|
|
776
|
+
|
|
757
777
|
|
|
758
778
|
class APIOrderingTestCase(testing.APITestCase):
|
|
759
779
|
"""
|
nautobot/core/tests/test_csv.py
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
import io
|
|
3
|
+
|
|
1
4
|
from django.contrib.contenttypes.models import ContentType
|
|
2
5
|
from django.test import override_settings, RequestFactory, TestCase
|
|
3
6
|
from django.urls import reverse
|
|
@@ -261,9 +264,28 @@ class CSVParsingRelatedTestCase(TestCase):
|
|
|
261
264
|
self.assertEqual(response.status_code, 200)
|
|
262
265
|
response_data = response.content.decode(response.charset)
|
|
263
266
|
|
|
264
|
-
#
|
|
265
|
-
|
|
266
|
-
|
|
267
|
+
# parse the csv data
|
|
268
|
+
csv_reader = csv.DictReader(response_data.splitlines())
|
|
269
|
+
# remove the 'id' column so that all the items are imported new
|
|
270
|
+
fieldnames = [field for field in csv_reader.fieldnames if field != "id"]
|
|
271
|
+
# read all entries into a list
|
|
272
|
+
response_csv = list(csv_reader)
|
|
273
|
+
|
|
274
|
+
# mutate our data for testing purposes
|
|
275
|
+
for row in response_csv:
|
|
276
|
+
if row["name"] == "TestDevice1":
|
|
277
|
+
row["name"] = "TestDevice3"
|
|
278
|
+
elif row["name"] == "TestDevice2":
|
|
279
|
+
row["name"] = ""
|
|
280
|
+
|
|
281
|
+
# prep our data to write out
|
|
282
|
+
with io.StringIO() as import_csv:
|
|
283
|
+
writer = csv.DictWriter(import_csv, fieldnames=fieldnames)
|
|
284
|
+
writer.writeheader()
|
|
285
|
+
for row in response_csv:
|
|
286
|
+
filtered_row = {key: row[key] for key in fieldnames}
|
|
287
|
+
writer.writerow(filtered_row)
|
|
288
|
+
data = {"csv_data": import_csv.getvalue()}
|
|
267
289
|
url = reverse("dcim:device_import")
|
|
268
290
|
response = self.client.post(url, data)
|
|
269
291
|
self.assertEqual(response.status_code, 200)
|
|
@@ -268,6 +268,14 @@ class GetFooForModelTest(TestCase):
|
|
|
268
268
|
lookup.get_model_for_view_name("unknown:plugins:example_app:examplemodel_list")
|
|
269
269
|
self.assertEqual(str(err.exception), "Unexpected View Name: unknown:plugins:example_app:examplemodel_list")
|
|
270
270
|
|
|
271
|
+
def test_get_table_class_string_from_view_name(self):
|
|
272
|
+
# Testing UIViewSet
|
|
273
|
+
self.assertEqual(lookup.get_table_class_string_from_view_name("circuits:circuit_list"), "CircuitTable")
|
|
274
|
+
# Testing Legacy View
|
|
275
|
+
self.assertEqual(lookup.get_table_class_string_from_view_name("dcim:location_list"), "LocationTable")
|
|
276
|
+
# Testing unconventional table name
|
|
277
|
+
self.assertEqual(lookup.get_table_class_string_from_view_name("ipam:prefix_list"), "PrefixDetailTable")
|
|
278
|
+
|
|
271
279
|
|
|
272
280
|
class IsTaggableTest(TestCase):
|
|
273
281
|
def test_is_taggable_true(self):
|
nautobot/core/utils/lookup.py
CHANGED
|
@@ -8,7 +8,7 @@ from django.conf import settings
|
|
|
8
8
|
from django.contrib.auth.models import Group
|
|
9
9
|
from django.contrib.contenttypes.models import ContentType
|
|
10
10
|
from django.db.models import Model
|
|
11
|
-
from django.urls import get_resolver, URLPattern, URLResolver
|
|
11
|
+
from django.urls import get_resolver, resolve, reverse, URLPattern, URLResolver
|
|
12
12
|
from django.utils.module_loading import import_string
|
|
13
13
|
|
|
14
14
|
|
|
@@ -212,7 +212,7 @@ def get_related_field_for_models(from_model, to_model):
|
|
|
212
212
|
return matching_field
|
|
213
213
|
|
|
214
214
|
|
|
215
|
-
def get_table_for_model(model):
|
|
215
|
+
def get_table_for_model(model, suffix=None):
|
|
216
216
|
"""Return the `Table` class associated with a given `model`.
|
|
217
217
|
|
|
218
218
|
The `Table` class is expected to be in the `tables` module within the application
|
|
@@ -222,11 +222,12 @@ def get_table_for_model(model):
|
|
|
222
222
|
|
|
223
223
|
Args:
|
|
224
224
|
model (BaseModel): A model class
|
|
225
|
+
suffix (str): A replacement suffix for the table name (e.g. `DetailTable`, such as to retrieve `FooDetailTable`)
|
|
225
226
|
|
|
226
227
|
Returns:
|
|
227
228
|
(Union[Table, None]): Either the `Table` class or `None`
|
|
228
229
|
"""
|
|
229
|
-
return get_related_class_for_model(model, module_name="tables", object_suffix="Table")
|
|
230
|
+
return get_related_class_for_model(model, module_name="tables", object_suffix=suffix or "Table")
|
|
230
231
|
|
|
231
232
|
|
|
232
233
|
def get_view_for_model(model, view_type=""):
|
|
@@ -275,11 +276,13 @@ def get_table_class_string_from_view_name(view_name):
|
|
|
275
276
|
Returns:
|
|
276
277
|
table_class_name (String): The name of the model table class or None e.g. LocationTable, CircuitTable
|
|
277
278
|
"""
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
279
|
+
|
|
280
|
+
view_func = resolve(reverse(view_name)).func
|
|
281
|
+
view_class = getattr(view_func, "cls", getattr(view_func, "view_class", None))
|
|
282
|
+
if hasattr(view_class, "table_class"):
|
|
283
|
+
return view_class.table_class.__name__
|
|
284
|
+
if hasattr(view_class, "table"):
|
|
285
|
+
return view_class.table.__name__
|
|
283
286
|
return None
|
|
284
287
|
|
|
285
288
|
|
nautobot/dcim/api/views.py
CHANGED
|
@@ -11,6 +11,7 @@ from drf_spectacular.types import OpenApiTypes
|
|
|
11
11
|
from drf_spectacular.utils import extend_schema, OpenApiParameter
|
|
12
12
|
from rest_framework.decorators import action
|
|
13
13
|
from rest_framework.mixins import ListModelMixin
|
|
14
|
+
from rest_framework.parsers import JSONParser, MultiPartParser
|
|
14
15
|
from rest_framework.permissions import IsAuthenticated
|
|
15
16
|
from rest_framework.response import Response
|
|
16
17
|
from rest_framework.viewsets import GenericViewSet, ViewSet
|
|
@@ -18,6 +19,7 @@ from rest_framework.viewsets import GenericViewSet, ViewSet
|
|
|
18
19
|
from nautobot.circuits.models import Circuit
|
|
19
20
|
from nautobot.cloud.models import CloudAccount
|
|
20
21
|
from nautobot.core.api.exceptions import ServiceUnavailable
|
|
22
|
+
from nautobot.core.api.parsers import NautobotCSVParser
|
|
21
23
|
from nautobot.core.api.utils import get_serializer_for_model
|
|
22
24
|
from nautobot.core.api.views import ModelViewSet
|
|
23
25
|
from nautobot.core.models.querysets import count_related
|
|
@@ -300,6 +302,7 @@ class DeviceTypeViewSet(NautobotModelViewSet):
|
|
|
300
302
|
)
|
|
301
303
|
serializer_class = serializers.DeviceTypeSerializer
|
|
302
304
|
filterset_class = filters.DeviceTypeFilterSet
|
|
305
|
+
parser_classes = [JSONParser, NautobotCSVParser, MultiPartParser]
|
|
303
306
|
|
|
304
307
|
|
|
305
308
|
#
|
nautobot/dcim/choices.py
CHANGED
|
@@ -804,6 +804,9 @@ class InterfaceTypeChoices(ChoiceSet):
|
|
|
804
804
|
TYPE_400GE_CFP8 = "400gbase-x-cfp8"
|
|
805
805
|
TYPE_800GE_QSFP_DD = "800gbase-x-qsfpdd"
|
|
806
806
|
TYPE_800GE_OSFP = "800gbase-x-osfp"
|
|
807
|
+
TYPE_800GE_OSFP_XD = "800gbase-x-osfp-xd"
|
|
808
|
+
TYPE_1600GE_OSFP = "1600gbase-x-osfp"
|
|
809
|
+
TYPE_1600GE_OSFP_XD = "1600gbase-x-osfp-xd"
|
|
807
810
|
|
|
808
811
|
# Ethernet Backplane
|
|
809
812
|
TYPE_1GE_KX = "1000base-kx"
|
|
@@ -977,6 +980,9 @@ class InterfaceTypeChoices(ChoiceSet):
|
|
|
977
980
|
(TYPE_400GE_CFP8, "CPF8 (400GE)"),
|
|
978
981
|
(TYPE_800GE_QSFP_DD, "QSFP-DD (800GE)"),
|
|
979
982
|
(TYPE_800GE_OSFP, "OSFP (800GE)"),
|
|
983
|
+
(TYPE_800GE_OSFP_XD, "OSFP-XD (800GE)"),
|
|
984
|
+
(TYPE_1600GE_OSFP, "OSFP (1600GE)"),
|
|
985
|
+
(TYPE_1600GE_OSFP_XD, "OSFP-XD (1600GE)"),
|
|
980
986
|
),
|
|
981
987
|
),
|
|
982
988
|
(
|
|
@@ -903,6 +903,19 @@ class DeviceFilterSet(
|
|
|
903
903
|
to_field_name="version",
|
|
904
904
|
label="Software version (version or ID)",
|
|
905
905
|
)
|
|
906
|
+
ip_addresses = MultiValueCharFilter(
|
|
907
|
+
method="filter_ip_addresses",
|
|
908
|
+
label="IP addresses (address or ID)",
|
|
909
|
+
distinct=True,
|
|
910
|
+
)
|
|
911
|
+
has_ip_addresses = RelatedMembershipBooleanFilter(field_name="interfaces__ip_addresses", label="Has IP addresses")
|
|
912
|
+
|
|
913
|
+
def filter_ip_addresses(self, queryset, name, value):
|
|
914
|
+
pk_values = set(item for item in value if is_uuid(item))
|
|
915
|
+
addresses = set(item for item in value if item not in pk_values)
|
|
916
|
+
|
|
917
|
+
ip_queryset = IPAddress.objects.filter_address_or_pk_in(addresses, pk_values)
|
|
918
|
+
return queryset.filter(interfaces__ip_addresses__in=ip_queryset).distinct()
|
|
906
919
|
|
|
907
920
|
class Meta:
|
|
908
921
|
model = Device
|
|
@@ -1130,6 +1143,19 @@ class InterfaceFilterSet(
|
|
|
1130
1143
|
queryset=InterfaceRedundancyGroup.objects.all(),
|
|
1131
1144
|
to_field_name="name",
|
|
1132
1145
|
)
|
|
1146
|
+
ip_addresses = MultiValueCharFilter(
|
|
1147
|
+
method="filter_ip_addresses",
|
|
1148
|
+
label="IP addresses (address or ID)",
|
|
1149
|
+
distinct=True,
|
|
1150
|
+
)
|
|
1151
|
+
has_ip_addresses = RelatedMembershipBooleanFilter(field_name="ip_addresses", label="Has IP addresses")
|
|
1152
|
+
|
|
1153
|
+
def filter_ip_addresses(self, queryset, name, value):
|
|
1154
|
+
pk_values = set(item for item in value if is_uuid(item))
|
|
1155
|
+
addresses = set(item for item in value if item not in pk_values)
|
|
1156
|
+
|
|
1157
|
+
ip_queryset = IPAddress.objects.filter_address_or_pk_in(addresses, pk_values)
|
|
1158
|
+
return queryset.filter(ip_addresses__in=ip_queryset).distinct()
|
|
1133
1159
|
|
|
1134
1160
|
class Meta:
|
|
1135
1161
|
model = Interface
|
|
@@ -1144,7 +1170,6 @@ class InterfaceFilterSet(
|
|
|
1144
1170
|
"description",
|
|
1145
1171
|
"label",
|
|
1146
1172
|
"tags",
|
|
1147
|
-
"interface_redundancy_groups",
|
|
1148
1173
|
]
|
|
1149
1174
|
|
|
1150
1175
|
def generate_query_filter_device(self, value):
|
nautobot/dcim/forms.py
CHANGED
|
@@ -2123,6 +2123,8 @@ class DeviceBulkEditForm(
|
|
|
2123
2123
|
rack_group = DynamicModelChoiceField(
|
|
2124
2124
|
queryset=RackGroup.objects.all(), required=False, query_params={"location": "$location"}
|
|
2125
2125
|
)
|
|
2126
|
+
cluster = DynamicModelChoiceField(queryset=Cluster.objects.all(), required=False)
|
|
2127
|
+
comments = CommentField(widget=SmallTextarea, label="Comments")
|
|
2126
2128
|
tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
|
2127
2129
|
platform = DynamicModelChoiceField(queryset=Platform.objects.all(), required=False)
|
|
2128
2130
|
serial = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False, label="Serial Number")
|
|
@@ -2146,6 +2148,8 @@ class DeviceBulkEditForm(
|
|
|
2146
2148
|
"position",
|
|
2147
2149
|
"face",
|
|
2148
2150
|
"rack_group",
|
|
2151
|
+
"cluster",
|
|
2152
|
+
"comments",
|
|
2149
2153
|
"secrets_group",
|
|
2150
2154
|
"device_redundancy_group",
|
|
2151
2155
|
"device_redundancy_group_priority",
|