nautobot 2.4.10__py3-none-any.whl → 2.4.12__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 (439) hide show
  1. nautobot/circuits/templates/circuits/circuittermination_retrieve.html +1 -114
  2. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +1 -1
  3. nautobot/circuits/views.py +76 -6
  4. nautobot/cloud/navigation.py +1 -1
  5. nautobot/cloud/tests/test_views.py +13 -1
  6. nautobot/cloud/views.py +39 -9
  7. nautobot/core/celery/__init__.py +21 -0
  8. nautobot/core/celery/encoders.py +3 -0
  9. nautobot/core/forms/forms.py +4 -1
  10. nautobot/core/jobs/bulk_actions.py +8 -8
  11. nautobot/core/jobs/cleanup.py +11 -0
  12. nautobot/core/management/commands/generate_test_data.py +2 -1
  13. nautobot/core/templates/components/panel/header_extra_content_table.html +12 -1
  14. nautobot/core/templates/components/panel/panel.html +4 -0
  15. nautobot/core/templates/generic/object_retrieve.html +2 -1
  16. nautobot/core/testing/mixins.py +19 -1
  17. nautobot/core/testing/views.py +104 -8
  18. nautobot/core/tests/test_jobs.py +20 -4
  19. nautobot/core/tests/test_utils.py +17 -0
  20. nautobot/core/tests/test_views.py +2 -2
  21. nautobot/core/tests/test_views_utils.py +53 -2
  22. nautobot/core/ui/object_detail.py +5 -1
  23. nautobot/core/utils/lookup.py +4 -2
  24. nautobot/core/utils/module_loading.py +23 -0
  25. nautobot/core/views/generic.py +2 -12
  26. nautobot/core/views/mixins.py +19 -1
  27. nautobot/core/views/renderers.py +4 -13
  28. nautobot/core/views/utils.py +16 -0
  29. nautobot/dcim/api/serializers.py +13 -0
  30. nautobot/dcim/api/urls.py +1 -0
  31. nautobot/dcim/api/views.py +20 -0
  32. nautobot/dcim/apps.py +1 -0
  33. nautobot/dcim/factory.py +11 -0
  34. nautobot/dcim/filters/__init__.py +116 -0
  35. nautobot/dcim/filters/mixins.py +2 -1
  36. nautobot/dcim/forms.py +205 -19
  37. nautobot/dcim/migrations/0070_modulefamily_models.py +92 -0
  38. nautobot/dcim/models/__init__.py +2 -0
  39. nautobot/dcim/models/device_component_templates.py +14 -0
  40. nautobot/dcim/models/device_components.py +13 -1
  41. nautobot/dcim/models/devices.py +72 -0
  42. nautobot/dcim/navigation.py +16 -0
  43. nautobot/dcim/tables/__init__.py +2 -0
  44. nautobot/dcim/tables/devices.py +50 -0
  45. nautobot/dcim/tables/devicetypes.py +35 -1
  46. nautobot/dcim/tables/template_code.py +2 -0
  47. nautobot/dcim/templates/dcim/controller/base.html +1 -9
  48. nautobot/dcim/templates/dcim/controller_retrieve.html +2 -83
  49. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +2 -25
  50. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +1 -90
  51. nautobot/dcim/templates/dcim/inc/cable_toggle_buttons.html +1 -1
  52. nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +1 -63
  53. nautobot/dcim/templates/dcim/location.html +2 -249
  54. nautobot/dcim/templates/dcim/location_edit.html +2 -38
  55. nautobot/dcim/templates/dcim/location_retrieve.html +249 -0
  56. nautobot/dcim/templates/dcim/location_update.html +38 -0
  57. nautobot/dcim/templates/dcim/module_update.html +1 -0
  58. nautobot/dcim/templates/dcim/modulebay_retrieve.html +93 -1
  59. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +31 -0
  60. nautobot/dcim/templates/dcim/moduletype_retrieve.html +6 -0
  61. nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -160
  62. nautobot/dcim/templates/dcim/virtualchassis.html +2 -51
  63. nautobot/dcim/templates/dcim/virtualchassis_add.html +2 -22
  64. nautobot/dcim/templates/dcim/virtualchassis_create.html +22 -0
  65. nautobot/dcim/templates/dcim/virtualchassis_edit.html +2 -93
  66. nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +51 -0
  67. nautobot/dcim/templates/dcim/virtualchassis_update.html +93 -0
  68. nautobot/dcim/tests/test_api.py +35 -0
  69. nautobot/dcim/tests/test_filters.py +102 -3
  70. nautobot/dcim/tests/test_models.py +146 -0
  71. nautobot/dcim/tests/test_views.py +70 -97
  72. nautobot/dcim/urls.py +5 -80
  73. nautobot/dcim/views.py +584 -342
  74. nautobot/extras/api/views.py +9 -2
  75. nautobot/extras/datasources/git.py +9 -1
  76. nautobot/extras/forms/forms.py +9 -5
  77. nautobot/extras/jobs.py +4 -2
  78. nautobot/extras/jobs_ui.py +208 -0
  79. nautobot/extras/models/datasources.py +5 -8
  80. nautobot/extras/models/jobs.py +5 -0
  81. nautobot/extras/models/tags.py +4 -0
  82. nautobot/extras/plugins/__init__.py +3 -0
  83. nautobot/extras/tables.py +40 -3
  84. nautobot/extras/templates/extras/configcontext.html +2 -220
  85. nautobot/extras/templates/extras/configcontext_edit.html +2 -50
  86. nautobot/extras/templates/extras/configcontext_retrieve.html +2 -0
  87. nautobot/extras/templates/extras/configcontext_update.html +50 -0
  88. nautobot/extras/templates/extras/configcontextschema.html +2 -48
  89. nautobot/extras/templates/extras/configcontextschema_edit.html +2 -19
  90. nautobot/extras/templates/extras/configcontextschema_retrieve.html +48 -0
  91. nautobot/extras/templates/extras/configcontextschema_update.html +19 -0
  92. nautobot/extras/templates/extras/inc/configcontext_data.html +1 -0
  93. nautobot/extras/templates/extras/inc/configcontext_format.html +6 -0
  94. nautobot/extras/templates/extras/job_detail.html +1 -326
  95. nautobot/extras/templates/extras/job_edit.html +12 -6
  96. nautobot/extras/templates/extras/tag.html +2 -52
  97. nautobot/extras/templates/extras/tag_edit.html +2 -15
  98. nautobot/extras/templates/extras/tag_retrieve.html +2 -0
  99. nautobot/extras/templates/extras/tag_update.html +15 -0
  100. nautobot/extras/templates/extras/team_retrieve.html +2 -2
  101. nautobot/extras/tests/test_api.py +15 -15
  102. nautobot/extras/tests/test_filters.py +4 -4
  103. nautobot/extras/tests/test_jobs.py +23 -10
  104. nautobot/extras/tests/test_models.py +19 -8
  105. nautobot/extras/tests/test_plugins.py +6 -3
  106. nautobot/extras/tests/test_views.py +66 -11
  107. nautobot/extras/urls.py +4 -134
  108. nautobot/extras/views.py +186 -178
  109. nautobot/ipam/models.py +19 -4
  110. nautobot/ipam/tables.py +19 -0
  111. nautobot/ipam/templates/ipam/vlan.html +2 -84
  112. nautobot/ipam/templates/ipam/vlan_edit.html +2 -24
  113. nautobot/ipam/templates/ipam/vlan_retrieve.html +84 -0
  114. nautobot/ipam/templates/ipam/vlan_update.html +24 -0
  115. nautobot/ipam/tests/test_views.py +5 -0
  116. nautobot/ipam/urls.py +1 -21
  117. nautobot/ipam/views.py +45 -70
  118. nautobot/project-static/docs/404.html +33 -10
  119. nautobot/project-static/docs/apps/index.html +33 -10
  120. nautobot/project-static/docs/apps/nautobot-apps.html +33 -10
  121. nautobot/project-static/docs/assets/javascripts/{bundle.13a4f30d.min.js → bundle.56ea9cef.min.js} +2 -2
  122. nautobot/project-static/docs/assets/javascripts/{bundle.13a4f30d.min.js.map → bundle.56ea9cef.min.js.map} +2 -2
  123. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +33 -10
  124. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +33 -10
  125. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +33 -10
  126. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +33 -10
  127. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +33 -10
  128. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +33 -10
  129. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +33 -10
  130. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +33 -10
  131. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +33 -10
  132. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +33 -10
  133. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +33 -10
  134. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +33 -10
  135. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +33 -10
  136. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +33 -10
  137. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +33 -10
  138. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +33 -10
  139. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +33 -10
  140. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +33 -10
  141. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +33 -10
  142. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +122 -10
  143. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +33 -10
  144. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +33 -10
  145. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +33 -10
  146. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +33 -10
  147. nautobot/project-static/docs/development/apps/api/configuration-view.html +33 -10
  148. nautobot/project-static/docs/development/apps/api/database-backend-config.html +33 -10
  149. nautobot/project-static/docs/development/apps/api/models/django-admin.html +33 -10
  150. nautobot/project-static/docs/development/apps/api/models/global-search.html +33 -10
  151. nautobot/project-static/docs/development/apps/api/models/graphql.html +33 -10
  152. nautobot/project-static/docs/development/apps/api/models/index.html +33 -10
  153. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +42 -10
  154. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +33 -10
  155. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +33 -10
  156. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +33 -10
  157. nautobot/project-static/docs/development/apps/api/platform-features/index.html +33 -10
  158. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +33 -10
  159. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +33 -10
  160. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +33 -10
  161. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +34 -11
  162. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +33 -10
  163. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +33 -10
  164. nautobot/project-static/docs/development/apps/api/prometheus.html +33 -10
  165. nautobot/project-static/docs/development/apps/api/setup.html +33 -10
  166. nautobot/project-static/docs/development/apps/api/testing.html +33 -10
  167. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +33 -10
  168. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +33 -10
  169. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +33 -10
  170. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +33 -10
  171. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +33 -10
  172. nautobot/project-static/docs/development/apps/api/views/base-template.html +33 -10
  173. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +33 -10
  174. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +33 -10
  175. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +33 -10
  176. nautobot/project-static/docs/development/apps/api/views/index.html +33 -10
  177. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +33 -10
  178. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +33 -10
  179. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +33 -10
  180. nautobot/project-static/docs/development/apps/api/views/notes.html +33 -10
  181. nautobot/project-static/docs/development/apps/api/views/rest-api.html +33 -10
  182. nautobot/project-static/docs/development/apps/api/views/urls.html +33 -10
  183. nautobot/project-static/docs/development/apps/index.html +33 -10
  184. nautobot/project-static/docs/development/apps/migration/code-updates.html +33 -10
  185. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +33 -10
  186. nautobot/project-static/docs/development/apps/migration/from-v1.html +33 -10
  187. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +33 -10
  188. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +33 -10
  189. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +33 -10
  190. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +33 -10
  191. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +33 -10
  192. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +33 -10
  193. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +33 -10
  194. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +33 -10
  195. nautobot/project-static/docs/development/apps/porting-from-netbox.html +33 -10
  196. nautobot/project-static/docs/development/core/application-registry.html +33 -10
  197. nautobot/project-static/docs/development/core/best-practices.html +33 -10
  198. nautobot/project-static/docs/development/core/bootstrap-ui.html +33 -10
  199. nautobot/project-static/docs/development/core/caching.html +33 -10
  200. nautobot/project-static/docs/development/core/controllers.html +33 -10
  201. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +33 -10
  202. nautobot/project-static/docs/development/core/generic-views.html +33 -10
  203. nautobot/project-static/docs/development/core/getting-started.html +33 -10
  204. nautobot/project-static/docs/development/core/homepage.html +33 -10
  205. nautobot/project-static/docs/development/core/index.html +33 -10
  206. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +33 -10
  207. nautobot/project-static/docs/development/core/model-checklist.html +33 -10
  208. nautobot/project-static/docs/development/core/model-features.html +33 -10
  209. nautobot/project-static/docs/development/core/natural-keys.html +33 -10
  210. nautobot/project-static/docs/development/core/navigation-menu.html +33 -10
  211. nautobot/project-static/docs/development/core/release-checklist.html +33 -10
  212. nautobot/project-static/docs/development/core/role-internals.html +33 -10
  213. nautobot/project-static/docs/development/core/settings.html +33 -10
  214. nautobot/project-static/docs/development/core/style-guide.html +33 -10
  215. nautobot/project-static/docs/development/core/templates.html +33 -10
  216. nautobot/project-static/docs/development/core/testing.html +33 -10
  217. nautobot/project-static/docs/development/core/ui-component-framework.html +33 -10
  218. nautobot/project-static/docs/development/core/user-preferences.html +33 -10
  219. nautobot/project-static/docs/development/index.html +33 -10
  220. nautobot/project-static/docs/development/jobs/getting-started.html +33 -10
  221. nautobot/project-static/docs/development/jobs/index.html +33 -10
  222. nautobot/project-static/docs/development/jobs/installation.html +33 -10
  223. nautobot/project-static/docs/development/jobs/job-extensions.html +33 -10
  224. nautobot/project-static/docs/development/jobs/job-logging.html +33 -10
  225. nautobot/project-static/docs/development/jobs/job-patterns.html +33 -10
  226. nautobot/project-static/docs/development/jobs/job-structure.html +33 -10
  227. nautobot/project-static/docs/development/jobs/migration/from-v1.html +33 -10
  228. nautobot/project-static/docs/development/jobs/testing.html +33 -10
  229. nautobot/project-static/docs/index.html +33 -10
  230. nautobot/project-static/docs/insert-analytics.sh +36 -0
  231. nautobot/project-static/docs/objects.inv +0 -0
  232. nautobot/project-static/docs/overview/application_stack.html +33 -10
  233. nautobot/project-static/docs/overview/design_philosophy.html +33 -10
  234. nautobot/project-static/docs/release-notes/index.html +33 -10
  235. nautobot/project-static/docs/release-notes/version-1.0.html +33 -10
  236. nautobot/project-static/docs/release-notes/version-1.1.html +33 -10
  237. nautobot/project-static/docs/release-notes/version-1.2.html +33 -10
  238. nautobot/project-static/docs/release-notes/version-1.3.html +33 -10
  239. nautobot/project-static/docs/release-notes/version-1.4.html +33 -10
  240. nautobot/project-static/docs/release-notes/version-1.5.html +33 -10
  241. nautobot/project-static/docs/release-notes/version-1.6.html +33 -10
  242. nautobot/project-static/docs/release-notes/version-2.0.html +33 -10
  243. nautobot/project-static/docs/release-notes/version-2.1.html +33 -10
  244. nautobot/project-static/docs/release-notes/version-2.2.html +33 -10
  245. nautobot/project-static/docs/release-notes/version-2.3.html +33 -10
  246. nautobot/project-static/docs/release-notes/version-2.4.html +363 -10
  247. nautobot/project-static/docs/requirements.txt +1 -1
  248. nautobot/project-static/docs/search/search_index.json +1 -1
  249. nautobot/project-static/docs/sitemap.xml +302 -298
  250. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  251. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +33 -10
  252. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +33 -10
  253. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +33 -10
  254. nautobot/project-static/docs/user-guide/administration/configuration/index.html +33 -10
  255. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +33 -10
  256. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +33 -10
  257. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +33 -10
  258. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +33 -10
  259. nautobot/project-static/docs/user-guide/administration/guides/docker.html +33 -10
  260. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +33 -10
  261. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +33 -10
  262. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +33 -10
  263. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +33 -10
  264. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +33 -10
  265. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +33 -10
  266. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +33 -10
  267. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +33 -10
  268. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +33 -10
  269. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +33 -10
  270. nautobot/project-static/docs/user-guide/administration/installation/index.html +33 -10
  271. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +33 -10
  272. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +33 -10
  273. nautobot/project-static/docs/user-guide/administration/installation/services.html +33 -10
  274. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +33 -10
  275. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +33 -10
  276. nautobot/project-static/docs/user-guide/administration/security/index.html +33 -10
  277. nautobot/project-static/docs/user-guide/administration/security/notices.html +33 -10
  278. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +33 -10
  279. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +33 -10
  280. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +33 -10
  281. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +33 -10
  282. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +33 -10
  283. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +33 -10
  284. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +33 -10
  285. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +33 -10
  286. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +33 -10
  287. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +33 -10
  288. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +33 -10
  289. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +33 -10
  290. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +33 -10
  291. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +33 -10
  292. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +33 -10
  293. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +33 -10
  294. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +33 -10
  295. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +33 -10
  296. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +33 -10
  297. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +33 -10
  298. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +33 -10
  299. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +33 -10
  300. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +33 -10
  301. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +33 -10
  302. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +33 -10
  303. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +33 -10
  304. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +33 -10
  305. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +33 -10
  306. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +33 -10
  307. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +33 -10
  308. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +33 -10
  309. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +33 -10
  310. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +33 -10
  311. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +33 -10
  312. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +45 -22
  313. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +33 -10
  314. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +33 -10
  315. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +33 -10
  316. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +33 -10
  317. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +33 -10
  318. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +33 -10
  319. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +33 -10
  320. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +33 -10
  321. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +33 -10
  322. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +33 -10
  323. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +37 -10
  324. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +37 -10
  325. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +37 -10
  326. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +10261 -0
  327. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +36 -13
  328. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +33 -10
  329. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +33 -10
  330. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +33 -10
  331. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +33 -10
  332. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +33 -10
  333. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +33 -10
  334. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +33 -10
  335. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +33 -10
  336. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +33 -10
  337. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +33 -10
  338. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +33 -10
  339. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +33 -10
  340. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +33 -10
  341. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +33 -10
  342. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +33 -10
  343. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +33 -10
  344. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +33 -10
  345. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +33 -10
  346. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +33 -10
  347. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +33 -10
  348. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +33 -10
  349. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +33 -10
  350. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +33 -10
  351. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +33 -10
  352. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +33 -10
  353. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +33 -10
  354. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +33 -10
  355. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +33 -10
  356. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +33 -10
  357. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +33 -10
  358. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +33 -10
  359. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +33 -10
  360. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +33 -10
  361. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +33 -10
  362. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +33 -10
  363. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +33 -10
  364. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +33 -10
  365. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +33 -10
  366. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +33 -10
  367. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +33 -10
  368. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +33 -10
  369. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +33 -10
  370. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +33 -10
  371. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +33 -10
  372. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +33 -10
  373. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +33 -10
  374. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +33 -10
  375. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +33 -10
  376. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +33 -10
  377. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +33 -10
  378. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +33 -10
  379. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +33 -10
  380. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +44 -18
  381. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +33 -10
  382. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +33 -10
  383. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +33 -10
  384. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +33 -10
  385. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +33 -10
  386. nautobot/project-static/docs/user-guide/index.html +33 -10
  387. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +33 -10
  388. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +33 -10
  389. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +33 -10
  390. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +33 -10
  391. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +33 -10
  392. nautobot/project-static/docs/user-guide/platform-functionality/events.html +33 -10
  393. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +33 -10
  394. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +33 -10
  395. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +39 -11
  396. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +33 -10
  397. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +33 -10
  398. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +33 -10
  399. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +33 -10
  400. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +33 -10
  401. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +33 -10
  402. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +33 -10
  403. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +33 -10
  404. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +33 -10
  405. nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +33 -10
  406. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +33 -10
  407. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +33 -10
  408. nautobot/project-static/docs/user-guide/platform-functionality/note.html +33 -10
  409. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +33 -10
  410. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +33 -10
  411. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +33 -10
  412. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +33 -10
  413. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +33 -10
  414. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +33 -10
  415. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +33 -10
  416. nautobot/project-static/docs/user-guide/platform-functionality/role.html +33 -10
  417. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +33 -10
  418. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +33 -10
  419. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +33 -10
  420. nautobot/project-static/docs/user-guide/platform-functionality/status.html +33 -10
  421. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +33 -10
  422. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +33 -10
  423. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +33 -10
  424. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +33 -10
  425. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +33 -10
  426. nautobot/tenancy/tables.py +2 -0
  427. nautobot/virtualization/tests/test_views.py +1 -1
  428. nautobot/wireless/forms.py +0 -1
  429. nautobot/wireless/models.py +1 -1
  430. nautobot/wireless/navigation.py +1 -1
  431. nautobot/wireless/tables.py +18 -3
  432. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/METADATA +4 -4
  433. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/RECORD +439 -419
  434. /nautobot/dcim/templates/dcim/{platform_edit.html → platform_create.html} +0 -0
  435. /nautobot/extras/test_jobs/{pass.py → pass_job.py} +0 -0
  436. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/LICENSE.txt +0 -0
  437. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/NOTICE +0 -0
  438. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/WHEEL +0 -0
  439. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/entry_points.txt +0 -0
