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.

Files changed (387) hide show
  1. nautobot/circuits/templates/circuits/circuittype.html +1 -1
  2. nautobot/circuits/templates/circuits/circuittype_retrieve.html +1 -39
  3. nautobot/circuits/views.py +18 -23
  4. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +4 -111
  5. nautobot/cloud/views.py +56 -25
  6. nautobot/core/api/parsers.py +56 -2
  7. nautobot/core/celery/schedulers.py +1 -0
  8. nautobot/core/filters.py +1 -1
  9. nautobot/core/graphql/schema.py +1 -0
  10. nautobot/core/jobs/__init__.py +14 -3
  11. nautobot/core/models/__init__.py +2 -0
  12. nautobot/core/tables.py +13 -6
  13. nautobot/core/testing/views.py +27 -2
  14. nautobot/core/tests/test_csv.py +92 -1
  15. nautobot/core/tests/test_jinja_filters.py +59 -0
  16. nautobot/core/tests/test_jobs.py +113 -0
  17. nautobot/core/tests/test_ui.py +53 -1
  18. nautobot/core/tests/test_utils.py +11 -0
  19. nautobot/core/tests/test_views.py +73 -0
  20. nautobot/core/ui/object_detail.py +19 -12
  21. nautobot/core/urls.py +2 -2
  22. nautobot/core/utils/filtering.py +3 -0
  23. nautobot/core/views/__init__.py +21 -0
  24. nautobot/core/views/renderers.py +1 -1
  25. nautobot/dcim/forms.py +10 -0
  26. nautobot/dcim/models/device_component_templates.py +4 -0
  27. nautobot/dcim/models/device_components.py +12 -0
  28. nautobot/dcim/models/devices.py +6 -0
  29. nautobot/dcim/templates/dcim/devicefamily_retrieve.html +1 -43
  30. nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +1 -59
  31. nautobot/dcim/templates/dcim/devicetype.html +2 -217
  32. nautobot/dcim/templates/dcim/devicetype_edit.html +2 -32
  33. nautobot/dcim/templates/dcim/devicetype_retrieve.html +217 -0
  34. nautobot/dcim/templates/dcim/devicetype_update.html +32 -0
  35. nautobot/dcim/templates/dcim/inc/rack_elevation.html +1 -1
  36. nautobot/dcim/templates/dcim/modulebay_retrieve.html +1 -84
  37. nautobot/dcim/templates/dcim/rack_elevation.html +14 -0
  38. nautobot/dcim/templates/dcim/rackreservation_retrieve.html +0 -68
  39. nautobot/dcim/tests/integration/test_fileinputpicker.py +1 -1
  40. nautobot/dcim/urls.py +1 -36
  41. nautobot/dcim/views.py +133 -81
  42. nautobot/extras/api/views.py +4 -6
  43. nautobot/extras/context_managers.py +2 -2
  44. nautobot/extras/migrations/0024_job_data_migration.py +1 -1
  45. nautobot/extras/models/customfields.py +2 -0
  46. nautobot/extras/models/datasources.py +8 -0
  47. nautobot/extras/models/groups.py +18 -0
  48. nautobot/extras/models/jobs.py +92 -62
  49. nautobot/extras/models/metadata.py +2 -0
  50. nautobot/extras/models/models.py +4 -0
  51. nautobot/extras/models/secrets.py +7 -0
  52. nautobot/extras/secrets/__init__.py +14 -0
  53. nautobot/extras/tables.py +11 -1
  54. nautobot/extras/templates/extras/computedfield_retrieve.html +1 -55
  55. nautobot/extras/templates/extras/inc/job_tiles.html +1 -1
  56. nautobot/extras/templates/extras/jobresult.html +1 -1
  57. nautobot/extras/templates/extras/metadatatype_retrieve.html +1 -66
  58. nautobot/extras/templates/extras/scheduledjob.html +25 -9
  59. nautobot/extras/tests/test_api.py +1 -1
  60. nautobot/extras/tests/test_context_managers.py +20 -0
  61. nautobot/extras/tests/test_models.py +26 -0
  62. nautobot/extras/tests/test_views.py +15 -2
  63. nautobot/extras/utils.py +18 -16
  64. nautobot/extras/views.py +65 -26
  65. nautobot/ipam/models.py +32 -0
  66. nautobot/ipam/tables.py +3 -4
  67. nautobot/project-static/docs/404.html +4 -4
  68. nautobot/project-static/docs/apps/index.html +4 -4
  69. nautobot/project-static/docs/apps/nautobot-apps.html +4 -4
  70. nautobot/project-static/docs/assets/javascripts/{bundle.c8b220af.min.js → bundle.13a4f30d.min.js} +4 -4
  71. nautobot/project-static/docs/assets/javascripts/{bundle.c8b220af.min.js.map → bundle.13a4f30d.min.js.map} +2 -2
  72. nautobot/project-static/docs/assets/javascripts/workers/{search.f8cc74c7.min.js → search.d50fe291.min.js} +2 -2
  73. nautobot/project-static/docs/assets/javascripts/workers/{search.f8cc74c7.min.js.map → search.d50fe291.min.js.map} +1 -1
  74. nautobot/project-static/docs/assets/stylesheets/{main.2afb09e1.min.css → main.342714a4.min.css} +1 -1
  75. nautobot/project-static/docs/assets/stylesheets/{main.2afb09e1.min.css.map → main.342714a4.min.css.map} +1 -1
  76. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +4 -4
  77. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +4 -4
  78. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +4 -4
  79. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +4 -4
  80. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +4 -4
  81. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +4 -4
  82. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +4 -4
  83. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +4 -4
  84. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +4 -4
  85. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +4 -4
  86. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +4 -4
  87. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +4 -4
  88. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +4 -4
  89. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +4 -4
  90. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +4 -4
  91. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +4 -4
  92. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +4 -4
  93. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +4 -4
  94. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +4 -4
  95. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +4 -4
  96. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +6 -8
  97. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +4 -4
  98. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +36 -6
  99. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +4 -4
  100. nautobot/project-static/docs/development/apps/api/configuration-view.html +4 -4
  101. nautobot/project-static/docs/development/apps/api/database-backend-config.html +4 -4
  102. nautobot/project-static/docs/development/apps/api/models/django-admin.html +4 -4
  103. nautobot/project-static/docs/development/apps/api/models/global-search.html +4 -4
  104. nautobot/project-static/docs/development/apps/api/models/graphql.html +4 -4
  105. nautobot/project-static/docs/development/apps/api/models/index.html +4 -4
  106. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +4 -4
  107. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +4 -4
  108. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +4 -4
  109. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +4 -4
  110. nautobot/project-static/docs/development/apps/api/platform-features/index.html +4 -4
  111. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +4 -4
  112. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +4 -4
  113. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +4 -4
  114. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +43 -42
  115. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +4 -4
  116. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +4 -4
  117. nautobot/project-static/docs/development/apps/api/prometheus.html +4 -4
  118. nautobot/project-static/docs/development/apps/api/setup.html +4 -4
  119. nautobot/project-static/docs/development/apps/api/testing.html +4 -4
  120. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +4 -4
  121. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +4 -4
  122. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +4 -4
  123. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +4 -4
  124. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +4 -4
  125. nautobot/project-static/docs/development/apps/api/views/base-template.html +4 -4
  126. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +4 -4
  127. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +4 -4
  128. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +4 -4
  129. nautobot/project-static/docs/development/apps/api/views/index.html +4 -4
  130. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +4 -4
  131. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +4 -4
  132. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +4 -4
  133. nautobot/project-static/docs/development/apps/api/views/notes.html +4 -4
  134. nautobot/project-static/docs/development/apps/api/views/rest-api.html +4 -4
  135. nautobot/project-static/docs/development/apps/api/views/urls.html +4 -4
  136. nautobot/project-static/docs/development/apps/index.html +4 -4
  137. nautobot/project-static/docs/development/apps/migration/code-updates.html +4 -4
  138. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +4 -4
  139. nautobot/project-static/docs/development/apps/migration/from-v1.html +4 -4
  140. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +4 -4
  141. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +4 -4
  142. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +4 -4
  143. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +4 -4
  144. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +4 -4
  145. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +4 -4
  146. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +4 -4
  147. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +4 -4
  148. nautobot/project-static/docs/development/apps/porting-from-netbox.html +4 -4
  149. nautobot/project-static/docs/development/core/application-registry.html +4 -4
  150. nautobot/project-static/docs/development/core/best-practices.html +4 -4
  151. nautobot/project-static/docs/development/core/bootstrap-ui.html +4 -4
  152. nautobot/project-static/docs/development/core/caching.html +4 -4
  153. nautobot/project-static/docs/development/core/controllers.html +4 -4
  154. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +41 -55
  155. nautobot/project-static/docs/development/core/generic-views.html +4 -4
  156. nautobot/project-static/docs/development/core/getting-started.html +4 -4
  157. nautobot/project-static/docs/development/core/homepage.html +4 -4
  158. nautobot/project-static/docs/development/core/index.html +4 -4
  159. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +4 -4
  160. nautobot/project-static/docs/development/core/model-checklist.html +4 -4
  161. nautobot/project-static/docs/development/core/model-features.html +4 -4
  162. nautobot/project-static/docs/development/core/natural-keys.html +4 -4
  163. nautobot/project-static/docs/development/core/navigation-menu.html +4 -4
  164. nautobot/project-static/docs/development/core/release-checklist.html +4 -4
  165. nautobot/project-static/docs/development/core/role-internals.html +4 -4
  166. nautobot/project-static/docs/development/core/settings.html +4 -4
  167. nautobot/project-static/docs/development/core/style-guide.html +4 -4
  168. nautobot/project-static/docs/development/core/templates.html +4 -4
  169. nautobot/project-static/docs/development/core/testing.html +4 -4
  170. nautobot/project-static/docs/development/core/ui-component-framework.html +4 -4
  171. nautobot/project-static/docs/development/core/user-preferences.html +4 -4
  172. nautobot/project-static/docs/development/index.html +4 -4
  173. nautobot/project-static/docs/development/jobs/getting-started.html +4 -4
  174. nautobot/project-static/docs/development/jobs/index.html +4 -4
  175. nautobot/project-static/docs/development/jobs/installation.html +4 -4
  176. nautobot/project-static/docs/development/jobs/job-extensions.html +4 -4
  177. nautobot/project-static/docs/development/jobs/job-logging.html +4 -4
  178. nautobot/project-static/docs/development/jobs/job-patterns.html +4 -4
  179. nautobot/project-static/docs/development/jobs/job-structure.html +4 -4
  180. nautobot/project-static/docs/development/jobs/migration/from-v1.html +4 -4
  181. nautobot/project-static/docs/development/jobs/testing.html +4 -4
  182. nautobot/project-static/docs/index.html +4 -4
  183. nautobot/project-static/docs/overview/application_stack.html +4 -4
  184. nautobot/project-static/docs/overview/design_philosophy.html +4 -4
  185. nautobot/project-static/docs/release-notes/index.html +4 -4
  186. nautobot/project-static/docs/release-notes/version-1.0.html +4 -4
  187. nautobot/project-static/docs/release-notes/version-1.1.html +4 -4
  188. nautobot/project-static/docs/release-notes/version-1.2.html +4 -4
  189. nautobot/project-static/docs/release-notes/version-1.3.html +4 -4
  190. nautobot/project-static/docs/release-notes/version-1.4.html +4 -4
  191. nautobot/project-static/docs/release-notes/version-1.5.html +4 -4
  192. nautobot/project-static/docs/release-notes/version-1.6.html +301 -4
  193. nautobot/project-static/docs/release-notes/version-2.0.html +4 -4
  194. nautobot/project-static/docs/release-notes/version-2.1.html +4 -4
  195. nautobot/project-static/docs/release-notes/version-2.2.html +4 -4
  196. nautobot/project-static/docs/release-notes/version-2.3.html +4 -4
  197. nautobot/project-static/docs/release-notes/version-2.4.html +291 -4
  198. nautobot/project-static/docs/requirements.txt +1 -1
  199. nautobot/project-static/docs/search/search_index.json +1 -1
  200. nautobot/project-static/docs/sitemap.xml +298 -298
  201. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  202. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +4 -4
  203. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +4 -4
  204. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +4 -4
  205. nautobot/project-static/docs/user-guide/administration/configuration/index.html +4 -4
  206. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +4 -4
  207. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +4 -4
  208. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +4 -4
  209. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +4 -4
  210. nautobot/project-static/docs/user-guide/administration/guides/docker.html +4 -4
  211. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +4 -4
  212. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +4 -4
  213. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +4 -4
  214. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +4 -4
  215. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +4 -4
  216. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +4 -4
  217. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +4 -4
  218. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +4 -4
  219. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +4 -4
  220. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +4 -4
  221. nautobot/project-static/docs/user-guide/administration/installation/index.html +4 -4
  222. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +4 -4
  223. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +4 -4
  224. nautobot/project-static/docs/user-guide/administration/installation/services.html +4 -4
  225. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +4 -4
  226. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +4 -4
  227. nautobot/project-static/docs/user-guide/administration/security/index.html +4 -5
  228. nautobot/project-static/docs/user-guide/administration/security/notices.html +117 -5
  229. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +4 -4
  230. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +4 -4
  231. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +4 -4
  232. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +4 -4
  233. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +4 -4
  234. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +4 -4
  235. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +4 -4
  236. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +4 -4
  237. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +4 -4
  238. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +4 -4
  239. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +4 -4
  240. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +4 -4
  241. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +4 -4
  242. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +4 -4
  243. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +4 -4
  244. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +4 -4
  245. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +4 -4
  246. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +4 -4
  247. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +4 -4
  248. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +4 -4
  249. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +4 -4
  250. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +4 -4
  251. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +4 -4
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +4 -4
  253. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +4 -4
  254. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +4 -4
  255. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +4 -4
  256. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +4 -4
  257. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +4 -4
  258. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +4 -4
  259. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +4 -4
  260. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +4 -4
  261. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +4 -4
  262. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +4 -4
  263. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +4 -4
  264. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +4 -4
  265. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +4 -4
  266. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +4 -4
  267. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +4 -4
  268. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +4 -4
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +4 -4
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +4 -4
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +4 -4
  272. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +4 -4
  273. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +4 -4
  274. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +4 -4
  275. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +4 -4
  276. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +4 -4
  277. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +4 -4
  278. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +4 -4
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +4 -4
  280. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +4 -4
  281. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +4 -4
  282. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +4 -4
  283. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +4 -4
  284. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +4 -4
  285. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +4 -4
  286. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +4 -4
  287. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +4 -4
  288. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +4 -4
  289. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +4 -4
  290. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +4 -4
  291. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +4 -4
  292. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +4 -4
  293. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +4 -4
  294. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +4 -4
  295. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +4 -4
  296. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +4 -4
  297. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +4 -4
  298. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +4 -4
  299. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +4 -4
  300. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +4 -4
  301. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +4 -4
  302. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +4 -4
  303. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +4 -4
  304. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +4 -4
  305. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +4 -4
  306. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +4 -4
  307. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +4 -4
  308. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +4 -4
  309. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +4 -4
  310. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +4 -4
  311. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +4 -4
  312. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +4 -4
  313. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +4 -4
  314. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +4 -4
  315. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +4 -4
  316. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +4 -4
  317. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +4 -4
  318. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +4 -4
  319. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +4 -4
  320. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +4 -4
  321. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +4 -4
  322. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +4 -4
  323. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +4 -4
  324. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +4 -4
  325. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +4 -4
  326. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +4 -4
  327. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +4 -4
  328. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +4 -4
  329. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +4 -4
  330. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +4 -4
  331. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +4 -4
  332. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +4 -4
  333. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +4 -4
  334. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +4 -4
  335. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +4 -4
  336. nautobot/project-static/docs/user-guide/index.html +4 -4
  337. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +4 -4
  338. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +4 -4
  339. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +4 -4
  340. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +4 -4
  341. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +4 -4
  342. nautobot/project-static/docs/user-guide/platform-functionality/events.html +4 -4
  343. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +4 -4
  344. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +4 -4
  345. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +4 -4
  346. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +4 -4
  347. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +4 -4
  348. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +4 -4
  349. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +4 -4
  350. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +4 -4
  351. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +4 -4
  352. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +4 -4
  353. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +4 -4
  354. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +4 -4
  355. nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +4 -4
  356. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +4 -4
  357. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +4 -4
  358. nautobot/project-static/docs/user-guide/platform-functionality/note.html +4 -4
  359. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +4 -4
  360. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +4 -4
  361. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +4 -4
  362. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +4 -4
  363. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +4 -4
  364. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +4 -4
  365. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +4 -4
  366. nautobot/project-static/docs/user-guide/platform-functionality/role.html +4 -4
  367. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +4 -4
  368. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +4 -4
  369. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +4 -4
  370. nautobot/project-static/docs/user-guide/platform-functionality/status.html +4 -4
  371. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +4 -4
  372. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +4 -4
  373. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +4 -4
  374. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +4 -4
  375. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +4 -4
  376. nautobot/project-static/js/forms.js +0 -14
  377. nautobot/users/models.py +4 -0
  378. nautobot/virtualization/models.py +4 -0
  379. nautobot/wireless/tables.py +1 -0
  380. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +1 -55
  381. nautobot/wireless/views.py +33 -28
  382. {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/METADATA +4 -4
  383. {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/RECORD +387 -384
  384. {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/LICENSE.txt +0 -0
  385. {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/NOTICE +0 -0
  386. {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/WHEEL +0 -0
  387. {nautobot-2.4.8.dist-info → nautobot-2.4.10.dist-info}/entry_points.txt +0 -0
@@ -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, job_model, user, *job_args, celery_kwargs=None, profile=False, job_result=None, **job_kwargs):
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
- job_model,
772
- user,
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
- task_queue=None,
791
- job_result=None,
792
- synchronous=False,
793
- ignore_singleton_lock=False,
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, optional): Dictionary of kwargs to pass as **kwargs to `apply_async()`/`apply()` when job is run.
802
- profile (bool, optional): If True, dump cProfile stats on the job execution.
803
- schedule (ScheduledJob, optional): ScheduledJob instance to link to the JobResult. Cannot be used with synchronous=True.
804
- task_queue (str, optional): The celery queue to send the job to. If not set, use the default celery queue.
805
- job_result (JobResult, optional): Existing JobResult with status PENDING, to be modified and to be used in kubernetes job execution.
806
- synchronous (bool, optional): If True, run the job in the current process, blocking until the job completes.
807
- ignore_singleton_lock (bool, optional): If True, invalidate the singleton lock before running the job.
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
- task_queue=None,
1311
- ignore_singleton_lock=False,
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, optional): The name of the scheduled job. Defaults to None.
1325
- start_time (datetime, optional): The start time for the job. Defaults to None.
1326
- interval (JobExecutionType, optional): The interval type for the job execution.
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, optional): The crontab string for the schedule. Defaults to "".
1329
- profile (bool, optional): Flag indicating whether to profile the job. Defaults to False.
1330
- approval_required (bool, optional): Flag indicating if approval is required. Defaults to False.
1331
- task_queue (str, optional): The task queue for the job. Defaults to None, which will use the configured default celery queue.
1332
- ignore_singleton_lock (bool, optional): Flag indicating whether to ignore singleton locks. Defaults to False.
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
- queue=task_queue,
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.
@@ -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.created }} by {{ value.user }}
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
- {% load helpers %}
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 %}
@@ -115,7 +115,7 @@
115
115
  <td>{{ result.worker }}</td>
116
116
  </tr>
117
117
  <tr>
118
- <td>Queue</td>
118
+ <td>Queue Name</td>
119
119
  <td>{{ result.celery_kwargs.queue}}</td>
120
120
  </tr>
121
121
  <tr>
@@ -1,67 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% load helpers %}
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:'Y-m-d H:i:s T' }}
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:'Y-m-d H:i:s T' }}
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:'Y-m-d H:i:s T' }}
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:'Y-m-d H:i:s T' }}
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 %}