nautobot 2.2.0b1__py3-none-any.whl → 2.2.1__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/__init__.py +31 -0
- nautobot/apps/api.py +1 -2
- nautobot/apps/utils.py +4 -0
- nautobot/apps/views.py +2 -0
- nautobot/circuits/api/urls.py +1 -2
- nautobot/circuits/api/views.py +0 -12
- nautobot/circuits/apps.py +1 -1
- nautobot/circuits/tests/test_filters.py +1 -1
- nautobot/core/api/routers.py +50 -3
- nautobot/core/api/utils.py +4 -0
- nautobot/core/api/views.py +21 -15
- nautobot/core/cli/__init__.py +18 -11
- nautobot/core/constants.py +85 -0
- nautobot/core/filters.py +7 -1
- nautobot/core/forms/widgets.py +1 -2
- nautobot/core/graphql/schema.py +1 -0
- nautobot/core/management/commands/generate_test_data.py +4 -4
- nautobot/core/models/__init__.py +1 -0
- nautobot/core/settings.py +24 -3
- nautobot/core/settings.yaml +20 -0
- nautobot/core/signals.py +1 -0
- nautobot/core/tables.py +2 -1
- nautobot/core/templates/admin/base.html +23 -94
- nautobot/core/templates/generic/object_retrieve.html +2 -2
- nautobot/core/templates/graphene/graphiql.html +18 -47
- nautobot/core/templates/inc/footer.html +5 -5
- nautobot/core/templates/inc/javascript.html +4 -4
- nautobot/core/templates/inc/media.html +2 -2
- nautobot/core/templates/inc/nav_menu.html +0 -7
- nautobot/core/templates/nautobot_config.py.j2 +14 -1
- nautobot/core/templates/rest_framework/api.html +12 -5
- nautobot/core/templatetags/helpers.py +2 -2
- nautobot/core/testing/__init__.py +1 -1
- nautobot/core/testing/filters.py +1 -1
- nautobot/core/testing/views.py +30 -0
- nautobot/core/tests/integration/test_view_authentication.py +68 -0
- nautobot/core/tests/test_api.py +13 -6
- nautobot/core/tests/test_csv.py +5 -4
- nautobot/core/tests/test_filters.py +2 -1
- nautobot/core/tests/test_graphql.py +4 -14
- nautobot/core/tests/test_navigations.py +3 -0
- nautobot/core/tests/test_views.py +44 -16
- nautobot/core/utils/data.py +1 -2
- nautobot/core/utils/lookup.py +126 -0
- nautobot/core/views/__init__.py +3 -7
- nautobot/core/views/generic.py +20 -6
- nautobot/core/views/mixins.py +7 -1
- nautobot/core/views/renderers.py +11 -6
- nautobot/dcim/api/serializers.py +4 -4
- nautobot/dcim/api/urls.py +2 -3
- nautobot/dcim/api/views.py +7 -18
- nautobot/dcim/apps.py +8 -4
- nautobot/dcim/elevations.py +5 -1
- nautobot/dcim/factory.py +7 -7
- nautobot/dcim/filters/__init__.py +16 -17
- nautobot/dcim/forms.py +61 -45
- nautobot/dcim/homepage.py +11 -3
- nautobot/dcim/management/commands/migrate_location_contacts.py +218 -0
- nautobot/dcim/migrations/0057_controller_models.py +11 -70
- nautobot/dcim/models/__init__.py +2 -2
- nautobot/dcim/models/devices.py +14 -16
- nautobot/dcim/models/racks.py +1 -3
- nautobot/dcim/navigation.py +23 -31
- nautobot/dcim/signals.py +6 -6
- nautobot/dcim/tables/__init__.py +2 -2
- nautobot/dcim/tables/devices.py +13 -16
- nautobot/dcim/tables/template_code.py +1 -1
- nautobot/dcim/templates/dcim/controller_create.html +70 -0
- nautobot/dcim/templates/dcim/controller_retrieve.html +35 -18
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +88 -0
- nautobot/dcim/templates/dcim/device/lldp_neighbors.html +75 -43
- nautobot/dcim/templates/dcim/device.html +11 -3
- nautobot/dcim/templates/dcim/device_edit.html +1 -1
- nautobot/dcim/templates/dcim/devicefamily_retrieve.html +4 -0
- nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +1 -1
- nautobot/dcim/tests/test_api.py +47 -6
- nautobot/dcim/tests/test_filters.py +92 -81
- nautobot/dcim/tests/test_graphql.py +11 -1
- nautobot/dcim/tests/test_models.py +15 -15
- nautobot/dcim/tests/test_signals.py +3 -1
- nautobot/dcim/tests/test_views.py +24 -12
- nautobot/dcim/urls.py +1 -1
- nautobot/dcim/views.py +25 -15
- nautobot/extras/api/serializers.py +20 -1
- nautobot/extras/api/urls.py +1 -2
- nautobot/extras/api/views.py +0 -10
- nautobot/extras/apps.py +7 -0
- nautobot/extras/context_managers.py +15 -4
- nautobot/extras/filters/__init__.py +53 -2
- nautobot/extras/filters/customfields.py +14 -9
- nautobot/extras/filters/mixins.py +6 -1
- nautobot/extras/forms/contacts.py +7 -0
- nautobot/extras/health_checks.py +1 -0
- nautobot/extras/jobs.py +1 -0
- nautobot/extras/managers.py +15 -2
- nautobot/extras/models/contacts.py +1 -0
- nautobot/extras/models/customfields.py +25 -2
- nautobot/extras/models/datasources.py +1 -0
- nautobot/extras/models/mixins.py +1 -0
- nautobot/extras/navigation.py +71 -65
- nautobot/extras/plugins/__init__.py +2 -1
- nautobot/extras/plugins/views.py +7 -11
- nautobot/extras/querysets.py +1 -2
- nautobot/extras/secrets/providers.py +1 -0
- nautobot/extras/signals.py +15 -5
- nautobot/extras/tasks.py +70 -17
- nautobot/extras/tests/test_api.py +2 -4
- nautobot/extras/tests/test_customfields.py +72 -9
- nautobot/extras/tests/test_dynamicgroups.py +2 -0
- nautobot/extras/tests/test_filters.py +89 -4
- nautobot/extras/tests/test_models.py +9 -0
- nautobot/extras/tests/test_relationships.py +10 -1
- nautobot/extras/tests/test_views.py +112 -1
- nautobot/extras/views.py +18 -17
- nautobot/ipam/api/serializers.py +10 -0
- nautobot/ipam/api/urls.py +1 -2
- nautobot/ipam/api/views.py +0 -11
- nautobot/ipam/apps.py +3 -2
- nautobot/ipam/tables.py +2 -22
- nautobot/ipam/tests/test_graphql.py +2 -3
- nautobot/ipam/tests/test_tables.py +42 -0
- nautobot/ipam/tests/test_views.py +1 -0
- nautobot/ipam/views.py +9 -9
- nautobot/project-static/css/base.css +1 -0
- nautobot/project-static/docs/404.html +126 -73
- nautobot/project-static/docs/apps/index.html +127 -71
- nautobot/project-static/docs/apps/nautobot-apps.html +127 -71
- nautobot/project-static/docs/assets/javascripts/{bundle.8fd75fb4.min.js → bundle.bd41221c.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.8fd75fb4.min.js.map → bundle.bd41221c.min.js.map} +3 -3
- nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css.map +1 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +167 -73
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +165 -72
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +128 -72
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +127 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +345 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +172 -73
- nautobot/project-static/docs/development/apps/api/configuration-view.html +127 -71
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +127 -71
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +127 -71
- nautobot/project-static/docs/development/apps/api/models/global-search.html +127 -71
- nautobot/project-static/docs/development/apps/api/models/graphql.html +127 -71
- nautobot/project-static/docs/development/apps/api/models/index.html +127 -71
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +127 -71
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +127 -71
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +127 -71
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +127 -71
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +127 -71
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +127 -71
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +127 -71
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +127 -71
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +127 -71
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +127 -71
- nautobot/project-static/docs/development/apps/api/prometheus.html +127 -71
- nautobot/project-static/docs/development/apps/api/setup.html +127 -71
- nautobot/project-static/docs/development/apps/api/testing.html +127 -71
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +127 -71
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +127 -71
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +127 -71
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +127 -71
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +127 -71
- nautobot/project-static/docs/development/apps/api/views/base-template.html +127 -71
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +141 -80
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +144 -83
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +127 -71
- nautobot/project-static/docs/development/apps/api/views/index.html +127 -71
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +127 -71
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +127 -71
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +127 -71
- nautobot/project-static/docs/development/apps/api/views/notes.html +127 -71
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +127 -71
- nautobot/project-static/docs/development/apps/api/views/urls.html +127 -71
- nautobot/project-static/docs/development/apps/index.html +127 -71
- nautobot/project-static/docs/development/apps/migration/code-updates.html +127 -71
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +127 -71
- nautobot/project-static/docs/development/apps/migration/from-v1.html +127 -71
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +127 -71
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +127 -71
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +127 -71
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +127 -71
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +127 -71
- nautobot/project-static/docs/development/core/application-registry.html +127 -71
- nautobot/project-static/docs/development/core/best-practices.html +145 -79
- nautobot/project-static/docs/development/core/bootstrap-ui.html +127 -71
- nautobot/project-static/docs/development/core/caching.html +127 -71
- nautobot/project-static/docs/development/core/controllers.html +141 -275
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +127 -71
- nautobot/project-static/docs/development/core/extending-models.html +13 -8166
- nautobot/project-static/docs/development/core/generic-views.html +142 -86
- nautobot/project-static/docs/development/core/getting-started.html +146 -81
- nautobot/project-static/docs/development/core/homepage.html +145 -89
- nautobot/project-static/docs/development/core/index.html +127 -71
- nautobot/project-static/docs/development/core/model-checklist.html +8354 -0
- nautobot/project-static/docs/development/core/model-features.html +130 -74
- nautobot/project-static/docs/development/core/natural-keys.html +127 -71
- nautobot/project-static/docs/development/core/navigation-menu.html +127 -71
- nautobot/project-static/docs/development/core/release-checklist.html +127 -71
- nautobot/project-static/docs/development/core/role-internals.html +127 -71
- nautobot/project-static/docs/development/core/settings.html +127 -71
- nautobot/project-static/docs/development/core/style-guide.html +127 -71
- nautobot/project-static/docs/development/core/templates.html +127 -71
- nautobot/project-static/docs/development/core/testing.html +127 -71
- nautobot/project-static/docs/development/core/user-preferences.html +127 -71
- nautobot/project-static/docs/development/extending-models.html +3 -3
- nautobot/project-static/docs/development/index.html +127 -71
- nautobot/project-static/docs/development/jobs/index.html +128 -72
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +127 -71
- nautobot/project-static/docs/index.html +126 -73
- nautobot/project-static/docs/models/dcim/{controllerdevicegroup.html → controllermanageddevicegroup.html} +3 -3
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/release-notes/index.html +127 -71
- nautobot/project-static/docs/release-notes/version-1.0.html +127 -71
- nautobot/project-static/docs/release-notes/version-1.1.html +127 -71
- nautobot/project-static/docs/release-notes/version-1.2.html +127 -71
- nautobot/project-static/docs/release-notes/version-1.3.html +127 -71
- nautobot/project-static/docs/release-notes/version-1.4.html +127 -71
- nautobot/project-static/docs/release-notes/version-1.5.html +127 -71
- nautobot/project-static/docs/release-notes/version-1.6.html +127 -71
- nautobot/project-static/docs/release-notes/version-2.0.html +127 -71
- nautobot/project-static/docs/release-notes/version-2.1.html +538 -254
- nautobot/project-static/docs/release-notes/version-2.2.html +520 -101
- nautobot/project-static/docs/requirements.txt +3 -3
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +264 -259
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +127 -71
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +127 -71
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +127 -71
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +127 -71
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +192 -71
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +127 -71
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +127 -71
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +127 -71
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +127 -71
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +127 -71
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +127 -71
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +131 -71
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +127 -71
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +127 -71
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +130 -74
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +127 -71
- nautobot/project-static/docs/user-guide/administration/installation/docker.html +134 -74
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +127 -71
- nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +8616 -0
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +127 -71
- nautobot/project-static/docs/user-guide/administration/installation/index.html +127 -71
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +127 -71
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +127 -71
- nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +130 -74
- nautobot/project-static/docs/user-guide/administration/installation/services.html +127 -71
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +127 -71
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +127 -71
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +127 -71
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +127 -71
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +127 -71
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +127 -71
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +127 -71
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +127 -71
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +127 -71
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +127 -71
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +127 -71
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +127 -71
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +362 -79
- nautobot/project-static/docs/user-guide/core-data-model/dcim/{controllerdevicegroup.html → controllermanageddevicegroup.html} +210 -85
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +130 -74
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +138 -71
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +138 -71
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +127 -71
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/{contact-and-team.html → contacts-and-teams.html} +128 -72
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +129 -73
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +129 -73
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +127 -71
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +127 -71
- nautobot/project-static/docs/user-guide/index.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +127 -71
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +127 -71
- nautobot/project-static/jquery/jquery-3.7.1.min.js +2 -0
- nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_444444_256x240.png +0 -0
- nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_555555_256x240.png +0 -0
- nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_777620_256x240.png +0 -0
- nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_777777_256x240.png +0 -0
- nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_cc0000_256x240.png +0 -0
- nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_ffffff_256x240.png +0 -0
- nautobot/project-static/jquery-ui-1.13.2/jquery-ui.min.css +7 -0
- nautobot/project-static/jquery-ui-1.13.2/jquery-ui.min.js +6 -0
- nautobot/project-static/jquery-ui-1.13.2/jquery-ui.structure.min.css +5 -0
- nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/jquery-ui.theme.min.css +1 -1
- nautobot/tenancy/api/urls.py +1 -2
- nautobot/tenancy/api/views.py +0 -12
- nautobot/tenancy/tables.py +1 -1
- nautobot/tenancy/tests/test_views.py +1 -0
- nautobot/users/api/urls.py +1 -2
- nautobot/users/api/views.py +2 -65
- nautobot/users/views.py +8 -8
- nautobot/virtualization/api/urls.py +1 -2
- nautobot/virtualization/api/views.py +0 -12
- {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/METADATA +24 -24
- {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/RECORD +418 -412
- nautobot/dcim/templates/dcim/controllerdevicegroup_create.html +0 -43
- nautobot/project-static/docs/assets/stylesheets/main.f2e4d321.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.f2e4d321.min.css.map +0 -1
- nautobot/project-static/jquery/jquery-3.6.0.min.js +0 -2
- nautobot/project-static/jquery-ui-1.13.1/jquery-ui.min.css +0 -7
- nautobot/project-static/jquery-ui-1.13.1/jquery-ui.min.js +0 -6
- nautobot/project-static/jquery-ui-1.13.1/jquery-ui.structure.min.css +0 -5
- /nautobot/dcim/templates/dcim/{controllerdevicegroup_retrieve.html → controllermanageddevicegroup_retrieve.html} +0 -0
- {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/NOTICE +0 -0
- {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/WHEEL +0 -0
- {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/entry_points.txt +0 -0
nautobot/__init__.py
CHANGED
|
@@ -1,4 +1,35 @@
|
|
|
1
1
|
from importlib import metadata
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import django
|
|
2
6
|
|
|
3
7
|
# Primary package version
|
|
4
8
|
__version__ = metadata.version(__name__)
|
|
9
|
+
|
|
10
|
+
# Sentinel to make sure we only initialize once.
|
|
11
|
+
__initialized = False
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def setup(config_path=None):
|
|
17
|
+
"""Similar to `django.setup()`, this configures Django with the appropriate Nautobot settings data."""
|
|
18
|
+
from nautobot.core.cli import get_config_path, load_settings
|
|
19
|
+
|
|
20
|
+
global __initialized
|
|
21
|
+
|
|
22
|
+
if __initialized:
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
if config_path is None:
|
|
26
|
+
config_path = get_config_path()
|
|
27
|
+
|
|
28
|
+
# Point Django to our 'nautobot_config' pseudo-module that we'll load from the provided config path
|
|
29
|
+
os.environ["DJANGO_SETTINGS_MODULE"] = "nautobot_config"
|
|
30
|
+
|
|
31
|
+
load_settings(config_path)
|
|
32
|
+
django.setup()
|
|
33
|
+
|
|
34
|
+
logger.info("Nautobot initialized!")
|
|
35
|
+
__initialized = True
|
nautobot/apps/api.py
CHANGED
|
@@ -19,7 +19,7 @@ from nautobot.core.api.fields import (
|
|
|
19
19
|
)
|
|
20
20
|
from nautobot.core.api.mixins import WritableSerializerMixin
|
|
21
21
|
from nautobot.core.api.parsers import NautobotCSVParser
|
|
22
|
-
from nautobot.core.api.routers import OrderedDefaultRouter
|
|
22
|
+
from nautobot.core.api.routers import AuthenticatedAPIRootView as APIRootView, OrderedDefaultRouter
|
|
23
23
|
from nautobot.core.api.schema import NautobotAutoSchema
|
|
24
24
|
from nautobot.core.api.serializers import (
|
|
25
25
|
OptInFieldsMixin,
|
|
@@ -36,7 +36,6 @@ from nautobot.core.api.utils import (
|
|
|
36
36
|
versioned_serializer_selector,
|
|
37
37
|
)
|
|
38
38
|
from nautobot.core.api.views import (
|
|
39
|
-
APIRootView,
|
|
40
39
|
BulkDestroyModelMixin,
|
|
41
40
|
BulkUpdateModelMixin,
|
|
42
41
|
GetObjectCountsView,
|
nautobot/apps/utils.py
CHANGED
|
@@ -32,6 +32,8 @@ from nautobot.core.utils.lookup import (
|
|
|
32
32
|
get_related_class_for_model,
|
|
33
33
|
get_route_for_model,
|
|
34
34
|
get_table_for_model,
|
|
35
|
+
get_url_for_url_pattern,
|
|
36
|
+
get_url_patterns,
|
|
35
37
|
get_view_for_model,
|
|
36
38
|
)
|
|
37
39
|
from nautobot.core.utils.migrations import migrate_content_type_references_to_new_model
|
|
@@ -113,6 +115,8 @@ __all__ = (
|
|
|
113
115
|
"get_settings_or_config",
|
|
114
116
|
"get_table_for_model",
|
|
115
117
|
"get_view_for_model",
|
|
118
|
+
"get_url_for_url_pattern",
|
|
119
|
+
"get_url_patterns",
|
|
116
120
|
"get_worker_count",
|
|
117
121
|
"GitRepo",
|
|
118
122
|
"hex_to_rgb",
|
nautobot/apps/views.py
CHANGED
|
@@ -8,6 +8,7 @@ from nautobot.core.views.generic import (
|
|
|
8
8
|
BulkImportView, # 3.0 TODO: deprecated, will be removed in 3.0
|
|
9
9
|
BulkRenameView,
|
|
10
10
|
ComponentCreateView,
|
|
11
|
+
GenericView,
|
|
11
12
|
ObjectDeleteView,
|
|
12
13
|
ObjectEditView,
|
|
13
14
|
ObjectImportView,
|
|
@@ -57,6 +58,7 @@ __all__ = (
|
|
|
57
58
|
"csv_format",
|
|
58
59
|
"EnhancedPage",
|
|
59
60
|
"EnhancedPaginator",
|
|
61
|
+
"GenericView",
|
|
60
62
|
"get_csv_form_fields_from_serializer_class",
|
|
61
63
|
"get_paginate_count",
|
|
62
64
|
"GetReturnURLMixin",
|
nautobot/circuits/api/urls.py
CHANGED
|
@@ -2,8 +2,7 @@ from nautobot.core.api.routers import OrderedDefaultRouter
|
|
|
2
2
|
|
|
3
3
|
from . import views
|
|
4
4
|
|
|
5
|
-
router = OrderedDefaultRouter()
|
|
6
|
-
router.APIRootView = views.CircuitsRootView
|
|
5
|
+
router = OrderedDefaultRouter(view_name="Circuits")
|
|
7
6
|
|
|
8
7
|
# Providers
|
|
9
8
|
router.register("providers", views.ProviderViewSet)
|
nautobot/circuits/api/views.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from rest_framework.routers import APIRootView
|
|
2
|
-
|
|
3
1
|
from nautobot.circuits import filters
|
|
4
2
|
from nautobot.circuits.models import Circuit, CircuitTermination, CircuitType, Provider, ProviderNetwork
|
|
5
3
|
from nautobot.core.models.querysets import count_related
|
|
@@ -8,16 +6,6 @@ from nautobot.extras.api.views import NautobotModelViewSet
|
|
|
8
6
|
|
|
9
7
|
from . import serializers
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
class CircuitsRootView(APIRootView):
|
|
13
|
-
"""
|
|
14
|
-
Circuits API root view
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
def get_view_name(self):
|
|
18
|
-
return "Circuits"
|
|
19
|
-
|
|
20
|
-
|
|
21
9
|
#
|
|
22
10
|
# Providers
|
|
23
11
|
#
|
nautobot/circuits/apps.py
CHANGED
|
@@ -57,7 +57,7 @@ class ProviderTestCase(FilterTestCases.NameOnlyFilterTestCase, FilterTestCases.F
|
|
|
57
57
|
def test_location(self):
|
|
58
58
|
expected = self.queryset.filter(
|
|
59
59
|
circuits__circuit_terminations__location__in=[self.locations[0].pk, self.locations[1].pk]
|
|
60
|
-
)
|
|
60
|
+
).distinct()
|
|
61
61
|
params = {"location": [self.locations[0].pk, self.locations[1].pk]}
|
|
62
62
|
self.assertQuerysetEqualAndNotEmpty(self.filterset(params, self.queryset).qs, expected)
|
|
63
63
|
params = {"location": [self.locations[0].name, self.locations[1].name]}
|
nautobot/core/api/routers.py
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
import logging
|
|
2
2
|
|
|
3
3
|
from rest_framework.routers import DefaultRouter
|
|
4
4
|
|
|
5
|
+
from nautobot.core.api.views import AuthenticatedAPIRootView
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
5
9
|
|
|
6
10
|
class OrderedDefaultRouter(DefaultRouter):
|
|
7
|
-
|
|
11
|
+
APIRootView = AuthenticatedAPIRootView
|
|
12
|
+
|
|
13
|
+
def __init__(self, *args, view_name=None, view_description=None, **kwargs):
|
|
8
14
|
super().__init__(*args, **kwargs)
|
|
9
15
|
|
|
16
|
+
self.view_name = view_name
|
|
17
|
+
if view_name and not view_description:
|
|
18
|
+
view_description = f"{view_name} API root view"
|
|
19
|
+
self.view_description = view_description
|
|
20
|
+
|
|
10
21
|
# Extend the list view mappings to support the DELETE operation
|
|
11
22
|
self.routes[0].mapping.update(
|
|
12
23
|
{
|
|
@@ -16,13 +27,49 @@ class OrderedDefaultRouter(DefaultRouter):
|
|
|
16
27
|
}
|
|
17
28
|
)
|
|
18
29
|
|
|
30
|
+
def register(self, prefix, viewset, basename=None):
|
|
31
|
+
"""
|
|
32
|
+
Override DRF's BaseRouter.register() to bypass an unnecessary restriction added in version 3.15.0.
|
|
33
|
+
|
|
34
|
+
(Reference: https://github.com/encode/django-rest-framework/pull/8438)
|
|
35
|
+
"""
|
|
36
|
+
if basename is None:
|
|
37
|
+
basename = self.get_default_basename(viewset)
|
|
38
|
+
|
|
39
|
+
# DRF:
|
|
40
|
+
# if self.is_already_registered(basename):
|
|
41
|
+
# msg = (f'Router with basename "{basename}" is already registered. '
|
|
42
|
+
# f'Please provide a unique basename for viewset "{viewset}"')
|
|
43
|
+
# raise ImproperlyConfigured(msg)
|
|
44
|
+
#
|
|
45
|
+
# We bypass this because we have at least one use case (/api/extras/jobs/) where we are *intentionally*
|
|
46
|
+
# registering two viewsets with the same basename, but have carefully defined them so as not to conflict.
|
|
47
|
+
|
|
48
|
+
# resuming standard DRF code...
|
|
49
|
+
self.registry.append((prefix, viewset, basename))
|
|
50
|
+
|
|
51
|
+
# invalidate the urls cache
|
|
52
|
+
if hasattr(self, "_urls"):
|
|
53
|
+
del self._urls
|
|
54
|
+
|
|
19
55
|
def get_api_root_view(self, api_urls=None):
|
|
20
56
|
"""
|
|
21
57
|
Wrap DRF's DefaultRouter to return an alphabetized list of endpoints.
|
|
22
58
|
"""
|
|
23
|
-
api_root_dict =
|
|
59
|
+
api_root_dict = {}
|
|
24
60
|
list_name = self.routes[0].name
|
|
61
|
+
|
|
25
62
|
for prefix, _viewset, basename in sorted(self.registry, key=lambda x: x[0]):
|
|
26
63
|
api_root_dict[prefix] = list_name.format(basename=basename)
|
|
27
64
|
|
|
65
|
+
if issubclass(self.APIRootView, AuthenticatedAPIRootView):
|
|
66
|
+
return self.APIRootView.as_view(
|
|
67
|
+
api_root_dict=api_root_dict, name=self.view_name, description=self.view_description
|
|
68
|
+
)
|
|
69
|
+
# Fallback for the established practice of overriding self.APIRootView with a custom class
|
|
70
|
+
logger.warning(
|
|
71
|
+
"Something has changed an OrderedDefaultRouter's APIRootView attribute to a custom class. "
|
|
72
|
+
"Please verify that class %s implements appropriate authentication controls.",
|
|
73
|
+
self.APIRootView.__name__,
|
|
74
|
+
)
|
|
28
75
|
return self.APIRootView.as_view(api_root_dict=api_root_dict)
|
nautobot/core/api/utils.py
CHANGED
|
@@ -178,6 +178,10 @@ def get_view_name(view, suffix=None):
|
|
|
178
178
|
|
|
179
179
|
else:
|
|
180
180
|
# Replicate DRF's built-in behavior.
|
|
181
|
+
name = getattr(view, "name", None)
|
|
182
|
+
if name is not None:
|
|
183
|
+
return view.name
|
|
184
|
+
|
|
181
185
|
name = view.__class__.__name__
|
|
182
186
|
name = formatting.remove_trailing_string(name, "View")
|
|
183
187
|
name = formatting.remove_trailing_string(name, "ViewSet")
|
nautobot/core/api/views.py
CHANGED
|
@@ -24,9 +24,9 @@ from graphql import get_default_backend
|
|
|
24
24
|
from graphql.execution import ExecutionResult
|
|
25
25
|
from graphql.execution.middleware import MiddlewareManager
|
|
26
26
|
from graphql.type.schema import GraphQLSchema
|
|
27
|
-
from rest_framework import status
|
|
27
|
+
from rest_framework import routers, status
|
|
28
28
|
from rest_framework.exceptions import ParseError, PermissionDenied
|
|
29
|
-
from rest_framework.permissions import
|
|
29
|
+
from rest_framework.permissions import IsAuthenticated
|
|
30
30
|
from rest_framework.response import Response
|
|
31
31
|
from rest_framework.reverse import reverse
|
|
32
32
|
from rest_framework.views import APIView
|
|
@@ -347,15 +347,25 @@ class ReadOnlyModelViewSet(NautobotAPIVersionMixin, ModelViewSetMixin, ReadOnlyM
|
|
|
347
347
|
#
|
|
348
348
|
|
|
349
349
|
|
|
350
|
-
class
|
|
350
|
+
class AuthenticatedAPIRootView(NautobotAPIVersionMixin, routers.APIRootView):
|
|
351
351
|
"""
|
|
352
|
-
|
|
352
|
+
Extends DRF's base APIRootView class to enforce user authentication.
|
|
353
353
|
"""
|
|
354
354
|
|
|
355
|
-
|
|
355
|
+
permission_classes = [IsAuthenticated]
|
|
356
|
+
|
|
357
|
+
name = None
|
|
358
|
+
description = None
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class APIRootView(AuthenticatedAPIRootView):
|
|
362
|
+
"""
|
|
363
|
+
This is the root of the REST API.
|
|
356
364
|
|
|
357
|
-
|
|
358
|
-
|
|
365
|
+
API endpoints are arranged by app and model name; e.g. `/api/dcim/locations/`.
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
name = "API Root"
|
|
359
369
|
|
|
360
370
|
@extend_schema(exclude=True)
|
|
361
371
|
def get(self, request, format=None): # pylint: disable=redefined-builtin
|
|
@@ -504,11 +514,6 @@ class NautobotSpectacularSwaggerView(APIVersioningGetSchemaURLMixin, Spectacular
|
|
|
504
514
|
@extend_schema(exclude=True)
|
|
505
515
|
def get(self, request, *args, **kwargs):
|
|
506
516
|
"""Fix up the rendering of the Swagger UI to work with Nautobot's UI."""
|
|
507
|
-
if not request.user.is_authenticated:
|
|
508
|
-
doc_url = reverse("api_docs")
|
|
509
|
-
login_url = reverse(settings.LOGIN_URL)
|
|
510
|
-
return redirect(f"{login_url}?next={doc_url}")
|
|
511
|
-
|
|
512
517
|
# For backward compatibility wtih drf-yasg, `/api/docs/?format=openapi` is a redirect to the JSON schema.
|
|
513
518
|
if request.GET.get("format") == "openapi":
|
|
514
519
|
return redirect("schema_json", permanent=True)
|
|
@@ -537,11 +542,12 @@ class NautobotSpectacularRedocView(APIVersioningGetSchemaURLMixin, SpectacularRe
|
|
|
537
542
|
class GraphQLDRFAPIView(NautobotAPIVersionMixin, APIView):
|
|
538
543
|
"""
|
|
539
544
|
API View for GraphQL to integrate properly with DRF authentication mechanism.
|
|
540
|
-
The code is a stripped down version of graphene-django default View
|
|
541
|
-
https://github.com/graphql-python/graphene-django/blob/main/graphene_django/views.py#L57
|
|
542
545
|
"""
|
|
543
546
|
|
|
544
|
-
|
|
547
|
+
# The code is a stripped down version of graphene-django default View
|
|
548
|
+
# https://github.com/graphql-python/graphene-django/blob/main/graphene_django/views.py#L57
|
|
549
|
+
|
|
550
|
+
permission_classes = [IsAuthenticated]
|
|
545
551
|
graphql_schema = None
|
|
546
552
|
executor = None
|
|
547
553
|
backend = None
|
nautobot/core/cli/__init__.py
CHANGED
|
@@ -13,7 +13,6 @@ from django.core.management import CommandError, CommandParser, execute_from_com
|
|
|
13
13
|
from django.core.management.utils import get_random_secret_key
|
|
14
14
|
from jinja2 import BaseLoader, Environment
|
|
15
15
|
|
|
16
|
-
from nautobot import __version__
|
|
17
16
|
from nautobot.core.settings_funcs import is_truthy
|
|
18
17
|
from nautobot.extras.plugins.utils import load_plugins
|
|
19
18
|
|
|
@@ -126,7 +125,7 @@ def _preprocess_settings(settings, config_path):
|
|
|
126
125
|
load_plugins(settings)
|
|
127
126
|
|
|
128
127
|
|
|
129
|
-
def
|
|
128
|
+
def load_settings(config_path):
|
|
130
129
|
"""Load nautobot_config.py or its equivalent into memory as a `nautobot_config` pseudo-module."""
|
|
131
130
|
if not os.path.exists(config_path):
|
|
132
131
|
raise FileNotFoundError(
|
|
@@ -154,6 +153,8 @@ class _VersionAction(argparse.Action):
|
|
|
154
153
|
super().__init__(*args, **kwargs)
|
|
155
154
|
|
|
156
155
|
def __call__(self, parser, namespace, values, option_string):
|
|
156
|
+
from nautobot import __version__
|
|
157
|
+
|
|
157
158
|
print(f"Nautobot version: {__version__}")
|
|
158
159
|
print(f"Django version: {django.__version__}")
|
|
159
160
|
print(f"Configuration file: {namespace.config_path}")
|
|
@@ -215,13 +216,9 @@ def _init_settings(args):
|
|
|
215
216
|
print(f"Configuration file created at {config_path}")
|
|
216
217
|
|
|
217
218
|
|
|
218
|
-
def
|
|
219
|
-
"""
|
|
220
|
-
|
|
221
|
-
os.environ["DJANGO_SETTINGS_MODULE"] = "nautobot_config"
|
|
222
|
-
|
|
223
|
-
# Default config path based on NAUTOBOT_CONFIG or NAUTOBOT_ROOT environment variables
|
|
224
|
-
config_path = os.getenv(
|
|
219
|
+
def get_config_path():
|
|
220
|
+
"""Get the default Nautobot config file path based on the NAUTOBOT_CONFIG or NAUTOBOT_ROOT environment variables."""
|
|
221
|
+
return os.getenv(
|
|
225
222
|
"NAUTOBOT_CONFIG",
|
|
226
223
|
os.path.join(
|
|
227
224
|
os.getenv("NAUTOBOT_ROOT", os.path.expanduser("~/.nautobot")),
|
|
@@ -229,13 +226,23 @@ def main():
|
|
|
229
226
|
),
|
|
230
227
|
)
|
|
231
228
|
|
|
229
|
+
|
|
230
|
+
def main():
|
|
231
|
+
"""Run administrative tasks."""
|
|
232
|
+
# Point Django to our 'nautobot_config' pseudo-module that we'll load from the provided config path
|
|
233
|
+
os.environ["DJANGO_SETTINGS_MODULE"] = "nautobot_config"
|
|
234
|
+
|
|
235
|
+
default_config_path = get_config_path()
|
|
236
|
+
|
|
232
237
|
# Intercept certain CLI parameters and arguments before they reach Django
|
|
233
238
|
parser = CommandParser(
|
|
234
239
|
description=DESCRIPTION,
|
|
235
240
|
usage=USAGE,
|
|
236
241
|
formatter_class=_VerboseHelpFormatter,
|
|
237
242
|
)
|
|
238
|
-
parser.add_argument(
|
|
243
|
+
parser.add_argument(
|
|
244
|
+
"-c", "--config-path", default=default_config_path, help="Path to the Nautobot configuration file"
|
|
245
|
+
)
|
|
239
246
|
parser.add_argument("--version", action=_VersionAction, help="Show version numbers and exit")
|
|
240
247
|
|
|
241
248
|
# Parse out the `--config` argument here and capture the rest of the CLI args
|
|
@@ -282,7 +289,7 @@ def main():
|
|
|
282
289
|
raise
|
|
283
290
|
|
|
284
291
|
# If we get here, it's a regular Django management command - so load in the nautobot_config.py then hand off
|
|
285
|
-
|
|
292
|
+
load_settings(args.config_path)
|
|
286
293
|
execute_from_command_line([sys.argv[0], *unparsed_args])
|
|
287
294
|
|
|
288
295
|
|
nautobot/core/constants.py
CHANGED
|
@@ -104,4 +104,89 @@ COMPOSITE_KEY_SEPARATOR = ";"
|
|
|
104
104
|
# For the natural slug separator, it's much simpler and we can just go with "_".
|
|
105
105
|
NATURAL_SLUG_SEPARATOR = "_"
|
|
106
106
|
|
|
107
|
+
# For config settings that contain a list of things.
|
|
108
|
+
# As environment variables only allow string types, these need to be split into the final list.
|
|
109
|
+
CONFIG_SETTING_SEPARATOR = ","
|
|
110
|
+
|
|
107
111
|
CHARFIELD_MAX_LENGTH = 255
|
|
112
|
+
|
|
113
|
+
# Models excluded from the global search list
|
|
114
|
+
GLOBAL_SEARCH_EXCLUDE_LIST = [
|
|
115
|
+
"anotherexamplemodel",
|
|
116
|
+
"cablepath",
|
|
117
|
+
"circuittermination",
|
|
118
|
+
"circuittype",
|
|
119
|
+
"clustergroup",
|
|
120
|
+
"clustertype",
|
|
121
|
+
"computedfield",
|
|
122
|
+
"configcontext",
|
|
123
|
+
"configcontextschema",
|
|
124
|
+
"consoleport",
|
|
125
|
+
"consoleporttemplate",
|
|
126
|
+
"consoleserverport",
|
|
127
|
+
"consoleserverporttemplate",
|
|
128
|
+
"contactassociation",
|
|
129
|
+
"controllermanageddevicegroup",
|
|
130
|
+
"customfield",
|
|
131
|
+
"customfieldchoice",
|
|
132
|
+
"customlink",
|
|
133
|
+
"devicebay",
|
|
134
|
+
"devicebaytemplate",
|
|
135
|
+
"devicetypetosoftwareimagefile",
|
|
136
|
+
"dynamicgroupmembership",
|
|
137
|
+
"exporttemplate",
|
|
138
|
+
"fileattachment",
|
|
139
|
+
"fileproxy",
|
|
140
|
+
"frontport",
|
|
141
|
+
"frontporttemplate",
|
|
142
|
+
"graphqlquery",
|
|
143
|
+
"healthchecktestmodel",
|
|
144
|
+
"imageattachment",
|
|
145
|
+
"interface",
|
|
146
|
+
"interfaceredundancygroup",
|
|
147
|
+
"interfaceredundancygroupassociation",
|
|
148
|
+
"interfacetemplate",
|
|
149
|
+
"inventoryitem",
|
|
150
|
+
"ipaddresstointerface",
|
|
151
|
+
"job",
|
|
152
|
+
"jobbutton",
|
|
153
|
+
"jobhook",
|
|
154
|
+
"joblogentry",
|
|
155
|
+
"jobresult",
|
|
156
|
+
"locationtype",
|
|
157
|
+
"manufacturer",
|
|
158
|
+
"note",
|
|
159
|
+
"objectchange",
|
|
160
|
+
"platform",
|
|
161
|
+
"poweroutlet",
|
|
162
|
+
"poweroutlettemplate",
|
|
163
|
+
"powerpanel",
|
|
164
|
+
"powerport",
|
|
165
|
+
"powerporttemplate",
|
|
166
|
+
"prefixlocationassignment",
|
|
167
|
+
"rackreservation",
|
|
168
|
+
"rearport",
|
|
169
|
+
"rearporttemplate",
|
|
170
|
+
"relationship",
|
|
171
|
+
"relationshipassociation",
|
|
172
|
+
"rir",
|
|
173
|
+
"role",
|
|
174
|
+
"routetarget",
|
|
175
|
+
"scheduledjob",
|
|
176
|
+
"scheduledjobs",
|
|
177
|
+
"secret",
|
|
178
|
+
"secretsgroup",
|
|
179
|
+
"secretsgroupassociation",
|
|
180
|
+
"service",
|
|
181
|
+
"softwareimagefile",
|
|
182
|
+
"status",
|
|
183
|
+
"tag",
|
|
184
|
+
"taggeditem",
|
|
185
|
+
"tenantgroup",
|
|
186
|
+
"vlangroup",
|
|
187
|
+
"vlanlocationassignment",
|
|
188
|
+
"vminterface",
|
|
189
|
+
"vrfdeviceassignment",
|
|
190
|
+
"vrfprefixassignment",
|
|
191
|
+
"webhook",
|
|
192
|
+
]
|
nautobot/core/filters.py
CHANGED
|
@@ -260,6 +260,9 @@ class ContentTypeMultipleChoiceFilter(django_filters.MultipleChoiceFilter):
|
|
|
260
260
|
if not self.conjoined:
|
|
261
261
|
qs = qs.filter(q)
|
|
262
262
|
|
|
263
|
+
if self.distinct:
|
|
264
|
+
qs = qs.distinct()
|
|
265
|
+
|
|
263
266
|
return qs
|
|
264
267
|
|
|
265
268
|
|
|
@@ -522,7 +525,10 @@ class TreeNodeMultipleChoiceFilter(NaturalKeyOrPKMultipleChoiceFilter):
|
|
|
522
525
|
|
|
523
526
|
# Fetch the generated Q object and filter the incoming qs with it before passing it along.
|
|
524
527
|
query = self.generate_query(value)
|
|
525
|
-
|
|
528
|
+
result = self.get_method(qs)(query)
|
|
529
|
+
if self.distinct:
|
|
530
|
+
result = result.distinct()
|
|
531
|
+
return result
|
|
526
532
|
|
|
527
533
|
|
|
528
534
|
#
|
nautobot/core/forms/widgets.py
CHANGED
|
@@ -182,8 +182,7 @@ class APISelect(SelectWithDisabled):
|
|
|
182
182
|
# ModelChoiceIterator.__iter__() yields a tuple of (value, label)
|
|
183
183
|
# using this approach first yield a tuple of (null(value), null_option(label))
|
|
184
184
|
yield "null", self.null_options
|
|
185
|
-
|
|
186
|
-
yield item
|
|
185
|
+
yield from super().__iter__()
|
|
187
186
|
|
|
188
187
|
null_option = self.attrs.get("data-null-option")
|
|
189
188
|
self.choices = ModelChoiceIteratorWithNullOption(field=self.choices.field, null_option=null_option)
|
nautobot/core/graphql/schema.py
CHANGED
|
@@ -58,8 +58,8 @@ class Command(BaseCommand):
|
|
|
58
58
|
ProviderNetworkFactory,
|
|
59
59
|
)
|
|
60
60
|
from nautobot.dcim.factory import (
|
|
61
|
-
ControllerDeviceGroupFactory,
|
|
62
61
|
ControllerFactory,
|
|
62
|
+
ControllerManagedDeviceGroupFactory,
|
|
63
63
|
DeviceFactory,
|
|
64
64
|
DeviceFamilyFactory,
|
|
65
65
|
DeviceRedundancyGroupFactory,
|
|
@@ -131,7 +131,7 @@ class Command(BaseCommand):
|
|
|
131
131
|
LocationFactory.create_batch(10, has_parent=False, using=db_name)
|
|
132
132
|
self.stdout.write("Creating Controller with Groups...")
|
|
133
133
|
ControllerFactory.create_batch(1)
|
|
134
|
-
|
|
134
|
+
ControllerManagedDeviceGroupFactory.create_batch(5)
|
|
135
135
|
self.stdout.write("Creating RIRs...")
|
|
136
136
|
RIRFactory.create_batch(9, using=db_name) # only 9 unique RIR names are hard-coded presently
|
|
137
137
|
self.stdout.write("Creating RouteTargets...")
|
|
@@ -207,7 +207,7 @@ class Command(BaseCommand):
|
|
|
207
207
|
ExternalIntegrationFactory.create_batch(20, using=db_name)
|
|
208
208
|
self.stdout.write("Creating Controllers with Device or DeviceRedundancyGroups...")
|
|
209
209
|
ControllerFactory.create_batch(10)
|
|
210
|
-
|
|
210
|
+
ControllerManagedDeviceGroupFactory.create_batch(30)
|
|
211
211
|
# make sure we have some tenants that have null relationships to make filter tests happy
|
|
212
212
|
self.stdout.write("Creating Tenants without Circuits, Locations, IPAddresses, or Prefixes...")
|
|
213
213
|
TenantFactory.create_batch(10, using=db_name)
|
|
@@ -227,7 +227,7 @@ class Command(BaseCommand):
|
|
|
227
227
|
CircuitTerminationFactory,
|
|
228
228
|
CircuitTypeFactory,
|
|
229
229
|
ContactFactory,
|
|
230
|
-
|
|
230
|
+
ControllerManagedDeviceGroupFactory,
|
|
231
231
|
ControllerFactory,
|
|
232
232
|
DeviceFactory,
|
|
233
233
|
DeviceFamilyFactory,
|
nautobot/core/models/__init__.py
CHANGED
nautobot/core/settings.py
CHANGED
|
@@ -10,6 +10,7 @@ import django.forms
|
|
|
10
10
|
from django.utils.safestring import mark_safe
|
|
11
11
|
|
|
12
12
|
from nautobot import __version__
|
|
13
|
+
from nautobot.core.constants import CONFIG_SETTING_SEPARATOR as _CONFIG_SETTING_SEPARATOR
|
|
13
14
|
from nautobot.core.settings_funcs import ConstanceConfigItem, is_truthy, parse_redis_connection
|
|
14
15
|
|
|
15
16
|
#
|
|
@@ -152,6 +153,9 @@ if "NAUTOBOT_MAX_PAGE_SIZE" in os.environ and os.environ["NAUTOBOT_MAX_PAGE_SIZE
|
|
|
152
153
|
# Metrics
|
|
153
154
|
METRICS_ENABLED = is_truthy(os.getenv("NAUTOBOT_METRICS_ENABLED", "False"))
|
|
154
155
|
METRICS_AUTHENTICATED = is_truthy(os.getenv("NAUTOBOT_METRICS_AUTHENTICATED", "False"))
|
|
156
|
+
METRICS_DISABLED_APPS = []
|
|
157
|
+
if "NAUTOBOT_METRICS_DISABLED_APPS" in os.environ and os.environ["NAUTOBOT_METRICS_DISABLED_APPS"] != "":
|
|
158
|
+
METRICS_DISABLED_APPS = os.getenv("NAUTOBOT_METRICS_DISABLED_APPS", "").split(_CONFIG_SETTING_SEPARATOR)
|
|
155
159
|
|
|
156
160
|
# Napalm
|
|
157
161
|
NAPALM_ARGS = {}
|
|
@@ -166,7 +170,7 @@ if "NAUTOBOT_PAGINATE_COUNT" in os.environ and os.environ["NAUTOBOT_PAGINATE_COU
|
|
|
166
170
|
# The options displayed in the web interface dropdown to limit the number of objects per page.
|
|
167
171
|
# Default is [25, 50, 100, 250, 500, 1000]
|
|
168
172
|
if "NAUTOBOT_PER_PAGE_DEFAULTS" in os.environ and os.environ["NAUTOBOT_PER_PAGE_DEFAULTS"] != "":
|
|
169
|
-
PER_PAGE_DEFAULTS = [int(val) for val in os.environ["NAUTOBOT_PER_PAGE_DEFAULTS"].split(
|
|
173
|
+
PER_PAGE_DEFAULTS = [int(val) for val in os.environ["NAUTOBOT_PER_PAGE_DEFAULTS"].split(_CONFIG_SETTING_SEPARATOR)]
|
|
170
174
|
|
|
171
175
|
# Plugins
|
|
172
176
|
PLUGINS = []
|
|
@@ -188,6 +192,13 @@ if (
|
|
|
188
192
|
):
|
|
189
193
|
RACK_ELEVATION_DEFAULT_UNIT_WIDTH = int(os.environ["NAUTOBOT_RACK_ELEVATION_DEFAULT_UNIT_WIDTH"])
|
|
190
194
|
|
|
195
|
+
# Enable two-digit format for the rack unit numbering in rack elevations.
|
|
196
|
+
if (
|
|
197
|
+
"NAUTOBOT_RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT" in os.environ
|
|
198
|
+
and os.environ["NAUTOBOT_RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT"] != ""
|
|
199
|
+
):
|
|
200
|
+
RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT = is_truthy(os.environ["NAUTOBOT_RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT"])
|
|
201
|
+
|
|
191
202
|
# How frequently to check for a new Nautobot release on GitHub, and the URL to check for this information.
|
|
192
203
|
# Defaults to disabled (no URL) and check every 24 hours when enabled
|
|
193
204
|
if "NAUTOBOT_RELEASE_CHECK_TIMEOUT" in os.environ and os.environ["NAUTOBOT_RELEASE_CHECK_TIMEOUT"] != "":
|
|
@@ -332,6 +343,7 @@ SPECTACULAR_SETTINGS = {
|
|
|
332
343
|
# trim it from all of the individual paths correspondingly.
|
|
333
344
|
# See also https://github.com/nautobot/nautobot-ansible/pull/135 for an example of why this is desirable.
|
|
334
345
|
"SERVERS": [{"url": "/api"}],
|
|
346
|
+
"SERVE_PERMISSIONS": ["rest_framework.permissions.IsAuthenticated"],
|
|
335
347
|
"SCHEMA_PATH_PREFIX": "/api",
|
|
336
348
|
"SCHEMA_PATH_PREFIX_TRIM": True,
|
|
337
349
|
# use sidecar - locally packaged UI files, not CDN
|
|
@@ -768,6 +780,11 @@ CONSTANCE_CONFIG = {
|
|
|
768
780
|
"RACK_ELEVATION_DEFAULT_UNIT_WIDTH": ConstanceConfigItem(
|
|
769
781
|
default=230, help_text="Default width (in pixels) of a rack unit in a rack elevation diagram", field_type=int
|
|
770
782
|
),
|
|
783
|
+
"RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT": ConstanceConfigItem(
|
|
784
|
+
default=False,
|
|
785
|
+
help_text="Enables two-digit format for the rack unit numbering in a rack elevation diagram",
|
|
786
|
+
field_type=bool,
|
|
787
|
+
),
|
|
771
788
|
"RELEASE_CHECK_TIMEOUT": ConstanceConfigItem(
|
|
772
789
|
default=24 * 3600,
|
|
773
790
|
help_text="Number of seconds (must be at least 3600, or one hour) to cache the result of a release check "
|
|
@@ -799,7 +816,11 @@ CONSTANCE_CONFIG_FIELDSETS = {
|
|
|
799
816
|
"Natural Keys": ["DEVICE_NAME_AS_NATURAL_KEY", "LOCATION_NAME_AS_NATURAL_KEY"],
|
|
800
817
|
"Pagination": ["PAGINATE_COUNT", "MAX_PAGE_SIZE", "PER_PAGE_DEFAULTS"],
|
|
801
818
|
"Performance": ["DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT", "JOB_CREATE_FILE_MAX_SIZE"],
|
|
802
|
-
"Rack Elevation Rendering": [
|
|
819
|
+
"Rack Elevation Rendering": [
|
|
820
|
+
"RACK_ELEVATION_DEFAULT_UNIT_HEIGHT",
|
|
821
|
+
"RACK_ELEVATION_DEFAULT_UNIT_WIDTH",
|
|
822
|
+
"RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT",
|
|
823
|
+
],
|
|
803
824
|
"Release Checking": ["RELEASE_CHECK_URL", "RELEASE_CHECK_TIMEOUT"],
|
|
804
825
|
"User Interface": ["SUPPORT_MESSAGE"],
|
|
805
826
|
"Debugging": ["ALLOW_REQUEST_PROFILING"],
|
|
@@ -913,7 +934,7 @@ CELERY_TASK_TIME_LIMIT = int(os.getenv("NAUTOBOT_CELERY_TASK_TIME_LIMIT", str(10
|
|
|
913
934
|
CELERY_WORKER_PROMETHEUS_PORTS = []
|
|
914
935
|
if os.getenv("NAUTOBOT_CELERY_WORKER_PROMETHEUS_PORTS"):
|
|
915
936
|
CELERY_WORKER_PROMETHEUS_PORTS = [
|
|
916
|
-
int(value) for value in os.getenv("NAUTOBOT_CELERY_WORKER_PROMETHEUS_PORTS").split(
|
|
937
|
+
int(value) for value in os.getenv("NAUTOBOT_CELERY_WORKER_PROMETHEUS_PORTS").split(_CONFIG_SETTING_SEPARATOR)
|
|
917
938
|
]
|
|
918
939
|
|
|
919
940
|
# These settings define the custom nautobot serialization encoding as an accepted data encoding format
|