nautobot 2.2.2__py3-none-any.whl → 2.2.4__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 (362) hide show
  1. nautobot/apps/jobs.py +2 -0
  2. nautobot/core/api/utils.py +12 -9
  3. nautobot/core/apps/__init__.py +2 -2
  4. nautobot/core/celery/__init__.py +79 -68
  5. nautobot/core/celery/backends.py +9 -1
  6. nautobot/core/celery/control.py +4 -7
  7. nautobot/core/celery/schedulers.py +4 -2
  8. nautobot/core/celery/task.py +78 -5
  9. nautobot/core/graphql/schema.py +2 -1
  10. nautobot/core/jobs/__init__.py +2 -1
  11. nautobot/core/settings.py +6 -4
  12. nautobot/core/settings.yaml +51 -16
  13. nautobot/core/templates/admin/base.html +2 -2
  14. nautobot/core/templates/base_django.html +2 -2
  15. nautobot/core/templates/buttons/export.html +47 -47
  16. nautobot/core/templates/generic/object_list.html +3 -3
  17. nautobot/core/templates/inc/javascript.html +3 -0
  18. nautobot/core/templates/inc/media.html +3 -0
  19. nautobot/core/templates/login.html +2 -2
  20. nautobot/core/templates/nautobot_config.py.j2 +2 -0
  21. nautobot/core/templatetags/helpers.py +66 -9
  22. nautobot/core/testing/__init__.py +6 -1
  23. nautobot/core/testing/api.py +12 -13
  24. nautobot/core/testing/mixins.py +2 -2
  25. nautobot/core/testing/views.py +50 -51
  26. nautobot/core/tests/test_api.py +23 -2
  27. nautobot/core/tests/test_jobs.py +79 -2
  28. nautobot/core/tests/test_templatetags_helpers.py +32 -0
  29. nautobot/core/tests/test_views.py +52 -0
  30. nautobot/core/tests/test_views_utils.py +22 -1
  31. nautobot/core/utils/module_loading.py +89 -0
  32. nautobot/core/views/mixins.py +4 -0
  33. nautobot/core/views/utils.py +3 -2
  34. nautobot/dcim/choices.py +14 -0
  35. nautobot/dcim/forms.py +51 -1
  36. nautobot/dcim/models/device_components.py +9 -5
  37. nautobot/dcim/templates/dcim/location.html +32 -13
  38. nautobot/dcim/templates/dcim/location_migrate_data_to_contact.html +102 -0
  39. nautobot/dcim/tests/test_views.py +376 -55
  40. nautobot/dcim/urls.py +5 -0
  41. nautobot/dcim/views.py +172 -21
  42. nautobot/extras/api/serializers.py +17 -6
  43. nautobot/extras/api/views.py +21 -10
  44. nautobot/extras/constants.py +3 -3
  45. nautobot/extras/datasources/git.py +47 -58
  46. nautobot/extras/forms/forms.py +3 -1
  47. nautobot/extras/jobs.py +79 -146
  48. nautobot/extras/models/datasources.py +0 -2
  49. nautobot/extras/models/jobs.py +36 -18
  50. nautobot/extras/plugins/__init__.py +1 -20
  51. nautobot/extras/signals.py +6 -9
  52. nautobot/extras/test_jobs/__init__.py +8 -0
  53. nautobot/extras/test_jobs/dry_run.py +3 -2
  54. nautobot/extras/test_jobs/fail.py +43 -0
  55. nautobot/extras/test_jobs/ipaddress_vars.py +40 -1
  56. nautobot/extras/test_jobs/jobs_module/__init__.py +5 -0
  57. nautobot/extras/test_jobs/jobs_module/jobs_submodule/__init__.py +1 -0
  58. nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +6 -0
  59. nautobot/extras/test_jobs/pass.py +40 -0
  60. nautobot/extras/test_jobs/relative_import.py +11 -0
  61. nautobot/extras/tests/test_api.py +3 -0
  62. nautobot/extras/tests/test_context_managers.py +18 -0
  63. nautobot/extras/tests/test_datasources.py +125 -118
  64. nautobot/extras/tests/test_job_variables.py +57 -15
  65. nautobot/extras/tests/test_jobs.py +135 -1
  66. nautobot/extras/tests/test_models.py +26 -19
  67. nautobot/extras/tests/test_plugins.py +1 -3
  68. nautobot/extras/tests/test_views.py +2 -4
  69. nautobot/extras/utils.py +2 -1
  70. nautobot/extras/views.py +82 -116
  71. nautobot/ipam/api/views.py +8 -1
  72. nautobot/ipam/graphql/types.py +11 -0
  73. nautobot/ipam/mixins.py +32 -0
  74. nautobot/ipam/models.py +2 -1
  75. nautobot/ipam/querysets.py +6 -1
  76. nautobot/ipam/tests/test_models.py +82 -0
  77. nautobot/ipam/views.py +6 -6
  78. nautobot/project-static/docs/404.html +107 -51
  79. nautobot/project-static/docs/apps/index.html +107 -51
  80. nautobot/project-static/docs/apps/nautobot-apps.html +107 -51
  81. nautobot/project-static/docs/assets/_mkdocstrings.css +6 -1
  82. nautobot/project-static/docs/assets/extra.css +11 -0
  83. nautobot/project-static/docs/assets/javascripts/bundle.3220b9d7.min.js +29 -0
  84. nautobot/project-static/docs/assets/javascripts/bundle.3220b9d7.min.js.map +7 -0
  85. nautobot/project-static/docs/assets/stylesheets/main.66ac8b77.min.css +1 -0
  86. nautobot/project-static/docs/assets/stylesheets/main.66ac8b77.min.css.map +1 -0
  87. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +107 -51
  88. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +107 -51
  89. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +108 -52
  90. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +107 -51
  91. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +107 -51
  92. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +107 -51
  93. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +107 -51
  94. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +107 -51
  95. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +107 -51
  96. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +107 -51
  97. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +107 -51
  98. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +107 -51
  99. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +107 -51
  100. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +287 -262
  101. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +107 -51
  102. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +107 -51
  103. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +107 -51
  104. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +107 -51
  105. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +107 -51
  106. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +107 -51
  107. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +107 -51
  108. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +107 -51
  109. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +107 -51
  110. nautobot/project-static/docs/development/apps/api/configuration-view.html +110 -54
  111. nautobot/project-static/docs/development/apps/api/database-backend-config.html +110 -54
  112. nautobot/project-static/docs/development/apps/api/models/django-admin.html +107 -51
  113. nautobot/project-static/docs/development/apps/api/models/global-search.html +110 -54
  114. nautobot/project-static/docs/development/apps/api/models/graphql.html +113 -57
  115. nautobot/project-static/docs/development/apps/api/models/index.html +107 -51
  116. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +113 -57
  117. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +107 -51
  118. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +110 -54
  119. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +107 -51
  120. nautobot/project-static/docs/development/apps/api/platform-features/index.html +107 -51
  121. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +110 -54
  122. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +111 -55
  123. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +110 -54
  124. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +110 -54
  125. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +107 -51
  126. nautobot/project-static/docs/development/apps/api/prometheus.html +110 -54
  127. nautobot/project-static/docs/development/apps/api/setup.html +107 -51
  128. nautobot/project-static/docs/development/apps/api/testing.html +113 -57
  129. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +110 -54
  130. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +110 -54
  131. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +107 -51
  132. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +107 -51
  133. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +113 -57
  134. nautobot/project-static/docs/development/apps/api/views/base-template.html +107 -51
  135. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +110 -54
  136. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +107 -51
  137. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +110 -54
  138. nautobot/project-static/docs/development/apps/api/views/index.html +107 -51
  139. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +113 -57
  140. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +122 -66
  141. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +110 -54
  142. nautobot/project-static/docs/development/apps/api/views/notes.html +110 -54
  143. nautobot/project-static/docs/development/apps/api/views/rest-api.html +107 -51
  144. nautobot/project-static/docs/development/apps/api/views/urls.html +107 -51
  145. nautobot/project-static/docs/development/apps/index.html +128 -72
  146. nautobot/project-static/docs/development/apps/migration/code-updates.html +107 -51
  147. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +107 -51
  148. nautobot/project-static/docs/development/apps/migration/from-v1.html +107 -51
  149. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +107 -51
  150. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +107 -51
  151. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +107 -51
  152. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +107 -51
  153. nautobot/project-static/docs/development/apps/porting-from-netbox.html +110 -54
  154. nautobot/project-static/docs/development/core/application-registry.html +242 -144
  155. nautobot/project-static/docs/development/core/best-practices.html +122 -66
  156. nautobot/project-static/docs/development/core/bootstrap-ui.html +107 -51
  157. nautobot/project-static/docs/development/core/caching.html +107 -51
  158. nautobot/project-static/docs/development/core/controllers.html +107 -51
  159. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +113 -57
  160. nautobot/project-static/docs/development/core/generic-views.html +110 -54
  161. nautobot/project-static/docs/development/core/getting-started.html +135 -79
  162. nautobot/project-static/docs/development/core/homepage.html +110 -54
  163. nautobot/project-static/docs/development/core/index.html +107 -51
  164. nautobot/project-static/docs/development/core/model-checklist.html +156 -52
  165. nautobot/project-static/docs/development/core/model-features.html +108 -52
  166. nautobot/project-static/docs/development/core/natural-keys.html +110 -54
  167. nautobot/project-static/docs/development/core/navigation-menu.html +107 -51
  168. nautobot/project-static/docs/development/core/release-checklist.html +107 -51
  169. nautobot/project-static/docs/development/core/role-internals.html +107 -51
  170. nautobot/project-static/docs/development/core/settings.html +107 -51
  171. nautobot/project-static/docs/development/core/style-guide.html +110 -54
  172. nautobot/project-static/docs/development/core/templates.html +113 -57
  173. nautobot/project-static/docs/development/core/testing.html +125 -69
  174. nautobot/project-static/docs/development/core/user-preferences.html +107 -51
  175. nautobot/project-static/docs/development/index.html +107 -51
  176. nautobot/project-static/docs/development/jobs/index.html +504 -172
  177. nautobot/project-static/docs/development/jobs/migration/from-v1.html +111 -55
  178. nautobot/project-static/docs/docker/index.html +3 -3
  179. nautobot/project-static/docs/index.html +125 -69
  180. nautobot/project-static/docs/installation/selinux-troubleshooting.html +3 -3
  181. nautobot/project-static/docs/objects.inv +0 -0
  182. nautobot/project-static/docs/release-notes/index.html +107 -51
  183. nautobot/project-static/docs/release-notes/version-1.0.html +107 -51
  184. nautobot/project-static/docs/release-notes/version-1.1.html +107 -51
  185. nautobot/project-static/docs/release-notes/version-1.2.html +107 -51
  186. nautobot/project-static/docs/release-notes/version-1.3.html +107 -51
  187. nautobot/project-static/docs/release-notes/version-1.4.html +107 -51
  188. nautobot/project-static/docs/release-notes/version-1.5.html +116 -60
  189. nautobot/project-static/docs/release-notes/version-1.6.html +107 -51
  190. nautobot/project-static/docs/release-notes/version-2.0.html +110 -54
  191. nautobot/project-static/docs/release-notes/version-2.1.html +107 -51
  192. nautobot/project-static/docs/release-notes/version-2.2.html +500 -114
  193. nautobot/project-static/docs/requirements.txt +2 -2
  194. nautobot/project-static/docs/search/search_index.json +1 -1
  195. nautobot/project-static/docs/sitemap.xml +262 -262
  196. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  197. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +107 -51
  198. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +107 -51
  199. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +107 -51
  200. nautobot/project-static/docs/user-guide/administration/configuration/index.html +107 -51
  201. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +251 -164
  202. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +113 -57
  203. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +107 -51
  204. nautobot/project-static/docs/user-guide/administration/guides/caching.html +113 -57
  205. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +107 -51
  206. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +107 -51
  207. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +107 -51
  208. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +113 -57
  209. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +107 -51
  210. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +107 -51
  211. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +107 -51
  212. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +171 -112
  213. nautobot/project-static/docs/user-guide/administration/installation/docker.html +13 -8626
  214. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +117 -61
  215. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +13 -8614
  216. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +252 -165
  217. nautobot/project-static/docs/user-guide/administration/installation/index.html +165 -192
  218. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +411 -691
  219. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +248 -229
  220. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +13 -8118
  221. nautobot/project-static/docs/user-guide/administration/installation/services.html +350 -240
  222. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +8684 -0
  223. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +8672 -0
  224. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +8176 -0
  225. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +110 -54
  226. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +110 -54
  227. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +155 -99
  228. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +107 -51
  229. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +109 -53
  230. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +107 -51
  231. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +107 -51
  232. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +107 -51
  233. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +107 -51
  234. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +107 -51
  235. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +107 -51
  236. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +117 -58
  237. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +113 -57
  238. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +107 -51
  239. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +107 -51
  240. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +107 -51
  241. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +107 -51
  242. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +110 -54
  243. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +107 -51
  244. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +110 -54
  245. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +110 -54
  246. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +110 -54
  247. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +110 -54
  248. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +107 -51
  249. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +107 -51
  250. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +113 -57
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +110 -54
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +110 -54
  253. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +110 -54
  254. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +110 -54
  255. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +116 -60
  256. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +110 -54
  257. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +110 -54
  258. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +119 -63
  259. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +110 -54
  260. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +110 -54
  261. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +113 -57
  262. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +113 -57
  263. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +113 -57
  264. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +107 -51
  265. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +113 -57
  266. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +107 -51
  267. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +110 -54
  268. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +110 -54
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +107 -51
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +110 -54
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +110 -54
  272. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +107 -51
  273. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +107 -51
  274. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +107 -51
  275. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +110 -54
  276. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +110 -54
  277. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +110 -54
  278. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +110 -54
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +107 -51
  280. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +113 -57
  281. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +110 -54
  282. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +110 -54
  283. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +110 -54
  284. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +125 -69
  285. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +113 -57
  286. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +128 -72
  287. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +110 -54
  288. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +107 -51
  289. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +110 -54
  290. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +227 -60
  291. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +107 -51
  292. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +113 -57
  293. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +107 -51
  294. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +110 -54
  295. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +107 -51
  296. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +107 -51
  297. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +107 -51
  298. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +107 -51
  299. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +113 -57
  300. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +113 -57
  301. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +107 -51
  302. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +113 -57
  303. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +107 -51
  304. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +107 -51
  305. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +107 -51
  306. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +107 -51
  307. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +107 -51
  308. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +107 -51
  309. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +107 -51
  310. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +107 -51
  311. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +107 -51
  312. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +110 -54
  313. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +113 -57
  314. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +107 -51
  315. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +110 -54
  316. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +107 -51
  317. nautobot/project-static/docs/user-guide/index.html +109 -53
  318. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +107 -51
  319. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +113 -57
  320. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +128 -72
  321. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +107 -51
  322. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +125 -69
  323. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +107 -51
  324. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +110 -54
  325. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +125 -69
  326. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +110 -54
  327. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +107 -51
  328. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +107 -51
  329. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +143 -100
  330. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +113 -57
  331. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +113 -57
  332. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +110 -54
  333. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +123 -67
  334. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +107 -51
  335. nautobot/project-static/docs/user-guide/platform-functionality/note.html +110 -54
  336. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +116 -60
  337. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +110 -54
  338. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +131 -75
  339. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +149 -93
  340. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +110 -54
  341. nautobot/project-static/docs/user-guide/platform-functionality/role.html +107 -51
  342. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +116 -60
  343. nautobot/project-static/docs/user-guide/platform-functionality/status.html +119 -63
  344. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +110 -54
  345. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +137 -81
  346. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +110 -54
  347. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +107 -51
  348. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +110 -54
  349. nautobot/project-static/js/forms.js +18 -11
  350. nautobot/tenancy/views.py +2 -6
  351. nautobot/virtualization/views.py +5 -9
  352. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/METADATA +4 -4
  353. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/RECORD +357 -348
  354. nautobot/extras/test_jobs/job_variables.py +0 -93
  355. nautobot/project-static/docs/assets/javascripts/bundle.bd41221c.min.js +0 -29
  356. nautobot/project-static/docs/assets/javascripts/bundle.bd41221c.min.js.map +0 -7
  357. nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css +0 -1
  358. nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css.map +0 -1
  359. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/LICENSE.txt +0 -0
  360. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/NOTICE +0 -0
  361. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/WHEEL +0 -0
  362. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  import datetime