@@ -167,7 +167,7 @@ class JobTest(TestCase):
167
167
  self.assertTrue(job_class.supports_dryrun)
168
168
  self.assertTrue(job_model.supports_dryrun)
169
169
 
170
- module = "pass"
170
+ module = "pass_job"
171
171
  name = "TestPassJob"
172
172
  job_class, job_model = get_job_class_and_model(module, name)
173
173
  self.assertFalse(job_class.supports_dryrun)
@@ -212,7 +212,7 @@ register_jobs(MyJob)
212
212
  self.assertIsNotNone(get_job("my_jobs.MyJob"))
213
213
  # Also make sure some representative previous JOBS_ROOT jobs aren't still around:
214
214
  self.assertNotIn("dry_run.TestDryRun", jobs_data.keys())
215
- self.assertNotIn("pass.TestPassJob", jobs_data.keys())
215
+ self.assertNotIn("pass_job.TestPassJob", jobs_data.keys())
216
216
 
217
217
  # Create a second Job in the same module
218
218
  with open(os.path.join(temp_dir, "my_jobs.py"), "a") as fd:
@@ -286,6 +286,19 @@ register_jobs(BadJob)
286
286
  # Clean up back to normal behavior
287
287
  get_jobs(reload=True)
288
288
 
289
+ def test_app_dynamic_jobs(self):
290
+ """
291
+ Test that get_job() correctly reloads dynamic jobs when `NautobotAppConfig.provides_dynamic_jobs` is True.
292
+ """
293
+ with mock.patch("nautobot.extras.jobs.get_jobs", autospec=True) as mock_get_jobs:
294
+ # example_app_with_view_override provides dynamic jobs
295
+ get_job("example_app_with_view_override.jobs.ExampleHiddenJob", reload=True)
296
+ mock_get_jobs.assert_called_once_with(reload=True)
297
+ mock_get_jobs.reset_mock()
298
+ # example_app does NOT provide dynamic jobs
299
+ get_job("example_app.jobs.ExampleEverythingJob", reload=True)
300
+ mock_get_jobs.assert_called_once_with(reload=False)
301
+
289
302
 
