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
nautobot/extras/models/jobs.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Data models relating to Jobs
|
|
2
2
|
|
|
3
3
|
import contextlib
|
|
4
|
-
from datetime import timedelta
|
|
4
|
+
from datetime import datetime, timedelta
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
7
|
import signal
|
|
8
|
+
from typing import Optional, TYPE_CHECKING, Union
|
|
8
9
|
|
|
9
10
|
from billiard.exceptions import SoftTimeLimitExceeded
|
|
10
11
|
from celery.exceptions import NotRegistered
|
|
@@ -58,6 +59,11 @@ from nautobot.extras.utils import (
|
|
|
58
59
|
|
|
59
60
|
from .customfields import CustomFieldModel
|
|
60
61
|
|
|
62
|
+
if TYPE_CHECKING:
|
|
63
|
+
from django.contrib.auth import get_user_model
|
|
64
|
+
|
|
65
|
+
User = get_user_model()
|
|
66
|
+
|
|
61
67
|
logger = logging.getLogger(__name__)
|
|
62
68
|
|
|
63
69
|
|
|
@@ -329,12 +335,12 @@ class Job(PrimaryModel):
|
|
|
329
335
|
raise NotRegistered from err
|
|
330
336
|
|
|
331
337
|
@property
|
|
332
|
-
def task_queues(self):
|
|
338
|
+
def task_queues(self) -> list[str]:
|
|
333
339
|
"""Deprecated backward-compatibility property for the list of queue names for this Job."""
|
|
334
340
|
return self.job_queues.values_list("name", flat=True)
|
|
335
341
|
|
|
336
342
|
@task_queues.setter
|
|
337
|
-
def task_queues(self, value):
|
|
343
|
+
def task_queues(self, value: Union[str, list[str]]):
|
|
338
344
|
job_queues = []
|
|
339
345
|
# value is going to be a comma separated list of queue names
|
|
340
346
|
if isinstance(value, str):
|
|
@@ -747,50 +753,39 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
747
753
|
duration.total_seconds()
|
|
748
754
|
)
|
|
749
755
|
|
|
756
|
+
set_status.alters_data = True
|
|
757
|
+
|
|
750
758
|
@classmethod
|
|
751
|
-
def execute_job(cls,
|
|
759
|
+
def execute_job(cls, *args, **kwargs):
|
|
752
760
|
"""
|
|
753
761
|
Create a JobResult instance and run a job in the current process, blocking until the job finishes.
|
|
754
762
|
|
|
755
763
|
Running tasks synchronously in celery is *NOT* supported and if possible `enqueue_job` with synchronous=False
|
|
756
764
|
should be used instead.
|
|
757
765
|
|
|
758
|
-
Args:
|
|
759
|
-
job_model (Job): The Job to be enqueued for execution
|
|
760
|
-
user (User): User object to link to the JobResult instance
|
|
761
|
-
celery_kwargs (dict, optional): Dictionary of kwargs to pass as **kwargs to Celery when job is run
|
|
762
|
-
profile (bool, optional): Whether to run cProfile on the job execution
|
|
763
|
-
job_result (JobResult, optional): Existing JobResult with status PENDING, used in kubernetes job execution
|
|
764
|
-
*job_args: positional args passed to the job task
|
|
765
|
-
**job_kwargs: keyword args passed to the job task
|
|
766
|
+
Args: see `enqueue_job()`
|
|
766
767
|
|
|
767
768
|
Returns:
|
|
768
769
|
JobResult instance
|
|
769
770
|
"""
|
|
770
|
-
return cls.enqueue_job(
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
*job_args,
|
|
774
|
-
celery_kwargs=celery_kwargs,
|
|
775
|
-
profile=profile,
|
|
776
|
-
job_result=job_result,
|
|
777
|
-
synchronous=True,
|
|
778
|
-
**job_kwargs,
|
|
779
|
-
)
|
|
771
|
+
return cls.enqueue_job(*args, **kwargs, synchronous=True)
|
|
772
|
+
|
|
773
|
+
execute_job.__func__.alters_data = True
|
|
780
774
|
|
|
781
775
|
@classmethod
|
|
782
776
|
def enqueue_job(
|
|
783
777
|
cls,
|
|
784
|
-
job_model,
|
|
785
|
-
user,
|
|
778
|
+
job_model: Job,
|
|
779
|
+
user: "User",
|
|
786
780
|
*job_args,
|
|
787
|
-
celery_kwargs=None,
|
|
788
|
-
profile=False,
|
|
789
|
-
schedule=None,
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
781
|
+
celery_kwargs: Optional[dict] = None,
|
|
782
|
+
profile: bool = False,
|
|
783
|
+
schedule: Optional["ScheduledJob"] = None,
|
|
784
|
+
job_queue: Optional["JobQueue"] = None,
|
|
785
|
+
task_queue: Optional[str] = None, # deprecated!
|
|
786
|
+
job_result: Optional["JobResult"] = None,
|
|
787
|
+
synchronous: bool = False,
|
|
788
|
+
ignore_singleton_lock: bool = False,
|
|
794
789
|
**job_kwargs,
|
|
795
790
|
):
|
|
796
791
|
"""Create/Modify a JobResult instance and enqueue a job to be executed asynchronously by a Celery worker.
|
|
@@ -798,13 +793,16 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
798
793
|
Args:
|
|
799
794
|
job_model (Job): The Job to be enqueued for execution.
|
|
800
795
|
user (User): User object to link to the JobResult instance.
|
|
801
|
-
celery_kwargs (dict
|
|
802
|
-
profile (bool
|
|
803
|
-
schedule (ScheduledJob
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
796
|
+
celery_kwargs (dict): Dictionary of kwargs to pass as **kwargs to `apply_async()`/`apply()` when job is run.
|
|
797
|
+
profile (bool): If True, dump cProfile stats on the job execution.
|
|
798
|
+
schedule (ScheduledJob): ScheduledJob instance to link to the JobResult.
|
|
799
|
+
Cannot be used with synchronous=True.
|
|
800
|
+
job_queue (JobQueue): Job queue to send the job to. If not set, use the default queue for the given Job.
|
|
801
|
+
task_queue (str): The celery queue name to send the job to. **Deprecated, prefer `job_queue` instead.**
|
|
802
|
+
job_result (JobResult): Existing JobResult with status PENDING, to be modified and to be used
|
|
803
|
+
in kubernetes job execution.
|
|
804
|
+
synchronous (bool): If True, run the job in the current process, blocking until the job completes.
|
|
805
|
+
ignore_singleton_lock (bool): If True, invalidate the singleton lock before running the job.
|
|
808
806
|
This allows singleton jobs to run twice, or makes it possible to remove the lock when the first instance
|
|
809
807
|
of the job failed to remove it for any reason.
|
|
810
808
|
*job_args: positional args passed to the job task (UNUSED)
|
|
@@ -818,6 +816,20 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
818
816
|
if schedule is not None and synchronous:
|
|
819
817
|
raise ValueError("Scheduled jobs cannot be run synchronously")
|
|
820
818
|
|
|
819
|
+
if job_queue is not None and task_queue is not None and job_queue.name != task_queue:
|
|
820
|
+
raise ValueError("task_queue and job_queue are mutually exclusive")
|
|
821
|
+
if job_queue is not None and task_queue is None:
|
|
822
|
+
task_queue = job_queue.name
|
|
823
|
+
elif task_queue is not None and job_queue is None:
|
|
824
|
+
job_queue = JobQueue.objects.get(name=task_queue)
|
|
825
|
+
else: # both none
|
|
826
|
+
if celery_kwargs is not None and "queue" in celery_kwargs:
|
|
827
|
+
task_queue = celery_kwargs["queue"]
|
|
828
|
+
job_queue = JobQueue.objects.get(name=task_queue)
|
|
829
|
+
else:
|
|
830
|
+
job_queue = job_model.default_job_queue
|
|
831
|
+
task_queue = job_queue.name
|
|
832
|
+
|
|
821
833
|
if job_result is None:
|
|
822
834
|
job_result = cls.objects.create(
|
|
823
835
|
name=job_model.name,
|
|
@@ -835,10 +847,6 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
835
847
|
f"There is a mismatch between the job specified {job_model} and the job associated with the job result {job_result.job_model}"
|
|
836
848
|
)
|
|
837
849
|
|
|
838
|
-
if task_queue is None:
|
|
839
|
-
task_queue = job_model.default_job_queue.name
|
|
840
|
-
|
|
841
|
-
job_queue = JobQueue.objects.get(name=task_queue)
|
|
842
850
|
# Kubernetes Job Queue logic
|
|
843
851
|
# As we execute Kubernetes jobs, we want to execute `run_kubernetes_job_and_return_job_result`
|
|
844
852
|
# the first time the kubernetes job is enqueued to spin up the kubernetes pod.
|
|
@@ -863,6 +871,7 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
863
871
|
job_celery_kwargs["time_limit"] = job_model.time_limit
|
|
864
872
|
|
|
865
873
|
if celery_kwargs is not None:
|
|
874
|
+
# TODO: this lets celery_kwargs override keys like `queue` and `nautobot_job_user_id`; is that desirable?
|
|
866
875
|
job_celery_kwargs.update(celery_kwargs)
|
|
867
876
|
|
|
868
877
|
if synchronous:
|
|
@@ -933,6 +942,8 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
933
942
|
|
|
934
943
|
return job_result
|
|
935
944
|
|
|
945
|
+
enqueue_job.__func__.alters_data = True
|
|
946
|
+
|
|
936
947
|
def log(
|
|
937
948
|
self,
|
|
938
949
|
message,
|
|
@@ -984,6 +995,8 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
984
995
|
else:
|
|
985
996
|
log.save(using=JOB_LOGS)
|
|
986
997
|
|
|
998
|
+
log.alters_data = True
|
|
999
|
+
|
|
987
1000
|
|
|
988
1001
|
#
|
|
989
1002
|
# Job Button
|
|
@@ -1071,6 +1084,8 @@ class ScheduledJobs(models.Model):
|
|
|
1071
1084
|
if not instance.no_changes:
|
|
1072
1085
|
cls.update_changed()
|
|
1073
1086
|
|
|
1087
|
+
changed.__func__.alters_data = True
|
|
1088
|
+
|
|
1074
1089
|
@classmethod
|
|
1075
1090
|
def update_changed(cls, raw=False, **kwargs):
|
|
1076
1091
|
"""This function acts as a signal handler to track changes to the scheduled job that is triggered after a change"""
|
|
@@ -1078,6 +1093,8 @@ class ScheduledJobs(models.Model):
|
|
|
1078
1093
|
return
|
|
1079
1094
|
cls.objects.update_or_create(ident=1, defaults={"last_update": timezone.now()})
|
|
1080
1095
|
|
|
1096
|
+
update_changed.__func__.alters_data = True
|
|
1097
|
+
|
|
1081
1098
|
@classmethod
|
|
1082
1099
|
def last_change(cls):
|
|
1083
1100
|
"""This function acts as a getter for the last update on scheduled jobs"""
|
|
@@ -1208,7 +1225,6 @@ class ScheduledJob(BaseModel):
|
|
|
1208
1225
|
ordering = ["name"]
|
|
1209
1226
|
|
|
1210
1227
|
def save(self, *args, **kwargs):
|
|
1211
|
-
self.queue = self.queue or ""
|
|
1212
1228
|
# make sure non-valid crontab doesn't get saved
|
|
1213
1229
|
if self.interval == JobExecutionType.TYPE_CUSTOM:
|
|
1214
1230
|
try:
|
|
@@ -1253,12 +1269,12 @@ class ScheduledJob(BaseModel):
|
|
|
1253
1269
|
return self.to_cron()
|
|
1254
1270
|
|
|
1255
1271
|
@property
|
|
1256
|
-
def queue(self):
|
|
1272
|
+
def queue(self) -> str:
|
|
1257
1273
|
"""Deprecated backward-compatibility property for the queue name this job is scheduled for."""
|
|
1258
1274
|
return self.job_queue.name if self.job_queue else ""
|
|
1259
1275
|
|
|
1260
1276
|
@queue.setter
|
|
1261
|
-
def queue(self, value):
|
|
1277
|
+
def queue(self, value: str):
|
|
1262
1278
|
if value:
|
|
1263
1279
|
try:
|
|
1264
1280
|
self.job_queue = JobQueue.objects.get(name=value)
|
|
@@ -1301,14 +1317,15 @@ class ScheduledJob(BaseModel):
|
|
|
1301
1317
|
cls,
|
|
1302
1318
|
job_model,
|
|
1303
1319
|
user,
|
|
1304
|
-
name=None,
|
|
1305
|
-
start_time=None,
|
|
1306
|
-
interval=JobExecutionType.TYPE_IMMEDIATELY,
|
|
1307
|
-
crontab="",
|
|
1308
|
-
profile=False,
|
|
1309
|
-
approval_required=False,
|
|
1310
|
-
|
|
1311
|
-
|
|
1320
|
+
name: Optional[str] = None,
|
|
1321
|
+
start_time: Optional[datetime] = None,
|
|
1322
|
+
interval: str = JobExecutionType.TYPE_IMMEDIATELY,
|
|
1323
|
+
crontab: str = "",
|
|
1324
|
+
profile: bool = False,
|
|
1325
|
+
approval_required: bool = False,
|
|
1326
|
+
job_queue: Optional[JobQueue] = None,
|
|
1327
|
+
task_queue: Optional[str] = None, # deprecated!
|
|
1328
|
+
ignore_singleton_lock: bool = False,
|
|
1312
1329
|
**job_kwargs,
|
|
1313
1330
|
):
|
|
1314
1331
|
"""
|
|
@@ -1321,21 +1338,32 @@ class ScheduledJob(BaseModel):
|
|
|
1321
1338
|
Parameters:
|
|
1322
1339
|
job_model (JobModel): The job model instance.
|
|
1323
1340
|
user (User): The user who is scheduling the job.
|
|
1324
|
-
name (str
|
|
1325
|
-
start_time (datetime
|
|
1326
|
-
interval (JobExecutionType
|
|
1341
|
+
name (str): The name of the scheduled job. Automatically derived from the job_model and start_time if unset.
|
|
1342
|
+
start_time (datetime): The start time for the job. Defaults to the current time if unset.
|
|
1343
|
+
interval (JobExecutionType): The interval type for the job execution.
|
|
1327
1344
|
Defaults to JobExecutionType.TYPE_IMMEDIATELY.
|
|
1328
|
-
crontab (str
|
|
1329
|
-
profile (bool
|
|
1330
|
-
approval_required (bool
|
|
1331
|
-
|
|
1332
|
-
|
|
1345
|
+
crontab (str): The crontab string for the schedule. Defaults to "".
|
|
1346
|
+
profile (bool): Flag indicating whether to profile the job. Defaults to False.
|
|
1347
|
+
approval_required (bool): Flag indicating if approval is required. Defaults to False.
|
|
1348
|
+
job_queue (JobQueue): The Job queue to use. If unset, use the configured default celery queue.
|
|
1349
|
+
task_queue (str): The queue name to use. **Deprecated, prefer `job_queue`.**
|
|
1350
|
+
ignore_singleton_lock (bool): Whether to ignore singleton locks. Defaults to False.
|
|
1333
1351
|
**job_kwargs: Additional keyword arguments to pass to the job.
|
|
1334
1352
|
|
|
1335
1353
|
Returns:
|
|
1336
1354
|
ScheduledJob instance
|
|
1337
1355
|
"""
|
|
1338
1356
|
|
|
1357
|
+
if job_queue is not None and task_queue is not None and job_queue.name != task_queue:
|
|
1358
|
+
raise ValueError("task_queue and job_queue are mutually exclusive")
|
|
1359
|
+
if job_queue is not None and task_queue is None:
|
|
1360
|
+
task_queue = job_queue.name
|
|
1361
|
+
elif task_queue is not None and job_queue is None:
|
|
1362
|
+
job_queue = JobQueue.objects.get(name=task_queue)
|
|
1363
|
+
else: # both None
|
|
1364
|
+
job_queue = job_model.default_job_queue
|
|
1365
|
+
task_queue = job_queue.name
|
|
1366
|
+
|
|
1339
1367
|
if interval == JobExecutionType.TYPE_IMMEDIATELY:
|
|
1340
1368
|
start_time = timezone.localtime()
|
|
1341
1369
|
name = name or f"{job_model.name} - {start_time}"
|
|
@@ -1376,11 +1404,13 @@ class ScheduledJob(BaseModel):
|
|
|
1376
1404
|
user=user,
|
|
1377
1405
|
approval_required=approval_required,
|
|
1378
1406
|
crontab=crontab,
|
|
1379
|
-
|
|
1407
|
+
job_queue=job_queue,
|
|
1380
1408
|
)
|
|
1381
1409
|
scheduled_job.validated_save()
|
|
1382
1410
|
return scheduled_job
|
|
1383
1411
|
|
|
1412
|
+
create_schedule.__func__.alters_data = True
|
|
1413
|
+
|
|
1384
1414
|
def to_cron(self):
|
|
1385
1415
|
tz = self.time_zone
|
|
1386
1416
|
t = self.start_time.astimezone(tz) # pylint: disable=no-member
|
|
@@ -251,6 +251,8 @@ class ObjectMetadata(ChangeLoggedModel, BaseModel):
|
|
|
251
251
|
self.clean()
|
|
252
252
|
return super().validated_save(*args, **kwargs)
|
|
253
253
|
|
|
254
|
+
validated_save.alters_data = True
|
|
255
|
+
|
|
254
256
|
def clean(self):
|
|
255
257
|
"""
|
|
256
258
|
Validate a value according to the field's type validation rules.
|
nautobot/extras/models/models.py
CHANGED
|
@@ -457,6 +457,8 @@ class ExportTemplate(
|
|
|
457
457
|
if self.file_extension.startswith("."):
|
|
458
458
|
self.file_extension = self.file_extension[1:]
|
|
459
459
|
|
|
460
|
+
clean.alters_data = True
|
|
461
|
+
|
|
460
462
|
|
|
461
463
|
#
|
|
462
464
|
# External integrations
|
|
@@ -919,6 +921,8 @@ class UserSavedViewAssociation(BaseModel):
|
|
|
919
921
|
super().clean()
|
|
920
922
|
self.view_name = self.saved_view.view
|
|
921
923
|
|
|
924
|
+
clean.alters_data = True
|
|
925
|
+
|
|
922
926
|
|
|
923
927
|
#
|
|
924
928
|
# Webhooks
|
|
@@ -4,6 +4,7 @@ from django.core.exceptions import ValidationError
|
|
|
4
4
|
from django.core.serializers.json import DjangoJSONEncoder
|
|
5
5
|
from django.db import models
|
|
6
6
|
from jinja2.exceptions import TemplateSyntaxError, UndefinedError
|
|
7
|
+
from jinja2.sandbox import unsafe
|
|
7
8
|
|
|
8
9
|
from nautobot.core.constants import CHARFIELD_MAX_LENGTH
|
|
9
10
|
from nautobot.core.models import BaseModel
|
|
@@ -58,6 +59,7 @@ class Secret(PrimaryModel):
|
|
|
58
59
|
except (TemplateSyntaxError, UndefinedError) as exc:
|
|
59
60
|
raise SecretParametersError(self, registry["secrets_providers"].get(self.provider), str(exc)) from exc
|
|
60
61
|
|
|
62
|
+
@unsafe
|
|
61
63
|
def get_value(self, obj=None):
|
|
62
64
|
"""Retrieve the secret value that this Secret is a representation of.
|
|
63
65
|
|
|
@@ -77,6 +79,8 @@ class Secret(PrimaryModel):
|
|
|
77
79
|
except Exception as exc:
|
|
78
80
|
raise SecretError(self, provider, str(exc)) from exc
|
|
79
81
|
|
|
82
|
+
get_value.do_not_call_in_templates = True
|
|
83
|
+
|
|
80
84
|
def clean(self):
|
|
81
85
|
provider = registry["secrets_providers"].get(self.provider)
|
|
82
86
|
if not provider:
|
|
@@ -108,6 +112,7 @@ class SecretsGroup(OrganizationalModel):
|
|
|
108
112
|
def __str__(self):
|
|
109
113
|
return self.name
|
|
110
114
|
|
|
115
|
+
@unsafe
|
|
111
116
|
def get_secret_value(self, access_type, secret_type, obj=None, **kwargs):
|
|
112
117
|
"""Helper method to retrieve a specific secret from this group.
|
|
113
118
|
|
|
@@ -118,6 +123,8 @@ class SecretsGroup(OrganizationalModel):
|
|
|
118
123
|
).secret
|
|
119
124
|
return secret.get_value(obj=obj, **kwargs)
|
|
120
125
|
|
|
126
|
+
get_secret_value.do_not_call_in_templates = True
|
|
127
|
+
|
|
121
128
|
|
|
122
129
|
@extras_features(
|
|
123
130
|
"graphql",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
|
|
3
|
+
from jinja2.sandbox import unsafe
|
|
4
|
+
|
|
3
5
|
from nautobot.extras.registry import registry
|
|
4
6
|
|
|
5
7
|
from .exceptions import SecretError, SecretParametersError, SecretProviderError, SecretValueNotFoundError
|
|
@@ -31,6 +33,7 @@ class SecretsProvider(ABC):
|
|
|
31
33
|
|
|
32
34
|
@classmethod
|
|
33
35
|
@abstractmethod
|
|
36
|
+
@unsafe
|
|
34
37
|
def get_value_for_secret(cls, secret, obj=None, **kwargs):
|
|
35
38
|
"""Retrieve the stored value described by the given Secret record.
|
|
36
39
|
|
|
@@ -41,6 +44,17 @@ class SecretsProvider(ABC):
|
|
|
41
44
|
obj (object): Django model instance or similar providing additional context for retrieving the secret.
|
|
42
45
|
"""
|
|
43
46
|
|
|
47
|
+
get_value_for_secret.__func__.do_not_call_in_templates = True
|
|
48
|
+
|
|
49
|
+
def __init_subclass__(cls, **kwargs):
|
|
50
|
+
# Automatically apply protection against Django and Jinja2 template execution to child classes.
|
|
51
|
+
if not getattr(cls.get_value_for_secret, "do_not_call_in_templates", False): # Django
|
|
52
|
+
cls.get_value_for_secret.__func__.do_not_call_in_templates = True
|
|
53
|
+
if not getattr(cls.get_value_for_secret, "unsafe_callable", False): # Jinja @unsafe decorator
|
|
54
|
+
cls.get_value_for_secret.__func__.unsafe_callable = True
|
|
55
|
+
|
|
56
|
+
super().__init_subclass__(**kwargs)
|
|
57
|
+
|
|
44
58
|
|
|
45
59
|
def register_secrets_provider(provider):
|
|
46
60
|
"""
|
nautobot/extras/tables.py
CHANGED
|
@@ -40,6 +40,7 @@ from .models import (
|
|
|
40
40
|
JobLogEntry,
|
|
41
41
|
JobQueue,
|
|
42
42
|
JobResult,
|
|
43
|
+
MetadataChoice,
|
|
43
44
|
MetadataType,
|
|
44
45
|
Note,
|
|
45
46
|
ObjectChange,
|
|
@@ -730,7 +731,7 @@ class JobTable(BaseTable):
|
|
|
730
731
|
accessor="latest_result",
|
|
731
732
|
template_code="""
|
|
732
733
|
{% if value %}
|
|
733
|
-
{{ value.
|
|
734
|
+
{{ value.date_created|date:settings.SHORT_DATETIME_FORMAT }} by {{ value.user }}
|
|
734
735
|
{% else %}
|
|
735
736
|
<span class="text-muted">Never</span>
|
|
736
737
|
{% endif %}
|
|
@@ -1008,6 +1009,15 @@ class MetadataTypeTable(BaseTable):
|
|
|
1008
1009
|
)
|
|
1009
1010
|
|
|
1010
1011
|
|
|
1012
|
+
class MetadataChoiceTable(BaseTable):
|
|
1013
|
+
value = tables.Column()
|
|
1014
|
+
weight = tables.Column()
|
|
1015
|
+
|
|
1016
|
+
class Meta(BaseTable.Meta):
|
|
1017
|
+
model = MetadataChoice
|
|
1018
|
+
fields = ("value", "weight")
|
|
1019
|
+
|
|
1020
|
+
|
|
1011
1021
|
class ObjectMetadataTable(BaseTable):
|
|
1012
1022
|
pk = ToggleColumn()
|
|
1013
1023
|
# NOTE: there is no identity column in this table; this is intentional as we have no detail view for ObjectMetadata
|
|
@@ -1,56 +1,2 @@
|
|
|
1
1
|
{% extends 'generic/object_retrieve.html' %}
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block content_left_page %}
|
|
5
|
-
<div class="panel panel-default">
|
|
6
|
-
<div class="panel-heading">
|
|
7
|
-
<strong>Computed Field</strong>
|
|
8
|
-
</div>
|
|
9
|
-
|
|
10
|
-
<table class="table table-hover panel-body attr-table">
|
|
11
|
-
<tr>
|
|
12
|
-
<td>Content Type</td>
|
|
13
|
-
<td><span>{{ object.content_type }}</span></td>
|
|
14
|
-
</tr>
|
|
15
|
-
<tr>
|
|
16
|
-
<td>Label</td>
|
|
17
|
-
<td><span>{{ object.label }}</span></td>
|
|
18
|
-
</tr>
|
|
19
|
-
<tr>
|
|
20
|
-
<td>Key</td>
|
|
21
|
-
<td><span>{{ object.key }}</span></td>
|
|
22
|
-
</tr>
|
|
23
|
-
<tr>
|
|
24
|
-
<td>Grouping</td>
|
|
25
|
-
<td>{{ object.grouping | placeholder }}</td>
|
|
26
|
-
</tr>
|
|
27
|
-
<tr>
|
|
28
|
-
<td>Description</td>
|
|
29
|
-
<td><span>{{ object.description|placeholder }}</span></td>
|
|
30
|
-
</tr>
|
|
31
|
-
<tr>
|
|
32
|
-
<td>Fallback Value</td>
|
|
33
|
-
<td><span>{{ object.fallback_value }}</span></td>
|
|
34
|
-
</tr>
|
|
35
|
-
<tr>
|
|
36
|
-
<td>Weight</td>
|
|
37
|
-
<td><span>{{ object.weight }}</span></td>
|
|
38
|
-
</tr>
|
|
39
|
-
<tr>
|
|
40
|
-
<td>Move to Advanced Tab</td>
|
|
41
|
-
<td><span>{{ object.advanced_ui | render_boolean }}</span></td>
|
|
42
|
-
</tr>
|
|
43
|
-
</table>
|
|
44
|
-
</div>
|
|
45
|
-
{% endblock content_left_page %}
|
|
46
|
-
|
|
47
|
-
{% block content_full_width_page %}
|
|
48
|
-
<div class="panel panel-default">
|
|
49
|
-
<div class="panel-heading">
|
|
50
|
-
<strong>Template</strong>
|
|
51
|
-
</div>
|
|
52
|
-
<div class="panel-body">
|
|
53
|
-
<pre>{{ object.template }}</pre>
|
|
54
|
-
</div>
|
|
55
|
-
</div>
|
|
56
|
-
{% endblock content_full_width_page %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
<div style="flex: 1;">
|
|
59
59
|
Last run:
|
|
60
60
|
{% if row.record.latest_result %}
|
|
61
|
-
<a href="{{ row.record.latest_result.get_absolute_url }}">{{ row.record.latest_result.date_created }} by {{ row.record.latest_result.user }}</a>
|
|
61
|
+
<a href="{{ row.record.latest_result.get_absolute_url }}">{{ row.record.latest_result.date_created|date:settings.DATETIME_FORMAT }} by {{ row.record.latest_result.user }}</a>
|
|
62
62
|
{% else %}
|
|
63
63
|
<span class="text-muted">Never</span>
|
|
64
64
|
{% endif %}
|
|
@@ -1,67 +1,2 @@
|
|
|
1
1
|
{% extends 'generic/object_retrieve.html' %}
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block content_left_page %}
|
|
5
|
-
<div class="panel panel-default">
|
|
6
|
-
<div class="panel-heading">
|
|
7
|
-
<strong>Metadata Type</strong>
|
|
8
|
-
</div>
|
|
9
|
-
<table class="table table-hover panel-body attr-table">
|
|
10
|
-
<tr>
|
|
11
|
-
<td>Name</td>
|
|
12
|
-
<td>{{ object.name }}</td>
|
|
13
|
-
</tr>
|
|
14
|
-
<tr>
|
|
15
|
-
<td>Description</td>
|
|
16
|
-
<td>{{ object.description|placeholder }}</td>
|
|
17
|
-
</tr>
|
|
18
|
-
<tr>
|
|
19
|
-
<td>Data Type</td>
|
|
20
|
-
<td>{{ object.get_data_type_display }}</td>
|
|
21
|
-
</tr>
|
|
22
|
-
</table>
|
|
23
|
-
</div>
|
|
24
|
-
{% if object.choices.exists %}
|
|
25
|
-
<div class="panel panel-default">
|
|
26
|
-
<div class="panel-heading">
|
|
27
|
-
<strong>Choices</strong>
|
|
28
|
-
</div>
|
|
29
|
-
<table class="table table-hover panel-body attr-table">
|
|
30
|
-
<thead>
|
|
31
|
-
<tr>
|
|
32
|
-
<th>Value</th>
|
|
33
|
-
<th>Weight</th>
|
|
34
|
-
</tr>
|
|
35
|
-
</thead>
|
|
36
|
-
<tbody>
|
|
37
|
-
{% for choice in object.choices.all %}
|
|
38
|
-
<tr>
|
|
39
|
-
<td>{{ choice.value }}</td>
|
|
40
|
-
<td>{{ choice.weight }}</td>
|
|
41
|
-
</tr>
|
|
42
|
-
{% endfor %}
|
|
43
|
-
</tbody>
|
|
44
|
-
</table>
|
|
45
|
-
</div>
|
|
46
|
-
{% endif %}
|
|
47
|
-
{% endblock content_left_page %}
|
|
48
|
-
|
|
49
|
-
{% block content_right_page %}
|
|
50
|
-
<div class="panel panel-default">
|
|
51
|
-
<div class="panel-heading">
|
|
52
|
-
<strong>Assignment</strong>
|
|
53
|
-
</div>
|
|
54
|
-
<table class="table table-hover panel-body attr-table">
|
|
55
|
-
<tr>
|
|
56
|
-
<td>Content Types</td>
|
|
57
|
-
<td>
|
|
58
|
-
<ul>
|
|
59
|
-
{% for ct in object.content_types.all %}
|
|
60
|
-
<li>{{ ct }}</li>
|
|
61
|
-
{% endfor %}
|
|
62
|
-
</ul>
|
|
63
|
-
</td>
|
|
64
|
-
</tr>
|
|
65
|
-
</table>
|
|
66
|
-
</div>
|
|
67
|
-
{% endblock content_right_page %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -48,22 +48,26 @@
|
|
|
48
48
|
<code>{{ object.task }}</code>
|
|
49
49
|
</td>
|
|
50
50
|
</tr>
|
|
51
|
+
<tr>
|
|
52
|
+
<td>Job</td>
|
|
53
|
+
<td>{{ object.job_model|hyperlinked_object }}</td>
|
|
54
|
+
</tr>
|
|
51
55
|
<tr>
|
|
52
56
|
<td>Requester</td>
|
|
53
57
|
<td>
|
|
54
|
-
{{ object.user }}
|
|
58
|
+
{{ object.user|placeholder }}
|
|
55
59
|
</td>
|
|
56
60
|
</tr>
|
|
61
|
+
<tr>
|
|
62
|
+
<td>Approval Required?</td>
|
|
63
|
+
<td>{{ object.approval_required | render_boolean }}</td>
|
|
64
|
+
</tr>
|
|
57
65
|
<tr>
|
|
58
66
|
<td>Approver</td>
|
|
59
67
|
<td>
|
|
60
68
|
{{ object.approved_by_user | placeholder }}
|
|
61
69
|
</td>
|
|
62
70
|
</tr>
|
|
63
|
-
<tr>
|
|
64
|
-
<td>Approval Required?</td>
|
|
65
|
-
<td>{{ object.approval_required | render_boolean }}</td>
|
|
66
|
-
</tr>
|
|
67
71
|
<tr>
|
|
68
72
|
<td>Approved At</td>
|
|
69
73
|
<td>
|
|
@@ -81,6 +85,10 @@
|
|
|
81
85
|
<td>Enabled?</td>
|
|
82
86
|
<td>{{ object.enabled | render_boolean }}</td>
|
|
83
87
|
</tr>
|
|
88
|
+
<tr>
|
|
89
|
+
<td>Job Queue</td>
|
|
90
|
+
<td>{{ object.job_queue | hyperlinked_object }}</td>
|
|
91
|
+
</tr>
|
|
84
92
|
<tr>
|
|
85
93
|
<td>Interval</td>
|
|
86
94
|
<td>
|
|
@@ -95,9 +103,9 @@
|
|
|
95
103
|
<tr>
|
|
96
104
|
<td>Start Time</td>
|
|
97
105
|
<td>
|
|
98
|
-
{{ object.start_time|timezone:object.time_zone|date:
|
|
106
|
+
{{ object.start_time|timezone:object.time_zone|date:settings.SHORT_DATETIME_FORMAT }}
|
|
99
107
|
{% if default_time_zone != object.time_zone %}
|
|
100
|
-
<br>{{ object.start_time|timezone:default_time_zone|date:
|
|
108
|
+
<br>{{ object.start_time|timezone:default_time_zone|date:settings.SHORT_DATETIME_FORMAT }}
|
|
101
109
|
{% endif %}
|
|
102
110
|
</td>
|
|
103
111
|
</tr>
|
|
@@ -105,9 +113,9 @@
|
|
|
105
113
|
<td>Last Run At</td>
|
|
106
114
|
<td>
|
|
107
115
|
{% if object.last_run_at %}
|
|
108
|
-
{{ object.last_run_at|timezone:object.time_zone|date:
|
|
116
|
+
{{ object.last_run_at|timezone:object.time_zone|date:settings.SHORT_DATETIME_FORMAT }}
|
|
109
117
|
{% if default_time_zone != object.time_zone %}
|
|
110
|
-
<br>{{ object.last_run_at|timezone:default_time_zone|date:
|
|
118
|
+
<br>{{ object.last_run_at|timezone:default_time_zone|date:SHORT_DATETIME_FORMAT }}
|
|
111
119
|
{% endif %}
|
|
112
120
|
{% else %}
|
|
113
121
|
{{ object.last_run_at|placeholder }}
|
|
@@ -141,4 +149,12 @@
|
|
|
141
149
|
</table>
|
|
142
150
|
</div>
|
|
143
151
|
{% endif %}
|
|
152
|
+
<div class="panel panel-default">
|
|
153
|
+
<div class="panel-heading">
|
|
154
|
+
<strong>Celery Keyword Arguments</strong>
|
|
155
|
+
</div>
|
|
156
|
+
<div class="panel-body">
|
|
157
|
+
{% include 'extras/inc/json_data.html' with data=object.celery_kwargs format="json" %}
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
144
160
|
{% endblock %}
|