2
2
  from io import StringIO
3
3
  import json
4
+ import os
4
5
  from pathlib import Path
5
6
  import re
6
7
  import tempfile
@@ -34,7 +35,7 @@ from nautobot.extras.choices import (
34
35
  ObjectChangeEventContextChoices,
35
36
  )
36
37
  from nautobot.extras.context_managers import change_logging, JobHookChangeContext, web_request_context
37
- from nautobot.extras.jobs import get_job
38
+ from nautobot.extras.jobs import get_job, get_jobs
38
39
 
39
40
 
40
41
  class JobTest(TestCase):
@@ -174,6 +175,111 @@ class JobTest(TestCase):
174
175
  self.assertFalse(job_class.supports_dryrun)
175
176
  self.assertFalse(job_model.supports_dryrun)
176
177
 
178
+ def test_submodule_in_jobs_root(self):
179
+ """
180
+ Test that a subdirectory/submodule in JOBS_ROOT can contain Jobs.
181
+ """
182
+ job_class, job_model = get_job_class_and_model("jobs_module.jobs_submodule.jobs", "ChildJob")
183
+ self.assertIsNotNone(job_class)
184
+ self.assertIsNotNone(job_model)
185
+
186
+ def test_relative_import_among_files_in_jobs_root(self):
187
+ """
188
+ Test that a module in JOBS_ROOT can import from other modules in JOBS_ROOT.
189
+ """
190
+ job_class, job_model = get_job_class_and_model("relative_import", "TestReallyPass")
191
+ self.assertIsNotNone(job_class)
192
+ self.assertIsNotNone(job_model)
193
+
194
+ def test_get_jobs_from_jobs_root(self):
195
+ """
196
+ Test that get_jobs() correctly loads jobs from JOBS_ROOT as its contents change.
197
+ """
198
+ try:
199
+ with tempfile.TemporaryDirectory() as temp_dir:
200
+ with override_settings(JOBS_ROOT=temp_dir):
201
+ # Create a new Job and make sure it's discovered correctly
202
+ with open(os.path.join(temp_dir, "my_jobs.py"), "w") as fd:
203
+ fd.write("""\
204
+ from nautobot.apps.jobs import Job, register_jobs
205
+ class MyJob(Job):
206
+ def run(self):
207
+ pass
208
+ register_jobs(MyJob)
209
+ """)
210
+ jobs_data = get_jobs(reload=True)
211
+ self.assertIn("my_jobs.MyJob", jobs_data.keys())
212
+ self.assertIsNotNone(get_job("my_jobs.MyJob"))
213
+ # Also make sure some representative previous JOBS_ROOT jobs aren't still around:
214
+ self.assertNotIn("dry_run.TestDryRun", jobs_data.keys())
215
+ self.assertNotIn("pass.TestPass", jobs_data.keys())
216
+
217
+ # Create a second Job in the same module
218
+ with open(os.path.join(temp_dir, "my_jobs.py"), "a") as fd:
219
+ fd.write("""
220
+ class MyOtherJob(MyJob):
221
+ pass
222
+ register_jobs(MyOtherJob)
223
+ """)
224
+ jobs_data = get_jobs(reload=True)
225
+ self.assertIn("my_jobs.MyJob", jobs_data.keys())
226
+ self.assertIsNotNone(get_job("my_jobs.MyJob"))
227
+ self.assertIn("my_jobs.MyOtherJob", jobs_data.keys())
228
+ self.assertIsNotNone(get_job("my_jobs.MyOtherJob"))
229
+
230
+ # Create a third Job in another module
231
+ with open(os.path.join(temp_dir, "their_jobs.py"), "w") as fd:
232
+ fd.write("""
233
+ from nautobot.apps.jobs import Job, register_jobs
234
+
235
+ class MyJob(Job):
236
+ def run(self):
237
+ pass
238
+ register_jobs(MyJob)
239
+ """)
240
+ jobs_data = get_jobs(reload=True)
241
+ self.assertIn("my_jobs.MyJob", jobs_data.keys())
242
+ self.assertIsNotNone(get_job("my_jobs.MyJob"))
243
+ self.assertIn("my_jobs.MyOtherJob", jobs_data.keys())
244
+ self.assertIsNotNone(get_job("my_jobs.MyOtherJob"))
245
+ self.assertIn("their_jobs.MyJob", jobs_data.keys())
246
+ self.assertIsNotNone(get_job("their_jobs.MyJob"))
247
+ self.assertNotEqual(get_job("my_jobs.MyJob"), get_job("their_jobs.MyJob"))
248
+
249
+ # Delete a module
250
+ os.remove(os.path.join(temp_dir, "their_jobs.py"))
251
+ jobs_data = get_jobs(reload=True)
252
+ self.assertIn("my_jobs.MyJob", jobs_data.keys())
253
+ self.assertIsNotNone(get_job("my_jobs.MyJob"))
254
+ self.assertIn("my_jobs.MyOtherJob", jobs_data.keys())
255
+ self.assertIsNotNone(get_job("my_jobs.MyOtherJob"))
256
+ self.assertNotIn("their_jobs", jobs_data.keys())
257
+ self.assertIsNone(get_job("their_jobs.MyJob"))
258
+
259
+ # Create a module with an inauspicious name
260
+ with open(os.path.join(temp_dir, "traceback.py"), "w") as fd:
261
+ fd.write("""
262
+ from nautobot.apps.jobs import Job, register_jobs
263
+
264
+ class BadJob(Job):
265
+ def run(self):
266
+ raise RuntimeError("You ran a bad job!")
267
+ register_jobs(BadJob)
268
+ """)
269
+ jobs_data = get_jobs(reload=True)
270
+ self.assertIn("my_jobs.MyJob", jobs_data.keys())
271
+ self.assertIsNotNone(get_job("my_jobs.MyJob"))
272
+ self.assertIn("my_jobs.MyOtherJob", jobs_data.keys())
273
+ self.assertIsNotNone(get_job("my_jobs.MyOtherJob"))
274
+ # Since `traceback` conflicts with a system module, it should not get loaded
275
+ self.assertNotIn("traceback.BadJob", jobs_data.keys())
276
+ self.assertIsNone(get_job("traceback.BadJob"))
277
+
278
+ # TODO: testing with subdirectories/submodules under JOBS_ROOT...
279
+ finally:
280
+ # Clean up back to normal behavior
281
+ get_jobs(reload=True)
282
+
177
283
 