290
303
  class JobTransactionTest(TransactionTestCase):
291
304
  """
@@ -423,7 +436,7 @@ class JobTransactionTest(TransactionTestCase):
423
436
  """
424
437
  Job test with pass result.
425
438
  """
426
- module = "pass"
439
+ module = "pass_job"
427
440
  name = "TestPassJob"
428
441
  job_result = create_job_result_and_run_job(module, name)
429
442
  self.assertJobResultStatus(job_result)
@@ -693,7 +706,7 @@ class JobTransactionTest(TransactionTestCase):
693
706
  """
694
707
  Job test to see if the latest_result property is indeed returning the most recent job result
695
708
  """
696
- module = "pass"
709
+ module = "pass_job"
697
710
  name = "TestPassJob"
698
711
  job_result_1 = create_job_result_and_run_job(module, name)
699
712
  self.assertJobResultStatus(job_result_1)
@@ -946,7 +959,7 @@ class RunJobManagementCommandTest(TransactionTestCase):
946
959
 
947
960
  def test_runjob_nochange_successful(self):
948
961
  """Basic success-path test for Jobs that don't modify the Nautobot database."""
949
- module = "pass"
962
+ module = "pass_job"
950
963
  name = "TestPassJob"
951
964
  _job_class, job_model = get_job_class_and_model(module, name)
