nautobot 2.4.8__py3-none-any.whl → 2.4.10__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/circuits/templates/circuits/circuittype.html +1 -1
- nautobot/circuits/templates/circuits/circuittype_retrieve.html +1 -39
- nautobot/circuits/views.py +18 -23
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +4 -111
- nautobot/cloud/views.py +56 -25
- nautobot/core/api/parsers.py +56 -2
- nautobot/core/celery/schedulers.py +1 -0
- nautobot/core/filters.py +1 -1
- nautobot/core/graphql/schema.py +1 -0
- nautobot/core/jobs/__init__.py +14 -3
- nautobot/core/models/__init__.py +2 -0
- nautobot/core/tables.py +13 -6
- nautobot/core/testing/views.py +27 -2
- nautobot/core/tests/test_csv.py +92 -1
- nautobot/core/tests/test_jinja_filters.py +59 -0
- nautobot/core/tests/test_jobs.py +113 -0
- nautobot/core/tests/test_ui.py +53 -1
- nautobot/core/tests/test_utils.py +11 -0
- nautobot/core/tests/test_views.py +73 -0
- nautobot/core/ui/object_detail.py +19 -12
- nautobot/core/urls.py +2 -2
- nautobot/core/utils/filtering.py +3 -0
- nautobot/core/views/__init__.py +21 -0
- nautobot/core/views/renderers.py +1 -1
- nautobot/dcim/forms.py +10 -0
- nautobot/dcim/models/device_component_templates.py +4 -0
- nautobot/dcim/models/device_components.py +12 -0
- nautobot/dcim/models/devices.py +6 -0
- nautobot/dcim/templates/dcim/devicefamily_retrieve.html +1 -43
- nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +1 -59
- nautobot/dcim/templates/dcim/devicetype.html +2 -217
- nautobot/dcim/templates/dcim/devicetype_edit.html +2 -32
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +217 -0
- nautobot/dcim/templates/dcim/devicetype_update.html +32 -0
- nautobot/dcim/templates/dcim/inc/rack_elevation.html +1 -1
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +1 -84
- nautobot/dcim/templates/dcim/rack_elevation.html +14 -0
- nautobot/dcim/templates/dcim/rackreservation_retrieve.html +0 -68
- nautobot/dcim/tests/integration/test_fileinputpicker.py +1 -1
- nautobot/dcim/urls.py +1 -36
- nautobot/dcim/views.py +133 -81
- nautobot/extras/api/views.py +4 -6
- nautobot/extras/context_managers.py +2 -2
- nautobot/extras/migrations/0024_job_data_migration.py +1 -1
- nautobot/extras/models/customfields.py +2 -0
- nautobot/extras/models/datasources.py +8 -0
- nautobot/extras/models/groups.py +18 -0
- nautobot/extras/models/jobs.py +92 -62
- nautobot/extras/models/metadata.py +2 -0
- nautobot/extras/models/models.py +4 -0
- nautobot/extras/models/secrets.py +7 -0
- nautobot/extras/secrets/__init__.py +14 -0
- nautobot/extras/tables.py +11 -1
- nautobot/extras/templates/extras/computedfield_retrieve.html +1 -55
- nautobot/extras/templates/extras/inc/job_tiles.html +1 -1
- nautobot/extras/templates/extras/jobresult.html +1 -1
- nautobot/extras/templates/extras/metadatatype_retrieve.html +1 -66
- nautobot/extras/templates/extras/scheduledjob.html +25 -9
- nautobot/extras/tests/test_api.py +1 -1
- nautobot/extras/tests/test_context_managers.py +20 -0
- nautobot/extras/tests/test_models.py +26 -0
- nautobot/extras/tests/test_views.py +15 -2
- nautobot/extras/utils.py +18 -16
- nautobot/extras/views.py +65 -26
- nautobot/ipam/models.py +32 -0
- nautobot/ipam/tables.py +3 -4
- nautobot/project-static/docs/404.html +4 -4
- nautobot/project-static/docs/apps/index.html +4 -4
- nautobot/project-static/docs/apps/nautobot-apps.html +4 -4
- nautobot/project-static/docs/assets/javascripts/{bundle.c8b220af.min.js → bundle.13a4f30d.min.js} +4 -4
- nautobot/project-static/docs/assets/javascripts/{bundle.c8b220af.min.js.map → bundle.13a4f30d.min.js.map} +2 -2
- nautobot/project-static/docs/assets/javascripts/workers/{search.f8cc74c7.min.js → search.d50fe291.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/workers/{search.f8cc74c7.min.js.map → search.d50fe291.min.js.map} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.2afb09e1.min.css → main.342714a4.min.css} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.2afb09e1.min.css.map → main.342714a4.min.css.map} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +6 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +36 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +4 -4
- nautobot/project-static/docs/development/apps/api/configuration-view.html +4 -4
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +4 -4
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +4 -4
- nautobot/project-static/docs/development/apps/api/models/global-search.html +4 -4
- nautobot/project-static/docs/development/apps/api/models/graphql.html +4 -4
- nautobot/project-static/docs/development/apps/api/models/index.html +4 -4
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +43 -42
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +4 -4
- nautobot/project-static/docs/development/apps/api/prometheus.html +4 -4
- nautobot/project-static/docs/development/apps/api/setup.html +4 -4
- nautobot/project-static/docs/development/apps/api/testing.html +4 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +4 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +4 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +4 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +4 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/base-template.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/index.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/notes.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/urls.html +4 -4
- nautobot/project-static/docs/development/apps/index.html +4 -4
- nautobot/project-static/docs/development/apps/migration/code-updates.html +4 -4
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +4 -4
- nautobot/project-static/docs/development/apps/migration/from-v1.html +4 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +4 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +4 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +4 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +4 -4
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +4 -4
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +4 -4
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +4 -4
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +4 -4
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +4 -4
- nautobot/project-static/docs/development/core/application-registry.html +4 -4
- nautobot/project-static/docs/development/core/best-practices.html +4 -4
- nautobot/project-static/docs/development/core/bootstrap-ui.html +4 -4
- nautobot/project-static/docs/development/core/caching.html +4 -4
- nautobot/project-static/docs/development/core/controllers.html +4 -4
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +41 -55
- nautobot/project-static/docs/development/core/generic-views.html +4 -4
- nautobot/project-static/docs/development/core/getting-started.html +4 -4
- nautobot/project-static/docs/development/core/homepage.html +4 -4
- nautobot/project-static/docs/development/core/index.html +4 -4
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +4 -4
- nautobot/project-static/docs/development/core/model-checklist.html +4 -4
- nautobot/project-static/docs/development/core/model-features.html +4 -4
- nautobot/project-static/docs/development/core/natural-keys.html +4 -4
- nautobot/project-static/docs/development/core/navigation-menu.html +4 -4
- nautobot/project-static/docs/development/core/release-checklist.html +4 -4
- nautobot/project-static/docs/development/core/role-internals.html +4 -4
- nautobot/project-static/docs/development/core/settings.html +4 -4
- nautobot/project-static/docs/development/core/style-guide.html +4 -4
- nautobot/project-static/docs/development/core/templates.html +4 -4
- nautobot/project-static/docs/development/core/testing.html +4 -4
- nautobot/project-static/docs/development/core/ui-component-framework.html +4 -4
- nautobot/project-static/docs/development/core/user-preferences.html +4 -4
- nautobot/project-static/docs/development/index.html +4 -4
- nautobot/project-static/docs/development/jobs/getting-started.html +4 -4
- nautobot/project-static/docs/development/jobs/index.html +4 -4
- nautobot/project-static/docs/development/jobs/installation.html +4 -4
- nautobot/project-static/docs/development/jobs/job-extensions.html +4 -4
- nautobot/project-static/docs/development/jobs/job-logging.html +4 -4
- nautobot/project-static/docs/development/jobs/job-patterns.html +4 -4
- nautobot/project-static/docs/development/jobs/job-structure.html +4 -4
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +4 -4
- nautobot/project-static/docs/development/jobs/testing.html +4 -4
- nautobot/project-static/docs/index.html +4 -4
- nautobot/project-static/docs/overview/application_stack.html +4 -4
- nautobot/project-static/docs/overview/design_philosophy.html +4 -4
- nautobot/project-static/docs/release-notes/index.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.0.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.1.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.2.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.3.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.4.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.5.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.6.html +301 -4
- nautobot/project-static/docs/release-notes/version-2.0.html +4 -4
- nautobot/project-static/docs/release-notes/version-2.1.html +4 -4
- nautobot/project-static/docs/release-notes/version-2.2.html +4 -4
- nautobot/project-static/docs/release-notes/version-2.3.html +4 -4
- nautobot/project-static/docs/release-notes/version-2.4.html +291 -4
- nautobot/project-static/docs/requirements.txt +1 -1
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +298 -298
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/index.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/services.html +4 -4
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +4 -4
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +4 -4
- nautobot/project-static/docs/user-guide/administration/security/index.html +4 -5
- nautobot/project-static/docs/user-guide/administration/security/notices.html +117 -5
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +4 -4
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +4 -4
- nautobot/project-static/docs/user-guide/index.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +4 -4
- nautobot/project-static/js/forms.js +0 -14
- nautobot/users/models.py +4 -0
- nautobot/virtualization/models.py +4 -0
- nautobot/wireless/tables.py +1 -0
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +1 -55
- nautobot/wireless/views.py +33 -28
- {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/METADATA +4 -4
- {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/RECORD +387 -384
- {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/NOTICE +0 -0
- {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/WHEEL +0 -0
- {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/entry_points.txt +0 -0
|
@@ -1739,7 +1739,7 @@ class JobTest(
|
|
|
1739
1739
|
# Ensure the enqueue_job args deserialize to the same as originally inputted
|
|
1740
1740
|
expected_enqueue_job_args = (self.job_model, self.user)
|
|
1741
1741
|
expected_enqueue_job_kwargs = {
|
|
1742
|
-
"
|
|
1742
|
+
"job_queue": self.job_model.default_job_queue,
|
|
1743
1743
|
**self.job_class.serialize_data(deserialized_data),
|
|
1744
1744
|
}
|
|
1745
1745
|
mock_enqueue_job.assert_called_with(*expected_enqueue_job_args, **expected_enqueue_job_kwargs)
|
|
@@ -2,6 +2,7 @@ from unittest import mock
|
|
|
2
2
|
|
|
3
3
|
from django.contrib.auth import get_user_model
|
|
4
4
|
from django.contrib.contenttypes.models import ContentType
|
|
5
|
+
from django.core.exceptions import ValidationError
|
|
5
6
|
from django.test import TestCase
|
|
6
7
|
|
|
7
8
|
from nautobot.core.celery import app
|
|
@@ -220,6 +221,25 @@ class WebRequestContextTestCase(TestCase):
|
|
|
220
221
|
self.assertEqual(call_args[6], oc_list[0].request_id)
|
|
221
222
|
self.assertEqual(call_args[7], oc_list[0].get_snapshots())
|
|
222
223
|
|
|
224
|
+
def test_web_request_context_raises_exception_correctly(self):
|
|
225
|
+
"""
|
|
226
|
+
Test implemented to ensure the fix for https://github.com/nautobot/nautobot/issues/7358 is working as intended.
|
|
227
|
+
The operation should raise and allow an exception to be passed through instead of raising an
|
|
228
|
+
AttributeError: 'NoneType' object has no attribute 'get'"
|
|
229
|
+
"""
|
|
230
|
+
valid_location_type = LocationType.objects.get(name="Campus")
|
|
231
|
+
location_status = Status.objects.get_for_model(Location).first()
|
|
232
|
+
invalid_location_type = LocationType(name="rackgroup")
|
|
233
|
+
with self.assertRaises(ValidationError):
|
|
234
|
+
with web_request_context(self.user, context_detail="test_web_request_context_raises_exception_correctly"):
|
|
235
|
+
# These operations should generate some ObjectChange records to test the code path that was causing the reported issue.
|
|
236
|
+
location = Location(name="Test Location 1", location_type=valid_location_type, status=location_status)
|
|
237
|
+
location.save()
|
|
238
|
+
location.description = "changed"
|
|
239
|
+
location.save()
|
|
240
|
+
# Location type name is not allowed to be "rackgroup" (reserved name), so this should raise an exception.
|
|
241
|
+
invalid_location_type.validated_save()
|
|
242
|
+
|
|
223
243
|
|
|
224
244
|
class WebRequestContextTransactionTestCase(TransactionTestCase):
|
|
225
245
|
def test_change_log_thread_safe(self):
|
|
@@ -125,6 +125,13 @@ class ComputedFieldTest(ModelTestCases.BaseModelTestCase):
|
|
|
125
125
|
fallback_value="An error occurred while rendering this template.",
|
|
126
126
|
weight=50,
|
|
127
127
|
)
|
|
128
|
+
self.evil_computed_field = ComputedField.objects.create(
|
|
129
|
+
content_type=ContentType.objects.get_for_model(Secret),
|
|
130
|
+
key="evil_computed_field",
|
|
131
|
+
label="Evil Computed Field",
|
|
132
|
+
template="{{ obj.get_value() }}",
|
|
133
|
+
weight=666,
|
|
134
|
+
)
|
|
128
135
|
self.blank_fallback_value = ComputedField.objects.create(
|
|
129
136
|
content_type=ContentType.objects.get_for_model(Location),
|
|
130
137
|
key="blank_fallback_value",
|
|
@@ -133,6 +140,18 @@ class ComputedFieldTest(ModelTestCases.BaseModelTestCase):
|
|
|
133
140
|
weight=50,
|
|
134
141
|
)
|
|
135
142
|
self.location1 = Location.objects.filter(location_type=LocationType.objects.get(name="Campus")).first()
|
|
143
|
+
self.secret = Secret.objects.create(
|
|
144
|
+
name="Environment Variable Secret",
|
|
145
|
+
provider="environment-variable",
|
|
146
|
+
parameters={"variable": "NAUTOBOT_ROOT"},
|
|
147
|
+
)
|
|
148
|
+
self.secrets_group = SecretsGroup.objects.create(name="Group of Secrets")
|
|
149
|
+
SecretsGroupAssociation.objects.create(
|
|
150
|
+
secrets_group=self.secrets_group,
|
|
151
|
+
secret=self.secret,
|
|
152
|
+
access_type=SecretsGroupAccessTypeChoices.TYPE_GENERIC,
|
|
153
|
+
secret_type=SecretsGroupSecretTypeChoices.TYPE_SECRET,
|
|
154
|
+
)
|
|
136
155
|
|
|
137
156
|
def test_render_method(self):
|
|
138
157
|
rendered_value = self.good_computed_field.render(context={"obj": self.location1})
|
|
@@ -146,6 +165,13 @@ class ComputedFieldTest(ModelTestCases.BaseModelTestCase):
|
|
|
146
165
|
rendered_value = self.bad_computed_field.render(context={"obj": self.location1})
|
|
147
166
|
self.assertEqual(rendered_value, self.bad_computed_field.fallback_value)
|
|
148
167
|
|
|
168
|
+
def test_render_method_evil_template(self):
|
|
169
|
+
rendered_value = self.evil_computed_field.render(context={"obj": self.secret})
|
|
170
|
+
self.assertEqual(rendered_value, "")
|
|
171
|
+
self.evil_computed_field.template = "{{ obj.secrets_groups.first().get_secret_value('Generic', 'secret') }}"
|
|
172
|
+
rendered_value = self.evil_computed_field.render(context={"obj": self.secret})
|
|
173
|
+
self.assertEqual(rendered_value, "")
|
|
174
|
+
|
|
149
175
|
def test_check_if_key_is_graphql_safe(self):
|
|
150
176
|
"""
|
|
151
177
|
Check the GraphQL validation method on CustomField Key Attribute.
|
|
@@ -1162,6 +1162,15 @@ class GitRepositoryTestCase(
|
|
|
1162
1162
|
):
|
|
1163
1163
|
model = GitRepository
|
|
1164
1164
|
slugify_function = staticmethod(slugify_dashes_to_underscores)
|
|
1165
|
+
expected_edit_form_buttons = [
|
|
1166
|
+
'<button type="submit" name="_dryrun_update" class="btn btn-warning">Update & Dry Run</button>',
|
|
1167
|
+
'<button type="submit" name="_update" class="btn btn-primary">Update & Sync</button>',
|
|
1168
|
+
]
|
|
1169
|
+
expected_create_form_buttons = [
|
|
1170
|
+
'<button type="submit" name="_dryrun_create" class="btn btn-info">Create & Dry Run</button>',
|
|
1171
|
+
'<button type="submit" name="_create" class="btn btn-primary">Create & Sync</button>',
|
|
1172
|
+
'<button type="submit" name="_addanother" class="btn btn-primary">Create and Add Another</button>',
|
|
1173
|
+
]
|
|
1165
1174
|
|
|
1166
1175
|
@classmethod
|
|
1167
1176
|
def setUpTestData(cls):
|
|
@@ -2773,10 +2782,14 @@ class JobTestCase(
|
|
|
2773
2782
|
@mock.patch("nautobot.extras.views.get_worker_count", return_value=0)
|
|
2774
2783
|
def test_run_now_no_worker(self, _):
|
|
2775
2784
|
self.add_permissions("extras.run_job")
|
|
2785
|
+
self.add_permissions("extras.view_jobresult")
|
|
2776
2786
|
|
|
2777
2787
|
for run_url in self.run_urls:
|
|
2778
|
-
response = self.client.post(run_url, self.data_run_immediately)
|
|
2779
|
-
|
|
2788
|
+
response = self.client.post(run_url, self.data_run_immediately, follow=True)
|
|
2789
|
+
|
|
2790
|
+
result = JobResult.objects.latest()
|
|
2791
|
+
self.assertRedirects(response, reverse("extras:jobresult", kwargs={"pk": result.pk}))
|
|
2792
|
+
self.assertBodyContains(response, "No celery workers found")
|
|
2780
2793
|
|
|
2781
2794
|
@mock.patch("nautobot.extras.views.get_worker_count", return_value=1)
|
|
2782
2795
|
def test_run_now(self, _):
|
nautobot/extras/utils.py
CHANGED
|
@@ -6,7 +6,7 @@ import hmac
|
|
|
6
6
|
import logging
|
|
7
7
|
import re
|
|
8
8
|
import sys
|
|
9
|
-
from typing import Optional
|
|
9
|
+
from typing import Optional, TYPE_CHECKING, Union
|
|
10
10
|
|
|
11
11
|
from django.apps import apps
|
|
12
12
|
from django.conf import settings
|
|
@@ -37,6 +37,9 @@ from nautobot.extras.constants import (
|
|
|
37
37
|
)
|
|
38
38
|
from nautobot.extras.registry import registry
|
|
39
39
|
|
|
40
|
+
if TYPE_CHECKING:
|
|
41
|
+
from nautobot.extras.models import JobQueue
|
|
42
|
+
|
|
40
43
|
logger = logging.getLogger(__name__)
|
|
41
44
|
|
|
42
45
|
|
|
@@ -409,10 +412,12 @@ def get_celery_queues():
|
|
|
409
412
|
return celery_queues
|
|
410
413
|
|
|
411
414
|
|
|
412
|
-
def get_worker_count(request=None, queue=None):
|
|
415
|
+
def get_worker_count(request=None, queue: Optional[Union[str, "JobQueue"]] = None) -> int:
|
|
413
416
|
"""
|
|
414
|
-
Return a count of the active Celery workers in a specified queue
|
|
415
|
-
|
|
417
|
+
Return a count of the active Celery workers in a specified queue.
|
|
418
|
+
|
|
419
|
+
Args:
|
|
420
|
+
queue (str, JobQueue, None): queue name or JobQueue to check; if unset, defaults to CELERY_TASK_DEFAULT_QUEUE.
|
|
416
421
|
"""
|
|
417
422
|
from nautobot.extras.models import JobQueue
|
|
418
423
|
|
|
@@ -434,7 +439,7 @@ def get_worker_count(request=None, queue=None):
|
|
|
434
439
|
return celery_queues.get(queue, 0)
|
|
435
440
|
|
|
436
441
|
|
|
437
|
-
def get_job_queue_worker_count(request=None, job_queue=None):
|
|
442
|
+
def get_job_queue_worker_count(request=None, job_queue: Optional["JobQueue"] = None) -> int:
|
|
438
443
|
"""
|
|
439
444
|
Return a count of the active Celery workers in a specified queue. Defaults to the `CELERY_TASK_DEFAULT_QUEUE` setting.
|
|
440
445
|
Same as get_worker_count() method above, but job_queue is an actual JobQueue model instance.
|
|
@@ -449,27 +454,24 @@ def get_job_queue_worker_count(request=None, job_queue=None):
|
|
|
449
454
|
return celery_queues.get(queue, 0)
|
|
450
455
|
|
|
451
456
|
|
|
452
|
-
def get_job_queue(job_queue):
|
|
457
|
+
def get_job_queue(job_queue: str) -> Optional["JobQueue"]:
|
|
453
458
|
"""
|
|
454
459
|
Search for a JobQueue instance based on the str job_queue.
|
|
455
460
|
If no existing Job Queue not found, return None
|
|
456
461
|
"""
|
|
457
462
|
from nautobot.extras.models import JobQueue
|
|
458
463
|
|
|
459
|
-
queue = None
|
|
460
464
|
if is_uuid(job_queue):
|
|
461
465
|
try:
|
|
462
466
|
# check if the string passed in is a valid UUID
|
|
463
|
-
|
|
467
|
+
return JobQueue.objects.get(pk=job_queue)
|
|
464
468
|
except JobQueue.DoesNotExist:
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
queue = None
|
|
472
|
-
return queue
|
|
469
|
+
return None
|
|
470
|
+
try:
|
|
471
|
+
# check if the string passed in is a valid name
|
|
472
|
+
return JobQueue.objects.get(name=job_queue)
|
|
473
|
+
except JobQueue.DoesNotExist:
|
|
474
|
+
return None
|
|
473
475
|
|
|
474
476
|
|
|
475
477
|
def task_queues_as_choices(task_queues):
|
nautobot/extras/views.py
CHANGED
|
@@ -73,7 +73,7 @@ from nautobot.dcim.tables import (
|
|
|
73
73
|
VirtualDeviceContextTable,
|
|
74
74
|
)
|
|
75
75
|
from nautobot.extras.context_managers import deferred_change_logging_for_bulk_operation
|
|
76
|
-
from nautobot.extras.utils import fixup_filterset_query_params, get_base_template,
|
|
76
|
+
from nautobot.extras.utils import fixup_filterset_query_params, get_base_template, get_worker_count
|
|
77
77
|
from nautobot.ipam.models import IPAddress, Prefix, VLAN
|
|
78
78
|
from nautobot.ipam.tables import IPAddressTable, PrefixTable, VLANTable
|
|
79
79
|
from nautobot.virtualization.models import VirtualMachine, VMInterface
|
|
@@ -153,6 +153,23 @@ class ComputedFieldUIViewSet(NautobotUIViewSet):
|
|
|
153
153
|
table_class = tables.ComputedFieldTable
|
|
154
154
|
queryset = ComputedField.objects.all()
|
|
155
155
|
action_buttons = ("add",)
|
|
156
|
+
object_detail_content = object_detail.ObjectDetailContent(
|
|
157
|
+
panels=(
|
|
158
|
+
object_detail.ObjectFieldsPanel(
|
|
159
|
+
section=SectionChoices.LEFT_HALF,
|
|
160
|
+
weight=100,
|
|
161
|
+
fields="__all__",
|
|
162
|
+
exclude_fields=["template"],
|
|
163
|
+
),
|
|
164
|
+
ObjectTextPanel(
|
|
165
|
+
label="Template",
|
|
166
|
+
section=SectionChoices.FULL_WIDTH,
|
|
167
|
+
weight=100,
|
|
168
|
+
object_field="template",
|
|
169
|
+
render_as=ObjectTextPanel.RenderOptions.CODE,
|
|
170
|
+
),
|
|
171
|
+
),
|
|
172
|
+
)
|
|
156
173
|
|
|
157
174
|
|
|
158
175
|
#
|
|
@@ -1359,14 +1376,16 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1359
1376
|
# for example "?kwargs_from_job_result=<UUID>&integervar=22"
|
|
1360
1377
|
explicit_initial = initial
|
|
1361
1378
|
initial = job_result.task_kwargs.copy()
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
if
|
|
1379
|
+
task_queue = job_result.celery_kwargs.get("queue", None)
|
|
1380
|
+
job_queue = None
|
|
1381
|
+
if task_queue is not None:
|
|
1365
1382
|
try:
|
|
1366
|
-
|
|
1383
|
+
job_queue = JobQueue.objects.get(
|
|
1384
|
+
name=task_queue, queue_type=JobQueueTypeChoices.TYPE_CELERY
|
|
1385
|
+
)
|
|
1367
1386
|
except JobQueue.DoesNotExist:
|
|
1368
1387
|
pass
|
|
1369
|
-
initial["_job_queue"] =
|
|
1388
|
+
initial["_job_queue"] = job_queue
|
|
1370
1389
|
initial["_profile"] = job_result.celery_kwargs.get("nautobot_job_profile", False)
|
|
1371
1390
|
initial["_ignore_singleton_lock"] = job_result.celery_kwargs.get(
|
|
1372
1391
|
"nautobot_job_ignore_singleton_lock", False
|
|
@@ -1410,7 +1429,6 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1410
1429
|
job_class = get_job(job_model.class_path, reload=True)
|
|
1411
1430
|
job_form = job_class.as_form(request.POST, request.FILES) if job_class is not None else None
|
|
1412
1431
|
schedule_form = forms.JobScheduleForm(request.POST)
|
|
1413
|
-
job_queue = request.POST.get("_job_queue")
|
|
1414
1432
|
|
|
1415
1433
|
return_url = request.POST.get("_return_url")
|
|
1416
1434
|
if return_url is not None and url_has_allowed_host_and_scheme(url=return_url, allowed_hosts=request.get_host()):
|
|
@@ -1418,13 +1436,8 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1418
1436
|
else:
|
|
1419
1437
|
return_url = None
|
|
1420
1438
|
|
|
1421
|
-
|
|
1422
|
-
if
|
|
1423
|
-
queue = job_model.default_job_queue
|
|
1424
|
-
# Allow execution only if a worker process is running on a celery queue and the job is runnable.
|
|
1425
|
-
if queue.queue_type == JobQueueTypeChoices.TYPE_CELERY and not get_worker_count(queue=job_queue):
|
|
1426
|
-
messages.error(request, "Unable to run or schedule job: Celery worker process not running.")
|
|
1427
|
-
elif not job_model.installed or job_class is None:
|
|
1439
|
+
# Allow execution only if the job is runnable.
|
|
1440
|
+
if not job_model.installed or job_class is None:
|
|
1428
1441
|
messages.error(request, "Unable to run or schedule job: Job is not presently installed.")
|
|
1429
1442
|
elif not job_model.enabled:
|
|
1430
1443
|
messages.error(request, "Unable to run or schedule job: Job is not enabled to be run.")
|
|
@@ -1442,15 +1455,17 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1442
1455
|
)
|
|
1443
1456
|
elif job_form is not None and job_form.is_valid() and schedule_form.is_valid():
|
|
1444
1457
|
job_queue = job_form.cleaned_data.pop("_job_queue", None)
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1458
|
+
if job_queue is None:
|
|
1459
|
+
job_queue = job_model.default_job_queue
|
|
1460
|
+
|
|
1461
|
+
if job_queue.queue_type == JobQueueTypeChoices.TYPE_CELERY and not get_worker_count(queue=job_queue):
|
|
1462
|
+
messages.warning(
|
|
1463
|
+
request,
|
|
1464
|
+
format_html(
|
|
1465
|
+
"No celery workers found for queue {}, job may never run unless a worker is started.",
|
|
1466
|
+
job_queue,
|
|
1467
|
+
),
|
|
1468
|
+
)
|
|
1454
1469
|
|
|
1455
1470
|
dryrun = job_form.cleaned_data.get("dryrun", False)
|
|
1456
1471
|
# Run the job. A new JobResult is created.
|
|
@@ -1467,7 +1482,7 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1467
1482
|
interval=schedule_type,
|
|
1468
1483
|
crontab=schedule_form.cleaned_data.get("_recurrence_custom_time"),
|
|
1469
1484
|
approval_required=job_model.approval_required,
|
|
1470
|
-
|
|
1485
|
+
job_queue=job_queue,
|
|
1471
1486
|
profile=profile,
|
|
1472
1487
|
ignore_singleton_lock=ignore_singleton_lock,
|
|
1473
1488
|
**job_class.serialize_data(job_form.cleaned_data),
|
|
@@ -1488,7 +1503,7 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1488
1503
|
request.user,
|
|
1489
1504
|
profile=profile,
|
|
1490
1505
|
ignore_singleton_lock=ignore_singleton_lock,
|
|
1491
|
-
|
|
1506
|
+
job_queue=job_queue,
|
|
1492
1507
|
**job_class.serialize_data(job_kwargs),
|
|
1493
1508
|
)
|
|
1494
1509
|
|
|
@@ -1585,7 +1600,7 @@ class JobApprovalRequestView(generic.ObjectView):
|
|
|
1585
1600
|
if job_class is not None:
|
|
1586
1601
|
# Render the form with all fields disabled
|
|
1587
1602
|
initial = instance.kwargs
|
|
1588
|
-
initial["_job_queue"] = instance.
|
|
1603
|
+
initial["_job_queue"] = instance.job_queue
|
|
1589
1604
|
initial["_profile"] = instance.celery_kwargs.get("profile", False)
|
|
1590
1605
|
job_form = job_class().as_form(initial=initial, approval_view=True)
|
|
1591
1606
|
else:
|
|
@@ -2312,6 +2327,28 @@ class MetadataTypeUIViewSet(NautobotUIViewSet):
|
|
|
2312
2327
|
serializer_class = serializers.MetadataTypeSerializer
|
|
2313
2328
|
table_class = tables.MetadataTypeTable
|
|
2314
2329
|
|
|
2330
|
+
object_detail_content = object_detail.ObjectDetailContent(
|
|
2331
|
+
panels=(
|
|
2332
|
+
object_detail.ObjectFieldsPanel(
|
|
2333
|
+
section=SectionChoices.LEFT_HALF,
|
|
2334
|
+
weight=100,
|
|
2335
|
+
exclude_fields=("content_types",),
|
|
2336
|
+
),
|
|
2337
|
+
object_detail.ObjectsTablePanel(
|
|
2338
|
+
section=SectionChoices.LEFT_HALF,
|
|
2339
|
+
weight=200,
|
|
2340
|
+
context_table_key="choices",
|
|
2341
|
+
table_title="Choices",
|
|
2342
|
+
),
|
|
2343
|
+
object_detail.ObjectFieldsPanel(
|
|
2344
|
+
section=SectionChoices.RIGHT_HALF,
|
|
2345
|
+
weight=100,
|
|
2346
|
+
fields=["content_types"],
|
|
2347
|
+
label="Assignment",
|
|
2348
|
+
),
|
|
2349
|
+
),
|
|
2350
|
+
)
|
|
2351
|
+
|
|
2315
2352
|
def get_extra_context(self, request, instance):
|
|
2316
2353
|
context = super().get_extra_context(request, instance)
|
|
2317
2354
|
|
|
@@ -2320,6 +2357,8 @@ class MetadataTypeUIViewSet(NautobotUIViewSet):
|
|
|
2320
2357
|
context["choices"] = forms.MetadataChoiceFormSet(data=request.POST, instance=instance)
|
|
2321
2358
|
else:
|
|
2322
2359
|
context["choices"] = forms.MetadataChoiceFormSet(instance=instance)
|
|
2360
|
+
elif self.action == "retrieve":
|
|
2361
|
+
context["choices"] = tables.MetadataChoiceTable(instance.choices.all())
|
|
2323
2362
|
|
|
2324
2363
|
return context
|
|
2325
2364
|
|
nautobot/ipam/models.py
CHANGED
|
@@ -200,6 +200,8 @@ class VRF(PrimaryModel):
|
|
|
200
200
|
instance.validated_save()
|
|
201
201
|
return instance
|
|
202
202
|
|
|
203
|
+
add_device.alters_data = True
|
|
204
|
+
|
|
203
205
|
def remove_device(self, device):
|
|
204
206
|
"""
|
|
205
207
|
Remove a `device` from this VRF.
|
|
@@ -213,6 +215,8 @@ class VRF(PrimaryModel):
|
|
|
213
215
|
instance = self.devices.through.objects.get(vrf=self, device=device)
|
|
214
216
|
return instance.delete()
|
|
215
217
|
|
|
218
|
+
remove_device.alters_data = True
|
|
219
|
+
|
|
216
220
|
def add_virtual_machine(self, virtual_machine, rd="", name=""):
|
|
217
221
|
"""
|
|
218
222
|
Add a `virtual_machine` to this VRF, optionally overloading `rd` and `name`.
|
|
@@ -231,6 +235,8 @@ class VRF(PrimaryModel):
|
|
|
231
235
|
instance.validated_save()
|
|
232
236
|
return instance
|
|
233
237
|
|
|
238
|
+
add_virtual_machine.alters_data = True
|
|
239
|
+
|
|
234
240
|
def remove_virtual_machine(self, virtual_machine):
|
|
235
241
|
"""
|
|
236
242
|
Remove a `virtual_machine` from this VRF.
|
|
@@ -244,6 +250,8 @@ class VRF(PrimaryModel):
|
|
|
244
250
|
instance = self.virtual_machines.through.objects.get(vrf=self, virtual_machine=virtual_machine)
|
|
245
251
|
return instance.delete()
|
|
246
252
|
|
|
253
|
+
remove_virtual_machine.alters_data = True
|
|
254
|
+
|
|
247
255
|
def add_virtual_device_context(self, virtual_device_context, rd="", name=""):
|
|
248
256
|
"""
|
|
249
257
|
Add a `virtual_device_context` to this VRF, optionally overloading `rd` and `name`.
|
|
@@ -264,6 +272,8 @@ class VRF(PrimaryModel):
|
|
|
264
272
|
instance.validated_save()
|
|
265
273
|
return instance
|
|
266
274
|
|
|
275
|
+
add_virtual_device_context.alters_data = True
|
|
276
|
+
|
|
267
277
|
def remove_virtual_device_context(self, virtual_device_context):
|
|
268
278
|
"""
|
|
269
279
|
Remove a `virtual_device_context` from this VRF.
|
|
@@ -279,6 +289,8 @@ class VRF(PrimaryModel):
|
|
|
279
289
|
)
|
|
280
290
|
return instance.delete()
|
|
281
291
|
|
|
292
|
+
remove_virtual_device_context.alters_data = True
|
|
293
|
+
|
|
282
294
|
def add_prefix(self, prefix):
|
|
283
295
|
"""
|
|
284
296
|
Add a `prefix` to this VRF. Each object must be in the same Namespace.
|
|
@@ -293,6 +305,8 @@ class VRF(PrimaryModel):
|
|
|
293
305
|
instance.validated_save()
|
|
294
306
|
return instance
|
|
295
307
|
|
|
308
|
+
add_prefix.alters_data = True
|
|
309
|
+
|
|
296
310
|
def remove_prefix(self, prefix):
|
|
297
311
|
"""
|
|
298
312
|
Remove a `prefix` from this VRF.
|
|
@@ -306,6 +320,8 @@ class VRF(PrimaryModel):
|
|
|
306
320
|
instance = self.prefixes.through.objects.get(vrf=self, prefix=prefix)
|
|
307
321
|
return instance.delete()
|
|
308
322
|
|
|
323
|
+
remove_prefix.alters_data = True
|
|
324
|
+
|
|
309
325
|
|
|
310
326
|
@extras_features("graphql")
|
|
311
327
|
class VRFDeviceAssignment(BaseModel):
|
|
@@ -374,6 +390,8 @@ class VRFDeviceAssignment(BaseModel):
|
|
|
374
390
|
"A VRFDeviceAssignment entry must be associated with a device, a virtual machine, or a virtual device context."
|
|
375
391
|
)
|
|
376
392
|
|
|
393
|
+
clean.alters_data = True
|
|
394
|
+
|
|
377
395
|
|
|
378
396
|
@extras_features("graphql")
|
|
379
397
|
class VRFPrefixAssignment(BaseModel):
|
|
@@ -640,6 +658,8 @@ class Prefix(PrimaryModel):
|
|
|
640
658
|
self.prefix_length = prefix.prefixlen
|
|
641
659
|
self.ip_version = prefix.version
|
|
642
660
|
|
|
661
|
+
_deconstruct_prefix.alters_data = True
|
|
662
|
+
|
|
643
663
|
def delete(self, *args, **kwargs):
|
|
644
664
|
"""
|
|
645
665
|
A Prefix with children will be impossible to delete and raise a `ProtectedError`.
|
|
@@ -705,6 +725,8 @@ class Prefix(PrimaryModel):
|
|
|
705
725
|
return parent
|
|
706
726
|
return None
|
|
707
727
|
|
|
728
|
+
get_parent.alters_data = True
|
|
729
|
+
|
|
708
730
|
def clean(self):
|
|
709
731
|
if self.prefix is not None: # missing network/prefix_length will be caught by super().clean()
|
|
710
732
|
# Clear host bits from prefix
|
|
@@ -716,6 +738,8 @@ class Prefix(PrimaryModel):
|
|
|
716
738
|
|
|
717
739
|
super().clean()
|
|
718
740
|
|
|
741
|
+
clean.alters_data = True
|
|
742
|
+
|
|
719
743
|
def save(self, *args, **kwargs):
|
|
720
744
|
self.clean()
|
|
721
745
|
|
|
@@ -821,6 +845,8 @@ class Prefix(PrimaryModel):
|
|
|
821
845
|
|
|
822
846
|
return query.update(parent=self)
|
|
823
847
|
|
|
848
|
+
reparent_subnets.alters_data = True
|
|
849
|
+
|
|
824
850
|
def reparent_ips(self):
|
|
825
851
|
"""Determine the list of child IPAddresses and set the parent to self."""
|
|
826
852
|
query = IPAddress.objects.select_for_update().filter(
|
|
@@ -832,6 +858,8 @@ class Prefix(PrimaryModel):
|
|
|
832
858
|
|
|
833
859
|
return query.update(parent=self)
|
|
834
860
|
|
|
861
|
+
reparent_ips.alters_data = True
|
|
862
|
+
|
|
835
863
|
def supernets(self, direct=False, include_self=False, for_update=False):
|
|
836
864
|
"""
|
|
837
865
|
Return supernets of this Prefix.
|
|
@@ -1228,6 +1256,8 @@ class IPAddress(PrimaryModel):
|
|
|
1228
1256
|
self.mask_length = address.prefixlen
|
|
1229
1257
|
self.ip_version = address.version
|
|
1230
1258
|
|
|
1259
|
+
_deconstruct_address.alters_data = True
|
|
1260
|
+
|
|
1231
1261
|
natural_key_field_names = ["parent__namespace", "host"]
|
|
1232
1262
|
|
|
1233
1263
|
def _get_closest_parent(self):
|
|
@@ -1289,6 +1319,8 @@ class IPAddress(PrimaryModel):
|
|
|
1289
1319
|
|
|
1290
1320
|
super().clean()
|
|
1291
1321
|
|
|
1322
|
+
clean.alters_data = True
|
|
1323
|
+
|
|
1292
1324
|
def save(self, *args, **kwargs):
|
|
1293
1325
|
self.clean() # MUST do data fixup as above
|
|
1294
1326
|
|
nautobot/ipam/tables.py
CHANGED
|
@@ -214,7 +214,7 @@ class NamespaceTable(BaseTable):
|
|
|
214
214
|
class VRFTable(StatusTableMixin, BaseTable):
|
|
215
215
|
pk = ToggleColumn()
|
|
216
216
|
name = tables.LinkColumn()
|
|
217
|
-
|
|
217
|
+
rd = tables.Column(verbose_name="RD")
|
|
218
218
|
tenant = TenantColumn()
|
|
219
219
|
import_targets = tables.TemplateColumn(template_code=VRF_TARGETS, orderable=False)
|
|
220
220
|
export_targets = tables.TemplateColumn(template_code=VRF_TARGETS, orderable=False)
|
|
@@ -225,7 +225,7 @@ class VRFTable(StatusTableMixin, BaseTable):
|
|
|
225
225
|
fields = (
|
|
226
226
|
"pk",
|
|
227
227
|
"name",
|
|
228
|
-
|
|
228
|
+
"rd",
|
|
229
229
|
"status",
|
|
230
230
|
"namespace",
|
|
231
231
|
"tenant",
|
|
@@ -234,8 +234,7 @@ class VRFTable(StatusTableMixin, BaseTable):
|
|
|
234
234
|
"export_targets",
|
|
235
235
|
"tags",
|
|
236
236
|
)
|
|
237
|
-
|
|
238
|
-
default_columns = ("pk", "name", "status", "namespace", "tenant", "description")
|
|
237
|
+
default_columns = ("pk", "name", "rd", "status", "namespace", "tenant", "description")
|
|
239
238
|
|
|
240
239
|
|
|
241
240
|
class VRFDeviceAssignmentTable(BaseTable):
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
<link rel="icon" href="/projects/core/en/stable/assets/favicon.ico">
|
|
15
|
-
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.
|
|
15
|
+
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.14">
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
<link rel="stylesheet" href="/projects/core/en/stable/assets/stylesheets/main.
|
|
23
|
+
<link rel="stylesheet" href="/projects/core/en/stable/assets/stylesheets/main.342714a4.min.css">
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
<link rel="stylesheet" href="/projects/core/en/stable/assets/stylesheets/palette.06af60db.min.css">
|
|
@@ -10122,10 +10122,10 @@
|
|
|
10122
10122
|
|
|
10123
10123
|
|
|
10124
10124
|
|
|
10125
|
-
<script id="__config" type="application/json">{"base": "/projects/core/en/stable/", "features": ["content.code.annotate", "content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "/projects/core/en/stable/assets/javascripts/workers/search.
|
|
10125
|
+
<script id="__config" type="application/json">{"base": "/projects/core/en/stable/", "features": ["content.code.annotate", "content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "/projects/core/en/stable/assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
|
|
10126
10126
|
|
|
10127
10127
|
|
|
10128
|
-
<script src="/projects/core/en/stable/assets/javascripts/bundle.
|
|
10128
|
+
<script src="/projects/core/en/stable/assets/javascripts/bundle.13a4f30d.min.js"></script>
|
|
10129
10129
|
|
|
10130
10130
|
|
|
10131
10131
|
</body>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
<link rel="icon" href="../assets/favicon.ico">
|
|
21
|
-
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.
|
|
21
|
+
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.14">
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
<link rel="stylesheet" href="../assets/stylesheets/main.
|
|
29
|
+
<link rel="stylesheet" href="../assets/stylesheets/main.342714a4.min.css">
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
|
|
@@ -10290,10 +10290,10 @@
|
|
|
10290
10290
|
|
|
10291
10291
|
|
|
10292
10292
|
|
|
10293
|
-
<script id="__config" type="application/json">{"base": "..", "features": ["content.code.annotate", "content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.
|
|
10293
|
+
<script id="__config" type="application/json">{"base": "..", "features": ["content.code.annotate", "content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
|
|
10294
10294
|
|
|
10295
10295
|
|
|
10296
|
-
<script src="../assets/javascripts/bundle.
|
|
10296
|
+
<script src="../assets/javascripts/bundle.13a4f30d.min.js"></script>
|
|
10297
10297
|
|
|
10298
10298
|
|
|
10299
10299
|
<script id="init-glightbox">const lightbox = GLightbox({"touchNavigation": true, "loop": false, "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom", "slideEffect": "slide"});
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
<link rel="icon" href="../assets/favicon.ico">
|
|
19
|
-
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.
|
|
19
|
+
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.14">
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
<link rel="stylesheet" href="../assets/stylesheets/main.
|
|
27
|
+
<link rel="stylesheet" href="../assets/stylesheets/main.342714a4.min.css">
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
|
|
@@ -10223,10 +10223,10 @@
|
|
|
10223
10223
|
|
|
10224
10224
|
|
|
10225
10225
|
|
|
10226
|
-
<script id="__config" type="application/json">{"base": "..", "features": ["content.code.annotate", "content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.
|
|
10226
|
+
<script id="__config" type="application/json">{"base": "..", "features": ["content.code.annotate", "content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
|
|
10227
10227
|
|
|
10228
10228
|
|
|
10229
|
-
<script src="../assets/javascripts/bundle.
|
|
10229
|
+
<script src="../assets/javascripts/bundle.13a4f30d.min.js"></script>
|
|
10230
10230
|
|
|
10231
10231
|
|
|
10232
10232
|
<script id="init-glightbox">const lightbox = GLightbox({"touchNavigation": true, "loop": false, "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom", "slideEffect": "slide"});
|