178
284
  class JobTransactionTest(TransactionTestCase):
179
285
  """
@@ -216,6 +322,19 @@ class JobTransactionTest(TransactionTestCase):
216
322
  name = "TestPass"
217
323
  job_result = create_job_result_and_run_job(module, name)
218
324
  self.assertEqual(job_result.status, JobResultStatusChoices.STATUS_SUCCESS)
325
+ self.assertEqual(job_result.result, True)
326
+ logs = job_result.job_log_entries
327
+ self.assertGreater(logs.count(), 0)
328
+ try:
329
+ logs.get(message="before_start() was called as expected")
330
+ logs.get(message="Success")
331
+ logs.get(message="on_success() was called as expected")
332
+ logs.get(message="after_return() was called as expected")
333
+ except models.JobLogEntry.DoesNotExist:
334
+ for log in logs.all():
335
+ print(log.message)
336
+ print(job_result.traceback)
337
+ raise
219
338
 
220
339
  def test_job_result_manager_censor_sensitive_variables(self):
221
340
  """
@@ -237,6 +356,18 @@ class JobTransactionTest(TransactionTestCase):
237
356
  name = "TestFail"
238
357
  job_result = create_job_result_and_run_job(module, name)
239
358
  self.assertEqual(job_result.status, JobResultStatusChoices.STATUS_FAILURE)
