nautobot 2.2.0__py3-none-any.whl → 2.2.0b1__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/apps/api.py +2 -1
- nautobot/apps/utils.py +0 -4
- nautobot/apps/views.py +0 -2
- nautobot/circuits/api/urls.py +2 -1
- nautobot/circuits/api/views.py +12 -0
- nautobot/circuits/tests/test_filters.py +1 -1
- nautobot/core/api/routers.py +3 -25
- nautobot/core/api/utils.py +0 -4
- nautobot/core/api/views.py +15 -21
- nautobot/core/filters.py +1 -7
- nautobot/core/management/commands/generate_test_data.py +4 -4
- nautobot/core/settings.py +0 -1
- nautobot/core/tables.py +1 -2
- nautobot/core/templates/admin/base.html +94 -23
- nautobot/core/templates/graphene/graphiql.html +47 -18
- nautobot/core/templates/inc/footer.html +5 -5
- nautobot/core/templates/inc/nav_menu.html +7 -0
- nautobot/core/templates/rest_framework/api.html +5 -12
- nautobot/core/templatetags/helpers.py +2 -2
- nautobot/core/testing/views.py +0 -30
- nautobot/core/tests/test_api.py +6 -13
- nautobot/core/tests/test_csv.py +4 -5
- nautobot/core/tests/test_filters.py +1 -2
- nautobot/core/tests/test_graphql.py +14 -4
- nautobot/core/tests/test_navigations.py +0 -3
- nautobot/core/tests/test_views.py +16 -22
- nautobot/core/utils/lookup.py +0 -124
- nautobot/core/views/__init__.py +7 -3
- nautobot/core/views/generic.py +3 -19
- nautobot/core/views/mixins.py +0 -7
- nautobot/core/views/renderers.py +1 -4
- nautobot/dcim/api/serializers.py +4 -4
- nautobot/dcim/api/urls.py +3 -2
- nautobot/dcim/api/views.py +18 -7
- nautobot/dcim/factory.py +7 -7
- nautobot/dcim/filters/__init__.py +17 -16
- nautobot/dcim/forms.py +45 -61
- nautobot/dcim/homepage.py +3 -11
- nautobot/dcim/migrations/0057_controller_models.py +70 -11
- nautobot/dcim/models/__init__.py +2 -2
- nautobot/dcim/models/devices.py +16 -14
- nautobot/dcim/models/racks.py +3 -1
- nautobot/dcim/navigation.py +31 -23
- nautobot/dcim/signals.py +6 -6
- nautobot/dcim/tables/__init__.py +2 -2
- nautobot/dcim/tables/devices.py +15 -12
- nautobot/dcim/tables/template_code.py +1 -1
- nautobot/dcim/templates/dcim/controller_retrieve.html +18 -35
- nautobot/dcim/templates/dcim/controllerdevicegroup_create.html +43 -0
- nautobot/dcim/templates/dcim/device/lldp_neighbors.html +43 -67
- nautobot/dcim/templates/dcim/device.html +2 -10
- nautobot/dcim/templates/dcim/device_edit.html +1 -1
- nautobot/dcim/tests/test_api.py +6 -11
- nautobot/dcim/tests/test_filters.py +81 -92
- nautobot/dcim/tests/test_graphql.py +1 -11
- nautobot/dcim/tests/test_models.py +15 -15
- nautobot/dcim/tests/test_signals.py +0 -2
- nautobot/dcim/tests/test_views.py +12 -24
- nautobot/dcim/urls.py +1 -1
- nautobot/dcim/views.py +15 -19
- nautobot/extras/api/urls.py +2 -1
- nautobot/extras/api/views.py +10 -0
- nautobot/extras/filters/__init__.py +2 -53
- nautobot/extras/forms/contacts.py +0 -7
- nautobot/extras/managers.py +0 -14
- nautobot/extras/navigation.py +65 -71
- nautobot/extras/plugins/views.py +11 -7
- nautobot/extras/tests/test_api.py +0 -2
- nautobot/extras/tests/test_dynamicgroups.py +0 -2
- nautobot/extras/tests/test_filters.py +4 -89
- nautobot/extras/tests/test_models.py +0 -9
- nautobot/extras/tests/test_relationships.py +1 -10
- nautobot/extras/tests/test_views.py +1 -112
- nautobot/extras/views.py +10 -10
- nautobot/ipam/api/urls.py +2 -1
- nautobot/ipam/api/views.py +11 -0
- nautobot/ipam/tables.py +22 -2
- nautobot/ipam/tests/test_graphql.py +3 -2
- nautobot/ipam/tests/test_views.py +0 -1
- nautobot/ipam/views.py +9 -9
- nautobot/project-static/css/base.css +0 -1
- nautobot/project-static/docs/404.html +3 -24
- nautobot/project-static/docs/apps/index.html +3 -24
- nautobot/project-static/docs/apps/nautobot-apps.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +5 -26
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +3 -24
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +3 -242
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +5 -69
- nautobot/project-static/docs/development/apps/api/configuration-view.html +3 -24
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +3 -24
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +3 -24
- nautobot/project-static/docs/development/apps/api/models/global-search.html +3 -24
- nautobot/project-static/docs/development/apps/api/models/graphql.html +3 -24
- nautobot/project-static/docs/development/apps/api/models/index.html +3 -24
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +3 -24
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +3 -24
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +3 -24
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +3 -24
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +3 -24
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +3 -24
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +3 -24
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +3 -24
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +3 -24
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +3 -24
- nautobot/project-static/docs/development/apps/api/prometheus.html +3 -24
- nautobot/project-static/docs/development/apps/api/setup.html +3 -24
- nautobot/project-static/docs/development/apps/api/testing.html +3 -24
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +3 -24
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +3 -24
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +3 -24
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +3 -24
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +3 -24
- nautobot/project-static/docs/development/apps/api/views/base-template.html +3 -24
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +12 -38
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +15 -41
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +3 -24
- nautobot/project-static/docs/development/apps/api/views/index.html +3 -24
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +3 -24
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +3 -24
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +3 -24
- nautobot/project-static/docs/development/apps/api/views/notes.html +3 -24
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +3 -24
- nautobot/project-static/docs/development/apps/api/views/urls.html +3 -24
- nautobot/project-static/docs/development/apps/index.html +3 -24
- nautobot/project-static/docs/development/apps/migration/code-updates.html +3 -24
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +3 -24
- nautobot/project-static/docs/development/apps/migration/from-v1.html +3 -24
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +3 -24
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +3 -24
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +3 -24
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +3 -24
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +3 -24
- nautobot/project-static/docs/development/core/application-registry.html +3 -24
- nautobot/project-static/docs/development/core/best-practices.html +3 -24
- nautobot/project-static/docs/development/core/bootstrap-ui.html +3 -24
- nautobot/project-static/docs/development/core/caching.html +3 -24
- nautobot/project-static/docs/development/core/controllers.html +204 -35
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +3 -24
- nautobot/project-static/docs/development/core/extending-models.html +3 -24
- nautobot/project-static/docs/development/core/generic-views.html +3 -24
- nautobot/project-static/docs/development/core/getting-started.html +13 -43
- nautobot/project-static/docs/development/core/homepage.html +3 -24
- nautobot/project-static/docs/development/core/index.html +3 -24
- nautobot/project-static/docs/development/core/model-features.html +3 -24
- nautobot/project-static/docs/development/core/natural-keys.html +3 -24
- nautobot/project-static/docs/development/core/navigation-menu.html +3 -24
- nautobot/project-static/docs/development/core/release-checklist.html +3 -24
- nautobot/project-static/docs/development/core/role-internals.html +3 -24
- nautobot/project-static/docs/development/core/settings.html +3 -24
- nautobot/project-static/docs/development/core/style-guide.html +3 -24
- nautobot/project-static/docs/development/core/templates.html +3 -24
- nautobot/project-static/docs/development/core/testing.html +3 -24
- nautobot/project-static/docs/development/core/user-preferences.html +3 -24
- nautobot/project-static/docs/development/index.html +3 -24
- nautobot/project-static/docs/development/jobs/index.html +3 -24
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +3 -24
- nautobot/project-static/docs/index.html +3 -24
- nautobot/project-static/docs/models/dcim/{controllermanageddevicegroup.html → controllerdevicegroup.html} +3 -3
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/release-notes/index.html +3 -24
- nautobot/project-static/docs/release-notes/version-1.0.html +3 -24
- nautobot/project-static/docs/release-notes/version-1.1.html +3 -24
- nautobot/project-static/docs/release-notes/version-1.2.html +3 -24
- nautobot/project-static/docs/release-notes/version-1.3.html +3 -24
- nautobot/project-static/docs/release-notes/version-1.4.html +3 -24
- nautobot/project-static/docs/release-notes/version-1.5.html +3 -24
- nautobot/project-static/docs/release-notes/version-1.6.html +3 -24
- nautobot/project-static/docs/release-notes/version-2.0.html +3 -24
- nautobot/project-static/docs/release-notes/version-2.1.html +162 -411
- nautobot/project-static/docs/release-notes/version-2.2.html +30 -212
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +255 -260
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +3 -24
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +3 -24
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +3 -24
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +3 -24
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +3 -24
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +3 -24
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +3 -24
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +3 -24
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +3 -24
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +3 -24
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +3 -24
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +3 -24
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +3 -24
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +3 -24
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +3 -24
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +3 -24
- nautobot/project-static/docs/user-guide/administration/installation/docker.html +6 -31
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +3 -24
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +3 -24
- nautobot/project-static/docs/user-guide/administration/installation/index.html +3 -24
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +3 -24
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +3 -24
- nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +6 -27
- nautobot/project-static/docs/user-guide/administration/installation/services.html +3 -24
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +3 -24
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +3 -24
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +3 -24
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +3 -24
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +3 -24
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +3 -24
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +3 -24
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +3 -24
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +3 -24
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +3 -24
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +3 -24
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +3 -24
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +11 -259
- nautobot/project-static/docs/user-guide/core-data-model/dcim/{controllermanageddevicegroup.html → controllerdevicegroup.html} +17 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +6 -27
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +3 -24
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/{contacts-and-teams.html → contact-and-team.html} +4 -25
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +5 -26
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +5 -26
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +3 -24
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +3 -24
- nautobot/project-static/docs/user-guide/index.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +3 -24
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +3 -24
- nautobot/tenancy/api/urls.py +2 -1
- nautobot/tenancy/api/views.py +12 -0
- nautobot/tenancy/tables.py +1 -1
- nautobot/tenancy/tests/test_views.py +0 -1
- nautobot/users/api/urls.py +2 -1
- nautobot/users/api/views.py +65 -2
- nautobot/users/views.py +8 -8
- nautobot/virtualization/api/urls.py +2 -1
- nautobot/virtualization/api/views.py +12 -0
- {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/METADATA +3 -3
- {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/RECORD +356 -361
- nautobot/core/tests/integration/test_view_authentication.py +0 -67
- nautobot/dcim/management/commands/migrate_location_contacts.py +0 -218
- nautobot/dcim/templates/dcim/controller_create.html +0 -70
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +0 -88
- nautobot/ipam/tests/test_tables.py +0 -42
- nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +0 -8581
- /nautobot/dcim/templates/dcim/{controllermanageddevicegroup_retrieve.html → controllerdevicegroup_retrieve.html} +0 -0
- {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/NOTICE +0 -0
- {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/WHEEL +0 -0
- {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from django.test import TestCase
|
|
4
4
|
|
|
5
5
|
from nautobot.dcim.models import (
|
|
6
|
-
Controller,
|
|
7
6
|
Device,
|
|
8
7
|
DeviceRedundancyGroup,
|
|
9
8
|
DeviceType,
|
|
@@ -104,7 +103,6 @@ class DeviceRedundancyGroupTest(TestCase):
|
|
|
104
103
|
self.device.device_redundancy_group_priority = 1
|
|
105
104
|
self.device.validated_save()
|
|
106
105
|
|
|
107
|
-
Controller.objects.all().delete()
|
|
108
106
|
deviceredundancygroup.delete()
|
|
109
107
|
|
|
110
108
|
self.device.refresh_from_db()
|
|
@@ -40,8 +40,8 @@ from nautobot.dcim.choices import (
|
|
|
40
40
|
)
|
|
41
41
|
from nautobot.dcim.filters import (
|
|
42
42
|
ConsoleConnectionFilterSet,
|
|
43
|
+
ControllerDeviceGroupFilterSet,
|
|
43
44
|
ControllerFilterSet,
|
|
44
|
-
ControllerManagedDeviceGroupFilterSet,
|
|
45
45
|
InterfaceConnectionFilterSet,
|
|
46
46
|
PowerConnectionFilterSet,
|
|
47
47
|
SoftwareImageFileFilterSet,
|
|
@@ -55,7 +55,7 @@ from nautobot.dcim.models import (
|
|
|
55
55
|
ConsoleServerPort,
|
|
56
56
|
ConsoleServerPortTemplate,
|
|
57
57
|
Controller,
|
|
58
|
-
|
|
58
|
+
ControllerDeviceGroup,
|
|
59
59
|
Device,
|
|
60
60
|
DeviceBay,
|
|
61
61
|
DeviceBayTemplate,
|
|
@@ -136,7 +136,6 @@ def create_test_device(name):
|
|
|
136
136
|
|
|
137
137
|
class LocationTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
|
138
138
|
model = LocationType
|
|
139
|
-
sort_on_field = "nestable"
|
|
140
139
|
|
|
141
140
|
@classmethod
|
|
142
141
|
def setUpTestData(cls):
|
|
@@ -255,20 +254,15 @@ class LocationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
255
254
|
|
|
256
255
|
class RackGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
|
257
256
|
model = RackGroup
|
|
258
|
-
sort_on_field = "name"
|
|
259
257
|
|
|
260
258
|
@classmethod
|
|
261
259
|
def setUpTestData(cls):
|
|
262
260
|
location = Location.objects.filter(location_type=LocationType.objects.get(name="Campus")).first()
|
|
263
261
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
RackGroup.objects.create(name="Rack Group 8", location=location),
|
|
269
|
-
)
|
|
270
|
-
RackGroup.objects.create(name="Rack Group Child 1", location=location, parent=rack_groups[0])
|
|
271
|
-
RackGroup.objects.create(name="Rack Group Child 2", location=location, parent=rack_groups[0])
|
|
262
|
+
RackGroup.objects.create(name="Rack Group 1", location=location)
|
|
263
|
+
RackGroup.objects.create(name="Rack Group 2", location=location)
|
|
264
|
+
RackGroup.objects.create(name="Rack Group 3", location=location)
|
|
265
|
+
RackGroup.objects.create(name="Rack Group 8", location=location)
|
|
272
266
|
|
|
273
267
|
cls.form_data = {
|
|
274
268
|
"name": "Rack Group X",
|
|
@@ -573,7 +567,6 @@ class ManufacturerTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
|
|
573
567
|
# FIXME(jathan): This has to be replaced with# `get_deletable_object` and
|
|
574
568
|
# `get_deletable_object_pks` but this is a workaround just so all of these objects are
|
|
575
569
|
# deletable for now.
|
|
576
|
-
Controller.objects.filter(controller_device__isnull=False).delete()
|
|
577
570
|
Device.objects.all().delete()
|
|
578
571
|
DeviceType.objects.all().delete()
|
|
579
572
|
Platform.objects.all().delete()
|
|
@@ -600,7 +593,6 @@ class DeviceTypeTestCase(
|
|
|
600
593
|
|
|
601
594
|
@classmethod
|
|
602
595
|
def setUpTestData(cls):
|
|
603
|
-
Controller.objects.filter(controller_device__isnull=False).delete()
|
|
604
596
|
Device.objects.all().delete()
|
|
605
597
|
manufacturers = Manufacturer.objects.all()[:2]
|
|
606
598
|
|
|
@@ -1286,7 +1278,6 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
1286
1278
|
|
|
1287
1279
|
@classmethod
|
|
1288
1280
|
def setUpTestData(cls):
|
|
1289
|
-
Controller.objects.filter(controller_device__isnull=False).delete()
|
|
1290
1281
|
Device.objects.all().delete()
|
|
1291
1282
|
locations = Location.objects.filter(location_type=LocationType.objects.get(name="Campus"))[:2]
|
|
1292
1283
|
|
|
@@ -1454,7 +1445,7 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
1454
1445
|
"face": DeviceFaceChoices.FACE_FRONT,
|
|
1455
1446
|
"secrets_group": secrets_groups[1].pk,
|
|
1456
1447
|
"software_version": software_versions[1].pk,
|
|
1457
|
-
"
|
|
1448
|
+
"controller_device_group": ControllerDeviceGroup.objects.first().pk,
|
|
1458
1449
|
}
|
|
1459
1450
|
|
|
1460
1451
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|
|
@@ -2236,9 +2227,6 @@ class InventoryItemTestCase(ViewTestCases.DeviceComponentViewTestCase):
|
|
|
2236
2227
|
"software_version": software_versions[2].pk,
|
|
2237
2228
|
}
|
|
2238
2229
|
|
|
2239
|
-
def test_table_with_indentation_is_removed_on_filter_or_sort(self):
|
|
2240
|
-
self.skipTest("InventoryItem table has no implementation of indentation.")
|
|
2241
|
-
|
|
2242
2230
|
|
|
2243
2231
|
# TODO: Change base class to PrimaryObjectViewTestCase
|
|
2244
2232
|
# Blocked by lack of common creation view for cables (termination A must be initialized)
|
|
@@ -3131,7 +3119,7 @@ class ControllerTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
3131
3119
|
tenant = Tenant.objects.first()
|
|
3132
3120
|
|
|
3133
3121
|
cls.form_data = {
|
|
3134
|
-
"
|
|
3122
|
+
"deployed_controller_device": device.pk,
|
|
3135
3123
|
"description": "Controller 1 description",
|
|
3136
3124
|
"external_integration": external_integration.pk,
|
|
3137
3125
|
"location": location.pk,
|
|
@@ -3152,16 +3140,16 @@ class ControllerTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
3152
3140
|
}
|
|
3153
3141
|
|
|
3154
3142
|
|
|
3155
|
-
class
|
|
3156
|
-
model =
|
|
3157
|
-
filterset =
|
|
3143
|
+
class ControllerDeviceGroupTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
3144
|
+
model = ControllerDeviceGroup
|
|
3145
|
+
filterset = ControllerDeviceGroupFilterSet
|
|
3158
3146
|
|
|
3159
3147
|
@classmethod
|
|
3160
3148
|
def setUpTestData(cls):
|
|
3161
3149
|
controllers = Controller.objects.all()
|
|
3162
3150
|
|
|
3163
3151
|
cls.form_data = {
|
|
3164
|
-
"name": "
|
|
3152
|
+
"name": "Controller Device Group 10",
|
|
3165
3153
|
"controller": controllers[0].pk,
|
|
3166
3154
|
"weight": 100,
|
|
3167
3155
|
"devices": [item.pk for item in Device.objects.all()[:2]],
|
nautobot/dcim/urls.py
CHANGED
|
@@ -40,7 +40,7 @@ router.register("interface-redundancy-groups-associations", views.InterfaceRedun
|
|
|
40
40
|
router.register("software-image-files", views.SoftwareImageFileUIViewSet)
|
|
41
41
|
router.register("software-versions", views.SoftwareVersionUIViewSet)
|
|
42
42
|
router.register("controllers", views.ControllerUIViewSet)
|
|
43
|
-
router.register("controller-
|
|
43
|
+
router.register("controller-device-groups", views.ControllerDeviceGroupUIViewSet)
|
|
44
44
|
|
|
45
45
|
urlpatterns = [
|
|
46
46
|
# Location types
|
nautobot/dcim/views.py
CHANGED
|
@@ -11,7 +11,7 @@ from django.forms import (
|
|
|
11
11
|
ModelMultipleChoiceField,
|
|
12
12
|
MultipleHiddenInput,
|
|
13
13
|
)
|
|
14
|
-
from django.shortcuts import get_object_or_404,
|
|
14
|
+
from django.shortcuts import get_object_or_404, redirect, render
|
|
15
15
|
from django.utils.functional import cached_property
|
|
16
16
|
from django.utils.html import format_html
|
|
17
17
|
from django.views.generic import View
|
|
@@ -48,7 +48,7 @@ from .models import (
|
|
|
48
48
|
ConsoleServerPort,
|
|
49
49
|
ConsoleServerPortTemplate,
|
|
50
50
|
Controller,
|
|
51
|
-
|
|
51
|
+
ControllerDeviceGroup,
|
|
52
52
|
Device,
|
|
53
53
|
DeviceBay,
|
|
54
54
|
DeviceBayTemplate,
|
|
@@ -1459,7 +1459,7 @@ class DeviceBulkEditView(generic.BulkEditView):
|
|
|
1459
1459
|
"device_type__manufacturer",
|
|
1460
1460
|
"secrets_group",
|
|
1461
1461
|
"device_redundancy_group",
|
|
1462
|
-
"
|
|
1462
|
+
"controller_device_group",
|
|
1463
1463
|
)
|
|
1464
1464
|
filterset = filters.DeviceFilterSet
|
|
1465
1465
|
table = tables.DeviceTable
|
|
@@ -2359,7 +2359,7 @@ class CableCreateView(generic.ObjectEditView):
|
|
|
2359
2359
|
"rear-port": forms.ConnectCableToRearPortForm,
|
|
2360
2360
|
"power-feed": forms.ConnectCableToPowerFeedForm,
|
|
2361
2361
|
"circuit-termination": forms.ConnectCableToCircuitTerminationForm,
|
|
2362
|
-
}
|
|
2362
|
+
}[kwargs.get("termination_b_type")]
|
|
2363
2363
|
|
|
2364
2364
|
return super().dispatch(request, *args, **kwargs)
|
|
2365
2365
|
|
|
@@ -2376,9 +2376,6 @@ class CableCreateView(generic.ObjectEditView):
|
|
|
2376
2376
|
return obj
|
|
2377
2377
|
|
|
2378
2378
|
def get(self, request, *args, **kwargs):
|
|
2379
|
-
if self.model_form is None:
|
|
2380
|
-
return HttpResponse(status_code=400)
|
|
2381
|
-
|
|
2382
2379
|
obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs)
|
|
2383
2380
|
|
|
2384
2381
|
# Parse initial data manually to avoid setting field values as lists
|
|
@@ -3024,13 +3021,12 @@ class ControllerUIViewSet(NautobotUIViewSet):
|
|
|
3024
3021
|
queryset = Controller.objects.all()
|
|
3025
3022
|
serializer_class = serializers.ControllerSerializer
|
|
3026
3023
|
table_class = tables.ControllerTable
|
|
3027
|
-
template_name = "dcim/controller_create.html"
|
|
3028
3024
|
|
|
3029
3025
|
def get_extra_context(self, request, instance):
|
|
3030
3026
|
context = super().get_extra_context(request, instance)
|
|
3031
3027
|
|
|
3032
3028
|
if self.action == "retrieve" and instance:
|
|
3033
|
-
devices = Device.objects.restrict(request.user).filter(
|
|
3029
|
+
devices = Device.objects.restrict(request.user).filter(controller_device_group__controller=instance)
|
|
3034
3030
|
devices_table = tables.DeviceTable(devices)
|
|
3035
3031
|
|
|
3036
3032
|
paginate = {
|
|
@@ -3044,19 +3040,19 @@ class ControllerUIViewSet(NautobotUIViewSet):
|
|
|
3044
3040
|
return context
|
|
3045
3041
|
|
|
3046
3042
|
|
|
3047
|
-
class
|
|
3048
|
-
filterset_class = filters.
|
|
3049
|
-
filterset_form_class = forms.
|
|
3050
|
-
form_class = forms.
|
|
3051
|
-
bulk_update_form_class = forms.
|
|
3043
|
+
class ControllerDeviceGroupUIViewSet(NautobotUIViewSet):
|
|
3044
|
+
filterset_class = filters.ControllerDeviceGroupFilterSet
|
|
3045
|
+
filterset_form_class = forms.ControllerDeviceGroupFilterForm
|
|
3046
|
+
form_class = forms.ControllerDeviceGroupForm
|
|
3047
|
+
bulk_update_form_class = forms.ControllerDeviceGroupBulkEditForm
|
|
3052
3048
|
queryset = (
|
|
3053
|
-
|
|
3049
|
+
ControllerDeviceGroup.objects.all()
|
|
3054
3050
|
.prefetch_related("devices")
|
|
3055
|
-
.annotate(device_count=count_related(Device, "
|
|
3051
|
+
.annotate(device_count=count_related(Device, "controller_device_group"))
|
|
3056
3052
|
)
|
|
3057
|
-
serializer_class = serializers.
|
|
3058
|
-
table_class = tables.
|
|
3059
|
-
template_name = "dcim/
|
|
3053
|
+
serializer_class = serializers.ControllerDeviceGroupSerializer
|
|
3054
|
+
table_class = tables.ControllerDeviceGroupTable
|
|
3055
|
+
template_name = "dcim/controllerdevicegroup_create.html"
|
|
3060
3056
|
|
|
3061
3057
|
def get_extra_context(self, request, instance):
|
|
3062
3058
|
context = super().get_extra_context(request, instance)
|
nautobot/extras/api/urls.py
CHANGED
|
@@ -2,7 +2,8 @@ from nautobot.core.api.routers import OrderedDefaultRouter
|
|
|
2
2
|
|
|
3
3
|
from . import views
|
|
4
4
|
|
|
5
|
-
router = OrderedDefaultRouter(
|
|
5
|
+
router = OrderedDefaultRouter()
|
|
6
|
+
router.APIRootView = views.ExtrasRootView
|
|
6
7
|
|
|
7
8
|
# Computed Fields
|
|
8
9
|
router.register("computed-fields", views.ComputedFieldViewSet)
|
nautobot/extras/api/views.py
CHANGED
|
@@ -16,6 +16,7 @@ from rest_framework.exceptions import MethodNotAllowed, PermissionDenied, Valida
|
|
|
16
16
|
from rest_framework.parsers import JSONParser, MultiPartParser
|
|
17
17
|
from rest_framework.permissions import IsAuthenticated
|
|
18
18
|
from rest_framework.response import Response
|
|
19
|
+
from rest_framework.routers import APIRootView
|
|
19
20
|
|
|
20
21
|
from nautobot.core.api.authentication import TokenPermissions
|
|
21
22
|
from nautobot.core.api.utils import get_serializer_for_model
|
|
@@ -76,6 +77,15 @@ from nautobot.extras.utils import get_worker_count
|
|
|
76
77
|
from . import serializers
|
|
77
78
|
|
|
78
79
|
|
|
80
|
+
class ExtrasRootView(APIRootView):
|
|
81
|
+
"""
|
|
82
|
+
Extras API root view
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
def get_view_name(self):
|
|
86
|
+
return "Extras"
|
|
87
|
+
|
|
88
|
+
|
|
79
89
|
class NotesViewSetMixin:
|
|
80
90
|
def restrict_queryset(self, request, *args, **kwargs):
|
|
81
91
|
"""
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
from difflib import get_close_matches
|
|
2
|
-
|
|
3
1
|
from django.conf import settings
|
|
4
2
|
from django.contrib.auth import get_user_model
|
|
5
3
|
from django.contrib.contenttypes.models import ContentType
|
|
6
|
-
from django.db.models import Q
|
|
7
4
|
import django_filters
|
|
8
|
-
from drf_spectacular.utils import extend_schema_field
|
|
9
5
|
|
|
10
6
|
from nautobot.core.api.exceptions import SerializerNotFound
|
|
11
7
|
from nautobot.core.api.utils import get_serializer_for_model
|
|
@@ -451,54 +447,7 @@ class NautobotFilterSet(
|
|
|
451
447
|
#
|
|
452
448
|
|
|
453
449
|
|
|
454
|
-
class
|
|
455
|
-
"""Base filter set for Contacts and Teams."""
|
|
456
|
-
|
|
457
|
-
similar_to_location_data = NaturalKeyOrPKMultipleChoiceFilter(
|
|
458
|
-
queryset=Location.objects.all(),
|
|
459
|
-
label="Similar to location contact data",
|
|
460
|
-
method="_similar_to_location_data",
|
|
461
|
-
)
|
|
462
|
-
|
|
463
|
-
def generate_query__similar_to_location_data(self, queryset, locations):
|
|
464
|
-
"""Helper method used by _similar_to_location_data() method."""
|
|
465
|
-
query_params = Q()
|
|
466
|
-
for location in locations:
|
|
467
|
-
contact_name = location.contact_name
|
|
468
|
-
contact_phone = location.contact_phone
|
|
469
|
-
contact_email = location.contact_email
|
|
470
|
-
if contact_name:
|
|
471
|
-
contact_names = list(queryset.order_by().values_list("name", flat=True).distinct())
|
|
472
|
-
name_matches = get_close_matches(contact_name, contact_names, cutoff=0.8)
|
|
473
|
-
if name_matches:
|
|
474
|
-
query_params |= Q(name__in=name_matches)
|
|
475
|
-
if contact_phone:
|
|
476
|
-
contact_phones = list(queryset.order_by().values_list("phone", flat=True).distinct())
|
|
477
|
-
phone_matches = get_close_matches(contact_phone, contact_phones, cutoff=0.8)
|
|
478
|
-
if phone_matches:
|
|
479
|
-
query_params |= Q(phone__in=phone_matches)
|
|
480
|
-
if contact_email:
|
|
481
|
-
contact_emails = list(queryset.order_by().values_list("email", flat=True).distinct())
|
|
482
|
-
# fuzzy matching for emails doesn't make sense, use case insensitive match here
|
|
483
|
-
email_matches = [e for e in contact_emails if e.casefold() == contact_email.casefold()]
|
|
484
|
-
if email_matches:
|
|
485
|
-
query_params |= Q(email__in=email_matches)
|
|
486
|
-
|
|
487
|
-
return query_params
|
|
488
|
-
|
|
489
|
-
@extend_schema_field({"type": "string"})
|
|
490
|
-
def _similar_to_location_data(self, queryset, name, value):
|
|
491
|
-
"""FilterSet method for getting Contacts or Teams that are similar to the explicit contact fields of a location"""
|
|
492
|
-
if value:
|
|
493
|
-
params = self.generate_query__similar_to_location_data(queryset, value)
|
|
494
|
-
if len(params) > 0:
|
|
495
|
-
return queryset.filter(params)
|
|
496
|
-
else:
|
|
497
|
-
return queryset.none()
|
|
498
|
-
return queryset
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
class ContactFilterSet(ContactTeamFilterSet):
|
|
450
|
+
class ContactFilterSet(NameSearchFilterSet, NautobotFilterSet):
|
|
502
451
|
class Meta:
|
|
503
452
|
model = Contact
|
|
504
453
|
fields = "__all__"
|
|
@@ -1160,7 +1109,7 @@ class TagFilterSet(NautobotFilterSet):
|
|
|
1160
1109
|
#
|
|
1161
1110
|
|
|
1162
1111
|
|
|
1163
|
-
class TeamFilterSet(
|
|
1112
|
+
class TeamFilterSet(NameSearchFilterSet, NautobotFilterSet):
|
|
1164
1113
|
class Meta:
|
|
1165
1114
|
model = Team
|
|
1166
1115
|
fields = "__all__"
|
|
@@ -28,13 +28,6 @@ class ContactForm(NautobotModelForm):
|
|
|
28
28
|
"tags",
|
|
29
29
|
]
|
|
30
30
|
|
|
31
|
-
def __init__(self, instance=None, initial=None, **kwargs):
|
|
32
|
-
if instance is not None:
|
|
33
|
-
if initial is None:
|
|
34
|
-
initial = {}
|
|
35
|
-
initial.setdefault("teams", instance.teams.all())
|
|
36
|
-
super().__init__(instance=instance, initial=initial, **kwargs)
|
|
37
|
-
|
|
38
31
|
def save(self, *args, **kwargs):
|
|
39
32
|
"""
|
|
40
33
|
Since `teams` field on Contact Model is the reverse side of an M2M,
|
nautobot/extras/managers.py
CHANGED
|
@@ -8,20 +8,6 @@ from nautobot.core.models.querysets import RestrictedQuerySet
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class JobResultManager(BaseManager.from_queryset(RestrictedQuerySet), TaskResultManager):
|
|
11
|
-
def get_task(self, task_id):
|
|
12
|
-
"""Get result for task by ``task_id``.
|
|
13
|
-
|
|
14
|
-
This overloads `TaskResultManager.get_task` provided by `django-celery-results` to manage custom
|
|
15
|
-
behaviors for integration with Nautobot.
|
|
16
|
-
"""
|
|
17
|
-
try:
|
|
18
|
-
return self.get(id=task_id)
|
|
19
|
-
except self.model.DoesNotExist:
|
|
20
|
-
if self._last_id == task_id:
|
|
21
|
-
self.warn_if_repeatable_read()
|
|
22
|
-
self._last_id = task_id
|
|
23
|
-
return self.model(id=task_id)
|
|
24
|
-
|
|
25
11
|
@transaction_retry(max_retries=2)
|
|
26
12
|
def store_result(
|
|
27
13
|
self,
|
nautobot/extras/navigation.py
CHANGED
|
@@ -13,51 +13,9 @@ menu_items = (
|
|
|
13
13
|
name="Organization",
|
|
14
14
|
weight=100,
|
|
15
15
|
groups=(
|
|
16
|
-
NavMenuGroup(
|
|
17
|
-
name="Contacts",
|
|
18
|
-
weight=400,
|
|
19
|
-
items=(
|
|
20
|
-
NavMenuItem(
|
|
21
|
-
link="extras:contact_list",
|
|
22
|
-
name="Contacts",
|
|
23
|
-
weight=100,
|
|
24
|
-
permissions=["extras.view_contact"],
|
|
25
|
-
buttons=[NavMenuAddButton(link="extras:contact_add", permissions=["extras.add_contact"])],
|
|
26
|
-
),
|
|
27
|
-
NavMenuItem(
|
|
28
|
-
link="extras:team_list",
|
|
29
|
-
name="Teams",
|
|
30
|
-
weight=200,
|
|
31
|
-
permissions=["extras.view_team"],
|
|
32
|
-
buttons=[NavMenuAddButton(link="extras:team_add", permissions=["extras.add_team"])],
|
|
33
|
-
),
|
|
34
|
-
),
|
|
35
|
-
),
|
|
36
|
-
NavMenuGroup(
|
|
37
|
-
name="Groups",
|
|
38
|
-
weight=500,
|
|
39
|
-
items=(
|
|
40
|
-
NavMenuItem(
|
|
41
|
-
link="extras:dynamicgroup_list",
|
|
42
|
-
name="Dynamic Groups",
|
|
43
|
-
weight=100,
|
|
44
|
-
permissions=[
|
|
45
|
-
"extras.view_dynamicgroup",
|
|
46
|
-
],
|
|
47
|
-
buttons=(
|
|
48
|
-
NavMenuAddButton(
|
|
49
|
-
link="extras:dynamicgroup_add",
|
|
50
|
-
permissions=[
|
|
51
|
-
"extras.add_dynamicgroup",
|
|
52
|
-
],
|
|
53
|
-
),
|
|
54
|
-
),
|
|
55
|
-
),
|
|
56
|
-
),
|
|
57
|
-
),
|
|
58
16
|
NavMenuGroup(
|
|
59
17
|
name="Metadata", # TODO: is there a better name for this grouping?
|
|
60
|
-
weight=
|
|
18
|
+
weight=400,
|
|
61
19
|
items=(
|
|
62
20
|
NavMenuItem(
|
|
63
21
|
link="extras:tag_list",
|
|
@@ -107,6 +65,42 @@ menu_items = (
|
|
|
107
65
|
),
|
|
108
66
|
),
|
|
109
67
|
),
|
|
68
|
+
NavMenuItem(
|
|
69
|
+
link="extras:contact_list",
|
|
70
|
+
name="Contacts",
|
|
71
|
+
weight=400,
|
|
72
|
+
permissions=["extras.view_contact"],
|
|
73
|
+
buttons=[NavMenuAddButton(link="extras:contact_add", permissions=["extras.add_contact"])],
|
|
74
|
+
),
|
|
75
|
+
NavMenuItem(
|
|
76
|
+
link="extras:team_list",
|
|
77
|
+
name="Teams",
|
|
78
|
+
weight=500,
|
|
79
|
+
permissions=["extras.view_team"],
|
|
80
|
+
buttons=[NavMenuAddButton(link="extras:team_add", permissions=["extras.add_team"])],
|
|
81
|
+
),
|
|
82
|
+
),
|
|
83
|
+
),
|
|
84
|
+
NavMenuGroup(
|
|
85
|
+
name="Dynamic Groups",
|
|
86
|
+
weight=500,
|
|
87
|
+
items=(
|
|
88
|
+
NavMenuItem(
|
|
89
|
+
link="extras:dynamicgroup_list",
|
|
90
|
+
name="Dynamic Groups",
|
|
91
|
+
weight=100,
|
|
92
|
+
permissions=[
|
|
93
|
+
"extras.view_dynamicgroup",
|
|
94
|
+
],
|
|
95
|
+
buttons=(
|
|
96
|
+
NavMenuAddButton(
|
|
97
|
+
link="extras:dynamicgroup_add",
|
|
98
|
+
permissions=[
|
|
99
|
+
"extras.add_dynamicgroup",
|
|
100
|
+
],
|
|
101
|
+
),
|
|
102
|
+
),
|
|
103
|
+
),
|
|
110
104
|
),
|
|
111
105
|
),
|
|
112
106
|
),
|
|
@@ -282,6 +276,22 @@ menu_items = (
|
|
|
282
276
|
),
|
|
283
277
|
),
|
|
284
278
|
),
|
|
279
|
+
NavMenuItem(
|
|
280
|
+
link="extras:relationship_list",
|
|
281
|
+
name="Relationships",
|
|
282
|
+
weight=200,
|
|
283
|
+
permissions=[
|
|
284
|
+
"extras.view_relationship",
|
|
285
|
+
],
|
|
286
|
+
buttons=(
|
|
287
|
+
NavMenuAddButton(
|
|
288
|
+
link="extras:relationship_add",
|
|
289
|
+
permissions=[
|
|
290
|
+
"extras.add_relationship",
|
|
291
|
+
],
|
|
292
|
+
),
|
|
293
|
+
),
|
|
294
|
+
),
|
|
285
295
|
NavMenuItem(
|
|
286
296
|
link="extras:note_list",
|
|
287
297
|
name="Notes",
|
|
@@ -379,53 +389,37 @@ menu_items = (
|
|
|
379
389
|
),
|
|
380
390
|
),
|
|
381
391
|
NavMenuGroup(
|
|
382
|
-
name="
|
|
392
|
+
name="Miscellaneous",
|
|
383
393
|
weight=600,
|
|
384
394
|
items=(
|
|
385
395
|
NavMenuItem(
|
|
386
|
-
link="extras:
|
|
387
|
-
name="
|
|
396
|
+
link="extras:computedfield_list",
|
|
397
|
+
name="Computed Fields",
|
|
388
398
|
weight=100,
|
|
389
399
|
permissions=[
|
|
390
|
-
"extras.
|
|
400
|
+
"extras.view_computedfield",
|
|
391
401
|
],
|
|
392
402
|
buttons=(
|
|
393
403
|
NavMenuAddButton(
|
|
394
|
-
link="extras:
|
|
404
|
+
link="extras:computedfield_add",
|
|
395
405
|
permissions=[
|
|
396
|
-
"extras.
|
|
406
|
+
"extras.add_computedfield",
|
|
397
407
|
],
|
|
398
408
|
),
|
|
399
409
|
),
|
|
400
410
|
),
|
|
401
411
|
NavMenuItem(
|
|
402
|
-
link="extras:
|
|
403
|
-
name="
|
|
412
|
+
link="extras:customfield_list",
|
|
413
|
+
name="Custom Fields",
|
|
404
414
|
weight=200,
|
|
405
415
|
permissions=[
|
|
406
|
-
"extras.
|
|
407
|
-
],
|
|
408
|
-
buttons=(
|
|
409
|
-
NavMenuAddButton(
|
|
410
|
-
link="extras:relationship_add",
|
|
411
|
-
permissions=[
|
|
412
|
-
"extras.add_relationship",
|
|
413
|
-
],
|
|
414
|
-
),
|
|
415
|
-
),
|
|
416
|
-
),
|
|
417
|
-
NavMenuItem(
|
|
418
|
-
link="extras:computedfield_list",
|
|
419
|
-
name="Computed Fields",
|
|
420
|
-
weight=300,
|
|
421
|
-
permissions=[
|
|
422
|
-
"extras.view_computedfield",
|
|
416
|
+
"extras.view_customfield",
|
|
423
417
|
],
|
|
424
418
|
buttons=(
|
|
425
419
|
NavMenuAddButton(
|
|
426
|
-
link="extras:
|
|
420
|
+
link="extras:customfield_add",
|
|
427
421
|
permissions=[
|
|
428
|
-
"extras.
|
|
422
|
+
"extras.add_customfield",
|
|
429
423
|
],
|
|
430
424
|
),
|
|
431
425
|
),
|
|
@@ -433,7 +427,7 @@ menu_items = (
|
|
|
433
427
|
NavMenuItem(
|
|
434
428
|
link="extras:customlink_list",
|
|
435
429
|
name="Custom Links",
|
|
436
|
-
weight=
|
|
430
|
+
weight=300,
|
|
437
431
|
permissions=[
|
|
438
432
|
"extras.view_customlink",
|
|
439
433
|
],
|
nautobot/extras/plugins/views.py
CHANGED
|
@@ -2,9 +2,11 @@ from collections import OrderedDict
|
|
|
2
2
|
|
|
3
3
|
from django.apps import apps
|
|
4
4
|
from django.conf import settings
|
|
5
|
+
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
5
6
|
from django.http import Http404
|
|
6
7
|
from django.shortcuts import render
|
|
7
8
|
from django.urls.exceptions import NoReverseMatch
|
|
9
|
+
from django.views.generic import View
|
|
8
10
|
from django_tables2 import RequestConfig
|
|
9
11
|
from drf_spectacular.utils import extend_schema
|
|
10
12
|
from rest_framework import permissions
|
|
@@ -12,14 +14,13 @@ from rest_framework.response import Response
|
|
|
12
14
|
from rest_framework.reverse import reverse
|
|
13
15
|
from rest_framework.views import APIView
|
|
14
16
|
|
|
15
|
-
from nautobot.core.api.views import
|
|
17
|
+
from nautobot.core.api.views import NautobotAPIVersionMixin
|
|
16
18
|
from nautobot.core.forms import TableConfigForm
|
|
17
|
-
from nautobot.core.views.generic import GenericView
|
|
18
19
|
from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
|
|
19
20
|
from nautobot.extras.plugins.tables import InstalledAppsTable
|
|
20
21
|
|
|
21
22
|
|
|
22
|
-
class InstalledAppsView(
|
|
23
|
+
class InstalledAppsView(LoginRequiredMixin, View):
|
|
23
24
|
"""
|
|
24
25
|
View for listing all installed Apps.
|
|
25
26
|
"""
|
|
@@ -65,7 +66,7 @@ class InstalledAppsView(GenericView):
|
|
|
65
66
|
)
|
|
66
67
|
|
|
67
68
|
|
|
68
|
-
class InstalledAppDetailView(
|
|
69
|
+
class InstalledAppDetailView(LoginRequiredMixin, View):
|
|
69
70
|
"""
|
|
70
71
|
View for showing details of an installed App.
|
|
71
72
|
"""
|
|
@@ -92,6 +93,7 @@ class InstalledAppsAPIView(NautobotAPIVersionMixin, APIView):
|
|
|
92
93
|
"""
|
|
93
94
|
|
|
94
95
|
permission_classes = [permissions.IsAdminUser]
|
|
96
|
+
_ignore_model_permissions = True
|
|
95
97
|
|
|
96
98
|
def get_view_name(self):
|
|
97
99
|
return "Installed Apps"
|
|
@@ -127,9 +129,11 @@ class InstalledAppsAPIView(NautobotAPIVersionMixin, APIView):
|
|
|
127
129
|
return Response([self._get_app_data(apps.get_app_config(app)) for app in settings.PLUGINS])
|
|
128
130
|
|
|
129
131
|
|
|
130
|
-
class AppsAPIRootView(
|
|
131
|
-
|
|
132
|
-
|
|
132
|
+
class AppsAPIRootView(NautobotAPIVersionMixin, APIView):
|
|
133
|
+
_ignore_model_permissions = True
|
|
134
|
+
|
|
135
|
+
def get_view_name(self):
|
|
136
|
+
return "Apps"
|
|
133
137
|
|
|
134
138
|
@staticmethod
|
|
135
139
|
def _get_app_entry(app_config, request, format_):
|
|
@@ -18,7 +18,6 @@ from nautobot.core.testing import APITestCase, APIViewTestCases
|
|
|
18
18
|
from nautobot.core.testing.utils import disable_warnings
|
|
19
19
|
from nautobot.core.utils.lookup import get_route_for_model
|
|
20
20
|
from nautobot.dcim.models import (
|
|
21
|
-
Controller,
|
|
22
21
|
Device,
|
|
23
22
|
DeviceType,
|
|
24
23
|
Location,
|
|
@@ -2852,7 +2851,6 @@ class RelationshipTest(APIViewTestCases.APIViewTestCase, RequiredRelationshipTes
|
|
|
2852
2851
|
vlan_groups = VLANGroup.objects.all()[:2]
|
|
2853
2852
|
|
|
2854
2853
|
# Try deleting all devices and then creating 2 VLANs (fails):
|
|
2855
|
-
Controller.objects.filter(controller_device__isnull=False).delete()
|
|
2856
2854
|
Device.objects.all().delete()
|
|
2857
2855
|
response = send_bulk_data(
|
|
2858
2856
|
"post",
|
|
@@ -16,7 +16,6 @@ from nautobot.dcim.choices import PortTypeChoices
|
|
|
16
16
|
from nautobot.dcim.filters import DeviceFilterSet
|
|
17
17
|
from nautobot.dcim.forms import DeviceFilterForm, DeviceForm
|
|
18
18
|
from nautobot.dcim.models import (
|
|
19
|
-
Controller,
|
|
20
19
|
Device,
|
|
21
20
|
DeviceType,
|
|
22
21
|
FrontPort,
|
|
@@ -49,7 +48,6 @@ from nautobot.tenancy.models import Tenant
|
|
|
49
48
|
class DynamicGroupTestBase(TestCase):
|
|
50
49
|
@classmethod
|
|
51
50
|
def setUpTestData(cls):
|
|
52
|
-
Controller.objects.filter(controller_device__isnull=False).delete()
|
|
53
51
|
Device.objects.all().delete()
|
|
54
52
|
cls.device_ct = ContentType.objects.get_for_model(Device)
|
|
55
53
|
cls.dynamicgroup_ct = ContentType.objects.get_for_model(DynamicGroup)
|