nautobot 2.4.0b1__py3-none-any.whl → 2.4.1__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 (601) hide show
  1. nautobot/apps/__init__.py +1 -1
  2. nautobot/apps/api.py +8 -8
  3. nautobot/apps/change_logging.py +2 -2
  4. nautobot/apps/choices.py +4 -4
  5. nautobot/apps/events.py +3 -3
  6. nautobot/apps/factory.py +2 -2
  7. nautobot/apps/filters.py +1 -1
  8. nautobot/apps/forms.py +20 -20
  9. nautobot/apps/graphql.py +2 -2
  10. nautobot/apps/jobs.py +8 -8
  11. nautobot/apps/models.py +19 -19
  12. nautobot/apps/tables.py +1 -1
  13. nautobot/apps/testing.py +10 -10
  14. nautobot/apps/ui.py +2 -2
  15. nautobot/apps/utils.py +7 -7
  16. nautobot/apps/views.py +7 -7
  17. nautobot/circuits/api/serializers.py +1 -0
  18. nautobot/circuits/api/views.py +4 -8
  19. nautobot/circuits/tables.py +2 -1
  20. nautobot/circuits/templates/circuits/circuit_create.html +1 -7
  21. nautobot/circuits/views.py +3 -3
  22. nautobot/cloud/api/views.py +6 -10
  23. nautobot/cloud/models.py +1 -1
  24. nautobot/cloud/views.py +0 -16
  25. nautobot/core/api/constants.py +11 -0
  26. nautobot/core/api/fields.py +5 -5
  27. nautobot/core/api/filter_backends.py +3 -9
  28. nautobot/core/api/schema.py +13 -2
  29. nautobot/core/api/serializers.py +40 -34
  30. nautobot/core/api/views.py +56 -4
  31. nautobot/core/celery/log.py +4 -4
  32. nautobot/core/celery/schedulers.py +2 -2
  33. nautobot/core/choices.py +2 -2
  34. nautobot/core/events/__init__.py +3 -3
  35. nautobot/core/filters.py +67 -35
  36. nautobot/core/forms/__init__.py +19 -19
  37. nautobot/core/forms/fields.py +14 -11
  38. nautobot/core/forms/forms.py +33 -2
  39. nautobot/core/graphql/types.py +1 -1
  40. nautobot/core/jobs/__init__.py +28 -7
  41. nautobot/core/jobs/bulk_actions.py +285 -0
  42. nautobot/core/jobs/cleanup.py +48 -12
  43. nautobot/core/jobs/groups.py +1 -1
  44. nautobot/core/management/commands/validate_models.py +1 -1
  45. nautobot/core/models/__init__.py +3 -1
  46. nautobot/core/models/query_functions.py +2 -2
  47. nautobot/core/models/tree_queries.py +6 -3
  48. nautobot/core/settings.py +29 -2
  49. nautobot/core/settings.yaml +21 -0
  50. nautobot/core/tables.py +79 -61
  51. nautobot/core/templates/about.html +67 -0
  52. nautobot/core/templates/inc/media.html +3 -0
  53. nautobot/core/templates/inc/nav_menu.html +1 -0
  54. nautobot/core/templates/inc/tenancy_form_panel.html +9 -0
  55. nautobot/core/templates/inc/tenant_table_row.html +11 -0
  56. nautobot/core/templates/nautobot_config.py.j2 +13 -0
  57. nautobot/core/templates/search.html +7 -0
  58. nautobot/core/templates/utilities/render_jinja2.html +1 -1
  59. nautobot/core/templates/utilities/templatetags/tag.html +1 -1
  60. nautobot/core/templates/utilities/theme_preview.html +7 -0
  61. nautobot/core/templatetags/helpers.py +11 -2
  62. nautobot/core/testing/__init__.py +8 -8
  63. nautobot/core/testing/api.py +170 -15
  64. nautobot/core/testing/filters.py +45 -10
  65. nautobot/core/testing/forms.py +2 -0
  66. nautobot/core/testing/integration.py +86 -4
  67. nautobot/core/testing/mixins.py +7 -2
  68. nautobot/core/testing/views.py +44 -29
  69. nautobot/core/tests/integration/test_app_home.py +0 -1
  70. nautobot/core/tests/integration/test_app_navbar.py +0 -1
  71. nautobot/core/tests/integration/test_filters.py +0 -2
  72. nautobot/core/tests/integration/test_home.py +0 -1
  73. nautobot/core/tests/integration/test_navbar.py +0 -1
  74. nautobot/core/tests/integration/test_view_authentication.py +1 -0
  75. nautobot/core/tests/runner.py +1 -1
  76. nautobot/core/tests/test_api.py +98 -1
  77. nautobot/core/tests/test_csv.py +25 -3
  78. nautobot/core/tests/test_filters.py +209 -246
  79. nautobot/core/tests/test_forms.py +1 -0
  80. nautobot/core/tests/test_jobs.py +460 -1
  81. nautobot/core/tests/test_models.py +9 -0
  82. nautobot/core/tests/test_settings_schema.py +7 -0
  83. nautobot/core/tests/test_tables.py +100 -0
  84. nautobot/core/tests/test_utils.py +63 -1
  85. nautobot/core/tests/test_views.py +30 -3
  86. nautobot/core/ui/nav.py +1 -0
  87. nautobot/core/ui/object_detail.py +15 -1
  88. nautobot/core/urls.py +11 -0
  89. nautobot/core/utils/lookup.py +11 -8
  90. nautobot/core/utils/querysets.py +64 -0
  91. nautobot/core/utils/requests.py +24 -9
  92. nautobot/core/views/__init__.py +42 -0
  93. nautobot/core/views/generic.py +131 -197
  94. nautobot/core/views/mixins.py +126 -38
  95. nautobot/core/views/renderers.py +6 -6
  96. nautobot/dcim/api/serializers.py +56 -64
  97. nautobot/dcim/api/views.py +47 -113
  98. nautobot/dcim/constants.py +6 -13
  99. nautobot/dcim/factory.py +6 -1
  100. nautobot/dcim/filters/__init__.py +31 -2
  101. nautobot/dcim/forms.py +36 -17
  102. nautobot/dcim/graphql/types.py +2 -2
  103. nautobot/dcim/migrations/0067_controllermanageddevicegroup_tenant.py +25 -0
  104. nautobot/dcim/models/__init__.py +1 -1
  105. nautobot/dcim/models/device_component_templates.py +2 -2
  106. nautobot/dcim/models/device_components.py +22 -20
  107. nautobot/dcim/models/devices.py +10 -1
  108. nautobot/dcim/models/locations.py +3 -3
  109. nautobot/dcim/models/power.py +6 -5
  110. nautobot/dcim/models/racks.py +4 -4
  111. nautobot/dcim/tables/__init__.py +3 -3
  112. nautobot/dcim/tables/devices.py +7 -5
  113. nautobot/dcim/tables/devicetypes.py +2 -2
  114. nautobot/dcim/tables/racks.py +1 -1
  115. nautobot/dcim/templates/dcim/controller_create.html +1 -7
  116. nautobot/dcim/templates/dcim/controller_retrieve.html +1 -9
  117. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +2 -0
  118. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +5 -0
  119. nautobot/dcim/templates/dcim/device.html +1 -9
  120. nautobot/dcim/templates/dcim/device_edit.html +36 -37
  121. nautobot/dcim/templates/dcim/location.html +1 -9
  122. nautobot/dcim/templates/dcim/location_edit.html +1 -7
  123. nautobot/dcim/templates/dcim/rack.html +1 -9
  124. nautobot/dcim/templates/dcim/rack_edit.html +1 -7
  125. nautobot/dcim/templates/dcim/rackreservation.html +1 -9
  126. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +1 -9
  127. nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +1 -7
  128. nautobot/dcim/tests/integration/test_controller.py +62 -0
  129. nautobot/dcim/tests/integration/test_controller_managed_device_group.py +71 -0
  130. nautobot/dcim/tests/integration/test_device_bulk_delete.py +189 -0
  131. nautobot/dcim/tests/integration/test_device_bulk_edit.py +181 -0
  132. nautobot/dcim/tests/test_api.py +16 -5
  133. nautobot/dcim/tests/test_filters.py +33 -0
  134. nautobot/dcim/tests/test_forms.py +51 -2
  135. nautobot/dcim/tests/test_graphql.py +52 -0
  136. nautobot/dcim/tests/test_jobs.py +118 -0
  137. nautobot/dcim/tests/test_models.py +52 -9
  138. nautobot/dcim/tests/test_views.py +21 -83
  139. nautobot/dcim/views.py +1 -13
  140. nautobot/extras/api/customfields.py +2 -2
  141. nautobot/extras/api/serializers.py +90 -85
  142. nautobot/extras/api/views.py +22 -27
  143. nautobot/extras/constants.py +2 -0
  144. nautobot/extras/filters/__init__.py +8 -6
  145. nautobot/extras/forms/base.py +2 -2
  146. nautobot/extras/forms/forms.py +139 -31
  147. nautobot/extras/forms/mixins.py +14 -6
  148. nautobot/extras/group_sync.py +3 -3
  149. nautobot/extras/health_checks.py +1 -2
  150. nautobot/extras/jobs.py +85 -18
  151. nautobot/extras/managers.py +3 -1
  152. nautobot/extras/migrations/0018_joblog_data_migration.py +7 -9
  153. nautobot/extras/migrations/0120_job_is_singleton_job_is_singleton_override.py +22 -0
  154. nautobot/extras/migrations/0121_alter_team_contacts.py +17 -0
  155. nautobot/extras/models/__init__.py +1 -1
  156. nautobot/extras/models/contacts.py +1 -1
  157. nautobot/extras/models/customfields.py +12 -11
  158. nautobot/extras/models/groups.py +11 -9
  159. nautobot/extras/models/jobs.py +23 -4
  160. nautobot/extras/models/models.py +2 -2
  161. nautobot/extras/plugins/__init__.py +13 -2
  162. nautobot/extras/plugins/marketplace_manifest.yml +84 -79
  163. nautobot/extras/plugins/tables.py +16 -14
  164. nautobot/extras/plugins/views.py +65 -69
  165. nautobot/extras/registry.py +1 -1
  166. nautobot/extras/secrets/__init__.py +2 -2
  167. nautobot/extras/tables.py +7 -5
  168. nautobot/extras/templates/extras/dynamicgroup.html +1 -9
  169. nautobot/extras/templates/extras/job_detail.html +16 -0
  170. nautobot/extras/templates/extras/job_edit.html +1 -0
  171. nautobot/extras/templates/extras/jobqueue_retrieve.html +1 -9
  172. nautobot/extras/templates/extras/marketplace.html +29 -11
  173. nautobot/extras/templates/extras/plugin_detail.html +32 -15
  174. nautobot/extras/templates/extras/plugins_tiles.html +21 -10
  175. nautobot/extras/templatetags/job_buttons.py +4 -4
  176. nautobot/extras/test_jobs/api_test_job.py +1 -1
  177. nautobot/extras/test_jobs/atomic_transaction.py +2 -2
  178. nautobot/extras/test_jobs/dry_run.py +1 -1
  179. nautobot/extras/test_jobs/fail.py +5 -5
  180. nautobot/extras/test_jobs/file_output.py +1 -1
  181. nautobot/extras/test_jobs/file_upload_fail.py +1 -1
  182. nautobot/extras/test_jobs/file_upload_pass.py +1 -1
  183. nautobot/extras/test_jobs/ipaddress_vars.py +3 -1
  184. nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
  185. nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
  186. nautobot/extras/test_jobs/log_redaction.py +1 -1
  187. nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
  188. nautobot/extras/test_jobs/modify_db.py +1 -1
  189. nautobot/extras/test_jobs/object_var_optional.py +1 -1
  190. nautobot/extras/test_jobs/object_var_required.py +1 -1
  191. nautobot/extras/test_jobs/object_vars.py +1 -1
  192. nautobot/extras/test_jobs/pass.py +3 -3
  193. nautobot/extras/test_jobs/profiling.py +1 -1
  194. nautobot/extras/test_jobs/relative_import.py +3 -3
  195. nautobot/extras/test_jobs/singleton.py +16 -0
  196. nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
  197. nautobot/extras/test_jobs/task_queues.py +1 -1
  198. nautobot/extras/tests/integration/test_plugin_banner.py +0 -2
  199. nautobot/extras/tests/test_api.py +13 -13
  200. nautobot/extras/tests/test_customfields.py +1 -1
  201. nautobot/extras/tests/test_datasources.py +2 -1
  202. nautobot/extras/tests/test_dynamicgroups.py +1 -1
  203. nautobot/extras/tests/test_filters.py +6 -6
  204. nautobot/extras/tests/test_forms.py +33 -1
  205. nautobot/extras/tests/test_jobs.py +178 -32
  206. nautobot/extras/tests/test_models.py +16 -10
  207. nautobot/extras/tests/test_plugins.py +62 -9
  208. nautobot/extras/tests/test_relationships.py +120 -9
  209. nautobot/extras/tests/test_views.py +56 -194
  210. nautobot/extras/utils.py +3 -2
  211. nautobot/extras/views.py +30 -98
  212. nautobot/ipam/api/fields.py +3 -3
  213. nautobot/ipam/api/serializers.py +41 -33
  214. nautobot/ipam/api/views.py +68 -117
  215. nautobot/ipam/factory.py +1 -1
  216. nautobot/ipam/filters.py +3 -2
  217. nautobot/ipam/lookups.py +101 -62
  218. nautobot/ipam/models.py +66 -16
  219. nautobot/ipam/querysets.py +2 -2
  220. nautobot/ipam/tables.py +23 -7
  221. nautobot/ipam/templates/ipam/ipaddress.html +1 -9
  222. nautobot/ipam/templates/ipam/ipaddress_bulk_add.html +1 -7
  223. nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -7
  224. nautobot/ipam/templates/ipam/prefix.html +1 -9
  225. nautobot/ipam/templates/ipam/prefix_edit.html +1 -7
  226. nautobot/ipam/templates/ipam/vlan.html +1 -9
  227. nautobot/ipam/templates/ipam/vlan_edit.html +1 -7
  228. nautobot/ipam/templates/ipam/vrf_edit.html +1 -7
  229. nautobot/ipam/tests/test_api.py +436 -3
  230. nautobot/ipam/tests/test_forms.py +49 -47
  231. nautobot/ipam/tests/test_migrations.py +30 -30
  232. nautobot/ipam/tests/test_models.py +95 -34
  233. nautobot/ipam/tests/test_querysets.py +63 -1
  234. nautobot/ipam/tests/test_views.py +3 -0
  235. nautobot/ipam/utils/__init__.py +36 -6
  236. nautobot/ipam/views.py +61 -87
  237. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -1
  238. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -1
  239. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css +40 -2
  240. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
  241. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
  242. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
  243. nautobot/project-static/docs/404.html +46 -4
  244. nautobot/project-static/docs/apps/index.html +46 -4
  245. nautobot/project-static/docs/apps/nautobot-apps.html +47 -6
  246. nautobot/project-static/docs/assets/_mkdocstrings.css +25 -1
  247. nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js → bundle.88dd0f4e.min.js} +2 -2
  248. nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js.map → bundle.88dd0f4e.min.js.map} +2 -2
  249. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +62 -10
  250. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +59 -7
  251. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +374 -122
  252. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +90 -18
  253. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +95 -21
  254. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +53 -6
  255. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +52 -5
  256. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +79 -17
  257. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +102 -28
  258. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +108 -21
  259. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +131 -38
  260. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +239 -65
  261. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +581 -165
  262. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +109 -36
  263. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +453 -167
  264. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +493 -211
  265. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +60 -8
  266. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +71 -15
  267. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +407 -55
  268. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +620 -205
  269. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +858 -412
  270. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +59 -7
  271. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +448 -186
  272. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +365 -147
  273. nautobot/project-static/docs/development/apps/api/configuration-view.html +46 -4
  274. nautobot/project-static/docs/development/apps/api/database-backend-config.html +46 -4
  275. nautobot/project-static/docs/development/apps/api/models/django-admin.html +46 -4
  276. nautobot/project-static/docs/development/apps/api/models/global-search.html +46 -4
  277. nautobot/project-static/docs/development/apps/api/models/graphql.html +46 -4
  278. nautobot/project-static/docs/development/apps/api/models/index.html +46 -4
  279. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +46 -4
  280. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +46 -4
  281. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +46 -4
  282. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +46 -4
  283. nautobot/project-static/docs/development/apps/api/platform-features/index.html +46 -4
  284. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +46 -4
  285. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +46 -4
  286. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +46 -4
  287. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +46 -4
  288. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +68 -7
  289. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +46 -4
  290. nautobot/project-static/docs/development/apps/api/prometheus.html +46 -4
  291. nautobot/project-static/docs/development/apps/api/setup.html +46 -4
  292. nautobot/project-static/docs/development/apps/api/testing.html +46 -4
  293. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +46 -4
  294. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +46 -4
  295. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +46 -4
  296. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +46 -4
  297. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +46 -4
  298. nautobot/project-static/docs/development/apps/api/views/base-template.html +46 -4
  299. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +46 -4
  300. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +46 -4
  301. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +46 -4
  302. nautobot/project-static/docs/development/apps/api/views/index.html +46 -4
  303. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +46 -4
  304. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +46 -4
  305. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +46 -4
  306. nautobot/project-static/docs/development/apps/api/views/notes.html +46 -4
  307. nautobot/project-static/docs/development/apps/api/views/rest-api.html +52 -6
  308. nautobot/project-static/docs/development/apps/api/views/urls.html +46 -4
  309. nautobot/project-static/docs/development/apps/index.html +46 -4
  310. nautobot/project-static/docs/development/apps/migration/code-updates.html +46 -4
  311. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +46 -4
  312. nautobot/project-static/docs/development/apps/migration/from-v1.html +46 -4
  313. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +46 -4
  314. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +46 -4
  315. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +46 -4
  316. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +46 -4
  317. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +50 -8
  318. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +46 -4
  319. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +211 -14
  320. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +46 -4
  321. nautobot/project-static/docs/development/apps/porting-from-netbox.html +46 -4
  322. nautobot/project-static/docs/development/core/application-registry.html +46 -4
  323. nautobot/project-static/docs/development/core/best-practices.html +46 -4
  324. nautobot/project-static/docs/development/core/bootstrap-ui.html +46 -4
  325. nautobot/project-static/docs/development/core/caching.html +46 -4
  326. nautobot/project-static/docs/development/core/controllers.html +46 -4
  327. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +73 -74
  328. nautobot/project-static/docs/development/core/generic-views.html +46 -4
  329. nautobot/project-static/docs/development/core/getting-started.html +249 -224
  330. nautobot/project-static/docs/development/core/homepage.html +49 -7
  331. nautobot/project-static/docs/development/core/index.html +46 -4
  332. nautobot/project-static/docs/development/core/{local-k8s.html → minikube-dev-environment-for-k8s-jobs.html} +469 -168
  333. nautobot/project-static/docs/development/core/model-checklist.html +56 -12
  334. nautobot/project-static/docs/development/core/model-features.html +46 -4
  335. nautobot/project-static/docs/development/core/natural-keys.html +46 -4
  336. nautobot/project-static/docs/development/core/navigation-menu.html +46 -4
  337. nautobot/project-static/docs/development/core/release-checklist.html +49 -7
  338. nautobot/project-static/docs/development/core/role-internals.html +46 -4
  339. nautobot/project-static/docs/development/core/settings.html +46 -4
  340. nautobot/project-static/docs/development/core/style-guide.html +49 -7
  341. nautobot/project-static/docs/development/core/templates.html +46 -4
  342. nautobot/project-static/docs/development/core/testing.html +46 -4
  343. nautobot/project-static/docs/development/core/ui-component-framework.html +369 -273
  344. nautobot/project-static/docs/development/core/user-preferences.html +46 -4
  345. nautobot/project-static/docs/development/index.html +46 -4
  346. nautobot/project-static/docs/development/jobs/index.html +216 -122
  347. nautobot/project-static/docs/development/jobs/migration/from-v1.html +46 -4
  348. nautobot/project-static/docs/index.html +54 -23
  349. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit.png +0 -0
  350. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit_button.png +0 -0
  351. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_nav.png +0 -0
  352. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_view.png +0 -0
  353. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue.png +0 -0
  354. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_add.png +0 -0
  355. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_config.png +0 -0
  356. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_completed.png +0 -0
  357. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_nav.png +0 -0
  358. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_pending.png +0 -0
  359. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_run_form.png +0 -0
  360. nautobot/project-static/docs/media/development/core/kubernetes/k8s_nautobot_login.png +0 -0
  361. nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_job.png +0 -0
  362. nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_scheduled_job_form.png +0 -0
  363. nautobot/project-static/docs/media/development/core/kubernetes/k8s_scheduled_job_result.png +0 -0
  364. nautobot/project-static/docs/media/development/core/ui-component-framework/buttons-example.png +0 -0
  365. nautobot/project-static/docs/media/development/core/ui-component-framework/cluster-type-before-after-example.png +0 -0
  366. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example_2.png +0 -0
  367. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example-code.png +0 -0
  368. nautobot/project-static/docs/objects.inv +0 -0
  369. nautobot/project-static/docs/overview/application_stack.html +47 -7
  370. nautobot/project-static/docs/overview/design_philosophy.html +46 -4
  371. nautobot/project-static/docs/release-notes/index.html +52 -12
  372. nautobot/project-static/docs/release-notes/version-1.0.html +234 -193
  373. nautobot/project-static/docs/release-notes/version-1.1.html +231 -190
  374. nautobot/project-static/docs/release-notes/version-1.2.html +306 -265
  375. nautobot/project-static/docs/release-notes/version-1.3.html +332 -291
  376. nautobot/project-static/docs/release-notes/version-1.4.html +417 -377
  377. nautobot/project-static/docs/release-notes/version-1.5.html +605 -566
  378. nautobot/project-static/docs/release-notes/version-1.6.html +904 -447
  379. nautobot/project-static/docs/release-notes/version-2.0.html +528 -489
  380. nautobot/project-static/docs/release-notes/version-2.1.html +363 -324
  381. nautobot/project-static/docs/release-notes/version-2.2.html +356 -317
  382. nautobot/project-static/docs/release-notes/version-2.3.html +997 -352
  383. nautobot/project-static/docs/release-notes/version-2.4.html +525 -101
  384. nautobot/project-static/docs/requirements.txt +2 -2
  385. nautobot/project-static/docs/search/search_index.json +1 -1
  386. nautobot/project-static/docs/sitemap.xml +295 -287
  387. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  388. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +46 -4
  389. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +46 -4
  390. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +48 -6
  391. nautobot/project-static/docs/user-guide/administration/configuration/index.html +46 -4
  392. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +46 -4
  393. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +110 -8
  394. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +46 -4
  395. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +46 -4
  396. nautobot/project-static/docs/user-guide/administration/guides/docker.html +46 -4
  397. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +46 -4
  398. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +46 -4
  399. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +46 -4
  400. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +46 -4
  401. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +46 -4
  402. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +48 -6
  403. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +46 -4
  404. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +46 -4
  405. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +46 -4
  406. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +66 -8
  407. nautobot/project-static/docs/user-guide/administration/installation/index.html +46 -4
  408. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +47 -5
  409. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +46 -4
  410. nautobot/project-static/docs/user-guide/administration/installation/services.html +46 -4
  411. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +46 -4
  412. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +46 -4
  413. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +46 -4
  414. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +46 -4
  415. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +46 -4
  416. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +46 -4
  417. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +46 -4
  418. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +46 -4
  419. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +46 -4
  420. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +49 -8
  421. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +46 -4
  422. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +46 -4
  423. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +46 -4
  424. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +46 -4
  425. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +46 -4
  426. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +46 -4
  427. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +46 -4
  428. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +46 -4
  429. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +46 -4
  430. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +46 -4
  431. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +46 -4
  432. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +46 -4
  433. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +46 -4
  434. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +46 -4
  435. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +46 -4
  436. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +46 -4
  437. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +46 -4
  438. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +46 -4
  439. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +46 -4
  440. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +46 -4
  441. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +46 -4
  442. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +46 -4
  443. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +46 -4
  444. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +46 -4
  445. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +46 -4
  446. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +46 -4
  447. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +46 -4
  448. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +46 -4
  449. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +46 -4
  450. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +46 -4
  451. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +46 -4
  452. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +46 -4
  453. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +46 -4
  454. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +46 -4
  455. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +46 -4
  456. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +46 -4
  457. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +46 -4
  458. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +46 -4
  459. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +46 -4
  460. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +46 -4
  461. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +46 -4
  462. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +46 -4
  463. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +46 -4
  464. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +46 -4
  465. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +46 -4
  466. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +46 -4
  467. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +46 -4
  468. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +46 -4
  469. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +46 -4
  470. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +46 -4
  471. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +46 -4
  472. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +46 -4
  473. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +46 -4
  474. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +46 -4
  475. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +46 -4
  476. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +46 -4
  477. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +46 -4
  478. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +50 -12
  479. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +46 -4
  480. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +46 -4
  481. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +46 -4
  482. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +46 -4
  483. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +46 -4
  484. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +46 -4
  485. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +46 -4
  486. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +46 -4
  487. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +46 -4
  488. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +46 -4
  489. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +46 -4
  490. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +46 -4
  491. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +49 -7
  492. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +46 -4
  493. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +46 -4
  494. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +46 -4
  495. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +46 -4
  496. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +46 -4
  497. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +46 -4
  498. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +46 -4
  499. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +46 -4
  500. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +46 -4
  501. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +46 -4
  502. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +46 -4
  503. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +46 -4
  504. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +46 -4
  505. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +46 -4
  506. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +46 -4
  507. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +46 -4
  508. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +46 -4
  509. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +46 -4
  510. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +46 -4
  511. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +46 -4
  512. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +46 -4
  513. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +46 -4
  514. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +51 -7
  515. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +46 -4
  516. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/central-mode.png +0 -0
  517. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-add.png +0 -0
  518. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-1.png +0 -0
  519. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-2.png +0 -0
  520. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-add.png +0 -0
  521. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-create.png +0 -0
  522. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-add.png +0 -0
  523. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-create.png +0 -0
  524. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-add.png +0 -0
  525. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-1.png +0 -0
  526. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-2.png +0 -0
  527. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-add.png +0 -0
  528. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-create.png +0 -0
  529. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +46 -4
  530. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +46 -4
  531. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +49 -7
  532. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +9444 -0
  533. nautobot/project-static/docs/user-guide/index.html +46 -4
  534. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +46 -4
  535. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +50 -8
  536. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +46 -4
  537. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +46 -4
  538. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +46 -4
  539. nautobot/project-static/docs/user-guide/platform-functionality/events.html +46 -4
  540. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +46 -4
  541. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +46 -4
  542. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +46 -4
  543. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +46 -4
  544. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +46 -4
  545. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +46 -4
  546. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +50 -7
  547. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +46 -4
  548. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +49 -7
  549. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +46 -4
  550. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +46 -4
  551. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +9722 -0
  552. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +46 -4
  553. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +46 -4
  554. nautobot/project-static/docs/user-guide/platform-functionality/note.html +46 -4
  555. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +46 -4
  556. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +47 -5
  557. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +46 -4
  558. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +46 -4
  559. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +94 -25
  560. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +74 -5
  561. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +46 -4
  562. nautobot/project-static/docs/user-guide/platform-functionality/role.html +46 -4
  563. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +46 -4
  564. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +46 -4
  565. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +46 -4
  566. nautobot/project-static/docs/user-guide/platform-functionality/status.html +46 -4
  567. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +46 -4
  568. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +46 -4
  569. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +46 -4
  570. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +46 -4
  571. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +46 -4
  572. nautobot/project-static/js/forms.js +1 -1
  573. nautobot/tenancy/api/views.py +9 -13
  574. nautobot/tenancy/views.py +4 -2
  575. nautobot/users/admin.py +1 -1
  576. nautobot/users/api/serializers.py +5 -4
  577. nautobot/users/api/views.py +3 -3
  578. nautobot/virtualization/api/serializers.py +4 -4
  579. nautobot/virtualization/api/views.py +5 -24
  580. nautobot/virtualization/filters.py +20 -3
  581. nautobot/virtualization/models.py +1 -1
  582. nautobot/virtualization/tables.py +2 -2
  583. nautobot/virtualization/templates/virtualization/cluster_edit.html +1 -7
  584. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -9
  585. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -8
  586. nautobot/virtualization/tests/test_filters.py +17 -0
  587. nautobot/wireless/filters.py +2 -2
  588. nautobot/wireless/forms.py +1 -1
  589. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +1 -9
  590. nautobot/wireless/tests/integration/__init__.py +0 -0
  591. nautobot/wireless/tests/integration/test_radio_profile.py +42 -0
  592. nautobot/wireless/tests/test_filters.py +29 -1
  593. nautobot/wireless/tests/test_views.py +22 -1
  594. nautobot/wireless/views.py +0 -10
  595. {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/METADATA +6 -6
  596. {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/RECORD +600 -550
  597. {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/WHEEL +1 -1
  598. nautobot/core/fixtures/user-data.json +0 -59
  599. {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/LICENSE.txt +0 -0
  600. {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/NOTICE +0 -0
  601. {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/entry_points.txt +0 -0
@@ -18,7 +18,7 @@
18
18
 
19
19
 
20
20
  <link rel="icon" href="../../assets/favicon.ico">
21
- <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.46">
21
+ <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.49">
22
22
 
23
23
 
24
24
 
@@ -2112,6 +2112,27 @@
2112
2112
 
2113
2113
 
2114
2114
 
2115
+
2116
+
2117
+
2118
+
2119
+
2120
+
2121
+ <li class="md-nav__item">
2122
+ <a href="../../user-guide/feature-guides/wireless-networks-and-controllers.html" class="md-nav__link">
2123
+
2124
+
2125
+ <span class="md-ellipsis">
2126
+ Wireless Networks and Controllers
2127
+ </span>
2128
+
2129
+
2130
+ </a>
2131
+ </li>
2132
+
2133
+
2134
+
2135
+
2115
2136
  </ul>
2116
2137
  </nav>
2117
2138
 
@@ -5131,6 +5152,27 @@
5131
5152
 
5132
5153
 
5133
5154
 
5155
+ <li class="md-nav__item">
5156
+ <a href="../../user-guide/platform-functionality/jobs/kubernetes-job-support.html" class="md-nav__link">
5157
+
5158
+
5159
+ <span class="md-ellipsis">
5160
+ Kubernetes Job Support
5161
+ </span>
5162
+
5163
+
5164
+ </a>
5165
+ </li>
5166
+
5167
+
5168
+
5169
+
5170
+
5171
+
5172
+
5173
+
5174
+
5175
+
5134
5176
  <li class="md-nav__item">
5135
5177
  <a href="../../user-guide/platform-functionality/jobs/jobbutton.html" class="md-nav__link">
5136
5178
 
@@ -8062,11 +8104,11 @@
8062
8104
 
8063
8105
 
8064
8106
  <li class="md-nav__item">
8065
- <a href="../core/local-k8s.html" class="md-nav__link">
8107
+ <a href="../core/minikube-dev-environment-for-k8s-jobs.html" class="md-nav__link">
8066
8108
 
8067
8109
 
8068
8110
  <span class="md-ellipsis">
8069
- Local Kubernetes Cluster
8111
+ Minikube Dev Environment for K8s Jobs
8070
8112
  </span>
8071
8113
 
8072
8114
 
@@ -9010,6 +9052,15 @@
9010
9052
  <nav class="md-nav" aria-label="Writing Jobs">
9011
9053
  <ul class="md-nav__list">
9012
9054
 
9055
+ <li class="md-nav__item">
9056
+ <a href="#introduction-to-writing-jobs" class="md-nav__link">
9057
+ <span class="md-ellipsis">
9058
+ Introduction to Writing Jobs
9059
+ </span>
9060
+ </a>
9061
+
9062
+ </li>
9063
+
9013
9064
  <li class="md-nav__item">
9014
9065
  <a href="#job-registration" class="md-nav__link">
9015
9066
  <span class="md-ellipsis">
@@ -9147,6 +9198,15 @@
9147
9198
  </span>
9148
9199
  </a>
9149
9200
 
9201
+ </li>
9202
+
9203
+ <li class="md-nav__item">
9204
+ <a href="#is_singleton" class="md-nav__link">
9205
+ <span class="md-ellipsis">
9206
+ is_singleton
9207
+ </span>
9208
+ </a>
9209
+
9150
9210
  </li>
9151
9211
 
9152
9212
  <li class="md-nav__item">
@@ -9471,11 +9531,11 @@
9471
9531
  <li class="md-nav__item">
9472
9532
  <a href="#debugging-job-performance" class="md-nav__link">
9473
9533
  <span class="md-ellipsis">
9474
- Debugging job performance
9534
+ Debugging Job Performance
9475
9535
  </span>
9476
9536
  </a>
9477
9537
 
9478
- <nav class="md-nav" aria-label="Debugging job performance">
9538
+ <nav class="md-nav" aria-label="Debugging Job Performance">
9479
9539
  <ul class="md-nav__list">
9480
9540
 
9481
9541
  <li class="md-nav__item">
@@ -9502,6 +9562,15 @@
9502
9562
  <nav class="md-nav" aria-label="Example Jobs">
9503
9563
  <ul class="md-nav__list">
9504
9564
 
9565
+ <li class="md-nav__item">
9566
+ <a href="#example-everything-job" class="md-nav__link">
9567
+ <span class="md-ellipsis">
9568
+ Example "Everything" Job
9569
+ </span>
9570
+ </a>
9571
+
9572
+ </li>
9573
+
9505
9574
  <li class="md-nav__item">
9506
9575
  <a href="#creating-objects-for-a-planned-location" class="md-nav__link">
9507
9576
  <span class="md-ellipsis">
@@ -9620,30 +9689,24 @@
9620
9689
 
9621
9690
  <h1 id="jobs">Jobs<a class="headerlink" href="#jobs" title="Permanent link">&para;</a></h1>
9622
9691
  <p>Familiarity with the basic concepts of <a href="../../user-guide/platform-functionality/jobs/index.html">Jobs</a>, especially the distinction between Job classes (Python code) and Job records (Nautobot database records), is recommended before authoring your first Job.</p>
9623
- <div class="admonition tip">
9624
- <p class="admonition-title">Tip</p>
9692
+ <details class="tip">
9693
+ <summary>More about Job class source code loading</summary>
9625
9694
  <p>From a development standpoint, it's especially important to understand that the Job database record never stores the Job class code. It only describes the <strong>existence</strong> of a Job class. The actual Job class source code is loaded into memory only.</p>
9626
- </div>
9627
- <div class="admonition info">
9628
- <p class="admonition-title">Info</p>
9629
9695
  <p>As an implementation detail in Nautobot 2.2.3 and later, all known Job <strong>classes</strong> are cached in the <a href="../core/application-registry.html#jobs">application registry</a>, which is refreshed at various times including Nautobot application startup and immediately prior to actually executing any given Job by a worker. This implementation detail should not be relied on directly; instead you should always use the <code>get_job()</code> and/or <code>get_jobs()</code> APIs to obtain a Job class when needed.</p>
9630
- </div>
9631
- <h2 id="migrating-jobs-from-v1-to-v2">Migrating Jobs from v1 to v2<a class="headerlink" href="#migrating-jobs-from-v1-to-v2" title="Permanent link">&para;</a></h2>
9632
- <details class="version-changed">
9633
- <summary>Changed in version 2.0.0</summary>
9634
- <p>See <a href="migration/from-v1.html">Migrating Jobs From Nautobot v1</a> for more information on how to migrate your existing jobs to Nautobot v2.</p>
9635
9696
  </details>
9697
+ <h2 id="migrating-jobs-from-v1-to-v2">Migrating Jobs from v1 to v2<a class="headerlink" href="#migrating-jobs-from-v1-to-v2" title="Permanent link">&para;</a></h2>
9698
+ <p>See <a href="migration/from-v1.html">Migrating Jobs From Nautobot v1</a> for more information on how to migrate your existing Jobs to Nautobot v2.</p>
9636
9699
  <h2 id="installing-jobs">Installing Jobs<a class="headerlink" href="#installing-jobs" title="Permanent link">&para;</a></h2>
9637
9700
  <p>Jobs may be installed in one of three ways:</p>
9638
9701
  <ul>
9639
9702
  <li>Manually installed as files in the <a href="../../user-guide/administration/configuration/settings.html#jobs_root"><code>JOBS_ROOT</code></a> path (which defaults to <code>$NAUTOBOT_ROOT/jobs/</code>).<ul>
9640
- <li>Python files and subdirectories containing Python files will be dynamically loaded at Nautobot startup in order to discover and register available Job classes. For example, a job class named <code>MyJobClass</code> in <code>$JOBS_ROOT/my_job.py</code> will be loaded into Nautobot as <code>my_job.MyJobClass</code>.</li>
9703
+ <li>Python files and subdirectories containing Python files will be dynamically loaded at Nautobot startup in order to discover and register available Job classes. For example, a Job class named <code>MyJobClass</code> in <code>$JOBS_ROOT/my_job.py</code> will be loaded into Nautobot as <code>my_job.MyJobClass</code>.</li>
9641
9704
  <li>All Python modules in this directory are imported by Nautobot and all worker processes at startup. If you have a <code>custom_jobs.py</code> and a <code>custom_jobs_module/__init__.py</code> file in your <code>JOBS_ROOT</code>, both of these files will be imported at startup.</li>
9642
9705
  </ul>
9643
9706
  </li>
9644
9707
  <li>Imported from an external <a href="../../user-guide/platform-functionality/gitrepository.html#jobs">Git repository</a>.<ul>
9645
- <li>Git repositories are loaded into the module namespace of the <code>GitRepository.slug</code> value at startup. For example, if your <code>slug</code> value is <code>my_git_jobs</code> your jobs will be loaded into Python as <code>my_git_jobs.jobs.MyJobClass</code>.</li>
9646
- <li>All git repositories providing jobs must include a <code>__init__.py</code> file at the root of the repository.</li>
9708
+ <li>Git repositories are loaded into the module namespace of the <code>GitRepository.slug</code> value at startup. For example, if your <code>slug</code> value is <code>my_git_jobs</code> your Jobs will be loaded into Python as <code>my_git_jobs.jobs.MyJobClass</code>.</li>
9709
+ <li>All git repositories providing Jobs must include a <code>__init__.py</code> file at the root of the repository.</li>
9647
9710
  <li>Nautobot and all worker processes will import the git repository's <code>jobs</code> module at startup so a <code>jobs.py</code> or <code>jobs/__init__.py</code> file must exist in the root of the repository.</li>
9648
9711
  </ul>
9649
9712
  </li>
@@ -9652,50 +9715,59 @@
9652
9715
  </ul>
9653
9716
  </li>
9654
9717
  </ul>
9655
- <p>In any case, each module holds one or more Job classes (Python classes), each of which serves a specific purpose. The logic of each job can be split into a number of distinct methods, each of which performs a discrete portion of the overall job logic.</p>
9656
- <p>For example, we can create a module named <code>devices.py</code> to hold all of our jobs which pertain to devices in Nautobot. Within that module, we might define several jobs. Each job is defined as a Python class inheriting from <code>nautobot.apps.jobs.Job</code>, which provides the base functionality needed to accept user input and log activity.</p>
9718
+ <p>In any case, each module holds one or more Job classes (Python classes), each of which serves a specific purpose. The logic of each Job can be split into a number of distinct methods, each of which performs a discrete portion of the overall Job logic.</p>
9719
+ <p>For example, we can create a module named <code>device_jobs.py</code> to hold all of our Jobs which pertain to devices in Nautobot. Within that module, we might define several Jobs. Each Job is defined as a Python class inheriting from <code>nautobot.apps.jobs.Job</code>, which provides the base functionality needed to accept user input and log activity.</p>
9657
9720
  <details class="version-changed">
9658
- <summary>Changed in version 2.0.0</summary>
9659
- <p>All job classes that are intended to be runnable must now be registered by a call to <code>nautobot.apps.jobs.register_jobs()</code> on module import. This allows for a module to, if desired, define "abstract" base Job classes that are defined in code but are not registered (and therefore are not runnable in Nautobot). The <code>register_jobs</code> method accepts one or more job classes as arguments.</p>
9721
+ <summary>Changed in version 2.0.0 — <code>register_jobs()</code> must be called</summary>
9722
+ <p>All Job classes that are intended to be runnable must now be registered by a call to <code>nautobot.apps.jobs.register_jobs()</code> on module import. This allows for a module to, if desired, define "abstract" base Job classes that are defined in code but are not registered (and therefore are not runnable in Nautobot). The <code>register_jobs</code> method accepts one or more Job classes as arguments.</p>
9660
9723
  </details>
9661
9724
  <h2 id="writing-jobs">Writing Jobs<a class="headerlink" href="#writing-jobs" title="Permanent link">&para;</a></h2>
9725
+ <h3 id="introduction-to-writing-jobs">Introduction to Writing Jobs<a class="headerlink" href="#introduction-to-writing-jobs" title="Permanent link">&para;</a></h3>
9662
9726
  <div class="admonition warning">
9663
9727
  <p class="admonition-title">Warning</p>
9664
- <p>Make sure your Job subclasses inherit from <code>nautobot.apps.Job</code> and <em>not</em> from <code>nautobot.extras.models.Job</code> instead; if you mistakenly inherit from the latter, Django will think you want to define a new database model.</p>
9728
+ <p>Make sure your Job subclasses inherit from <code>nautobot.apps.jobs.Job</code> and <em>not</em> from <code>nautobot.extras.models.Job</code> instead; if you mistakenly inherit from the latter, Django will think you want to define a new database model!</p>
9665
9729
  </div>
9666
- <div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">register_jobs</span>
9730
+ <p>The most basic structure of a Python file providing one or more Jobs is as follows:</p>
9731
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps</span> <span class="kn">import</span> <span class="n">jobs</span>
9667
9732
  <a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>
9668
- <a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="k">class</span> <span class="nc">CreateDevices</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
9669
- <a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> <span class="o">...</span>
9670
- <a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a>
9671
- <a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a><span class="k">class</span> <span class="nc">DeviceConnectionsReport</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
9672
- <a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="o">...</span>
9673
- <a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a>
9674
- <a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a><span class="k">class</span> <span class="nc">DeviceIPsReport</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
9675
- <a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a> <span class="o">...</span>
9676
- <a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a>
9677
- <a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">CreateDevices</span><span class="p">,</span> <span class="n">DeviceConnectionsReport</span><span class="p">,</span> <span class="n">DeviceIPsReport</span><span class="p">)</span>
9733
+ <a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;My Group Of Jobs&quot;</span> <span class="c1"># optional, but recommended to define a grouping name</span>
9734
+ <a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a>
9735
+ <a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="k">class</span> <span class="nc">MyNewJob</span><span class="p">(</span><span class="n">jobs</span><span class="o">.</span><span class="n">Job</span><span class="p">):</span>
9736
+ <a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
9737
+ <a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="c1"># metadata attributes go here</span>
9738
+ <a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;My New Job&quot;</span>
9739
+ <a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a> <span class="c1"># ... etc.</span>
9740
+ <a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a>
9741
+ <a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a> <span class="c1"># input variable definitions go here</span>
9742
+ <a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a> <span class="n">some_text_input</span> <span class="o">=</span> <span class="n">jobs</span><span class="o">.</span><span class="n">StringVar</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
9743
+ <a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a> <span class="c1"># ... etc.</span>
9744
+ <a id="__codelineno-0-14" name="__codelineno-0-14" href="#__codelineno-0-14"></a>
9745
+ <a id="__codelineno-0-15" name="__codelineno-0-15" href="#__codelineno-0-15"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">some_text_input</span><span class="p">,</span> <span class="o">...</span><span class="p">):</span>
9746
+ <a id="__codelineno-0-16" name="__codelineno-0-16" href="#__codelineno-0-16"></a> <span class="c1"># code to execute when the Job is run goes here</span>
9747
+ <a id="__codelineno-0-17" name="__codelineno-0-17" href="#__codelineno-0-17"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;some_text_input: </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">some_text_input</span><span class="p">)</span>
9748
+ <a id="__codelineno-0-18" name="__codelineno-0-18" href="#__codelineno-0-18"></a>
9749
+ <a id="__codelineno-0-19" name="__codelineno-0-19" href="#__codelineno-0-19"></a><span class="n">jobs</span><span class="o">.</span><span class="n">register_jobs</span><span class="p">(</span><span class="n">MyNewJob</span><span class="p">)</span>
9678
9750
  </code></pre></div>
9679
- <p>Each job class will implement some or all of the following components:</p>
9751
+ <p>Each Job class will implement some or all of the following components:</p>
9680
9752
  <ul>
9681
- <li>Module and class attributes, providing for default behavior, documentation and discoverability</li>
9682
- <li>a set of variables for user input via the Nautobot UI (if your job requires any user inputs)</li>
9683
- <li>a <code>run()</code> method, which is the only required attribute on a Job class and receives the user input values, if any, as keyword arguments.</li>
9684
- <li>Optionally, any of the special methods <code>before_start()</code>, <code>on_success()</code>, <code>on_failure()</code>, and/or <code>after_return()</code> (more on these later).</li>
9753
+ <li><a href="#module-metadata-attributes">Module</a> and class <a href="#class-metadata-attributes">metadata attributes</a>, configuring the system-level behavior of the Job and providing for documentation and discoverability by users.</li>
9754
+ <li>A set of <a href="#variables">variables</a> for user input via the Nautobot UI or API.</li>
9755
+ <li>The <a href="#the-run-method"><code>run()</code> method</a>, which is the only <strong>required</strong> attribute on a Job class and receives the user input values as keyword arguments.</li>
9756
+ <li>Optionally, any of the special methods <a href="#the-before_start-method"><code>before_start()</code></a>, <a href="#the-on_success-method"><code>on_success()</code></a>, <a href="#the-on_failure-method"><code>on_failure()</code></a>, and/or <a href="#the-after_return-method"><code>after_return()</code></a>.</li>
9685
9757
  </ul>
9686
- <p>It's important to understand that jobs execute on the server asynchronously as background tasks; they log messages and report their status to the database by updating <a href="../../user-guide/platform-functionality/jobs/models.html#job-results"><code>JobResult</code></a> records and creating <a href="../../user-guide/platform-functionality/jobs/models.html#job-log-entry"><code>JobLogEntry</code></a> records.</p>
9758
+ <p>It's important to understand that Jobs execute on the server asynchronously as background tasks; they log messages and report their status to the database by updating <a href="../../user-guide/platform-functionality/jobs/models.html#job-results"><code>JobResult</code></a> records and creating <a href="../../user-guide/platform-functionality/jobs/models.html#job-log-entry"><code>JobLogEntry</code></a> records.</p>
9687
9759
  <div class="admonition note">
9688
- <p class="admonition-title">Note</p>
9760
+ <p class="admonition-title">About detection of changes while developing a Job</p>
9689
9761
  <p>When actively developing a Job utilizing a development environment it's important to understand that the "automatically reload when code changes are detected" debugging functionality provided by <code>nautobot-server runserver</code> does <strong>not</strong> automatically restart the Celery <code>worker</code> process when code changes are made; therefore, it is required to restart the <code>worker</code> after each update to your Job source code or else it will continue to run the version of the Job code that was present when it first started. In the Nautobot core development environment, we use <code>watchmedo auto-restart</code> as a helper tool to auto-restart the workers as well on code changes; you may wish to configure your local development environment similarly for convenience.</p>
9690
9762
  <p>Additionally, as of Nautobot 1.3, the Job database records corresponding to installed Jobs are <em>not</em> automatically refreshed when the development server auto-restarts. If you make changes to any of the class and module metadata attributes described in the following sections, the database will be refreshed to reflect these changes only after running <code>nautobot-server migrate</code> or <code>nautobot-server post_upgrade</code> (recommended) or if you manually edit a Job database record to force it to be refreshed. The exception here is Git-repository-provided Jobs; resyncing the Git repository through Nautobot will also trigger a refresh of the Job records corresponding to this repository's contents.</p>
9691
9763
  </div>
9692
9764
  <h3 id="job-registration">Job Registration<a class="headerlink" href="#job-registration" title="Permanent link">&para;</a></h3>
9693
9765
  <details class="version-changed">
9694
- <summary>Changed in version 2.0.0</summary>
9766
+ <summary>Changed in version 2.0.0 — <code>register_jobs()</code> is now required</summary>
9695
9767
  </details>
9696
- <p>All Job classes, including <code>JobHookReceiver</code> and <code>JobButtonReceiver</code> classes must be registered at <strong>import time</strong> using the <code>nautobot.apps.jobs.register_jobs</code> method. This method accepts one or more job classes as arguments. You must account for how your jobs are imported when deciding where to call this method.</p>
9768
+ <p>All Job classes, including <code>JobHookReceiver</code> and <code>JobButtonReceiver</code> classes must be registered at <strong>import time</strong> using the <code>nautobot.apps.jobs.register_jobs</code> method. This method accepts one or more Job classes as arguments. You must account for how your Jobs are imported when deciding where to call this method.</p>
9697
9769
  <h4 id="registering-jobs-in-jobs_root-or-git-repositories">Registering Jobs in <code>JOBS_ROOT</code> or Git Repositories<a class="headerlink" href="#registering-jobs-in-jobs_root-or-git-repositories" title="Permanent link">&para;</a></h4>
9698
- <p>Only top level module names within <code>JOBS_ROOT</code> are imported by Nautobot at runtime. This means that if you're using submodules, you need to ensure that your jobs are either registered in your top level <code>__init__.py</code> or that this file imports your submodules where the jobs are registered:</p>
9770
+ <p>Only top level module names within <code>JOBS_ROOT</code> are imported by Nautobot at runtime. This means that if you're using submodules, you need to ensure that your Jobs are either registered in your top level <code>__init__.py</code> or that this file imports your submodules where the Jobs are registered:</p>
9699
9771
  <div class="highlight"><span class="filename">$JOBS_ROOT/my_jobs/__init__.py</span><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">my_job_module</span>
9700
9772
  </code></pre></div>
9701
9773
  <div class="highlight"><span class="filename">$JOBS_ROOT/my_jobs/my_job_module.py</span><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">register_jobs</span>
@@ -9705,12 +9777,12 @@
9705
9777
  <a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a>
9706
9778
  <a id="__codelineno-2-6" name="__codelineno-2-6" href="#__codelineno-2-6"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">MyJob</span><span class="p">)</span>
9707
9779
  </code></pre></div>
9708
- <p>Similarly, only the <code>jobs</code> module is loaded from Git repositories. If you're using submodules, you need to ensure that your jobs are either registered in the repository's <code>jobs/__init__.py</code> or that this file imports your submodules where the jobs are registered.</p>
9709
- <p>If not using submodules, you should register your job in the file where your job is defined.</p>
9710
- <p>Examples of the different directory structures when registering jobs in Git repositories:</p>
9780
+ <p>Similarly, only the <code>jobs</code> module is loaded from Git repositories. If you're using submodules, you need to ensure that your Jobs are either registered in the repository's <code>jobs/__init__.py</code> or that this file imports your submodules where the Jobs are registered.</p>
9781
+ <p>If not using submodules, you should register your Job in the file where it is defined.</p>
9782
+ <p>Examples of the different directory structures when registering Jobs in Git repositories:</p>
9711
9783
  <div class="admonition note">
9712
- <p class="admonition-title">Note</p>
9713
- <p>Take note of the <code>__init__.py</code> at the root of the repository. This is required to register jobs in a Git repository.</p>
9784
+ <p class="admonition-title"><code>__init__.py</code></p>
9785
+ <p>Take note of the <code>__init__.py</code> at the root of the repository. This is required to register Jobs in a Git repository.</p>
9714
9786
  </div>
9715
9787
  <div class="highlight"><span class="filename">jobs.py</span><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a>.
9716
9788
  <a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a>├── __init__.py
@@ -9723,14 +9795,14 @@
9723
9795
  <a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a> └── my_job_module.py
9724
9796
  </code></pre></div>
9725
9797
  <h4 id="registering-jobs-in-an-app">Registering Jobs in an App<a class="headerlink" href="#registering-jobs-in-an-app" title="Permanent link">&para;</a></h4>
9726
- <p>Apps should register jobs in the module defined in their <a href="../apps/api/nautobot-app-config.html#nautobotappconfig-code-location-attributes"><code>NautobotAppConfig.jobs</code></a> property. This defaults to the <code>jobs</code> module of the App.</p>
9798
+ <p>Apps should register Jobs in the module defined in their <a href="../apps/api/nautobot-app-config.html#nautobotappconfig-code-location-attributes"><code>NautobotAppConfig.jobs</code></a> property. This defaults to the <code>jobs</code> module of the App.</p>
9727
9799
  <h3 id="reserved-attribute-names">Reserved Attribute Names<a class="headerlink" href="#reserved-attribute-names" title="Permanent link">&para;</a></h3>
9728
9800
  <p>There are many attributes and methods of the Job class that serve as reserved names. You must be careful when implementing custom methods or defining the user input <a href="#variables">variables</a> for your Job that you do not inadvertently "step on" one of these reserved attributes causing unexpected behavior or errors.</p>
9729
9801
  <div class="admonition example">
9730
9802
  <p class="admonition-title">Example</p>
9731
9803
  <p>One classic pitfall here is the the reserved <code>name</code> metadata attribute - if you attempt to redefine <code>name</code> as a user input variable, your Job will not work.</p>
9732
9804
  </div>
9733
- <p>As of Nautobot 2.2.3, the current list of reserved names (not including low-level Python built-ins such as <code>__dict__</code> or <code>__str__</code> includes:</p>
9805
+ <p>As of Nautobot 2.4.0, the current list of reserved names (not including low-level Python built-ins such as <code>__dict__</code> or <code>__str__</code> includes:</p>
9734
9806
  <table>
9735
9807
  <thead>
9736
9808
  <tr>
@@ -9816,6 +9888,10 @@
9816
9888
  <td><a href="#hidden">metadata property</a></td>
9817
9889
  </tr>
9818
9890
  <tr>
9891
+ <td><code>is_singleton</code></td>
9892
+ <td><a href="#is_singleton">metadata property</a></td>
9893
+ </tr>
9894
+ <tr>
9819
9895
  <td><code>job_model</code></td>
9820
9896
  <td>property</td>
9821
9897
  </tr>
@@ -9903,21 +9979,21 @@
9903
9979
  </table>
9904
9980
  <h3 id="module-metadata-attributes">Module Metadata Attributes<a class="headerlink" href="#module-metadata-attributes" title="Permanent link">&para;</a></h3>
9905
9981
  <h4 id="name-grouping"><code>name</code> (Grouping)<a class="headerlink" href="#name-grouping" title="Permanent link">&para;</a></h4>
9906
- <p>You can define a global constant called <code>name</code> within a job module (the Python file which contains one or more job classes) to set the default grouping under which jobs in this module will be displayed in the Nautobot UI. If this value is not defined, the module's file name will be used. This "grouping" value may also be defined or overridden when editing Job records in the database.</p>
9982
+ <p>You can define a global constant called <code>name</code> within a job module (the Python file which contains one or more Job classes) to set the default grouping under which the Jobs in this module will be displayed in the Nautobot UI. If this value is not defined, the module's file name will be used. This "grouping" value may also be defined or overridden when editing Job records in the database.</p>
9907
9983
  <div class="admonition note">
9908
9984
  <p class="admonition-title">Note</p>
9909
9985
  <p>In some UI elements and API endpoints, the module file name is displayed in addition to or in place of this attribute, so even if defining this attribute, you should still choose an appropriately explanatory file name as well.</p>
9910
9986
  </div>
9911
9987
  <h3 id="class-metadata-attributes">Class Metadata Attributes<a class="headerlink" href="#class-metadata-attributes" title="Permanent link">&para;</a></h3>
9912
- <p>Job-specific attributes may be defined under a class named <code>Meta</code> within each job class you implement. All of these are optional, but encouraged.</p>
9988
+ <p>Job-specific attributes may be defined under a class named <code>Meta</code> within each Job class you implement. All of these are optional, but encouraged.</p>
9913
9989
  <h4 id="name"><code>name</code><a class="headerlink" href="#name" title="Permanent link">&para;</a></h4>
9914
- <p>This is the human-friendly name of your job, as will be displayed in the Nautobot UI. If not set, the class name will be used.</p>
9990
+ <p>This is the human-friendly name of your Job, as will be displayed in the Nautobot UI. If not set, the class name will be used.</p>
9915
9991
  <div class="admonition note">
9916
9992
  <p class="admonition-title">Note</p>
9917
9993
  <p>In some UI elements and API endpoints, the class name is displayed in addition to or in place of this attribute, so even if defining this attribute, you should still choose an appropriately explanatory class name as well.</p>
9918
9994
  </div>
9919
9995
  <h4 id="description"><code>description</code><a class="headerlink" href="#description" title="Permanent link">&para;</a></h4>
9920
- <p>An optional human-friendly description of what this job does.
9996
+ <p>An optional human-friendly description of what this Job does.
9921
9997
  This can accept either plain text, Markdown-formatted text, or <a href="../../user-guide/platform-functionality/template-filters.html#render_markdown">a limited subset of HTML</a>. It can also be multiple lines:</p>
9922
9998
  <div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="k">class</span> <span class="nc">ExampleJob</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
9923
9999
  <a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a> <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
@@ -9929,63 +10005,79 @@ This can accept either plain text, Markdown-formatted text, or <a href="../../us
9929
10005
  <a id="__codelineno-5-8" name="__codelineno-5-8" href="#__codelineno-5-8"></a><span class="s2"> 3. It&#39;s a floor wax *and* a dessert topping</span>
9930
10006
  <a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a><span class="s2"> &quot;&quot;&quot;</span>
9931
10007
  </code></pre></div>
9932
- <p>If you code a multi-line description, the first line only will be used in the description column of the jobs list, while the full description will be rendered in the job detail view, submission, approval, and results pages.</p>
10008
+ <p>If you code a multi-line description, the first line only will be used in the description column of the Jobs list, while the full description will be rendered in the Job detail view, submission, approval, and results pages.</p>
9933
10009
  <h4 id="approval_required"><code>approval_required</code><a class="headerlink" href="#approval_required" title="Permanent link">&para;</a></h4>
9934
10010
  <p>Default: <code>False</code></p>
9935
- <p>A boolean that will mark this job as requiring approval from another user to be run. For more details on approvals, <a href="../../user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html">please refer to the section on scheduling and approvals</a>.</p>
10011
+ <p>A boolean that will mark this Job as requiring approval from another user to be run. For more details on approvals, <a href="../../user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html">please refer to the section on scheduling and approvals</a>.</p>
9936
10012
  <h4 id="dryrun_default"><code>dryrun_default</code><a class="headerlink" href="#dryrun_default" title="Permanent link">&para;</a></h4>
9937
10013
  <details class="version-changed">
9938
- <summary>Changed in version 2.0.0</summary>
9939
- <p>The <code>commit_default</code> field was renamed to <code>dryrun_default</code> and the default value was changed from <code>True</code> to <code>False</code>. The <code>commit</code> functionality that provided an automatic rollback of database changes if the job failed was removed. The <code>dryrun</code> functionality was added to provide a way to bypass job approval if a job implements a <a href="#dryrunvar"><code>DryRunVar</code></a>.</p>
10014
+ <summary>Changed in version 2.0.0 — Replacement for <code>commit_default</code></summary>
10015
+ <p>The <code>commit_default</code> field was renamed to <code>dryrun_default</code> and the default value was changed from <code>True</code> to <code>False</code>. The <code>commit</code> functionality that provided an automatic rollback of database changes if the Job failed was removed.</p>
9940
10016
  </details>
9941
10017
  <p>Default: <code>False</code></p>
9942
- <p>The checkbox to enable dryrun when executing a job is unchecked by default in the Nautobot UI. You can set <code>dryrun_default</code> to <code>True</code> under the <code>Meta</code> class if you want this option to instead be checked by default.</p>
10018
+ <p>If the Job implements a <a href="#dryrunvar"><code>DryRunVar</code></a>, what its default value should be.
10019
+ The checkbox to enable dryrun when executing a Job is unchecked by default in the Nautobot UI. You can set <code>dryrun_default</code> to <code>True</code> under the <code>Meta</code> class if you want this option to instead be checked by default.</p>
9943
10020
  <div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="k">class</span> <span class="nc">MyJob</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
9944
10021
  <a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a> <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
9945
10022
  <a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a> <span class="n">dryrun_default</span> <span class="o">=</span> <span class="kc">True</span>
9946
10023
  </code></pre></div>
9947
10024
  <h4 id="field_order"><code>field_order</code><a class="headerlink" href="#field_order" title="Permanent link">&para;</a></h4>
9948
10025
  <p>Default: <code>[]</code></p>
9949
- <p>A list of strings (field names) representing the order your job <a href="#variables">variables</a> should be rendered as form fields in the job submission UI. If not defined, the variables will be listed in order of their definition in the code. If variables are defined on a parent class and no field order is defined, the parent class variables will appear before the subclass variables.</p>
10026
+ <p>A list of strings (field names) representing the order your Job <a href="#variables">variables</a> should be rendered as form fields in the Job submission UI. If not defined, the variables will be listed in order of their definition in the code. If variables are defined on a parent class and no field order is defined, the parent class variables will appear before the subclass variables.</p>
9950
10027
  <h4 id="has_sensitive_variables"><code>has_sensitive_variables</code><a class="headerlink" href="#has_sensitive_variables" title="Permanent link">&para;</a></h4>
9951
10028
  <details class="version-added">
9952
10029
  <summary>Added in version 1.3.10</summary>
9953
10030
  </details>
9954
10031
  <p>Default: <code>True</code></p>
9955
- <p>Unless set to False, it prevents the job's input parameters from being saved to the database. This defaults to True so as to protect against inadvertent database exposure of input parameters that may include sensitive data such as passwords or other user credentials. Review whether each job's inputs contain any such variables before setting this to False; if a job <em>does</em> contain sensitive inputs, if possible you should consider whether the job could be re-implemented using Nautobot's <a href="../../user-guide/platform-functionality/secret.html"><code>Secrets</code></a> feature as a way to ensure that the sensitive data is not directly provided as a job variable at all.</p>
9956
- <p>Important notes about jobs with sensitive variables:</p>
10032
+ <p>Unless set to False, it prevents the Job's input parameters from being saved to the database. This defaults to True so as to protect against inadvertent database exposure of input parameters that may include sensitive data such as passwords or other user credentials. Review whether each Job's inputs contain any such variables before setting this to False; if a Job <em>does</em> contain sensitive inputs, if possible you should consider whether the Job could be re-implemented using Nautobot's <a href="../../user-guide/platform-functionality/secret.html"><code>Secrets</code></a> feature as a way to ensure that the sensitive data is not directly provided as a Job variable at all.</p>
10033
+ <p>Important notes about Jobs with sensitive variables:</p>
9957
10034
  <ul>
9958
- <li>Such jobs cannot be scheduled to run in the future or on a recurring schedule (as scheduled jobs must by necessity store their variables in the database for future reference).</li>
9959
- <li>Jobs with sensitive variables cannot be marked as requiring approval (as jobs pending approval must store their variables in the database until approved).</li>
10035
+ <li>Such Jobs cannot be scheduled to run in the future or on a recurring schedule (as Scheduled Jobs must by necessity store their variables in the database for future reference).</li>
10036
+ <li>Jobs with sensitive variables cannot be marked as requiring approval (as Jobs pending approval must store their variables in the database until approved).</li>
9960
10037
  </ul>
9961
10038
  <h4 id="hidden"><code>hidden</code><a class="headerlink" href="#hidden" title="Permanent link">&para;</a></h4>
9962
10039
  <p>Default: <code>False</code></p>
9963
- <p>A Boolean that if set to <code>True</code> prevents the job from being displayed by default in the list of Jobs in the Nautobot UI.</p>
9964
- <p>Since the jobs execution framework is designed to be generic, there may be several technical jobs defined by users which interact with or are invoked by external systems. In such cases, these jobs are not meant to be executed by a human and likely do not make sense to expose to end users for execution, and thus having them exposed in the UI at all is extraneous.</p>
9965
- <p>Important notes about hidden jobs:</p>
10040
+ <p>A Boolean that if set to <code>True</code> prevents the Job from being displayed by default in the list of Jobs in the Nautobot UI.</p>
10041
+ <p>Since the Job execution framework is designed to be generic, there may be several technical Jobs defined by users which interact with or are invoked by external systems. In such cases, these Jobs are not meant to be executed by a human and likely do not make sense to expose to end users for execution, and thus having them exposed in the UI at all is extraneous.</p>
10042
+ <p>Important notes about hidden Jobs:</p>
9966
10043
  <ul>
9967
10044
  <li>This is merely hiding them by default from the web interface. It is NOT a security feature.</li>
9968
- <li>In the Jobs list view it is possible to filter to "Hidden: (no selection)" or even "Hidden: Yes" to list the hidden jobs.</li>
9969
- <li>All Job UI and REST API endpoints still exist for hidden jobs and can be accessed by any user who is aware of their existence.</li>
9970
- <li>Hidden jobs can still be executed through the UI or the REST API given the appropriate URL.</li>
9971
- <li>Results for hidden jobs will still appear in the Job Results list after they are run.</li>
10045
+ <li>In the Jobs list view it is possible to filter to "Hidden: (no selection)" or even "Hidden: Yes" to list the hidden Jobs.</li>
10046
+ <li>All Job UI and REST API endpoints still exist for hidden Jobs and can be accessed by any user who is aware of their existence.</li>
10047
+ <li>Hidden Jobs can still be executed through the UI or the REST API given the appropriate URL.</li>
10048
+ <li>Results for hidden Jobs will still appear in the Job Results list after they are run.</li>
10049
+ </ul>
10050
+ <h4 id="is_singleton"><code>is_singleton</code><a class="headerlink" href="#is_singleton" title="Permanent link">&para;</a></h4>
10051
+ <details class="version-added">
10052
+ <summary>Added in version 2.4.0</summary>
10053
+ </details>
10054
+ <p>Default: <code>False</code>
10055
+ A Boolean that if set to <code>True</code> prevents the job from running twice simultaneously.</p>
10056
+ <p>Any duplicate job instances will error out with a singleton-specific error message.</p>
10057
+ <p>Important notes about singleton jobs:</p>
10058
+ <ul>
10059
+ <li>The singleton functionality is implemented with a Redis key set to timeout either on the hard time out of the job or whenever the job terminates.<ul>
10060
+ <li>Therefore, a restart of Redis will wipe the singleton locks</li>
10061
+ </ul>
10062
+ </li>
10063
+ <li>A checkbox on the job run form makes it possible to force the singleton lock to be overridden. This makes it possible to recover from failure scenarios such as the original singleton job being stopped before it can unset the lock.</li>
9972
10064
  </ul>
9973
10065
  <h4 id="read_only"><code>read_only</code><a class="headerlink" href="#read_only" title="Permanent link">&para;</a></h4>
9974
10066
  <details class="version-added">
9975
10067
  <summary>Added in version 1.1.0</summary>
9976
10068
  </details>
9977
10069
  <details class="version-changed">
9978
- <summary>Changed in version 2.0.0</summary>
9979
- <p>The <code>read_only</code> flag no longer changes the behavior of Nautobot core and is up to the job author to decide whether their job should be considered read only.</p>
10070
+ <summary>Changed in version 2.0.0 — No automatic functionality</summary>
10071
+ <p>The <code>read_only</code> flag no longer changes the behavior of Nautobot core and is up to the Job author to decide whether their Job should be considered read only.</p>
9980
10072
  </details>
9981
10073
  <p>Default: <code>False</code></p>
9982
- <p>A boolean that can be set by the job author to indicate that the job does not make any changes to the environment. What behavior makes each job "read only" is up to the individual job author to decide. Note that user input may still be optionally collected with read-only jobs via job variables, as described below.</p>
10074
+ <p>A boolean that can be set by the Job author to indicate that the Job does not make any changes to the environment. What behavior makes each Job "read only" is up to the individual Job author to decide. Note that user input may still be optionally collected with read-only Jobs via Job variables, as described below.</p>
9983
10075
  <h4 id="soft_time_limit"><code>soft_time_limit</code><a class="headerlink" href="#soft_time_limit" title="Permanent link">&para;</a></h4>
9984
10076
  <details class="version-added">
9985
10077
  <summary>Added in version 1.3.0</summary>
9986
10078
  </details>
9987
- <p>An int or float value, in seconds, which can be used to override the default <a href="../../user-guide/administration/configuration/settings.html#celery_task_soft_time_limit">soft time limit</a> for a job task to complete.</p>
9988
- <p>The <code>celery.exceptions.SoftTimeLimitExceeded</code> exception will be raised when this soft time limit is exceeded. The job task can catch this to clean up before the <a href="../../user-guide/administration/configuration/settings.html#celery_task_time_limit">hard time limit</a> (10 minutes by default) is reached:</p>
10079
+ <p>An int or float value, in seconds, which can be used to override the default <a href="../../user-guide/administration/configuration/settings.html#celery_task_soft_time_limit">soft time limit</a> for a Job task to complete.</p>
10080
+ <p>The <code>celery.exceptions.SoftTimeLimitExceeded</code> exception will be raised when this soft time limit is exceeded. The Job task can catch this to clean up before the <a href="../../user-guide/administration/configuration/settings.html#celery_task_time_limit">hard time limit</a> (10 minutes by default) is reached:</p>
9989
10081
  <div class="highlight"><pre><span></span><code><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="kn">from</span> <span class="nn">celery.exceptions</span> <span class="kn">import</span> <span class="n">SoftTimeLimitExceeded</span>
9990
10082
  <a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span>
9991
10083
  <a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a>
@@ -10008,20 +10100,20 @@ This can accept either plain text, Markdown-formatted text, or <a href="../../us
10008
10100
  <summary>Added in version 1.5.0</summary>
10009
10101
  </details>
10010
10102
  <p>Default: <code>[]</code></p>
10011
- <p>A list of Job Queue names that the job can be routed to. An empty list will default to only allowing the user to select the <a href="../../user-guide/administration/configuration/settings.html#celery_task_default_queue">default Celery queue</a> (<code>default</code> unless changed by an administrator). The queue specified in the job's <code>default_job_queue</code> will be used if a queue is not specified in a job run API call.</p>
10103
+ <p>A list of Job Queue names that the Job can be routed to. An empty list will default to only allowing the user to select the <a href="../../user-guide/administration/configuration/settings.html#celery_task_default_queue">default Celery queue</a> (<code>default</code> unless changed by an administrator). The queue specified in the Job's <code>default_job_queue</code> will be used if a queue is not specified in a Job run API call.</p>
10012
10104
  <details class="version-changed">
10013
10105
  <summary>Changed in version 2.4.0 — Changed default queue selection</summary>
10014
10106
  <p>As a result of the addition of Job Queues, the default queue when running a Job without explicitly selecting a queue is now the job queue specified in the <code>default_job_queue</code> field on the Job model. <code>default_job_queue</code> fields for any existing Job instances are automatically populated with the name of the first entry in <code>task_queues</code> list of the Job class. When <code>task_queues</code> list on the Job class is empty, the corresponding Job instance's <code>default_job_queue</code> will be the job queue with the name provided by <code>settings.CELERY_TASK_DEFAULT_QUEUE</code>. You can also override the initial <code>default_job_queue</code> by setting <code>default_job_queue_override</code> to True and assign the field with a different Job Queue instance.</p>
10015
10107
  </details>
10016
10108
  <div class="admonition note">
10017
10109
  <p class="admonition-title">Note</p>
10018
- <p>A worker must be listening on the requested queue or the job will not run. See the documentation on <a href="../../user-guide/administration/guides/celery-queues.html">task queues</a> for more information.</p>
10110
+ <p>A worker must be listening on the requested queue or the Job will not run. See the documentation on <a href="../../user-guide/administration/guides/celery-queues.html">task queues</a> for more information.</p>
10019
10111
  </div>
10020
10112
  <h4 id="template_name"><code>template_name</code><a class="headerlink" href="#template_name" title="Permanent link">&para;</a></h4>
10021
10113
  <details class="version-added">
10022
10114
  <summary>Added in version 1.4.0</summary>
10023
10115
  </details>
10024
- <p>A path relative to the job source code containing a Django template which provides additional code to customize the Job's submission form. This template should extend the existing job template, <code>extras/job.html</code>, otherwise the base form and functionality may not be available.</p>
10116
+ <p>A path relative to the Job source code containing a Django template which provides additional code to customize the Job's submission form. This template should extend the existing Job template, <code>extras/job.html</code>, otherwise the base form and functionality may not be available.</p>
10025
10117
  <p>A template can provide additional JavaScript, CSS, or even display HTML. A good starting template would be:</p>
10026
10118
  <div class="highlight"><pre><span></span><code><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a>{% extends &#39;extras/job.html&#39; %}
10027
10119
  <a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a>
@@ -10039,7 +10131,7 @@ This can accept either plain text, Markdown-formatted text, or <a href="../../us
10039
10131
  <a id="__codelineno-8-14" name="__codelineno-8-14" href="#__codelineno-8-14"></a>{% endblock javascript %}
10040
10132
  </code></pre></div>
10041
10133
  <details class="version-added">
10042
- <summary>Added in version 2.2.0</summary>
10134
+ <summary>Added in version 2.2.0 — Additional blocks</summary>
10043
10135
  <p>Added the <code>job_form</code> and <code>schedule_form</code> sub-blocks to <code>extras/job.html</code>, for use by Jobs that just want to override the rendered forms without replacing all of <code>{% block content %}</code>.</p>
10044
10136
  </details>
10045
10137
  <p>For another example checkout <a href="https://github.com/nautobot/nautobot/blob/main/examples/example_app/example_app/templates/example_app/example_with_custom_template.html">the template used in the Example App</a> in the GitHub repo.</p>
@@ -10048,7 +10140,7 @@ This can accept either plain text, Markdown-formatted text, or <a href="../../us
10048
10140
  <summary>Added in version 1.3.0</summary>
10049
10141
  </details>
10050
10142
  <p>An int or float value, in seconds, which can be used to override the
10051
- default <a href="../../user-guide/administration/configuration/settings.html#celery_task_time_limit">hard time limit</a> (10 minutes by default) for a job task to complete.</p>
10143
+ default <a href="../../user-guide/administration/configuration/settings.html#celery_task_time_limit">hard time limit</a> (10 minutes by default) for a Job task to complete.</p>
10052
10144
  <p>Unlike the <code>soft_time_limit</code> above, no exceptions are raised when a <code>time_limit</code> is exceeded. The task will just terminate silently:</p>
10053
10145
  <div class="highlight"><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span>
10054
10146
  <a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a>
@@ -10064,11 +10156,11 @@ default <a href="../../user-guide/administration/configuration/settings.html#cel
10064
10156
  <a id="__codelineno-9-12" name="__codelineno-9-12" href="#__codelineno-9-12"></a> <span class="n">job_code</span><span class="p">()</span>
10065
10157
  </code></pre></div>
10066
10158
  <div class="admonition note">
10067
- <p class="admonition-title">Note</p>
10068
- <p>If the <code>time_limit</code> is set to a value less than or equal to the <code>soft_time_limit</code>, a warning log is generated to inform the user that this job will fail silently after the <code>time_limit</code> as the <code>soft_time_limit</code> will never be reached.</p>
10159
+ <p class="admonition-title"><code>time_limit</code> versus <code>soft_time_limit</code></p>
10160
+ <p>If the <code>time_limit</code> is set to a value less than or equal to the <code>soft_time_limit</code>, a warning log is generated to inform the user that this Job will fail silently after the <code>time_limit</code> as the <code>soft_time_limit</code> will never be reached.</p>
10069
10161
  </div>
10070
10162
  <h3 id="variables">Variables<a class="headerlink" href="#variables" title="Permanent link">&para;</a></h3>
10071
- <p>Variables allow your job to accept user input via the Nautobot UI, but they are optional; if your job does not require any user input, there is no need to define any variables. Conversely, if you are making use of user input in your job, you <em>must</em> also implement the <code>run()</code> method, as it is the only entry point to your job that has visibility into the variable values provided by the user.</p>
10163
+ <p>Variables allow your Job to accept user input via the Nautobot UI, but they are optional; if your Job does not require any user input, there is no need to define any variables. Conversely, if you are making use of user input in your Job, you <em>must</em> also implement the <code>run()</code> method, as it is the only entry point to your Job that has visibility into the variable values provided by the user.</p>
10072
10164
  <div class="highlight"><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">StringVar</span><span class="p">,</span> <span class="n">IntegerVar</span><span class="p">,</span> <span class="n">ObjectVar</span>
10073
10165
  <a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a>
10074
10166
  <a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a><span class="k">class</span> <span class="nc">CreateDevices</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
@@ -10081,7 +10173,7 @@ default <a href="../../user-guide/administration/configuration/settings.html#cel
10081
10173
  </code></pre></div>
10082
10174
  <p>The remainder of this section documents the various supported variable types and how to make use of them.</p>
10083
10175
  <h4 id="default-variable-options">Default Variable Options<a class="headerlink" href="#default-variable-options" title="Permanent link">&para;</a></h4>
10084
- <p>All job variables support the following default options:</p>
10176
+ <p>All Job variables support the following default options:</p>
10085
10177
  <ul>
10086
10178
  <li><code>default</code> - The field's default value</li>
10087
10179
  <li><code>description</code> - A brief user-friendly description of the field</li>
@@ -10103,7 +10195,7 @@ default <a href="../../user-guide/administration/configuration/settings.html#cel
10103
10195
  <details class="version-added">
10104
10196
  <summary>Added in version 2.1.0</summary>
10105
10197
  </details>
10106
- <p>Accepts JSON-formatted data of any length. Renders as a multi-line text input field. The variable passed to <code>run()</code> method on the job has been serialized to the appropriate Python objects.</p>
10198
+ <p>Accepts JSON-formatted data of any length. Renders as a multi-line text input field. The variable passed to <code>run()</code> method on the Job has been serialized to the appropriate Python objects.</p>
10107
10199
  <div class="highlight"><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="k">class</span> <span class="nc">ExampleJSONVarJob</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
10108
10200
  <a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a> <span class="n">var1</span> <span class="o">=</span> <span class="n">JSONVar</span><span class="p">()</span>
10109
10201
  <a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a>
@@ -10111,7 +10203,7 @@ default <a href="../../user-guide/administration/configuration/settings.html#cel
10111
10203
  <a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a> <span class="c1"># var1 form data equals &#39;{&quot;key1&quot;: &quot;value1&quot;}&#39;</span>
10112
10204
  <a id="__codelineno-11-6" name="__codelineno-11-6" href="#__codelineno-11-6"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;The value of key1 is: </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">var1</span><span class="p">[</span><span class="s2">&quot;key1&quot;</span><span class="p">])</span>
10113
10205
  </code></pre></div>
10114
- <p>In the above example <code>{"key1": "value1"}</code> is provided to the job form, on submission first the field is validated to be JSON-formatted data then is serialized and passed to the <code>run()</code> method as a dictionary without any need for the job developer to post-process the variable into a Python dictionary.</p>
10206
+ <p>In the above example <code>{"key1": "value1"}</code> is provided to the Job form, on submission first the field is validated to be JSON-formatted data then is serialized and passed to the <code>run()</code> method as a dictionary without any need for the Job developer to post-process the variable into a Python dictionary.</p>
10115
10207
  <h4 id="integervar"><code>IntegerVar</code><a class="headerlink" href="#integervar" title="Permanent link">&para;</a></h4>
10116
10208
  <p>Stores a numeric integer. Options include:</p>
10117
10209
  <ul>
@@ -10121,7 +10213,7 @@ default <a href="../../user-guide/administration/configuration/settings.html#cel
10121
10213
  <h4 id="booleanvar"><code>BooleanVar</code><a class="headerlink" href="#booleanvar" title="Permanent link">&para;</a></h4>
10122
10214
  <p>A true/false flag. This field has no options beyond the defaults listed above.</p>
10123
10215
  <h4 id="dryrunvar"><code>DryRunVar</code><a class="headerlink" href="#dryrunvar" title="Permanent link">&para;</a></h4>
10124
- <p>A true/false flag with special handling for jobs that require approval. If <code>dryrun = DryRunVar()</code> is declared on a job class, approval may be bypassed if <code>dryrun</code> is set to <code>True</code> on job execution.</p>
10216
+ <p>A true/false flag with special handling for Jobs that require approval. If <code>dryrun = DryRunVar()</code> is declared on a Job class, approval may be bypassed if <code>dryrun</code> is set to <code>True</code> on Job execution.</p>
10125
10217
  <h4 id="choicevar"><code>ChoiceVar</code><a class="headerlink" href="#choicevar" title="Permanent link">&para;</a></h4>
10126
10218
  <p>A set of choices from which the user can select one.</p>
10127
10219
  <ul>
@@ -10198,7 +10290,7 @@ Another example of using the nested reference would be to access <a href="../../
10198
10290
  <h4 id="multiobjectvar"><code>MultiObjectVar</code><a class="headerlink" href="#multiobjectvar" title="Permanent link">&para;</a></h4>
10199
10291
  <p>Similar to <code>ObjectVar</code>, but allows for the selection of multiple objects.</p>
10200
10292
  <h4 id="filevar"><code>FileVar</code><a class="headerlink" href="#filevar" title="Permanent link">&para;</a></h4>
10201
- <p>An uploaded file. Note that uploaded files are present in memory only for the duration of the job's execution: They will not be automatically saved for future use. The job is responsible for writing file contents to disk where necessary.</p>
10293
+ <p>An uploaded file. Note that uploaded files are present in memory only for the duration of the Job's execution: They will not be automatically saved for future use. The Job is responsible for writing file contents to disk where necessary.</p>
10202
10294
  <h4 id="ipaddressvar"><code>IPAddressVar</code><a class="headerlink" href="#ipaddressvar" title="Permanent link">&para;</a></h4>
10203
10295
  <p>An IPv4 or IPv6 address, without a mask. Returns a <code>netaddr.IPAddress</code> object.</p>
10204
10296
  <h4 id="ipaddresswithmaskvar"><code>IPAddressWithMaskVar</code><a class="headerlink" href="#ipaddresswithmaskvar" title="Permanent link">&para;</a></h4>
@@ -10213,14 +10305,14 @@ Another example of using the nested reference would be to access <a href="../../
10213
10305
  <p>Nautobot Jobs when executed will be instantiated by Nautobot, then Nautobot will call in order the special API methods <code>before_start()</code>, <code>run()</code>, <code>on_success()</code>/<code>on_failure()</code>, and <code>after_return()</code>. You must implement the <code>run()</code> method; the other methods have default implementations that do nothing.</p>
10214
10306
  <p>As Jobs are Python classes, you are of course free to define any number of other helper methods or functions that you call yourself from within any of the above special methods, but the above are the only ones that will be automatically called.</p>
10215
10307
  <details class="version-removed">
10216
- <summary>Removed in version 2.0.0</summary>
10308
+ <summary>Removed in version 2.0.0 — Removal of <code>test</code> and <code>post_run</code> special methods</summary>
10217
10309
  <p>The NetBox backwards compatible <code>test_*()</code> and <code>post_run()</code> special methods have been removed.</p>
10218
10310
  </details>
10219
10311
  <h4 id="the-before_start-method">The <code>before_start()</code> Method<a class="headerlink" href="#the-before_start-method" title="Permanent link">&para;</a></h4>
10220
10312
  <p>The <code>before_start()</code> method may optionally be implemented to perform any appropriate Job-specific setup before the <code>run()</code> method is called. It has the signature <code>before_start(self, task_id, args, kwargs)</code> for historical reasons; the <code>task_id</code> parameter will always be identical to <code>self.request.id</code>, the <code>args</code> parameter will generally be empty, and any user-specified variables passed into the Job execution will be present in the <code>kwargs</code> parameter.</p>
10221
10313
  <p>The return value from <code>before_start()</code> is ignored, but if it raises any exception, the Job execution will be marked as a failure and <code>run()</code> will not be called.</p>
10222
10314
  <h4 id="the-run-method">The <code>run()</code> Method<a class="headerlink" href="#the-run-method" title="Permanent link">&para;</a></h4>
10223
- <p>The <code>run()</code> method is the primary worker of any Job, and must be implemented. After the <code>self</code> argument, it should accept keyword arguments for any variables defined on the job:</p>
10315
+ <p>The <code>run()</code> method is the primary worker of any Job, and must be implemented. After the <code>self</code> argument, it should accept keyword arguments for any variables defined on the Job:</p>
10224
10316
  <div class="highlight"><pre><span></span><code><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">StringVar</span><span class="p">,</span> <span class="n">IntegerVar</span><span class="p">,</span> <span class="n">ObjectVar</span>
10225
10317
  <a id="__codelineno-18-2" name="__codelineno-18-2" href="#__codelineno-18-2"></a>
10226
10318
  <a id="__codelineno-18-3" name="__codelineno-18-3" href="#__codelineno-18-3"></a><span class="k">class</span> <span class="nc">CreateDevices</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
@@ -10231,13 +10323,13 @@ Another example of using the nested reference would be to access <a href="../../
10231
10323
  <a id="__codelineno-18-8" name="__codelineno-18-8" href="#__codelineno-18-8"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">var1</span><span class="p">,</span> <span class="n">var2</span><span class="p">,</span> <span class="n">var3</span><span class="p">):</span>
10232
10324
  <a id="__codelineno-18-9" name="__codelineno-18-9" href="#__codelineno-18-9"></a> <span class="o">...</span>
10233
10325
  </code></pre></div>
10234
- <p>Again, defining user variables is totally optional; you may create a job with a <code>run()</code> method with only the <code>self</code> argument if no user input is needed.</p>
10326
+ <p>Again, defining user variables is totally optional; you may create a Job with a <code>run()</code> method with only the <code>self</code> argument if no user input is needed.</p>
10235
10327
  <div class="admonition warning">
10236
- <p class="admonition-title">Warning</p>
10328
+ <p class="admonition-title">Use <code>validated_save()</code> where applicable</p>
10237
10329
  <p>When writing Jobs that create and manipulate data it is recommended to make use of the <code>validated_save()</code> convenience method which exists on all core models. This method saves the instance data but first enforces model validation logic. Simply calling <code>save()</code> on the model instance <strong>does not</strong> enforce validation automatically and may lead to bad data. See the development <a href="../core/best-practices.html">best practices</a>.</p>
10238
10330
  </div>
10239
10331
  <div class="admonition warning">
10240
- <p class="admonition-title">Warning</p>
10332
+ <p class="admonition-title">Be cautious around bulk operations</p>
10241
10333
  <p>The Django ORM provides methods to create/edit many objects at once, namely <code>bulk_create()</code> and <code>update()</code>. These are best avoided in most cases as they bypass a model's built-in validation and can easily lead to database corruption if not used carefully.</p>
10242
10334
  </div>
10243
10335
  <p>If <code>run()</code> returns any value (even the implicit <code>None</code>), the Job execution will be marked as a success and the returned value will be stored in the associated JobResult database record. Conversely, if <code>run()</code> raises any exception, the Job execution will be marked as a failure and the traceback will be stored in the JobResult.</p>
@@ -10251,8 +10343,8 @@ Another example of using the nested reference would be to access <a href="../../
10251
10343
  <details class="version-changed">
10252
10344
  <summary>Changed in version 2.0.0</summary>
10253
10345
  </details>
10254
- <p>Messages logged from a job's logger will be stored in <a href="../../user-guide/platform-functionality/jobs/models.html#job-log-entry"><code>JobLogEntry</code></a> records associated with the current <a href="../../user-guide/platform-functionality/jobs/models.html#job-results"><code>JobResult</code></a>.</p>
10255
- <p>The logger can be accessed either by using the <code>logger</code> property on the job class or <code>nautobot.extras.jobs.get_task_logger(__name__)</code>. Both will return the same logger instance. For more information on the standard Python logging module, see the <a href="https://docs.python.org/3/library/logging.html">Python documentation</a>.</p>
10346
+ <p>Messages logged from a Job's logger will be stored in <a href="../../user-guide/platform-functionality/jobs/models.html#job-log-entry"><code>JobLogEntry</code></a> records associated with the current <a href="../../user-guide/platform-functionality/jobs/models.html#job-results"><code>JobResult</code></a>.</p>
10347
+ <p>The logger can be accessed either by using the <code>logger</code> property on the Job class or <code>nautobot.extras.jobs.get_task_logger(__name__)</code>. Both will return the same logger instance. For more information on the standard Python logging module, see the <a href="https://docs.python.org/3/library/logging.html">Python documentation</a>.</p>
10256
10348
  <p>The logger accepts an <code>extra</code> kwarg that you can optionally set for the following features:</p>
10257
10349
  <ul>
10258
10350
  <li><code>grouping</code>- Replaces the <code>active_test</code> Job property in Nautobot v1.X</li>
@@ -10281,16 +10373,16 @@ Another example of using the nested reference would be to access <a href="../../
10281
10373
  </div>
10282
10374
  <p>Markdown rendering is supported for log messages, as well as <a href="../../user-guide/platform-functionality/template-filters.html#render_markdown">a limited subset of HTML</a>.</p>
10283
10375
  <details class="version-changed">
10284
- <summary>Changed in version 1.3.4</summary>
10285
- <p>As a security measure, the <code>message</code> passed to any of these methods will be passed through the <code>nautobot.core.utils.logging.sanitize()</code> function in an attempt to strip out information such as usernames/passwords that should not be saved to the logs. This is of course best-effort only, and Job authors should take pains to ensure that such information is not passed to the logging APIs in the first place. The set of redaction rules used by the <code>sanitize()</code> function can be configured as <a href="../../user-guide/administration/configuration/settings.html#sanitizer_patterns">settings.SANITIZER_PATTERNS</a>.</p>
10376
+ <summary>Changed in version 1.3.4 — Log entry sanitization</summary>
10377
+ <p>As a security measure, the <code>message</code> passed to any of these methods will be passed through the <code>nautobot.core.utils.logging.sanitize()</code> function in an attempt to strip out information such as usernames/passwords that should not be saved to the logs. This is of course best-effort only, and Job authors should take pains to ensure that such information is not passed to the logging APIs in the first place. The set of redaction rules used by the <code>sanitize()</code> function can be configured as <a href="../../user-guide/administration/configuration/settings.html#sanitizer_patterns"><code>settings.SANITIZER_PATTERNS</code></a>.</p>
10286
10378
  </details>
10287
10379
  <details class="version-changed">
10288
- <summary>Changed in version 2.0.0</summary>
10289
- <p>The Job class logging functions (example: <code>self.log(message)</code>, <code>self.log_success(obj=None, message=message)</code>, etc) have been removed. Also, the convenience method to mark a job as failed, <code>log_failure()</code>, has been removed. To replace the functionality of this method, you can log an error message with <code>self.logger.error()</code> and then raise an exception to fail the job. Note that it is no longer possible to manually set the job result status as failed without raising an exception in the job.</p>
10380
+ <summary>Changed in version 2.0.0 — Significant API changes</summary>
10381
+ <p>The Job class logging functions (example: <code>self.log(message)</code>, <code>self.log_success(obj=None, message=message)</code>, etc) have been removed. Also, the convenience method to mark a Job as failed, <code>log_failure()</code>, has been removed. To replace the functionality of this method, you can log an error message with <code>self.logger.error()</code> and then raise an exception to fail the Job. Note that it is no longer possible to manually set the Job Result status as failed without raising an exception in the Job.</p>
10290
10382
  </details>
10291
10383
  <details class="version-changed">
10292
10384
  <summary>Changed in version 2.0.0</summary>
10293
- <p>The <code>AbortTransaction</code> class was moved from the <code>nautobot.utilities.exceptions</code> module to <code>nautobot.core.exceptions</code>.</p>
10385
+ <p>The <code>AbortTransaction</code> class was moved from the <code>nautobot.utilities.exceptions</code> module to <code>nautobot.core.exceptions</code>. Jobs should generally import it from <code>nautobot.apps.exceptions</code> if needed.</p>
10294
10386
  </details>
10295
10387
  <details class="version-added">
10296
10388
  <summary>Added in version 2.4.0</summary>
@@ -10311,8 +10403,8 @@ Another example of using the nested reference would be to access <a href="../../
10311
10403
  <p>The above Job when run will create two files, "greeting.txt" and "farewell.txt", that will be made available for download from the JobResult detail view's "Advanced" tab and via the REST API. These files will persist indefinitely, but can automatically be deleted if the JobResult itself is deleted; they can also be deleted manually by an administrator via the "File Proxies" link in the Admin UI.</p>
10312
10404
  <p>The maximum size of any single created file (or in other words, the maximum number of bytes that can be passed to <code>self.create_file()</code>) is controlled by the <a href="../../user-guide/administration/configuration/settings.html#job_create_file_max_size"><code>JOB_CREATE_FILE_MAX_SIZE</code></a> system setting. A <code>ValueError</code> exception will be raised if <code>create_file()</code> is called with an overly large <code>content</code> value.</p>
10313
10405
  <h3 id="marking-a-job-as-failed">Marking a Job as Failed<a class="headerlink" href="#marking-a-job-as-failed" title="Permanent link">&para;</a></h3>
10314
- <p>To mark a job as failed, raise an exception from within the <code>run()</code> method. The exception message will be logged to the traceback of the job result. The job result status will be set to <code>failed</code>. To output a job log message you can use the <code>self.logger.error()</code> method.</p>
10315
- <p>As an example, the following job will fail if the user does not put the word "Taco" in <code>var1</code>:</p>
10406
+ <p>To mark a Job as failed, raise an exception from within the <code>run()</code> method. The exception message will be logged to the traceback of the Job Result. The Job Result status will be set to <code>failed</code>. To output a Job log message you can use the <code>self.logger.error()</code> method.</p>
10407
+ <p>As an example, the following Job will fail if the user does not put the word "Taco" in <code>var1</code>:</p>
10316
10408
  <div class="highlight"><pre><span></span><code><a id="__codelineno-22-1" name="__codelineno-22-1" href="#__codelineno-22-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">StringVar</span>
10317
10409
  <a id="__codelineno-22-2" name="__codelineno-22-2" href="#__codelineno-22-2"></a>
10318
10410
  <a id="__codelineno-22-3" name="__codelineno-22-3" href="#__codelineno-22-3"></a><span class="k">class</span> <span class="nc">MyJob</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
@@ -10325,10 +10417,10 @@ Another example of using the nested reference would be to access <a href="../../
10325
10417
  </code></pre></div>
10326
10418
  <h3 id="accessing-user-and-job-result">Accessing User and Job Result<a class="headerlink" href="#accessing-user-and-job-result" title="Permanent link">&para;</a></h3>
10327
10419
  <details class="version-changed">
10328
- <summary>Changed in version 2.0.0</summary>
10420
+ <summary>Changed in version 2.0.0 — Significant API change</summary>
10329
10421
  <p>The <code>request</code> property has been changed to a Celery request instead of a Django web request and no longer includes the information from the web request that initiated the Job. The <code>user</code> object is now available as <code>self.user</code> instead of <code>self.request.user</code>.</p>
10330
10422
  </details>
10331
- <p>The user that initiated the job and the job result associated to the job can be accessed through properties on the job class:</p>
10423
+ <p>The user that initiated the Job and the Job Result associated to the Job can be accessed through properties on the Job class:</p>
10332
10424
  <div class="highlight"><pre><span></span><code><a id="__codelineno-23-1" name="__codelineno-23-1" href="#__codelineno-23-1"></a><span class="n">username</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">username</span>
10333
10425
  <a id="__codelineno-23-2" name="__codelineno-23-2" href="#__codelineno-23-2"></a><span class="n">job_result_id</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">job_result</span><span class="o">.</span><span class="n">id</span>
10334
10426
  <a id="__codelineno-23-3" name="__codelineno-23-3" href="#__codelineno-23-3"></a><span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Job </span><span class="si">%s</span><span class="s2"> initiated by user </span><span class="si">%s</span><span class="s2"> is running.&quot;</span><span class="p">,</span> <span class="n">job_result_id</span><span class="p">,</span> <span class="n">username</span><span class="p">)</span>
@@ -10350,7 +10442,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
10350
10442
  </details>
10351
10443
  <p>The simplest way to test the entire execution of Jobs is via calling the <code>nautobot.apps.testing.run_job_for_testing()</code> method, which is a helper wrapper around the <code>JobResult.enqueue_job</code> function used to execute a Job via Nautobot's Celery worker process.</p>
10352
10444
  <p>Because of the way <code>run_job_for_testing</code> and more specifically Celery tasks work, which is somewhat complex behind the scenes, you need to inherit from <code>nautobot.apps.testing.TransactionTestCase</code> instead of <code>django.test.TestCase</code> (Refer to the <a href="https://docs.djangoproject.com/en/stable/topics/testing/tools/#provided-test-case-classes">Django documentation</a> if you're interested in the differences between these classes - <code>TransactionTestCase</code> from Nautobot is a small wrapper around Django's <code>TransactionTestCase</code>).</p>
10353
- <p>When using <code>TransactionTestCase</code> (whether from Django or from Nautobot) each tests runs on a completely empty database. Furthermore, Nautobot requires new jobs to be enabled before they can run. Therefore, we need to make sure the job is enabled before each run which <code>run_job_for_testing</code> handles for us.</p>
10445
+ <p>When using <code>TransactionTestCase</code> (whether from Django or from Nautobot) each tests runs on a completely empty database. Furthermore, Nautobot requires new Jobs to be enabled before they can run. Therefore, we need to make sure the Job is enabled before each run which <code>run_job_for_testing</code> handles for us.</p>
10354
10446
  <p>A simple example of a Job test case might look like the following:</p>
10355
10447
  <div class="highlight"><pre><span></span><code><a id="__codelineno-24-1" name="__codelineno-24-1" href="#__codelineno-24-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.testing</span> <span class="kn">import</span> <span class="n">run_job_for_testing</span><span class="p">,</span> <span class="n">TransactionTestCase</span>
10356
10448
  <a id="__codelineno-24-2" name="__codelineno-24-2" href="#__codelineno-24-2"></a><span class="kn">from</span> <span class="nn">nautobot.extras.models</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">JobLogEntry</span>
@@ -10372,15 +10464,15 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
10372
10464
  <p class="admonition-title">Tip</p>
10373
10465
  <p>For more advanced examples refer to the Nautobot source code, specifically <code>nautobot/extras/tests/test_jobs.py</code>.</p>
10374
10466
  </div>
10375
- <h2 id="debugging-job-performance">Debugging job performance<a class="headerlink" href="#debugging-job-performance" title="Permanent link">&para;</a></h2>
10467
+ <h2 id="debugging-job-performance">Debugging Job Performance<a class="headerlink" href="#debugging-job-performance" title="Permanent link">&para;</a></h2>
10376
10468
  <details class="version-added">
10377
10469
  <summary>Added in version 1.5.17</summary>
10378
10470
  </details>
10379
- <p>Debugging the performance of Nautobot jobs can be tricky, because they are executed in the worker context. In order to gain extra visibility, <a href="https://docs.python.org/3/library/profile.html">cProfile</a> can be used to profile the job execution.</p>
10380
- <p>The 'profile' form field on jobs is automatically available when the <code>DEBUG</code> settings is <code>True</code>. When you select that checkbox, a profiling report in the pstats format will be written to the file system of the environment where the job runs. Normally, this is on the file system of the worker process, but if you are using the <code>nautobot-server runjob</code> command with <code>--local</code>, it will end up in the file system of the web application itself. The path of the written file will be logged in the job.</p>
10471
+ <p>Debugging the performance of Nautobot Jobs can be tricky, because they are executed in the worker context. In order to gain extra visibility, <a href="https://docs.python.org/3/library/profile.html">cProfile</a> can be used to profile the Job execution.</p>
10472
+ <p>The 'profile' form field on Jobs is automatically available when the <code>DEBUG</code> settings is <code>True</code>. When you select that checkbox, a profiling report in the pstats format will be written to the file system of the environment where the Job runs. Normally, this is on the file system of the worker process, but if you are using the <code>nautobot-server runjob</code> command with <code>--local</code>, it will end up in the file system of the web application itself. The path of the written file will be logged in the Job.</p>
10381
10473
  <div class="admonition note">
10382
10474
  <p class="admonition-title">Note</p>
10383
- <p>If you need to run this in an environment where <code>DEBUG</code> is <code>False</code>, you have the option of using <code>nautobot-server runjob</code> with the <code>--profile</code> flag. According to the docs, <code>cProfile</code> should have minimal impact on the performance of the job; still, proceed with caution when using this in a production environment.</p>
10475
+ <p>If you need to run this in an environment where <code>DEBUG</code> is <code>False</code>, you have the option of using <code>nautobot-server runjob</code> with the <code>--profile</code> flag. According to the docs, <code>cProfile</code> should have minimal impact on the performance of the Job; still, proceed with caution when using this in a production environment.</p>
10384
10476
  </div>
10385
10477
  <h3 id="reading-profiling-reports">Reading profiling reports<a class="headerlink" href="#reading-profiling-reports" title="Permanent link">&para;</a></h3>
10386
10478
  <p>A full description on how to deal with the output of <code>cProfile</code> can be found in the <a href="https://docs.python.org/3/library/profile.html#instant-user-s-manual">Instant User's Manual</a>, but here is something to get you started:</p>
@@ -10389,16 +10481,18 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
10389
10481
  <a id="__codelineno-25-3" name="__codelineno-25-3" href="#__codelineno-25-3"></a><span class="n">stats</span> <span class="o">=</span> <span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;/tmp/nautobot-jobresult-</span><span class="si">{</span><span class="n">job_result_uuid</span><span class="si">}</span><span class="s2">.pstats&quot;</span><span class="p">)</span>
10390
10482
  <a id="__codelineno-25-4" name="__codelineno-25-4" href="#__codelineno-25-4"></a><span class="n">stats</span><span class="o">.</span><span class="n">sort_stats</span><span class="p">(</span><span class="n">pstats</span><span class="o">.</span><span class="n">SortKey</span><span class="o">.</span><span class="n">CUMULATIVE</span><span class="p">)</span><span class="o">.</span><span class="n">print_stats</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
10391
10483
  </code></pre></div>
10392
- <p>This will print the 10 functions that the job execution spent the most time in - adapt this to your needs!</p>
10484
+ <p>This will print the 10 functions that the Job execution spent the most time in - adapt this to your needs!</p>
10393
10485
  <h2 id="example-jobs">Example Jobs<a class="headerlink" href="#example-jobs" title="Permanent link">&para;</a></h2>
10486
+ <h3 id="example-everything-job">Example "Everything" Job<a class="headerlink" href="#example-everything-job" title="Permanent link">&para;</a></h3>
10487
+ <p>The "Example App" included with the Nautobot source code <a href="https://github.com/nautobot/nautobot/blob/main/examples/example_app/example_app/jobs.py">includes a number of simple sample Jobs</a>, including an <code>ExampleEverythingJob</code> class that demonstrates and documents the usage of the various metadata attributes, input variable types, and magic methods that a Job can support. As Job functionality will continue to evolve over time, if using this file as a reference, please make sure that you're viewing the version of this Job that corresponds to your target Nautobot version.</p>
10394
10488
  <h3 id="creating-objects-for-a-planned-location">Creating objects for a planned location<a class="headerlink" href="#creating-objects-for-a-planned-location" title="Permanent link">&para;</a></h3>
10395
- <p>This job prompts the user for three variables:</p>
10489
+ <p>This Job prompts the user for three variables:</p>
10396
10490
  <ul>
10397
10491
  <li>The name of the new location</li>
10398
10492
  <li>The device model (a filtered list of defined device types)</li>
10399
10493
  <li>The number of access switches to create</li>
10400
10494
  </ul>
10401
- <p>These variables are presented as a web form to be completed by the user. Once submitted, the job's <code>run()</code> method is called to create the appropriate objects, and it returns simple CSV output to the user summarizing the created objects.</p>
10495
+ <p>These variables are presented as a web form to be completed by the user. Once submitted, the Job's <code>run()</code> method is called to create the appropriate objects, and it returns simple CSV output to the user summarizing the created objects.</p>
10402
10496
  <div class="highlight"><pre><span></span><code><a id="__codelineno-26-1" name="__codelineno-26-1" href="#__codelineno-26-1"></a><span class="kn">from</span> <span class="nn">django.contrib.contenttypes.models</span> <span class="kn">import</span> <span class="n">ContentType</span>
10403
10497
  <a id="__codelineno-26-2" name="__codelineno-26-2" href="#__codelineno-26-2"></a>
10404
10498
  <a id="__codelineno-26-3" name="__codelineno-26-3" href="#__codelineno-26-3"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">StringVar</span><span class="p">,</span> <span class="n">IntegerVar</span><span class="p">,</span> <span class="n">ObjectVar</span><span class="p">,</span> <span class="n">register_jobs</span>
@@ -10458,7 +10552,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
10458
10552
  <a id="__codelineno-26-57" name="__codelineno-26-57" href="#__codelineno-26-57"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">NewBranch</span><span class="p">)</span>
10459
10553
  </code></pre></div>
10460
10554
  <h3 id="device-validation">Device validation<a class="headerlink" href="#device-validation" title="Permanent link">&para;</a></h3>
10461
- <p>A job to perform various validation of Device data in Nautobot. As this job does not require any user input, it does not define any variables.</p>
10555
+ <p>A Job to perform various validation of Device data in Nautobot. As this Job does not require any user input, it does not define any variables.</p>
10462
10556
  <div class="highlight"><pre><span></span><code><a id="__codelineno-27-1" name="__codelineno-27-1" href="#__codelineno-27-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">register_jobs</span>
10463
10557
  <a id="__codelineno-27-2" name="__codelineno-27-2" href="#__codelineno-27-2"></a><span class="kn">from</span> <span class="nn">nautobot.dcim.models</span> <span class="kn">import</span> <span class="n">ConsolePort</span><span class="p">,</span> <span class="n">Device</span><span class="p">,</span> <span class="n">PowerPort</span>
10464
10558
  <a id="__codelineno-27-3" name="__codelineno-27-3" href="#__codelineno-27-3"></a><span class="kn">from</span> <span class="nn">nautobot.extras.models</span> <span class="kn">import</span> <span class="n">Status</span>
@@ -10511,9 +10605,9 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
10511
10605
  <a id="__codelineno-27-50" name="__codelineno-27-50" href="#__codelineno-27-50"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">DeviceConnectionsReport</span><span class="p">)</span>
10512
10606
  </code></pre></div>
10513
10607
  <h2 id="job-button-receivers">Job Button Receivers<a class="headerlink" href="#job-button-receivers" title="Permanent link">&para;</a></h2>
10514
- <p>Job Buttons are only able to initiate a specific type of job called a <strong>Job Button Receiver</strong>. These are jobs that subclass the <code>nautobot.apps.jobs.JobButtonReceiver</code> class. Job Button Receivers are similar to normal jobs except they are hard coded to accept only <code>object_pk</code> and <code>object_model_name</code> <a href="#variables">variables</a>. Job Button Receivers are hidden from the jobs listing UI by default but otherwise function similarly to other jobs. The <code>JobButtonReceiver</code> class only implements one method called <code>receive_job_button</code>.</p>
10608
+ <p>Job Buttons are only able to initiate a specific type of Job called a <strong>Job Button Receiver</strong>. These are Jobs that subclass the <code>nautobot.apps.jobs.JobButtonReceiver</code> class. Job Button Receivers are similar to normal Jobs except they are hard coded to accept only <code>object_pk</code> and <code>object_model_name</code> <a href="#variables">variables</a>. The <code>JobButtonReceiver</code> class only implements one method called <code>receive_job_button</code>.</p>
10515
10609
  <div class="admonition note">
10516
- <p class="admonition-title">Note</p>
10610
+ <p class="admonition-title">Disabled by default just like other Jobs</p>
10517
10611
  <p>Job Button Receivers still need to be <a href="../../user-guide/platform-functionality/jobs/index.html#enabling-jobs-for-running">enabled through the web UI</a> before they can be used just like other Jobs.</p>
10518
10612
  </div>
10519
10613
  <h3 id="the-receive_job_button-method">The <code>receive_job_button()</code> Method<a class="headerlink" href="#the-receive_job_button-method" title="Permanent link">&para;</a></h3>
@@ -10576,14 +10670,14 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
10576
10670
  <a id="__codelineno-29-36" name="__codelineno-29-36" href="#__codelineno-29-36"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">ExampleComplexJobButtonReceiver</span><span class="p">)</span>
10577
10671
  </code></pre></div>
10578
10672
  <h2 id="job-hook-receivers">Job Hook Receivers<a class="headerlink" href="#job-hook-receivers" title="Permanent link">&para;</a></h2>
10579
- <p>Job Hooks are only able to initiate a specific type of job called a <strong>Job Hook Receiver</strong>. These are jobs that subclass the <code>nautobot.apps.jobs.JobHookReceiver</code> class. Job hook receivers are similar to normal jobs except they are hard coded to accept only an <code>object_change</code> <a href="#variables">variable</a>. Job Hook Receivers are hidden from the jobs listing UI by default but otherwise function similarly to other jobs. The <code>JobHookReceiver</code> class only implements one method called <code>receive_job_hook</code>.</p>
10673
+ <p>Job Hooks are only able to initiate a specific type of Job called a <strong>Job Hook Receiver</strong>. These are Jobs that subclass the <code>nautobot.apps.jobs.JobHookReceiver</code> class. Job Hook Receivers are similar to normal Jobs except they are hard coded to accept only an <code>object_change</code> <a href="#variables">variable</a>. The <code>JobHookReceiver</code> class only implements one method called <code>receive_job_hook</code>.</p>
10580
10674
  <div class="admonition warning">
10581
- <p class="admonition-title">Warning</p>
10675
+ <p class="admonition-title">No support for <code>approval_required</code> at this time</p>
10582
10676
  <p>Requiring approval for execution of Job Hooks by setting the <code>Meta.approval_required</code> attribute to <code>True</code> on your <code>JobHookReceiver</code> subclass is not supported. The value of this attribute will be ignored. Support for requiring approval of Job Hooks will be added in a future release.</p>
10583
10677
  </div>
10584
10678
  <div class="admonition important">
10585
- <p class="admonition-title">Important</p>
10586
- <p>To prevent negatively impacting system performance through an infinite loop, a change that was made by a <code>JobHookReceiver</code> job will not trigger another <code>JobHookReceiver</code> job to run.</p>
10679
+ <p class="admonition-title">No recursive JobHookReceivers</p>
10680
+ <p>To prevent negatively impacting system performance through an infinite loop, a change that was made by a <code>JobHookReceiver</code> Job will not trigger another <code>JobHookReceiver</code> Job to run.</p>
10587
10681
  </div>
10588
10682
  <h3 id="example-job-hook-receiver">Example Job Hook Receiver<a class="headerlink" href="#example-job-hook-receiver" title="Permanent link">&para;</a></h3>
10589
10683
  <div class="highlight"><pre><span></span><code><a id="__codelineno-30-1" name="__codelineno-30-1" href="#__codelineno-30-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">JobHookReceiver</span><span class="p">,</span> <span class="n">register_jobs</span>
@@ -10774,7 +10868,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
10774
10868
  <script id="__config" type="application/json">{"base": "../..", "features": ["content.code.annotate", "content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
10775
10869
 
10776
10870
 
10777
- <script src="../../assets/javascripts/bundle.83f73b43.min.js"></script>
10871
+ <script src="../../assets/javascripts/bundle.88dd0f4e.min.js"></script>
10778
10872
 
10779
10873
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
10780
10874