359
+ logs = job_result.job_log_entries
360
+ self.assertGreater(logs.count(), 0)
361
+ try:
362
+ logs.get(message="before_start() was called as expected")
363
+ logs.get(message="I'm a test job that fails!")
364
+ logs.get(message="on_failure() was called as expected")
365
+ logs.get(message="after_return() was called as expected")
366
+ except models.JobLogEntry.DoesNotExist:
367
+ for log in logs.all():
368
+ print(log.message)
369
+ print(job_result.traceback)
370
+ raise
240
371
 
241
372
  def test_job_fail_with_sanitization(self):
242
373
  """
@@ -876,6 +1007,7 @@ class JobHookReceiverTransactionTest(TransactionTestCase):
876
1007
  test_location = Location.objects.get(name="test_jhr")
877
1008
  oc = get_changes_for_model(test_location).first()
878
1009
  self.assertEqual(oc.change_context, ObjectChangeEventContextChoices.CONTEXT_JOB_HOOK)
1010
+ self.assertIsNotNone(job_result.user)
879
1011
  self.assertEqual(oc.user_id, job_result.user.pk)
880
1012
 
881
1013
  def test_missing_receive_job_hook_method(self):
@@ -933,6 +1065,8 @@ class JobHookTransactionTest(TransactionTestCase): # TODO: BaseModelTestCase mi
933
1065
  module = "job_hook_receiver"
934
1066
  name = "TestJobHookReceiverLog"
935
1067
  self.job_class, self.job_model = get_job_class_and_model(module, name)
1068
+ self.assertIsNotNone(self.job_class)
1069
+ self.assertIsNotNone(self.job_model)
936
1070
  job_hook = models.JobHook(
937
1071
  name="JobHookTest",
938
1072
  type_create=True,
@@ -65,6 +65,7 @@ from nautobot.extras.models import (
65
65
  Webhook,
66
66
  )
67
67
  from nautobot.extras.models.statuses import StatusModel
68
+ from nautobot.extras.registry import registry
68
69
  from nautobot.extras.secrets.exceptions import SecretParametersError, SecretProviderError, SecretValueNotFoundError
69
70
  from nautobot.ipam.models import IPAddress
70
71
  from nautobot.tenancy.models import Tenant
@@ -1079,25 +1080,31 @@ class JobModelTest(ModelTestCases.BaseModelTestCase):
1079
1080
  def test_defaults(self):
1080
1081
  """Verify that defaults for discovered JobModel instances are as expected."""
1081
1082
  for job_model in JobModel.objects.all():
1082
- self.assertTrue(job_model.installed)
1083
- # System jobs should be enabled by default, all others are disabled by default
1084
- if job_model.module_name.startswith("nautobot."):
1085
- self.assertTrue(job_model.enabled)
1086
- else:
1087
- self.assertFalse(job_model.enabled)
1088
- for field_name in JOB_OVERRIDABLE_FIELDS:
1089
- if field_name == "name" and "duplicate_name" in job_model.job_class.__module__:
1090
- pass # name field for test_duplicate_name jobs tested in test_duplicate_job_name below
1091
- else:
1092
- self.assertFalse(
1093
- getattr(job_model, f"{field_name}_override"),
1094
- (field_name, getattr(job_model, field_name), getattr(job_model.job_class, field_name)),
1095
- )
1096
- self.assertEqual(
1097
- getattr(job_model, field_name),
1098
- getattr(job_model.job_class, field_name),
1099
- field_name,
1100
- )
1083
+ with self.subTest(class_path=job_model.class_path):
1084
+ try:
1085
+ self.assertTrue(job_model.installed)
1086
+ # System jobs should be enabled by default, all others are disabled by default
1087
+ if job_model.module_name.startswith("nautobot."):
1088
+ self.assertTrue(job_model.enabled)
1089
+ else:
1090
+ self.assertFalse(job_model.enabled)
1091
+ for field_name in JOB_OVERRIDABLE_FIELDS:
1092
+ if field_name == "name" and "duplicate_name" in job_model.job_class.__module__:
1093
+ pass # name field for test_duplicate_name jobs tested in test_duplicate_job_name below
1094
+ else:
1095
+ self.assertFalse(
1096
+ getattr(job_model, f"{field_name}_override"),
1097
+ (field_name, getattr(job_model, field_name), getattr(job_model.job_class, field_name)),
1098
+ )
1099
+ self.assertEqual(
1100
+ getattr(job_model, field_name),
1101
+ getattr(job_model.job_class, field_name),
1102
+ field_name,
1103
+ )
1104
+ except AssertionError:
1105
+ print(list(JobModel.objects.all()))
1106
+ print(registry["jobs"])
1107
+ raise
1101
1108
 
1102
1109
  def test_duplicate_job_name(self):
1103
1110
  self.assertTrue(JobModel.objects.filter(name="TestDuplicateNameNoMeta").exists())
@@ -9,7 +9,6 @@ from django.urls import NoReverseMatch, reverse
9
9
  import netaddr
10
10
 
11
11
  from nautobot.circuits.models import Circuit, CircuitType, Provider
12
- from nautobot.core.celery import app
13
12
  from nautobot.core.testing import APIViewTestCases, disable_warnings, extract_page_body, TestCase, ViewTestCases
14
13
  from nautobot.dcim.models import Device, DeviceType, Location, LocationType, Manufacturer
15
14
  from nautobot.dcim.tests.test_views import create_test_device
@@ -114,9 +113,8 @@ class AppTest(TestCase):
114
113
  """