952
965
 
@@ -1044,7 +1057,7 @@ class JobButtonReceiverTest(TestCase):
1044
1057
 
1045
1058
  def test_is_job_button(self):
1046
1059
  with self.subTest(expected=False):
1047
- module = "pass"
1060
+ module = "pass_job"
1048
1061
  name = "TestPassJob"
1049
1062
  _job_class, job_model = get_job_class_and_model(module, name)
1050
1063
  self.assertFalse(job_model.is_job_button_receiver)
@@ -1107,7 +1120,7 @@ class JobHookReceiverTest(TestCase):
1107
1120
 
1108
1121
  def test_is_job_hook(self):
1109
1122
  with self.subTest(expected=False):
1110
- module = "pass"
1123
+ module = "pass_job"
1111
1124
  name = "TestPassJob"
1112
1125
  _job_class, job_model = get_job_class_and_model(module, name)
1113
1126
  self.assertFalse(job_model.is_job_hook_receiver)
@@ -1269,7 +1282,7 @@ class RemoveScheduledJobManagementCommandTestCase(TestCase):
1269
1282
  for i in range(1, 7):
1270
1283
  models.ScheduledJob.objects.create(
1271
1284
  name=f"test{i}",
1272
- task="pass.TestPassJob",
1285
+ task="pass_job.TestPassJob",
1273
1286
  interval=JobExecutionType.TYPE_FUTURE,
1274
1287
  user=self.user,
1275
1288
  start_time=timezone.now() - datetime.timedelta(days=i * 30),
@@ -1278,7 +1291,7 @@ class RemoveScheduledJobManagementCommandTestCase(TestCase):
1278
1291
 
1279
1292
  models.ScheduledJob.objects.create(
1280
1293
  name="test7",
1281
- task="pass.TestPassJob",
1294
+ task="pass_job.TestPassJob",
1282
1295
  interval=JobExecutionType.TYPE_DAILY,
1283
1296
  user=self.user,
1284
1297
  start_time=timezone.now() - datetime.timedelta(days=180),
@@ -1306,7 +1319,7 @@ class ScheduledJobIntervalTestCase(TestCase):
1306
1319
  start_time = timezone.now() + datetime.timedelta(days=6)
1307
1320
  scheduled_job = models.ScheduledJob.objects.create(
1308
1321
  name="weekly_interval",
1309
- task="pass.TestPassJob",
1322
+ task="pass_job.TestPassJob",
1310
1323
  interval=JobExecutionType.TYPE_WEEKLY,
1311
1324
  user=self.user,
1312
1325
  start_time=start_time,
@@ -1404,7 +1404,7 @@ class JobModelTest(ModelTestCases.BaseModelTestCase):
1404
1404
  self.assertEqual(self.app_job.job_class, ExampleJob)
1405
1405
 
1406
1406
  def test_class_path(self):
1407
- self.assertEqual(self.local_job.class_path, "pass.TestPassJob")
1407
+ self.assertEqual(self.local_job.class_path, "pass_job.TestPassJob")
1408
1408
  self.assertIsNotNone(self.local_job.job_class)
1409
1409
  self.assertEqual(self.local_job.class_path, self.local_job.job_class.class_path)
1410
1410
 
@@ -2145,7 +2145,7 @@ class ScheduledJobTest(ModelTestCases.BaseModelTestCase):
2145
2145
 
2146
2146
  self.daily_utc_job = ScheduledJob.objects.create(
2147
2147
  name="Daily UTC Job",
2148
- task="pass.TestPassJob",
2148
+ task="pass_job.TestPassJob",
2149
2149
  job_model=self.job_model,
2150
2150
  interval=JobExecutionType.TYPE_DAILY,
2151
2151
  start_time=datetime(year=2050, month=1, day=22, hour=17, minute=0, tzinfo=get_default_timezone()),
@@ -2153,7 +2153,7 @@ class ScheduledJobTest(ModelTestCases.BaseModelTestCase):
2153
2153
  )
2154
2154
  self.daily_est_job = ScheduledJob.objects.create(
2155
2155
  name="Daily EST Job",
2156
- task="pass.TestPassJob",
2156
+ task="pass_job.TestPassJob",
2157
2157
  job_model=self.job_model,
2158
2158
  interval=JobExecutionType.TYPE_DAILY,
2159
2159
  start_time=datetime(year=2050, month=1, day=22, hour=17, minute=0, tzinfo=ZoneInfo("America/New_York")),
@@ -2168,7 +2168,7 @@ class ScheduledJobTest(ModelTestCases.BaseModelTestCase):
2168
2168
  )
2169
2169
  self.crontab_est_job = ScheduledJob.objects.create(
2170
2170
  name="Crontab EST Job",
2171
- task="pass.TestPassJob",
2171
+ task="pass_job.TestPassJob",
2172
2172
  job_model=self.job_model,
2173
2173
  interval=JobExecutionType.TYPE_CUSTOM,
2174
2174
  start_time=datetime(year=2050, month=1, day=22, hour=17, minute=0, tzinfo=ZoneInfo("America/New_York")),
@@ -2177,7 +2177,7 @@ class ScheduledJobTest(ModelTestCases.BaseModelTestCase):
2177
2177
  )
2178
2178
  self.one_off_utc_job = ScheduledJob.objects.create(
2179
2179
  name="One-off UTC Job",
2180
- task="pass.TestPassJob",
2180
+ task="pass_job.TestPassJob",
2181
2181
  job_model=self.job_model,
2182
2182
  interval=JobExecutionType.TYPE_FUTURE,
2183
2183
  start_time=datetime(year=2050, month=1, day=22, hour=0, minute=0, tzinfo=ZoneInfo("UTC")),
@@ -2190,6 +2190,13 @@ class ScheduledJobTest(ModelTestCases.BaseModelTestCase):
2190
2190
  interval=JobExecutionType.TYPE_FUTURE,
2191
2191
  start_time=datetime(year=2050, month=1, day=22, hour=0, minute=0, tzinfo=ZoneInfo("America/New_York")),
2192
2192
  )
2193
+ self.one_off_immediately_job = ScheduledJob.create_schedule(
2194
+ job_model=self.job_model,
2195
+ user=self.user,
2196
+ name="One-off IMMEDIATELY job",
2197
+ interval=JobExecutionType.TYPE_IMMEDIATELY,
2198
+ start_time=now(),
2199
+ )
2193
2200
 
2194
2201
  def test_scheduled_job_queue_setter(self):
2195
2202
  """Test the queue property setter on ScheduledJob."""
@@ -2226,6 +2233,10 @@ class ScheduledJobTest(ModelTestCases.BaseModelTestCase):
2226
2233
  timedelta(hours=5),
2227
2234
  )
2228
2235
 
2236
+ with self.subTest("Test TYPE IMMEDIATELY schedules"):
2237
+ self.assertTrue(self.one_off_immediately_job.one_off)
2238
+ self.assertEqual(self.one_off_immediately_job.interval, JobExecutionType.TYPE_FUTURE)
2239
+
2229
2240
  def test_to_cron(self):
2230
2241
  """Test the to_cron() method and its interaction with time zone variants."""
2231
2242
 
@@ -2324,7 +2335,7 @@ class ScheduledJobTest(ModelTestCases.BaseModelTestCase):
2324
2335
  """Test that TYPE_CUSTOM behavior around DST is as expected."""
2325
2336
  cronjob = ScheduledJob.objects.create(
2326
2337
  name="DST Aware Cronjob",
2327
- task="pass.TestPassJob",
2338
+ task="pass_job.TestPassJob",
2328
2339
  job_model=self.job_model,
2329
2340
  enabled=False,
2330
2341
  interval=JobExecutionType.TYPE_CUSTOM,
@@ -2379,7 +2390,7 @@ class ScheduledJobTest(ModelTestCases.BaseModelTestCase):
2379
2390
  """Test the interaction of TYPE_DAILY around DST."""
2380
2391
  daily = ScheduledJob.objects.create(
2381
2392
  name="Daily Job",
2382
- task="pass.TestPassJob",
2393
+ task="pass_job.TestPassJob",
2383
2394
  job_model=self.job_model,
2384
2395
  enabled=False,
2385
2396
  interval=JobExecutionType.TYPE_DAILY,
@@ -2952,7 +2963,7 @@ class JobLogEntryTest(TestCase): # TODO: change to BaseModelTestCase
2952
2963
  """
2953
2964
 
2954
2965
  def setUp(self):
2955
- module = "pass"
2966
+ module = "pass_job"
2956
2967
  name = "TestPassJob"
2957
2968
  job_class = get_job(f"{module}.{name}")
2958
2969
 
@@ -567,7 +567,10 @@ class ExampleModelCustomActionViewTest(TestCase):
567
567
  def test_custom_action_view_anonymous(self):
568
568
  self.client.logout()
569
569
  response = self.client.get(self.custom_view_url)
570
- self.assertHttpStatus(response, 302)
570
+ self.assertHttpStatus(response, 200)
571
+ # TODO: all this is doing is checking that a login link appears somewhere on the page (i.e. in the nav).
572
+ response_body = response.content.decode(response.charset)
573
+ self.assertIn("/login/?next=", response_body, msg=response_body)
571
574
 
572
575
  def test_custom_action_view_without_permission(self):
573
576
  with disable_warnings("django.request"):
@@ -577,7 +580,7 @@ class ExampleModelCustomActionViewTest(TestCase):
577
580
  self.assertNotIn("/login/", response_body, msg=response_body)
578
581
 
579
582
  def test_custom_action_view_with_permission(self):
580
- self.add_permissions(f"{self.model._meta.app_label}.all_names_{self.model._meta.model_name}")
583
+ self.add_permissions(f"{self.model._meta.app_label}.view_{self.model._meta.model_name}")
581
584
 
582
585
  response = self.client.get(self.custom_view_url)
583
586
  self.assertHttpStatus(response, 200)
@@ -593,7 +596,7 @@ class ExampleModelCustomActionViewTest(TestCase):
593
596
  obj_perm = ObjectPermission(
594
597
  name="Test permission",
595
598
  constraints={"pk": instance1.pk},
596
- actions=["all_names"],
599
+ actions=["view"],
597
600
  )
598
601
  obj_perm.save()
599
602
  obj_perm.users.add(self.user)
@@ -1137,7 +1137,7 @@ class ExportTemplateTestCase(
1137
1137
 
1138
1138
  class ExternalIntegrationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
1139
1139
  model = ExternalIntegration
1140
- bulk_edit_data = {"timeout": 10, "verify_ssl": True, "extra_config": r"{}", "headers": r"{}"}
1140
+ bulk_edit_data = {"timeout": 10, "verify_ssl": True, "extra_config": '{"baz": "quux"}', "headers": '{"a": "b"}'}
1141
1141
  form_data = {
1142
1142
  "name": "Test External Integration",
1143
1143
  "remote_url": "https://example.com/test1/",
@@ -1956,21 +1956,21 @@ class ScheduledJobTestCase(
1956
1956
  user = User.objects.create(username="user1", is_active=True)
1957
1957
  ScheduledJob.objects.create(
1958
1958
  name="test1",
1959
- task="pass.TestPassJob",
1959
+ task="pass_job.TestPassJob",
1960
1960
  interval=JobExecutionType.TYPE_IMMEDIATELY,
1961
1961
  user=user,
1962
1962
  start_time=timezone.now(),
1963
1963
  )
1964
1964
  ScheduledJob.objects.create(
1965
1965
  name="test2",
1966
- task="pass.TestPassJob",
1966
+ task="pass_job.TestPassJob",
1967
1967
  interval=JobExecutionType.TYPE_DAILY,
1968
1968
  user=user,
1969
1969
  start_time=timezone.now(),
1970
1970
  )
1971
1971
  ScheduledJob.objects.create(
1972
1972
  name="test3",
1973
- task="pass.TestPassJob",
1973
+ task="pass_job.TestPassJob",
1974
1974
  interval=JobExecutionType.TYPE_CUSTOM,
1975
1975
  user=user,
1976
1976
  start_time=timezone.now(),
@@ -1984,7 +1984,7 @@ class ScheduledJobTestCase(
1984
1984
  ScheduledJob.objects.create(
1985
1985
  enabled=False,
1986
1986
  name="test4",
1987
- task="pass.TestPassJob",
1987
+ task="pass_job.TestPassJob",
1988
1988
  interval=JobExecutionType.TYPE_IMMEDIATELY,
1989
1989
  user=self.user,
1990
1990
  start_time=timezone.now(),
@@ -2001,7 +2001,7 @@ class ScheduledJobTestCase(
2001
2001
  ScheduledJob.objects.create(
2002
2002
  enabled=True,
2003
2003
  name=name,
2004
- task="pass.TestPassJob",
2004
+ task="pass_job.TestPassJob",
2005
2005
  interval=JobExecutionType.TYPE_CUSTOM,
2006
2006
  user=self.user,
2007
2007
  start_time=timezone.now(),
@@ -2032,7 +2032,7 @@ class ScheduledJobTestCase(
2032
2032
  ScheduledJob.objects.create(
2033
2033
  enabled=True,
2034
2034
  name="test11",
2035
- task="pass.TestPassJob",
2035
+ task="pass_job.TestPassJob",
2036
2036
  interval=JobExecutionType.TYPE_CUSTOM,
2037
2037
  user=self.user,
2038
2038
  start_time=timezone.now(),
@@ -2092,7 +2092,7 @@ class ApprovalQueueTestCase(
2092
2092
 
2093
2093
  ScheduledJob.objects.create(
2094
2094
  name="test4",
2095
- task="pass.TestPassJob",
2095
+ task="pass_job.TestPassJob",
2096
2096
  job_model=self.job_model,
2097
2097
  interval=JobExecutionType.TYPE_IMMEDIATELY,
2098
2098
  user=self.user,
@@ -2483,7 +2483,7 @@ class JobResultTestCase(
2483
2483
 
2484
2484
  @classmethod
2485
2485
  def setUpTestData(cls):
2486
- JobResult.objects.create(name="pass.TestPassJob")
2486
+ JobResult.objects.create(name="pass_job.TestPassJob")
2487
2487
  JobResult.objects.create(name="fail.TestFailJob")
2488
2488
  JobLogEntry.objects.create(
2489
2489
  log_level=LogLevelChoices.LOG_INFO,
@@ -3079,6 +3079,25 @@ class JobTestCase(
3079
3079
  "One of these two flags must be removed before this job can be scheduled or run.",
3080
3080
  )
3081
3081
 
3082
+ @mock.patch("nautobot.extras.views.get_worker_count", return_value=1)
3083
+ def test_run_job_with_approval_required_creates_scheduled_job_internal_future(self, _):
3084
+ self.add_permissions("extras.run_job")
3085
+ self.add_permissions("extras.view_scheduledjob")
3086
+
3087
+ self.test_pass.approval_required = True
3088
+ self.test_pass.save()
3089
+ data = {
3090
+ "_schedule_type": "immediately",
3091
+ }
3092
+ for run_url in self.run_urls:
3093
+ response = self.client.post(run_url, data)
3094
+ scheduled_job = ScheduledJob.objects.last()
3095
+ self.assertTrue(scheduled_job.interval, JobExecutionType.TYPE_FUTURE)
3096
+ self.assertRedirects(
3097
+ response,
3098
+ reverse("extras:scheduledjob_approval_queue_list"),
3099
+ )
3100
+
3082
3101
  def test_job_object_change_log_view(self):
3083
3102
  """Assert Job change log view displays appropriate header"""
3084
3103
  instance = self.test_pass
@@ -3657,6 +3676,43 @@ class RelationshipAssociationTestCase(
3657
3676
  self.assertNotIn(instance2.source.name, content, msg=content)
3658
3677
  self.assertNotIn(instance2.destination.name, content, msg=content)
3659
3678
 
3679
+ def test_get_object_with_advanced_relationships(self):
3680
+ device_type = ContentType.objects.get_for_model(Device)
3681
+ vlan_type = ContentType.objects.get_for_model(VLAN)
3682
+ Relationship.objects.create(
3683
+ label="Device VLANs 4",
3684
+ key="device_vlans_4",
3685
+ type="one-to-many",
3686
+ source_type=device_type,
3687
+ source_label="Device VLANs Advanced",
3688
+ destination_type=vlan_type,
3689
+ destination_label="VLANs",
3690
+ advanced_ui=True,
3691
+ )
3692
+ Relationship.objects.create(
3693
+ label="Device VLANs 5",
3694
+ key="device_vlans_5",
3695
+ type="one-to-many",
3696
+ source_type=device_type,
3697
+ source_label="Device VLANs Main",
3698
+ destination_type=vlan_type,
3699
+ destination_label="VLANs",
3700
+ advanced_ui=False,
3701
+ )
3702
+
3703
+ device = Device.objects.first()
3704
+ # Add model-level permission
3705
+ self.add_permissions(f"{Device._meta.app_label}.view_{Device._meta.model_name}")
3706
+ # Try GET the main tab
3707
+ response = self.client.get(device.get_absolute_url())
3708
+ response_content = extract_page_body(response.content.decode(response.charset))
3709
+ # The relationship's source label should be in the advanced tab since advance_ui=True
3710
+ # a.k.a its index should be greater than the index of the advanced tab
3711
+ self.assertGreater(response_content.find("Device VLANs Advanced"), response_content.find('id="advanced"'))
3712
+ # The relationship's source label should not be in the advanced tab since advance_ui=False
3713
+ # a.k.a its index should be smaller than the index of the advanced tab
3714
+ self.assertGreater(response_content.find('id="advanced"'), response_content.find("Device VLANs Main"))
3715
+
3660
3716
 
3661
3717
  class StaticGroupAssociationTestCase(
3662
3718
  ViewTestCases.BulkDeleteObjectsViewTestCase,
@@ -3920,8 +3976,7 @@ class WebhookTestCase(
3920
3976
  "http_content_type": "application/json",
3921
3977
  }
3922
3978
  cls.bulk_edit_data = {
3923
- "name": "webhook-4",
3924
- "enabled": True,
3979
+ "enabled": False,
3925
3980
  "type_create": True,
3926
3981
  "type_update": True,
3927
3982
  "type_delete": False,
nautobot/extras/urls.py CHANGED
@@ -3,8 +3,6 @@ from django.urls import path
3
3
  from nautobot.core.views.routers import NautobotUIViewSetRouter
4
4
  from nautobot.extras import views
5
5
  from nautobot.extras.models import (
6
- ConfigContext,
7
- ConfigContextSchema,
8
6
  CustomField,
9
7
  DynamicGroup,
10
8
  GitRepository,
@@ -13,13 +11,14 @@ from nautobot.extras.models import (
13
11
  Note,
14
12
  Relationship,
15
13
  SecretsGroup,
16
- Tag,
17
14
  )
18
15
 
19
16
  app_name = "extras"
20
17
 
21
18
  router = NautobotUIViewSetRouter()
22
19
  router.register("computed-fields", views.ComputedFieldUIViewSet)
20
+ router.register("config-context-schemas", views.ConfigContextSchemaUIViewSet)
21
+ router.register("config-contexts", views.ConfigContextUIViewSet)
23
22
  router.register("contacts", views.ContactUIViewSet)
24
23
  router.register("contact-associations", views.ContactAssociationUIViewSet)
25
24
  router.register("custom-links", views.CustomLinkUIViewSet)
@@ -30,12 +29,14 @@ router.register("job-hooks", views.JobHookUIViewSet)
30
29
  router.register("job-queues", views.JobQueueUIViewSet)
31
30
  router.register("metadata-types", views.MetadataTypeUIViewSet)
32
31
  router.register("object-metadata", views.ObjectMetadataUIViewSet)
32
+ router.register("relationship-associations", views.RelationshipAssociationUIViewSet)
33
33
  router.register("relationships", views.RelationshipUIViewSet)
34
34
  router.register("roles", views.RoleUIViewSet)
35
35
  router.register("saved-views", views.SavedViewUIViewSet)
36
36
  router.register("secrets", views.SecretUIViewSet)
37
37
  router.register("static-group-associations", views.StaticGroupAssociationUIViewSet)
38
38
  router.register("statuses", views.StatusUIViewSet)
39
+ router.register("tags", views.TagUIViewSet)
39
40
  router.register("teams", views.TeamUIViewSet)
40
41
  router.register("webhooks", views.WebhookUIViewSet)
41
42
 
@@ -43,107 +44,12 @@ urlpatterns = [
43
44
  # Change logging
44
45
  path("object-changes/", views.ObjectChangeListView.as_view(), name="objectchange_list"),
45
46
  path("object-changes/<uuid:pk>/", views.ObjectChangeView.as_view(), name="objectchange"),
46
- # Config contexts
47
- path(
48
- "config-contexts/",
49
- views.ConfigContextListView.as_view(),
50
- name="configcontext_list",
51
- ),
52
- path(
53
- "config-contexts/add/",
54
- views.ConfigContextEditView.as_view(),
55
- name="configcontext_add",
56
- ),
57
- path(
58
- "config-contexts/edit/",
59
- views.ConfigContextBulkEditView.as_view(),
60
- name="configcontext_bulk_edit",
61
- ),
62
- path(
63
- "config-contexts/delete/",
64
- views.ConfigContextBulkDeleteView.as_view(),
65
- name="configcontext_bulk_delete",
66
- ),
67
- path(
68
- "config-contexts/<uuid:pk>/",
69
- views.ConfigContextView.as_view(),
70
- name="configcontext",
71
- ),
72
- path(
73
- "config-contexts/<uuid:pk>/edit/",
74
- views.ConfigContextEditView.as_view(),
75
- name="configcontext_edit",
76
- ),
77
- path(
78
- "config-contexts/<uuid:pk>/delete/",
79
- views.ConfigContextDeleteView.as_view(),
80
- name="configcontext_delete",
81
- ),
82
- path(
83
- "config-contexts/<uuid:pk>/changelog/",
84
- views.ObjectChangeLogView.as_view(),
85
- name="configcontext_changelog",
86
- kwargs={"model": ConfigContext},
87
- ),
88
- path(
89
- "config-contexts/<uuid:pk>/notes/",
90
- views.ObjectNotesView.as_view(),
91
- name="configcontext_notes",
92
- kwargs={"model": ConfigContext},
93
- ),
94
47
  # Config context schema
95
- path(
96
- "config-context-schemas/",
97
- views.ConfigContextSchemaListView.as_view(),
98
- name="configcontextschema_list",
99
- ),
100
- path(
101
- "config-context-schemas/add/",
102
- views.ConfigContextSchemaEditView.as_view(),
103
- name="configcontextschema_add",
104
- ),
105
- path(
106
- "config-context-schemas/edit/",
107
- views.ConfigContextSchemaBulkEditView.as_view(),
108
- name="configcontextschema_bulk_edit",
109
- ),
110
- path(
111
- "config-context-schemas/delete/",
112
- views.ConfigContextSchemaBulkDeleteView.as_view(),
113
- name="configcontextschema_bulk_delete",
114
- ),
115
- path(
116
- "config-context-schemas/<uuid:pk>/",
117
- views.ConfigContextSchemaView.as_view(),
118
- name="configcontextschema",
119
- ),
120
48
  path(
121
49
  "config-context-schemas/<uuid:pk>/validation/",
122
50
  views.ConfigContextSchemaObjectValidationView.as_view(),
123
51
  name="configcontextschema_object_validation",
124
52
  ),
125
- path(
126
- "config-context-schemas/<uuid:pk>/edit/",
127
- views.ConfigContextSchemaEditView.as_view(),
128
- name="configcontextschema_edit",
129
- ),
130
- path(
131
- "config-context-schemas/<uuid:pk>/delete/",
132
- views.ConfigContextSchemaDeleteView.as_view(),
133
- name="configcontextschema_delete",
134
- ),
135
- path(
136
- "config-context-schemas/<uuid:pk>/changelog/",
137
- views.ObjectChangeLogView.as_view(),
138
- name="configcontextschema_changelog",
139
- kwargs={"model": ConfigContextSchema},
140
- ),
141
- path(
142
- "config-context-schemas/<uuid:pk>/notes/",
143
- views.ObjectNotesView.as_view(),
144
- name="configcontextschema_notes",
145
- kwargs={"model": ConfigContextSchema},
146
- ),
147
53
  # contacts
148
54
  path("contact-associations/add-new-contact/", views.ObjectNewContactView.as_view(), name="object_contact_add"),
149
55
  path("contact-associations/add-new-team/", views.ObjectNewTeamView.as_view(), name="object_team_add"),
@@ -399,21 +305,6 @@ urlpatterns = [
399
305
  name="relationship_notes",
400
306
  kwargs={"model": Relationship},
401
307
  ),
402
- path(
403
- "relationship-associations/",
404
- views.RelationshipAssociationListView.as_view(),
405
- name="relationshipassociation_list",
406
- ),
407
- path(
408
- "relationship-associations/delete/",
409
- views.RelationshipAssociationBulkDeleteView.as_view(),
410
- name="relationshipassociation_bulk_delete",
411
- ),
412
- path(
413
- "relationship-associations/<uuid:pk>/delete/",
414
- views.RelationshipAssociationDeleteView.as_view(),
415
- name="relationshipassociation_delete",
416
- ),
417
308
  # Secrets
418
309
  path(
419
310
  "secrets/provider/<str:provider_slug>/form/",
@@ -438,27 +329,6 @@ urlpatterns = [
438
329
  name="secretsgroup_notes",
439
330
  kwargs={"model": SecretsGroup},
440
331
  ),
441
- # Tags
442
- path("tags/", views.TagListView.as_view(), name="tag_list"),
443
- path("tags/add/", views.TagEditView.as_view(), name="tag_add"),
444
- path("tags/import/", views.TagBulkImportView.as_view(), name="tag_import"), # 3.0 TODO: remove, unused
445
- path("tags/edit/", views.TagBulkEditView.as_view(), name="tag_bulk_edit"),
446
- path("tags/delete/", views.TagBulkDeleteView.as_view(), name="tag_bulk_delete"),
447
- path("tags/<uuid:pk>/", views.TagView.as_view(), name="tag"),
448
- path("tags/<uuid:pk>/edit/", views.TagEditView.as_view(), name="tag_edit"),
449
- path("tags/<uuid:pk>/delete/", views.TagDeleteView.as_view(), name="tag_delete"),
450
- path(
451
- "tags/<uuid:pk>/changelog/",
452
- views.ObjectChangeLogView.as_view(),
453
- name="tag_changelog",
454
- kwargs={"model": Tag},
455
- ),
456
- path(
457
- "tags/<uuid:pk>/notes/",
458
- views.ObjectNotesView.as_view(),
459
- name="tag_notes",
460
- kwargs={"model": Tag},
461
- ),
462
332
  ]
463
333
 
464
334
  urlpatterns += router.urls