115
114
  from example_app.jobs import ExampleJob
116
115
 
117
- self.assertIn(ExampleJob, registry.get("plugin_jobs", []))
116
+ self.assertIn(ExampleJob.class_path, registry.get("jobs", {}))
118
117
  self.assertEqual(ExampleJob, get_job("example_app.jobs.ExampleJob"))
119
- self.assertIn("example_app.jobs.ExampleJob", app.tasks)
120
118
 
121
119
  def test_git_datasource_contents_registration(self):
122
120
  """
@@ -1765,10 +1765,8 @@ class JobTestCase(
1765
1765
  model = Job
1766
1766
 
1767
1767
  def _get_queryset(self):
1768
- """Don't include hidden Jobs, non-installed Jobs, JobHookReceivers or JobButtonReceivers as they won't appear in the UI by default."""
1769
- return self.model.objects.filter(
1770
- installed=True, hidden=False, is_job_hook_receiver=False, is_job_button_receiver=False
1771
- )
1768
+ """Don't include hidden Jobs or non-installed Jobs, as they won't appear in the UI by default."""
1769
+ return self.model.objects.filter(installed=True, hidden=False)
1772
1770
 
1773
1771
  @classmethod
1774
1772
  def setUpTestData(cls):
nautobot/extras/utils.py CHANGED
@@ -637,7 +637,8 @@ def bulk_delete_with_bulk_change_logging(qs, batch_size=1000):
637
637
  ObjectChange.objects.bulk_create(queued_object_changes)
638
638
  queued_object_changes = []
639
639
  oc = obj.to_objectchange(ObjectChangeActionChoices.ACTION_DELETE)
640
- oc.user = change_context.user
640
+ oc.user = change_context.get_user()
641
+ oc.user_name = oc.user.username
641
642
  oc.request_id = change_context.change_id
642
643
  oc.change_context = change_context.context
643
644
  oc.change_context_detail = change_context.context_detail[:CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL]