nautobot 2.2.2__py3-none-any.whl → 2.2.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of nautobot might be problematic. Click here for more details.

Files changed (362) hide show
  1. nautobot/apps/jobs.py +2 -0
  2. nautobot/core/api/utils.py +12 -9
  3. nautobot/core/apps/__init__.py +2 -2
  4. nautobot/core/celery/__init__.py +79 -68
  5. nautobot/core/celery/backends.py +9 -1
  6. nautobot/core/celery/control.py +4 -7
  7. nautobot/core/celery/schedulers.py +4 -2
  8. nautobot/core/celery/task.py +78 -5
  9. nautobot/core/graphql/schema.py +2 -1
  10. nautobot/core/jobs/__init__.py +2 -1
  11. nautobot/core/settings.py +6 -4
  12. nautobot/core/settings.yaml +51 -16
  13. nautobot/core/templates/admin/base.html +2 -2
  14. nautobot/core/templates/base_django.html +2 -2
  15. nautobot/core/templates/buttons/export.html +47 -47
  16. nautobot/core/templates/generic/object_list.html +3 -3
  17. nautobot/core/templates/inc/javascript.html +3 -0
  18. nautobot/core/templates/inc/media.html +3 -0
  19. nautobot/core/templates/login.html +2 -2
  20. nautobot/core/templates/nautobot_config.py.j2 +2 -0
  21. nautobot/core/templatetags/helpers.py +66 -9
  22. nautobot/core/testing/__init__.py +6 -1
  23. nautobot/core/testing/api.py +12 -13
  24. nautobot/core/testing/mixins.py +2 -2
  25. nautobot/core/testing/views.py +50 -51
  26. nautobot/core/tests/test_api.py +23 -2
  27. nautobot/core/tests/test_jobs.py +79 -2
  28. nautobot/core/tests/test_templatetags_helpers.py +32 -0
  29. nautobot/core/tests/test_views.py +52 -0
  30. nautobot/core/tests/test_views_utils.py +22 -1
  31. nautobot/core/utils/module_loading.py +89 -0
  32. nautobot/core/views/mixins.py +4 -0
  33. nautobot/core/views/utils.py +3 -2
  34. nautobot/dcim/choices.py +14 -0
  35. nautobot/dcim/forms.py +51 -1
  36. nautobot/dcim/models/device_components.py +9 -5
  37. nautobot/dcim/templates/dcim/location.html +32 -13
  38. nautobot/dcim/templates/dcim/location_migrate_data_to_contact.html +102 -0
  39. nautobot/dcim/tests/test_views.py +376 -55
  40. nautobot/dcim/urls.py +5 -0
  41. nautobot/dcim/views.py +172 -21
  42. nautobot/extras/api/serializers.py +17 -6
  43. nautobot/extras/api/views.py +21 -10
  44. nautobot/extras/constants.py +3 -3
  45. nautobot/extras/datasources/git.py +47 -58
  46. nautobot/extras/forms/forms.py +3 -1
  47. nautobot/extras/jobs.py +79 -146
  48. nautobot/extras/models/datasources.py +0 -2
  49. nautobot/extras/models/jobs.py +36 -18
  50. nautobot/extras/plugins/__init__.py +1 -20
  51. nautobot/extras/signals.py +6 -9
  52. nautobot/extras/test_jobs/__init__.py +8 -0
  53. nautobot/extras/test_jobs/dry_run.py +3 -2
  54. nautobot/extras/test_jobs/fail.py +43 -0
  55. nautobot/extras/test_jobs/ipaddress_vars.py +40 -1
  56. nautobot/extras/test_jobs/jobs_module/__init__.py +5 -0
  57. nautobot/extras/test_jobs/jobs_module/jobs_submodule/__init__.py +1 -0
  58. nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +6 -0
  59. nautobot/extras/test_jobs/pass.py +40 -0
  60. nautobot/extras/test_jobs/relative_import.py +11 -0
  61. nautobot/extras/tests/test_api.py +3 -0
  62. nautobot/extras/tests/test_context_managers.py +18 -0
  63. nautobot/extras/tests/test_datasources.py +125 -118
  64. nautobot/extras/tests/test_job_variables.py +57 -15
  65. nautobot/extras/tests/test_jobs.py +135 -1
  66. nautobot/extras/tests/test_models.py +26 -19
  67. nautobot/extras/tests/test_plugins.py +1 -3
  68. nautobot/extras/tests/test_views.py +2 -4
  69. nautobot/extras/utils.py +2 -1
  70. nautobot/extras/views.py +82 -116
  71. nautobot/ipam/api/views.py +8 -1
  72. nautobot/ipam/graphql/types.py +11 -0
  73. nautobot/ipam/mixins.py +32 -0
  74. nautobot/ipam/models.py +2 -1
  75. nautobot/ipam/querysets.py +6 -1
  76. nautobot/ipam/tests/test_models.py +82 -0
  77. nautobot/ipam/views.py +6 -6
  78. nautobot/project-static/docs/404.html +107 -51
  79. nautobot/project-static/docs/apps/index.html +107 -51
  80. nautobot/project-static/docs/apps/nautobot-apps.html +107 -51
  81. nautobot/project-static/docs/assets/_mkdocstrings.css +6 -1
  82. nautobot/project-static/docs/assets/extra.css +11 -0
  83. nautobot/project-static/docs/assets/javascripts/bundle.3220b9d7.min.js +29 -0
  84. nautobot/project-static/docs/assets/javascripts/bundle.3220b9d7.min.js.map +7 -0
  85. nautobot/project-static/docs/assets/stylesheets/main.66ac8b77.min.css +1 -0
  86. nautobot/project-static/docs/assets/stylesheets/main.66ac8b77.min.css.map +1 -0
  87. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +107 -51
  88. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +107 -51
  89. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +108 -52
  90. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +107 -51
  91. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +107 -51
  92. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +107 -51
  93. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +107 -51
  94. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +107 -51
  95. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +107 -51
  96. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +107 -51
  97. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +107 -51
  98. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +107 -51
  99. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +107 -51
  100. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +287 -262
  101. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +107 -51
  102. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +107 -51
  103. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +107 -51
  104. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +107 -51
  105. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +107 -51
  106. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +107 -51
  107. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +107 -51
  108. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +107 -51
  109. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +107 -51
  110. nautobot/project-static/docs/development/apps/api/configuration-view.html +110 -54
  111. nautobot/project-static/docs/development/apps/api/database-backend-config.html +110 -54
  112. nautobot/project-static/docs/development/apps/api/models/django-admin.html +107 -51
  113. nautobot/project-static/docs/development/apps/api/models/global-search.html +110 -54
  114. nautobot/project-static/docs/development/apps/api/models/graphql.html +113 -57
  115. nautobot/project-static/docs/development/apps/api/models/index.html +107 -51
  116. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +113 -57
  117. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +107 -51
  118. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +110 -54
  119. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +107 -51
  120. nautobot/project-static/docs/development/apps/api/platform-features/index.html +107 -51
  121. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +110 -54
  122. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +111 -55
  123. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +110 -54
  124. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +110 -54
  125. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +107 -51
  126. nautobot/project-static/docs/development/apps/api/prometheus.html +110 -54
  127. nautobot/project-static/docs/development/apps/api/setup.html +107 -51
  128. nautobot/project-static/docs/development/apps/api/testing.html +113 -57
  129. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +110 -54
  130. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +110 -54
  131. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +107 -51
  132. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +107 -51
  133. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +113 -57
  134. nautobot/project-static/docs/development/apps/api/views/base-template.html +107 -51
  135. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +110 -54
  136. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +107 -51
  137. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +110 -54
  138. nautobot/project-static/docs/development/apps/api/views/index.html +107 -51
  139. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +113 -57
  140. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +122 -66
  141. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +110 -54
  142. nautobot/project-static/docs/development/apps/api/views/notes.html +110 -54
  143. nautobot/project-static/docs/development/apps/api/views/rest-api.html +107 -51
  144. nautobot/project-static/docs/development/apps/api/views/urls.html +107 -51
  145. nautobot/project-static/docs/development/apps/index.html +128 -72
  146. nautobot/project-static/docs/development/apps/migration/code-updates.html +107 -51
  147. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +107 -51
  148. nautobot/project-static/docs/development/apps/migration/from-v1.html +107 -51
  149. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +107 -51
  150. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +107 -51
  151. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +107 -51
  152. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +107 -51
  153. nautobot/project-static/docs/development/apps/porting-from-netbox.html +110 -54
  154. nautobot/project-static/docs/development/core/application-registry.html +242 -144
  155. nautobot/project-static/docs/development/core/best-practices.html +122 -66
  156. nautobot/project-static/docs/development/core/bootstrap-ui.html +107 -51
  157. nautobot/project-static/docs/development/core/caching.html +107 -51
  158. nautobot/project-static/docs/development/core/controllers.html +107 -51
  159. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +113 -57
  160. nautobot/project-static/docs/development/core/generic-views.html +110 -54
  161. nautobot/project-static/docs/development/core/getting-started.html +135 -79
  162. nautobot/project-static/docs/development/core/homepage.html +110 -54
  163. nautobot/project-static/docs/development/core/index.html +107 -51
  164. nautobot/project-static/docs/development/core/model-checklist.html +156 -52
  165. nautobot/project-static/docs/development/core/model-features.html +108 -52
  166. nautobot/project-static/docs/development/core/natural-keys.html +110 -54
  167. nautobot/project-static/docs/development/core/navigation-menu.html +107 -51
  168. nautobot/project-static/docs/development/core/release-checklist.html +107 -51
  169. nautobot/project-static/docs/development/core/role-internals.html +107 -51
  170. nautobot/project-static/docs/development/core/settings.html +107 -51
  171. nautobot/project-static/docs/development/core/style-guide.html +110 -54
  172. nautobot/project-static/docs/development/core/templates.html +113 -57
  173. nautobot/project-static/docs/development/core/testing.html +125 -69
  174. nautobot/project-static/docs/development/core/user-preferences.html +107 -51
  175. nautobot/project-static/docs/development/index.html +107 -51
  176. nautobot/project-static/docs/development/jobs/index.html +504 -172
  177. nautobot/project-static/docs/development/jobs/migration/from-v1.html +111 -55
  178. nautobot/project-static/docs/docker/index.html +3 -3
  179. nautobot/project-static/docs/index.html +125 -69
  180. nautobot/project-static/docs/installation/selinux-troubleshooting.html +3 -3
  181. nautobot/project-static/docs/objects.inv +0 -0
  182. nautobot/project-static/docs/release-notes/index.html +107 -51
  183. nautobot/project-static/docs/release-notes/version-1.0.html +107 -51
  184. nautobot/project-static/docs/release-notes/version-1.1.html +107 -51
  185. nautobot/project-static/docs/release-notes/version-1.2.html +107 -51
  186. nautobot/project-static/docs/release-notes/version-1.3.html +107 -51
  187. nautobot/project-static/docs/release-notes/version-1.4.html +107 -51
  188. nautobot/project-static/docs/release-notes/version-1.5.html +116 -60
  189. nautobot/project-static/docs/release-notes/version-1.6.html +107 -51
  190. nautobot/project-static/docs/release-notes/version-2.0.html +110 -54
  191. nautobot/project-static/docs/release-notes/version-2.1.html +107 -51
  192. nautobot/project-static/docs/release-notes/version-2.2.html +500 -114
  193. nautobot/project-static/docs/requirements.txt +2 -2
  194. nautobot/project-static/docs/search/search_index.json +1 -1
  195. nautobot/project-static/docs/sitemap.xml +262 -262
  196. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  197. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +107 -51
  198. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +107 -51
  199. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +107 -51
  200. nautobot/project-static/docs/user-guide/administration/configuration/index.html +107 -51
  201. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +251 -164
  202. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +113 -57
  203. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +107 -51
  204. nautobot/project-static/docs/user-guide/administration/guides/caching.html +113 -57
  205. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +107 -51
  206. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +107 -51
  207. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +107 -51
  208. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +113 -57
  209. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +107 -51
  210. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +107 -51
  211. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +107 -51
  212. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +171 -112
  213. nautobot/project-static/docs/user-guide/administration/installation/docker.html +13 -8626
  214. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +117 -61
  215. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +13 -8614
  216. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +252 -165
  217. nautobot/project-static/docs/user-guide/administration/installation/index.html +165 -192
  218. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +411 -691
  219. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +248 -229
  220. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +13 -8118
  221. nautobot/project-static/docs/user-guide/administration/installation/services.html +350 -240
  222. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +8684 -0
  223. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +8672 -0
  224. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +8176 -0
  225. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +110 -54
  226. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +110 -54
  227. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +155 -99
  228. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +107 -51
  229. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +109 -53
  230. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +107 -51
  231. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +107 -51
  232. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +107 -51
  233. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +107 -51
  234. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +107 -51
  235. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +107 -51
  236. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +117 -58
  237. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +113 -57
  238. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +107 -51
  239. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +107 -51
  240. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +107 -51
  241. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +107 -51
  242. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +110 -54
  243. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +107 -51
  244. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +110 -54
  245. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +110 -54
  246. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +110 -54
  247. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +110 -54
  248. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +107 -51
  249. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +107 -51
  250. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +113 -57
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +110 -54
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +110 -54
  253. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +110 -54
  254. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +110 -54
  255. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +116 -60
  256. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +110 -54
  257. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +110 -54
  258. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +119 -63
  259. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +110 -54
  260. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +110 -54
  261. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +113 -57
  262. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +113 -57
  263. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +113 -57
  264. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +107 -51
  265. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +113 -57
  266. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +107 -51
  267. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +110 -54
  268. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +110 -54
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +107 -51
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +110 -54
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +110 -54
  272. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +107 -51
  273. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +107 -51
  274. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +107 -51
  275. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +110 -54
  276. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +110 -54
  277. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +110 -54
  278. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +110 -54
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +107 -51
  280. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +113 -57
  281. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +110 -54
  282. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +110 -54
  283. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +110 -54
  284. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +125 -69
  285. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +113 -57
  286. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +128 -72
  287. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +110 -54
  288. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +107 -51
  289. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +110 -54
  290. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +227 -60
  291. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +107 -51
  292. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +113 -57
  293. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +107 -51
  294. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +110 -54
  295. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +107 -51
  296. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +107 -51
  297. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +107 -51
  298. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +107 -51
  299. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +113 -57
  300. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +113 -57
  301. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +107 -51
  302. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +113 -57
  303. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +107 -51
  304. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +107 -51
  305. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +107 -51
  306. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +107 -51
  307. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +107 -51
  308. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +107 -51
  309. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +107 -51
  310. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +107 -51
  311. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +107 -51
  312. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +110 -54
  313. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +113 -57
  314. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +107 -51
  315. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +110 -54
  316. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +107 -51
  317. nautobot/project-static/docs/user-guide/index.html +109 -53
  318. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +107 -51
  319. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +113 -57
  320. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +128 -72
  321. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +107 -51
  322. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +125 -69
  323. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +107 -51
  324. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +110 -54
  325. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +125 -69
  326. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +110 -54
  327. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +107 -51
  328. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +107 -51
  329. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +143 -100
  330. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +113 -57
  331. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +113 -57
  332. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +110 -54
  333. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +123 -67
  334. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +107 -51
  335. nautobot/project-static/docs/user-guide/platform-functionality/note.html +110 -54
  336. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +116 -60
  337. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +110 -54
  338. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +131 -75
  339. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +149 -93
  340. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +110 -54
  341. nautobot/project-static/docs/user-guide/platform-functionality/role.html +107 -51
  342. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +116 -60
  343. nautobot/project-static/docs/user-guide/platform-functionality/status.html +119 -63
  344. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +110 -54
  345. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +137 -81
  346. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +110 -54
  347. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +107 -51
  348. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +110 -54
  349. nautobot/project-static/js/forms.js +18 -11
  350. nautobot/tenancy/views.py +2 -6
  351. nautobot/virtualization/views.py +5 -9
  352. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/METADATA +4 -4
  353. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/RECORD +357 -348
  354. nautobot/extras/test_jobs/job_variables.py +0 -93
  355. nautobot/project-static/docs/assets/javascripts/bundle.bd41221c.min.js +0 -29
  356. nautobot/project-static/docs/assets/javascripts/bundle.bd41221c.min.js.map +0 -7
  357. nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css +0 -1
  358. nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css.map +0 -1
  359. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/LICENSE.txt +0 -0
  360. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/NOTICE +0 -0
  361. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/WHEEL +0 -0
  362. {nautobot-2.2.2.dist-info → nautobot-2.2.4.dist-info}/entry_points.txt +0 -0
@@ -18,7 +18,7 @@
18
18
 
19
19
 
20
20
  <link rel="icon" href="../../assets/favicon.ico">
21
- <meta name="generator" content="mkdocs-1.5.3, mkdocs-material-9.5.16">
21
+ <meta name="generator" content="mkdocs-1.5.3, mkdocs-material-9.5.18">
22
22
 
23
23
 
24
24
 
@@ -26,12 +26,20 @@
26
26
 
27
27
 
28
28
 
29
- <link rel="stylesheet" href="../../assets/stylesheets/main.bcfcd587.min.css">
29
+ <link rel="stylesheet" href="../../assets/stylesheets/main.66ac8b77.min.css">
30
30
 
31
31
 
32
32
  <link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
33
33
 
34
34
 
35
+
36
+
37
+
38
+
39
+
40
+
41
+ <style>:root{--md-admonition-icon--example:url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M288 0H128c-17.7 0-32 14.3-32 32s14.3 32 32 32v132.8c0 11.8-3.3 23.5-9.5 33.5L10.3 406.2C3.6 417.2 0 429.7 0 442.6 0 480.9 31.1 512 69.4 512h309.2c38.3 0 69.4-31.1 69.4-69.4 0-12.8-3.6-25.4-10.3-36.4L329.5 230.4c-6.2-10.1-9.5-21.7-9.5-33.5V64c17.7 0 32-14.3 32-32S337.7 0 320 0h-32zm-96 196.8V64h64v132.8c0 23.7 6.6 46.9 19 67.1l34.5 56.1h-171l34.5-56.1c12.4-20.2 19-43.4 19-67.1z"/></svg>');}</style>
42
+
35
43
 
36
44
 
37
45
 
@@ -200,7 +208,7 @@
200
208
  <a href="https://github.com/nautobot/nautobot" title="Go to repository" class="md-source" data-md-component="source">
201
209
  <div class="md-source__icon md-icon">
202
210
 
203
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
211
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
204
212
  </div>
205
213
  <div class="md-source__repository">
206
214
  GitHub
@@ -360,7 +368,7 @@
360
368
  <a href="https://github.com/nautobot/nautobot" title="Go to repository" class="md-source" data-md-component="source">
361
369
  <div class="md-source__icon md-icon">
362
370
 
363
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
371
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
364
372
  </div>
365
373
  <div class="md-source__repository">
366
374
  GitHub
@@ -523,7 +531,7 @@
523
531
 
524
532
 
525
533
  <span class="md-ellipsis">
526
- Prerequisites
534
+ Getting Started
527
535
  </span>
528
536
 
529
537
 
@@ -624,11 +632,11 @@
624
632
 
625
633
 
626
634
  <li class="md-nav__item">
627
- <a href="../../user-guide/administration/installation/external-authentication.html" class="md-nav__link">
635
+ <a href="../../user-guide/administration/installation/app-install.html" class="md-nav__link">
628
636
 
629
637
 
630
638
  <span class="md-ellipsis">
631
- External Authentication (Optional)
639
+ Installing and Using Apps
632
640
  </span>
633
641
 
634
642
 
@@ -645,11 +653,11 @@
645
653
 
646
654
 
647
655
  <li class="md-nav__item">
648
- <a href="../../user-guide/administration/installation/app-install.html" class="md-nav__link">
656
+ <a href="../../user-guide/administration/installation/external-authentication.html" class="md-nav__link">
649
657
 
650
658
 
651
659
  <span class="md-ellipsis">
652
- Installing and Using Plugins
660
+ External Authentication (Optional)
653
661
  </span>
654
662
 
655
663
 
@@ -659,6 +667,52 @@
659
667
 
660
668
 
661
669
 
670
+ </ul>
671
+ </nav>
672
+
673
+ </li>
674
+
675
+
676
+
677
+
678
+
679
+
680
+
681
+
682
+
683
+
684
+
685
+
686
+
687
+
688
+
689
+
690
+
691
+ <li class="md-nav__item md-nav__item--nested">
692
+
693
+
694
+
695
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_2" >
696
+
697
+
698
+ <label class="md-nav__link" for="__nav_2_1_2" id="__nav_2_1_2_label" tabindex="0">
699
+
700
+
701
+ <span class="md-ellipsis">
702
+ Installation Extras
703
+ </span>
704
+
705
+
706
+ <span class="md-nav__icon md-icon"></span>
707
+ </label>
708
+
709
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_2_label" aria-expanded="false">
710
+ <label class="md-nav__title" for="__nav_2_1_2">
711
+ <span class="md-nav__icon md-icon"></span>
712
+ Installation Extras
713
+ </label>
714
+ <ul class="md-nav__list" data-md-scrollfix>
715
+
662
716
 
663
717
 
664
718
 
@@ -666,7 +720,7 @@
666
720
 
667
721
 
668
722
  <li class="md-nav__item">
669
- <a href="../../user-guide/administration/installation/docker.html" class="md-nav__link">
723
+ <a href="../../user-guide/administration/installation-extras/docker.html" class="md-nav__link">
670
724
 
671
725
 
672
726
  <span class="md-ellipsis">
@@ -687,7 +741,7 @@
687
741
 
688
742
 
689
743
  <li class="md-nav__item">
690
- <a href="../../user-guide/administration/installation/health-checks.html" class="md-nav__link">
744
+ <a href="../../user-guide/administration/installation-extras/health-checks.html" class="md-nav__link">
691
745
 
692
746
 
693
747
  <span class="md-ellipsis">
@@ -708,7 +762,7 @@
708
762
 
709
763
 
710
764
  <li class="md-nav__item">
711
- <a href="../../user-guide/administration/installation/selinux-troubleshooting.html" class="md-nav__link">
765
+ <a href="../../user-guide/administration/installation-extras/selinux-troubleshooting.html" class="md-nav__link">
712
766
 
713
767
 
714
768
  <span class="md-ellipsis">
@@ -747,10 +801,10 @@
747
801
 
748
802
 
749
803
 
750
- <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_2" >
804
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_3" >
751
805
 
752
806
 
753
- <label class="md-nav__link" for="__nav_2_1_2" id="__nav_2_1_2_label" tabindex="0">
807
+ <label class="md-nav__link" for="__nav_2_1_3" id="__nav_2_1_3_label" tabindex="0">
754
808
 
755
809
 
756
810
  <span class="md-ellipsis">
@@ -761,8 +815,8 @@
761
815
  <span class="md-nav__icon md-icon"></span>
762
816
  </label>
763
817
 
764
- <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_2_label" aria-expanded="false">
765
- <label class="md-nav__title" for="__nav_2_1_2">
818
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_3_label" aria-expanded="false">
819
+ <label class="md-nav__title" for="__nav_2_1_3">
766
820
  <span class="md-nav__icon md-icon"></span>
767
821
  Upgrading
768
822
  </label>
@@ -827,7 +881,7 @@
827
881
 
828
882
 
829
883
 
830
- <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_2_3" >
884
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_3_3" >
831
885
 
832
886
 
833
887
 
@@ -843,14 +897,14 @@
843
897
  </a>
844
898
 
845
899
 
846
- <label class="md-nav__link " for="__nav_2_1_2_3" id="__nav_2_1_2_3_label" tabindex="0">
900
+ <label class="md-nav__link " for="__nav_2_1_3_3" id="__nav_2_1_3_3_label" tabindex="0">
847
901
  <span class="md-nav__icon md-icon"></span>
848
902
  </label>
849
903
 
850
904
  </div>
851
905
 
852
- <nav class="md-nav" data-md-level="4" aria-labelledby="__nav_2_1_2_3_label" aria-expanded="false">
853
- <label class="md-nav__title" for="__nav_2_1_2_3">
906
+ <nav class="md-nav" data-md-level="4" aria-labelledby="__nav_2_1_3_3_label" aria-expanded="false">
907
+ <label class="md-nav__title" for="__nav_2_1_3_3">
854
908
  <span class="md-nav__icon md-icon"></span>
855
909
  Upgrading Nautobot from v1.X to v2.0
856
910
  </label>
@@ -894,7 +948,7 @@
894
948
 
895
949
 
896
950
 
897
- <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_2_3_2" >
951
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_3_3_2" >
898
952
 
899
953
 
900
954
 
@@ -910,14 +964,14 @@
910
964
  </a>
911
965
 
912
966
 
913
- <label class="md-nav__link " for="__nav_2_1_2_3_2" id="__nav_2_1_2_3_2_label" tabindex="0">
967
+ <label class="md-nav__link " for="__nav_2_1_3_3_2" id="__nav_2_1_3_3_2_label" tabindex="0">
914
968
  <span class="md-nav__icon md-icon"></span>
915
969
  </label>
916
970
 
917
971
  </div>
918
972
 
919
- <nav class="md-nav" data-md-level="5" aria-labelledby="__nav_2_1_2_3_2_label" aria-expanded="false">
920
- <label class="md-nav__title" for="__nav_2_1_2_3_2">
973
+ <nav class="md-nav" data-md-level="5" aria-labelledby="__nav_2_1_3_3_2_label" aria-expanded="false">
974
+ <label class="md-nav__title" for="__nav_2_1_3_3_2">
921
975
  <span class="md-nav__icon md-icon"></span>
922
976
  IPAM Migration Guide
923
977
  </label>
@@ -1048,10 +1102,10 @@
1048
1102
 
1049
1103
 
1050
1104
 
1051
- <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_3" >
1105
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_4" >
1052
1106
 
1053
1107
 
1054
- <label class="md-nav__link" for="__nav_2_1_3" id="__nav_2_1_3_label" tabindex="0">
1108
+ <label class="md-nav__link" for="__nav_2_1_4" id="__nav_2_1_4_label" tabindex="0">
1055
1109
 
1056
1110
 
1057
1111
  <span class="md-ellipsis">
@@ -1062,8 +1116,8 @@
1062
1116
  <span class="md-nav__icon md-icon"></span>
1063
1117
  </label>
1064
1118
 
1065
- <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_3_label" aria-expanded="false">
1066
- <label class="md-nav__title" for="__nav_2_1_3">
1119
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_4_label" aria-expanded="false">
1120
+ <label class="md-nav__title" for="__nav_2_1_4">
1067
1121
  <span class="md-nav__icon md-icon"></span>
1068
1122
  Migration
1069
1123
  </label>
@@ -1136,7 +1190,7 @@
1136
1190
 
1137
1191
 
1138
1192
 
1139
- <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_4" >
1193
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_5" >
1140
1194
 
1141
1195
 
1142
1196
 
@@ -1152,14 +1206,14 @@
1152
1206
  </a>
1153
1207
 
1154
1208
 
1155
- <label class="md-nav__link " for="__nav_2_1_4" id="__nav_2_1_4_label" tabindex="0">
1209
+ <label class="md-nav__link " for="__nav_2_1_5" id="__nav_2_1_5_label" tabindex="0">
1156
1210
  <span class="md-nav__icon md-icon"></span>
1157
1211
  </label>
1158
1212
 
1159
1213
  </div>
1160
1214
 
1161
- <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_4_label" aria-expanded="false">
1162
- <label class="md-nav__title" for="__nav_2_1_4">
1215
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_5_label" aria-expanded="false">
1216
+ <label class="md-nav__title" for="__nav_2_1_5">
1163
1217
  <span class="md-nav__icon md-icon"></span>
1164
1218
  Configuration
1165
1219
  </label>
@@ -1245,10 +1299,10 @@
1245
1299
 
1246
1300
 
1247
1301
 
1248
- <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_4_4" >
1302
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_5_4" >
1249
1303
 
1250
1304
 
1251
- <label class="md-nav__link" for="__nav_2_1_4_4" id="__nav_2_1_4_4_label" tabindex="0">
1305
+ <label class="md-nav__link" for="__nav_2_1_5_4" id="__nav_2_1_5_4_label" tabindex="0">
1252
1306
 
1253
1307
 
1254
1308
  <span class="md-ellipsis">
@@ -1259,8 +1313,8 @@
1259
1313
  <span class="md-nav__icon md-icon"></span>
1260
1314
  </label>
1261
1315
 
1262
- <nav class="md-nav" data-md-level="4" aria-labelledby="__nav_2_1_4_4_label" aria-expanded="false">
1263
- <label class="md-nav__title" for="__nav_2_1_4_4">
1316
+ <nav class="md-nav" data-md-level="4" aria-labelledby="__nav_2_1_5_4_label" aria-expanded="false">
1317
+ <label class="md-nav__title" for="__nav_2_1_5_4">
1264
1318
  <span class="md-nav__icon md-icon"></span>
1265
1319
  External Authentication
1266
1320
  </label>
@@ -1362,10 +1416,10 @@
1362
1416
 
1363
1417
 
1364
1418
 
1365
- <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_5" >
1419
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_6" >
1366
1420
 
1367
1421
 
1368
- <label class="md-nav__link" for="__nav_2_1_5" id="__nav_2_1_5_label" tabindex="0">
1422
+ <label class="md-nav__link" for="__nav_2_1_6" id="__nav_2_1_6_label" tabindex="0">
1369
1423
 
1370
1424
 
1371
1425
  <span class="md-ellipsis">
@@ -1376,8 +1430,8 @@
1376
1430
  <span class="md-nav__icon md-icon"></span>
1377
1431
  </label>
1378
1432
 
1379
- <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_5_label" aria-expanded="false">
1380
- <label class="md-nav__title" for="__nav_2_1_5">
1433
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_6_label" aria-expanded="false">
1434
+ <label class="md-nav__title" for="__nav_2_1_6">
1381
1435
  <span class="md-nav__icon md-icon"></span>
1382
1436
  Tools
1383
1437
  </label>
@@ -1450,10 +1504,10 @@
1450
1504
 
1451
1505
 
1452
1506
 
1453
- <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_6" >
1507
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1_7" >
1454
1508
 
1455
1509
 
1456
- <label class="md-nav__link" for="__nav_2_1_6" id="__nav_2_1_6_label" tabindex="0">
1510
+ <label class="md-nav__link" for="__nav_2_1_7" id="__nav_2_1_7_label" tabindex="0">
1457
1511
 
1458
1512
 
1459
1513
  <span class="md-ellipsis">
@@ -1464,8 +1518,8 @@
1464
1518
  <span class="md-nav__icon md-icon"></span>
1465
1519
  </label>
1466
1520
 
1467
- <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_6_label" aria-expanded="false">
1468
- <label class="md-nav__title" for="__nav_2_1_6">
1521
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_1_7_label" aria-expanded="false">
1522
+ <label class="md-nav__title" for="__nav_2_1_7">
1469
1523
  <span class="md-nav__icon md-icon"></span>
1470
1524
  Guides
1471
1525
  </label>
@@ -7712,6 +7766,15 @@
7712
7766
  </span>
7713
7767
  </a>
7714
7768
 
7769
+ </li>
7770
+
7771
+ <li class="md-nav__item">
7772
+ <a href="#installing-jobs" class="md-nav__link">
7773
+ <span class="md-ellipsis">
7774
+ Installing Jobs
7775
+ </span>
7776
+ </a>
7777
+
7715
7778
  </li>
7716
7779
 
7717
7780
  <li class="md-nav__item">
@@ -7755,6 +7818,15 @@
7755
7818
  </ul>
7756
7819
  </nav>
7757
7820
 
7821
+ </li>
7822
+
7823
+ <li class="md-nav__item">
7824
+ <a href="#reserved-attribute-names" class="md-nav__link">
7825
+ <span class="md-ellipsis">
7826
+ Reserved Attribute Names
7827
+ </span>
7828
+ </a>
7829
+
7758
7830
  </li>
7759
7831
 
7760
7832
  <li class="md-nav__item">
@@ -8052,6 +8124,25 @@
8052
8124
  </ul>
8053
8125
  </nav>
8054
8126
 
8127
+ </li>
8128
+
8129
+ <li class="md-nav__item">
8130
+ <a href="#special-methods" class="md-nav__link">
8131
+ <span class="md-ellipsis">
8132
+ Special Methods
8133
+ </span>
8134
+ </a>
8135
+
8136
+ <nav class="md-nav" aria-label="Special Methods">
8137
+ <ul class="md-nav__list">
8138
+
8139
+ <li class="md-nav__item">
8140
+ <a href="#the-before_start-method" class="md-nav__link">
8141
+ <span class="md-ellipsis">
8142
+ The before_start() Method
8143
+ </span>
8144
+ </a>
8145
+
8055
8146
  </li>
8056
8147
 
8057
8148
  <li class="md-nav__item">
@@ -8061,6 +8152,38 @@
8061
8152
  </span>
8062
8153
  </a>
8063
8154
 
8155
+ </li>
8156
+
8157
+ <li class="md-nav__item">
8158
+ <a href="#the-on_success-method" class="md-nav__link">
8159
+ <span class="md-ellipsis">
8160
+ The on_success() Method
8161
+ </span>
8162
+ </a>
8163
+
8164
+ </li>
8165
+
8166
+ <li class="md-nav__item">
8167
+ <a href="#the-on_failure-method" class="md-nav__link">
8168
+ <span class="md-ellipsis">
8169
+ The on_failure() Method
8170
+ </span>
8171
+ </a>
8172
+
8173
+ </li>
8174
+
8175
+ <li class="md-nav__item">
8176
+ <a href="#the-after_return-method" class="md-nav__link">
8177
+ <span class="md-ellipsis">
8178
+ The after_return() Method
8179
+ </span>
8180
+ </a>
8181
+
8182
+ </li>
8183
+
8184
+ </ul>
8185
+ </nav>
8186
+
8064
8187
  </li>
8065
8188
 
8066
8189
  <li class="md-nav__item">
@@ -8273,22 +8396,30 @@
8273
8396
 
8274
8397
 
8275
8398
  <h1 id="jobs">Jobs<a class="headerlink" href="#jobs" title="Permanent link">&para;</a></h1>
8276
- <p>TODO: Jobs authorship introduction</p>
8399
+ <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>
8400
+ <div class="admonition tip">
8401
+ <p class="admonition-title">Tip</p>
8402
+ <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>
8403
+ </div>
8404
+ <div class="admonition info">
8405
+ <p class="admonition-title">Info</p>
8406
+ <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>
8407
+ </div>
8277
8408
  <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>
8278
- <div class="admonition version-changed">
8279
- <p class="admonition-title">Changed in version 2.0.0</p>
8409
+ <details class="version-changed">
8410
+ <summary>Changed in version 2.0.0</summary>
8280
8411
  <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>
8281
- </div>
8282
- <h2 id="writing-jobs">Writing Jobs<a class="headerlink" href="#writing-jobs" title="Permanent link">&para;</a></h2>
8412
+ </details>
8413
+ <h2 id="installing-jobs">Installing Jobs<a class="headerlink" href="#installing-jobs" title="Permanent link">&para;</a></h2>
8283
8414
  <p>Jobs may be installed in one of three ways:</p>
8284
8415
  <ul>
8285
8416
  <li>Manually installed as files in the <a href="../../user-guide/administration/configuration/optional-settings.html#jobs_root"><code>JOBS_ROOT</code></a> path (which defaults to <code>$NAUTOBOT_ROOT/jobs/</code>).<ul>
8286
- <li>This directory is added to Python's <code>sys.path</code> at runtime, so any Python modules placed in this directory will be imported in the root module namespace. For example, a job class named <code>MyJobClass</code> in <code>$JOBS_ROOT/my_job.py</code> will be loaded into Python as <code>my_job.MyJobClass</code>.</li>
8417
+ <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>
8287
8418
  <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>
8288
8419
  </ul>
8289
8420
  </li>
8290
8421
  <li>Imported from an external <a href="../../user-guide/platform-functionality/gitrepository.html#jobs">Git repository</a>.<ul>
8291
- <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</code>.</li>
8422
+ <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>
8292
8423
  <li>All git repositories providing jobs must include a <code>__init__.py</code> file at the root of the repository.</li>
8293
8424
  <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>
8294
8425
  </ul>
@@ -8298,15 +8429,16 @@
8298
8429
  </ul>
8299
8430
  </li>
8300
8431
  </ul>
8301
- <p>In any case, each module holds one or more Jobs (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>
8432
+ <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>
8302
8433
  <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>
8303
- <div class="admonition version-changed">
8304
- <p class="admonition-title">Changed in version 2.0.0</p>
8305
- <p>All job classes must now be registered with <code>nautobot.apps.jobs.register_jobs</code> on module import. For Apps providing jobs, the <code>register_jobs</code> method must called from the App's <code>jobs.py</code> file/submodule at import time. The <code>register_jobs</code> method accepts one or more job classes as arguments.</p>
8306
- </div>
8434
+ <details class="version-changed">
8435
+ <summary>Changed in version 2.0.0</summary>
8436
+ <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>
8437
+ </details>
8438
+ <h2 id="writing-jobs">Writing Jobs<a class="headerlink" href="#writing-jobs" title="Permanent link">&para;</a></h2>
8307
8439
  <div class="admonition warning">
8308
8440
  <p class="admonition-title">Warning</p>
8309
- <p>Make sure you are <em>not</em> inheriting <code>extras.jobs.models.Job</code> instead, otherwise Django will think you want to define a new database model.</p>
8441
+ <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>
8310
8442
  </div>
8311
8443
  <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>
8312
8444
  <a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>
@@ -8325,21 +8457,22 @@
8325
8457
  <ul>
8326
8458
  <li>Module and class attributes, providing for default behavior, documentation and discoverability</li>
8327
8459
  <li>a set of variables for user input via the Nautobot UI (if your job requires any user inputs)</li>
8328
- <li>a <code>run()</code> method, which is the only required attribute on a Job class and receives the user input values, if any</li>
8460
+ <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>
8461
+ <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>
8329
8462
  </ul>
8330
8463
  <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>
8331
8464
  <div class="admonition note">
8332
8465
  <p class="admonition-title">Note</p>
8333
- <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.</p>
8334
- <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.</p>
8466
+ <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>
8467
+ <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>
8335
8468
  </div>
8336
8469
  <h3 id="job-registration">Job Registration<a class="headerlink" href="#job-registration" title="Permanent link">&para;</a></h3>
8337
- <div class="admonition version-changed">
8338
- <p class="admonition-title">Changed in version 2.0.0</p>
8339
- </div>
8470
+ <details class="version-changed">
8471
+ <summary>Changed in version 2.0.0</summary>
8472
+ </details>
8340
8473
  <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>
8341
- <h4 id="registering-jobs-in-jobs_root-or-git-repositories">Registering Jobs in JOBS_ROOT or Git Repositories<a class="headerlink" href="#registering-jobs-in-jobs_root-or-git-repositories" title="Permanent link">&para;</a></h4>
8342
- <p>Only top level module names within JOBS_ROOT 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>
8474
+ <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>
8475
+ <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>
8343
8476
  <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>
8344
8477
  </code></pre></div>
8345
8478
  <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>
@@ -8353,6 +8486,183 @@
8353
8486
  <p>If not using submodules, you should register your job in the file where your job is defined.</p>
8354
8487
  <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>
8355
8488
  <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>
8489
+ <h3 id="reserved-attribute-names">Reserved Attribute Names<a class="headerlink" href="#reserved-attribute-names" title="Permanent link">&para;</a></h3>
8490
+ <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>
8491
+ <div class="admonition example">
8492
+ <p class="admonition-title">Example</p>
8493
+ <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>
8494
+ </div>
8495
+ <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>
8496
+ <table>
8497
+ <thead>
8498
+ <tr>
8499
+ <th>Reserved Name</th>
8500
+ <th>Purpose</th>
8501
+ </tr>
8502
+ </thead>
8503
+ <tbody>
8504
+ <tr>
8505
+ <td><code>after_return</code></td>
8506
+ <td><a href="#special-methods">special method</a></td>
8507
+ </tr>
8508
+ <tr>
8509
+ <td><code>approval_required</code></td>
8510
+ <td><a href="#approval_required">metadata property</a></td>
8511
+ </tr>
8512
+ <tr>
8513
+ <td><code>as_form</code></td>
8514
+ <td>class method</td>
8515
+ </tr>
8516
+ <tr>
8517
+ <td><code>as_form_class</code></td>
8518
+ <td>class method</td>
8519
+ </tr>
8520
+ <tr>
8521
+ <td><code>before_start</code></td>
8522
+ <td><a href="#special-methods">special method</a></td>
8523
+ </tr>
8524
+ <tr>
8525
+ <td><code>celery_kwargs</code></td>
8526
+ <td>property</td>
8527
+ </tr>
8528
+ <tr>
8529
+ <td><code>class_path</code></td>
8530
+ <td>class property</td>
8531
+ </tr>
8532
+ <tr>
8533
+ <td><code>class_path_dotted</code></td>
8534
+ <td>deprecated class property</td>
8535
+ </tr>
8536
+ <tr>
8537
+ <td><code>class_path_js_escaped</code></td>
8538
+ <td>class property</td>
8539
+ </tr>
8540
+ <tr>
8541
+ <td><code>create_file</code></td>
8542
+ <td><a href="#file-output">helper method</a></td>
8543
+ </tr>
8544
+ <tr>
8545
+ <td><code>description</code></td>
8546
+ <td><a href="#description">metadata property</a></td>
8547
+ </tr>
8548
+ <tr>
8549
+ <td><code>description_first_line</code></td>
8550
+ <td><a href="#description">metadata property</a></td>
8551
+ </tr>
8552
+ <tr>
8553
+ <td><code>deserialize_data</code></td>
8554
+ <td>internal class method</td>
8555
+ </tr>
8556
+ <tr>
8557
+ <td><code>dryrun_default</code></td>
8558
+ <td><a href="#dryrun_default">metadata property</a></td>
8559
+ </tr>
8560
+ <tr>
8561
+ <td><code>file_path</code></td>
8562
+ <td>deprecated class property</td>
8563
+ </tr>
8564
+ <tr>
8565
+ <td><code>field_order</code></td>
8566
+ <td><a href="#field_order">metadata property</a></td>
8567
+ </tr>
8568
+ <tr>
8569
+ <td><code>grouping</code></td>
8570
+ <td><a href="#module-metadata-attributes">module metadata property</a></td>
8571
+ </tr>
8572
+ <tr>
8573
+ <td><code>has_sensitive_variables</code></td>
8574
+ <td><a href="#has_sensitive_variables">metadata property</a></td>
8575
+ </tr>
8576
+ <tr>
8577
+ <td><code>hidden</code></td>
8578
+ <td><a href="#hidden">metadata property</a></td>
8579
+ </tr>
8580
+ <tr>
8581
+ <td><code>job_model</code></td>
8582
+ <td>property</td>
8583
+ </tr>
8584
+ <tr>
8585
+ <td><code>job_result</code></td>
8586
+ <td>property</td>
8587
+ </tr>
8588
+ <tr>
8589
+ <td><code>load_json</code></td>
8590
+ <td><a href="#reading-data-from-files">helper method</a></td>
8591
+ </tr>
8592
+ <tr>
8593
+ <td><code>load_yaml</code></td>
8594
+ <td><a href="#reading-data-from-files">helper method</a></td>
8595
+ </tr>
8596
+ <tr>
8597
+ <td><code>name</code></td>
8598
+ <td><a href="#name">metadata property</a></td>
8599
+ </tr>
8600
+ <tr>
8601
+ <td><code>on_failure</code></td>
8602
+ <td><a href="#special-methods">special method</a></td>
8603
+ </tr>
8604
+ <tr>
8605
+ <td><code>on_retry</code></td>
8606
+ <td>reserved as a future <a href="#special-methods">special method</a></td>
8607
+ </tr>
8608
+ <tr>
8609
+ <td><code>on_success</code></td>
8610
+ <td><a href="#special-methods">special method</a></td>
8611
+ </tr>
8612
+ <tr>
8613
+ <td><code>prepare_job_kwargs</code></td>
8614
+ <td>internal class method</td>
8615
+ </tr>
8616
+ <tr>
8617
+ <td><code>properties_dict</code></td>
8618
+ <td>class property</td>
8619
+ </tr>
8620
+ <tr>
8621
+ <td><code>read_only</code></td>
8622
+ <td><a href="#read_only">metadata property</a></td>
8623
+ </tr>
8624
+ <tr>
8625
+ <td><code>registered_name</code></td>
8626
+ <td>deprecated class property</td>
8627
+ </tr>
8628
+ <tr>
8629
+ <td><code>run</code></td>
8630
+ <td><a href="#special-methods">special method</a></td>
8631
+ </tr>
8632
+ <tr>
8633
+ <td><code>serialize_data</code></td>
8634
+ <td>internal method</td>
8635
+ </tr>
8636
+ <tr>
8637
+ <td><code>soft_time_limit</code></td>
8638
+ <td><a href="#soft_time_limit">metadata property</a></td>
8639
+ </tr>
8640
+ <tr>
8641
+ <td><code>supports_dryrun</code></td>
8642
+ <td>class property</td>
8643
+ </tr>
8644
+ <tr>
8645
+ <td><code>task_queues</code></td>
8646
+ <td><a href="#task_queues">metadata property</a></td>
8647
+ </tr>
8648
+ <tr>
8649
+ <td><code>template_name</code></td>
8650
+ <td><a href="#template_name">metadata property</a></td>
8651
+ </tr>
8652
+ <tr>
8653
+ <td><code>time_limit</code></td>
8654
+ <td><a href="#time_limit">metadata property</a></td>
8655
+ </tr>
8656
+ <tr>
8657
+ <td><code>user</code></td>
8658
+ <td>property</td>
8659
+ </tr>
8660
+ <tr>
8661
+ <td><code>validate_data</code></td>
8662
+ <td>internal class method</td>
8663
+ </tr>
8664
+ </tbody>
8665
+ </table>
8356
8666
  <h3 id="module-metadata-attributes">Module Metadata Attributes<a class="headerlink" href="#module-metadata-attributes" title="Permanent link">&para;</a></h3>
8357
8667
  <h4 id="name-grouping"><code>name</code> (Grouping)<a class="headerlink" href="#name-grouping" title="Permanent link">&para;</a></h4>
8358
8668
  <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>
@@ -8386,10 +8696,10 @@ This can accept either plain text, Markdown-formatted text, or <a href="../../us
8386
8696
  <p>Default: <code>False</code></p>
8387
8697
  <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>
8388
8698
  <h4 id="dryrun_default"><code>dryrun_default</code><a class="headerlink" href="#dryrun_default" title="Permanent link">&para;</a></h4>
8389
- <div class="admonition version-changed">
8390
- <p class="admonition-title">Changed in version 2.0.0</p>
8699
+ <details class="version-changed">
8700
+ <summary>Changed in version 2.0.0</summary>
8391
8701
  <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>
8392
- </div>
8702
+ </details>
8393
8703
  <p>Default: <code>False</code></p>
8394
8704
  <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>
8395
8705
  <div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-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>
@@ -8400,9 +8710,9 @@ This can accept either plain text, Markdown-formatted text, or <a href="../../us
8400
8710
  <p>Default: <code>[]</code></p>
8401
8711
  <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>
8402
8712
  <h4 id="has_sensitive_variables"><code>has_sensitive_variables</code><a class="headerlink" href="#has_sensitive_variables" title="Permanent link">&para;</a></h4>
8403
- <div class="admonition version-added">
8404
- <p class="admonition-title">Added in version 1.3.10</p>
8405
- </div>
8713
+ <details class="version-added">
8714
+ <summary>Added in version 1.3.10</summary>
8715
+ </details>
8406
8716
  <p>Default: <code>True</code></p>
8407
8717
  <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>
8408
8718
  <p>Important notes about jobs with sensitive variables:</p>
@@ -8423,19 +8733,19 @@ This can accept either plain text, Markdown-formatted text, or <a href="../../us
8423
8733
  <li>Results for hidden jobs will still appear in the Job Results list after they are run.</li>
8424
8734
  </ul>
8425
8735
  <h4 id="read_only"><code>read_only</code><a class="headerlink" href="#read_only" title="Permanent link">&para;</a></h4>
8426
- <div class="admonition version-added">
8427
- <p class="admonition-title">Added in version 1.1.0</p>
8428
- </div>
8429
- <div class="admonition version-changed">
8430
- <p class="admonition-title">Changed in version 2.0.0</p>
8736
+ <details class="version-added">
8737
+ <summary>Added in version 1.1.0</summary>
8738
+ </details>
8739
+ <details class="version-changed">
8740
+ <summary>Changed in version 2.0.0</summary>
8431
8741
  <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>
8432
- </div>
8742
+ </details>
8433
8743
  <p>Default: <code>False</code></p>
8434
8744
  <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>
8435
8745
  <h4 id="soft_time_limit"><code>soft_time_limit</code><a class="headerlink" href="#soft_time_limit" title="Permanent link">&para;</a></h4>
8436
- <div class="admonition version-added">
8437
- <p class="admonition-title">Added in version 1.3.0</p>
8438
- </div>
8746
+ <details class="version-added">
8747
+ <summary>Added in version 1.3.0</summary>
8748
+ </details>
8439
8749
  <p>An int or float value, in seconds, which can be used to override the default <a href="../../user-guide/administration/configuration/optional-settings.html#celery_task_soft_time_limit">soft time limit</a> for a job task to complete.</p>
8440
8750
  <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/optional-settings.html#celery_task_time_limit">hard time limit</a> (10 minutes by default) is reached:</p>
8441
8751
  <div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="kn">from</span> <span class="nn">celery.exceptions</span> <span class="kn">import</span> <span class="n">SoftTimeLimitExceeded</span>
@@ -8456,9 +8766,9 @@ This can accept either plain text, Markdown-formatted text, or <a href="../../us
8456
8766
  <a id="__codelineno-5-16" name="__codelineno-5-16" href="#__codelineno-5-16"></a> <span class="n">cleanup_in_a_hurry</span><span class="p">()</span>
8457
8767
  </code></pre></div>
8458
8768
  <h4 id="task_queues"><code>task_queues</code><a class="headerlink" href="#task_queues" title="Permanent link">&para;</a></h4>
8459
- <div class="admonition version-added">
8460
- <p class="admonition-title">Added in version 1.5.0</p>
8461
- </div>
8769
+ <details class="version-added">
8770
+ <summary>Added in version 1.5.0</summary>
8771
+ </details>
8462
8772
  <p>Default: <code>[]</code></p>
8463
8773
  <p>A list of task 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/optional-settings.html#celery_task_default_queue">default queue</a> (<code>default</code> unless changed by an administrator). The first queue in the list will be used if a queue is not specified in a job run API call.</p>
8464
8774
  <div class="admonition note">
@@ -8466,9 +8776,9 @@ This can accept either plain text, Markdown-formatted text, or <a href="../../us
8466
8776
  <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>
8467
8777
  </div>
8468
8778
  <h4 id="template_name"><code>template_name</code><a class="headerlink" href="#template_name" title="Permanent link">&para;</a></h4>
8469
- <div class="admonition version-added">
8470
- <p class="admonition-title">Added in version 1.4.0</p>
8471
- </div>
8779
+ <details class="version-added">
8780
+ <summary>Added in version 1.4.0</summary>
8781
+ </details>
8472
8782
  <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>
8473
8783
  <p>A template can provide additional JavaScript, CSS, or even display HTML. A good starting template would be:</p>
8474
8784
  <div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a>{% extends &#39;extras/job.html&#39; %}
@@ -8486,15 +8796,15 @@ This can accept either plain text, Markdown-formatted text, or <a href="../../us
8486
8796
  <a id="__codelineno-6-13" name="__codelineno-6-13" href="#__codelineno-6-13"></a> <span class="cm">&lt;!-- Add additional JavaScript here. --&gt;</span>
8487
8797
  <a id="__codelineno-6-14" name="__codelineno-6-14" href="#__codelineno-6-14"></a>{% endblock javascript %}
8488
8798
  </code></pre></div>
8489
- <div class="admonition version-added">
8490
- <p class="admonition-title">Added in version 2.2.0</p>
8799
+ <details class="version-added">
8800
+ <summary>Added in version 2.2.0</summary>
8491
8801
  <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>
8492
- </div>
8802
+ </details>
8493
8803
  <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>
8494
8804
  <h4 id="time_limit"><code>time_limit</code><a class="headerlink" href="#time_limit" title="Permanent link">&para;</a></h4>
8495
- <div class="admonition version-added">
8496
- <p class="admonition-title">Added in version 1.3.0</p>
8497
- </div>
8805
+ <details class="version-added">
8806
+ <summary>Added in version 1.3.0</summary>
8807
+ </details>
8498
8808
  <p>An int or float value, in seconds, which can be used to override the
8499
8809
  default <a href="../../user-guide/administration/configuration/optional-settings.html#celery_task_time_limit">hard time limit</a> (10 minutes by default) for a job task to complete.</p>
8500
8810
  <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>
@@ -8548,9 +8858,9 @@ default <a href="../../user-guide/administration/configuration/optional-settings
8548
8858
  <h4 id="textvar"><code>TextVar</code><a class="headerlink" href="#textvar" title="Permanent link">&para;</a></h4>
8549
8859
  <p>Arbitrary text of any length. Renders as a multi-line text input field.</p>
8550
8860
  <h4 id="jsonvar"><code>JSONVar</code><a class="headerlink" href="#jsonvar" title="Permanent link">&para;</a></h4>
8551
- <div class="admonition version-added">
8552
- <p class="admonition-title">Added in version 2.1.0</p>
8553
- </div>
8861
+ <details class="version-added">
8862
+ <summary>Added in version 2.1.0</summary>
8863
+ </details>
8554
8864
  <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>
8555
8865
  <div class="highlight"><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-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>
8556
8866
  <a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a> <span class="n">var1</span> <span class="o">=</span> <span class="n">JSONVar</span><span class="p">()</span>
@@ -8657,8 +8967,18 @@ Another example of using the nested reference would be to access <a href="../../
8657
8967
  <li><code>min_prefix_length</code> - Minimum length of the mask</li>
8658
8968
  <li><code>max_prefix_length</code> - Maximum length of the mask</li>
8659
8969
  </ul>
8660
- <h3 id="the-run-method">The <code>run()</code> Method<a class="headerlink" href="#the-run-method" title="Permanent link">&para;</a></h3>
8661
- <p>The <code>run()</code> method must be implemented. After the <code>self</code> argument, it should accept keyword arguments for any variables defined on the job:</p>
8970
+ <h3 id="special-methods">Special Methods<a class="headerlink" href="#special-methods" title="Permanent link">&para;</a></h3>
8971
+ <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>
8972
+ <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>
8973
+ <details class="version-removed">
8974
+ <summary>Removed in version 2.0.0</summary>
8975
+ <p>The NetBox backwards compatible <code>test_*()</code> and <code>post_run()</code> special methods have been removed.</p>
8976
+ </details>
8977
+ <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>
8978
+ <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>
8979
+ <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>
8980
+ <h4 id="the-run-method">The <code>run()</code> Method<a class="headerlink" href="#the-run-method" title="Permanent link">&para;</a></h4>
8981
+ <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>
8662
8982
  <div class="highlight"><pre><span></span><code><a id="__codelineno-16-1" name="__codelineno-16-1" href="#__codelineno-16-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>
8663
8983
  <a id="__codelineno-16-2" name="__codelineno-16-2" href="#__codelineno-16-2"></a>
8664
8984
  <a id="__codelineno-16-3" name="__codelineno-16-3" href="#__codelineno-16-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>
@@ -8666,7 +8986,7 @@ Another example of using the nested reference would be to access <a href="../../
8666
8986
  <a id="__codelineno-16-5" name="__codelineno-16-5" href="#__codelineno-16-5"></a> <span class="n">var2</span> <span class="o">=</span> <span class="n">IntegerVar</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
8667
8987
  <a id="__codelineno-16-6" name="__codelineno-16-6" href="#__codelineno-16-6"></a> <span class="n">var3</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
8668
8988
  <a id="__codelineno-16-7" name="__codelineno-16-7" href="#__codelineno-16-7"></a>
8669
- <a id="__codelineno-16-8" name="__codelineno-16-8" href="#__codelineno-16-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="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>
8989
+ <a id="__codelineno-16-8" name="__codelineno-16-8" href="#__codelineno-16-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>
8670
8990
  <a id="__codelineno-16-9" name="__codelineno-16-9" href="#__codelineno-16-9"></a> <span class="o">...</span>
8671
8991
  </code></pre></div>
8672
8992
  <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>
@@ -8678,14 +8998,17 @@ Another example of using the nested reference would be to access <a href="../../
8678
8998
  <p class="admonition-title">Warning</p>
8679
8999
  <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>
8680
9000
  </div>
8681
- <div class="admonition version-removed">
8682
- <p class="admonition-title">Removed in version 2.0.0</p>
8683
- <p>The NetBox backwards compatible <code>test_*()</code> and <code>post_run()</code> methods have been removed.</p>
8684
- </div>
9001
+ <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>
9002
+ <h4 id="the-on_success-method">The <code>on_success()</code> Method<a class="headerlink" href="#the-on_success-method" title="Permanent link">&para;</a></h4>
9003
+ <p>If both <code>before_start()</code> and <code>run()</code> are successful, the <code>on_success()</code> method will be called next, if implemented. It has the signature <code>on_success(self, retval, task_id, args, kwargs)</code>; as with <code>before_start()</code> the <code>task_id</code> and <code>args</code> parameters can generally be ignored, while <code>retval</code> is the return value from <code>run()</code>, and <code>kwargs</code> will contain the user-specified variables passed into the Job execution.</p>
9004
+ <h4 id="the-on_failure-method">The <code>on_failure()</code> Method<a class="headerlink" href="#the-on_failure-method" title="Permanent link">&para;</a></h4>
9005
+ <p>If either <code>before_start()</code> or <code>run()</code> raises any unhandled exception, the <code>on_failure()</code> method will be called next, if implemented. It has the signature <code>on_failure(self, exc, task_id, args, kwargs, einfo)</code>; of these parameters, the <code>exc</code> will contain the exception that was raised, and <code>kwargs</code> will contain the user-specified variables passed into the Job.</p>
9006
+ <h4 id="the-after_return-method">The <code>after_return()</code> Method<a class="headerlink" href="#the-after_return-method" title="Permanent link">&para;</a></h4>
9007
+ <p>Regardless of the overall Job execution success or failure, the <code>after_return()</code> method will be called after <code>on_success()</code> or <code>on_failure()</code>. It has the signature <code>after_return(self, status, retval, task_id, args, kwargs, einfo)</code>; the <code>status</code> will indicate success or failure (using the <code>JobResultStatusChoices</code> enum), <code>retval</code> is <em>either</em> the return value from <code>run()</code> (on success) or the exception raised (on failure), and once again <code>kwargs</code> contains the user variables.</p>
8685
9008
  <h3 id="logging">Logging<a class="headerlink" href="#logging" title="Permanent link">&para;</a></h3>
8686
- <div class="admonition version-changed">
8687
- <p class="admonition-title">Changed in version 2.0.0</p>
8688
- </div>
9009
+ <details class="version-changed">
9010
+ <summary>Changed in version 2.0.0</summary>
9011
+ </details>
8689
9012
  <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>
8690
9013
  <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>
8691
9014
  <p>The logger accepts an <code>extra</code> kwarg that you can optionally set for the following features:</p>
@@ -8715,22 +9038,22 @@ Another example of using the nested reference would be to access <a href="../../
8715
9038
  </code></pre></div>
8716
9039
  </div>
8717
9040
  <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>
8718
- <div class="admonition version-changed">
8719
- <p class="admonition-title">Changed in version 1.3.4</p>
9041
+ <details class="version-changed">
9042
+ <summary>Changed in version 1.3.4</summary>
8720
9043
  <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/optional-settings.html#sanitizer_patterns">settings.SANITIZER_PATTERNS</a>.</p>
8721
- </div>
8722
- <div class="admonition version-changed">
8723
- <p class="admonition-title">Changed in version 2.0.0</p>
9044
+ </details>
9045
+ <details class="version-changed">
9046
+ <summary>Changed in version 2.0.0</summary>
8724
9047
  <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>
8725
- </div>
8726
- <div class="admonition version-changed">
8727
- <p class="admonition-title">Changed in version 2.0.0</p>
9048
+ </details>
9049
+ <details class="version-changed">
9050
+ <summary>Changed in version 2.0.0</summary>
8728
9051
  <p>The <code>AbortTransaction</code> class was moved from the <code>nautobot.utilities.exceptions</code> module to <code>nautobot.core.exceptions</code>.</p>
8729
- </div>
9052
+ </details>
8730
9053
  <h3 id="file-output">File Output<a class="headerlink" href="#file-output" title="Permanent link">&para;</a></h3>
8731
- <div class="admonition version-added">
8732
- <p class="admonition-title">Added in version 2.1.0</p>
8733
- </div>
9054
+ <details class="version-added">
9055
+ <summary>Added in version 2.1.0</summary>
9056
+ </details>
8734
9057
  <p>A Job can create files that will be saved and can later be downloaded by a user. (The specifics of how and where these files are stored will depend on your system's <a href="../../user-guide/administration/configuration/optional-settings.html#job_file_io_storage"><code>JOB_FILE_IO_STORAGE</code></a> configuration.) To do so, use the <code>Job.create_file(filename, content)</code> method:</p>
8735
9058
  <div class="highlight"><pre><span></span><code><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a><span class="kn">from</span> <span class="nn">nautobot.extras.jobs</span> <span class="kn">import</span> <span class="n">Job</span>
8736
9059
  <a id="__codelineno-19-2" name="__codelineno-19-2" href="#__codelineno-19-2"></a>
@@ -8755,10 +9078,10 @@ Another example of using the nested reference would be to access <a href="../../
8755
9078
  <a id="__codelineno-20-9" name="__codelineno-20-9" href="#__codelineno-20-9"></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Argument input validation failed.&quot;</span><span class="p">)</span>
8756
9079
  </code></pre></div>
8757
9080
  <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>
8758
- <div class="admonition version-changed">
8759
- <p class="admonition-title">Changed in version 2.0.0</p>
9081
+ <details class="version-changed">
9082
+ <summary>Changed in version 2.0.0</summary>
8760
9083
  <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>
8761
- </div>
9084
+ </details>
8762
9085
  <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>
8763
9086
  <div class="highlight"><pre><span></span><code><a id="__codelineno-21-1" name="__codelineno-21-1" href="#__codelineno-21-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>
8764
9087
  <a id="__codelineno-21-2" name="__codelineno-21-2" href="#__codelineno-21-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>
@@ -8774,11 +9097,11 @@ Another example of using the nested reference would be to access <a href="../../
8774
9097
  <h2 id="testing-jobs">Testing Jobs<a class="headerlink" href="#testing-jobs" title="Permanent link">&para;</a></h2>
8775
9098
  <p>Jobs are Python code and can be tested as such, usually via <a href="https://docs.djangoproject.com/en/stable/topics/testing/">Django unit-test features</a>. That said, there are a few useful tricks specific to testing Jobs.</p>
8776
9099
  <p>While individual methods within your Job can and should be tested in isolation, you'll likely also want to test the entire execution of the Job.</p>
8777
- <div class="admonition version-added">
8778
- <p class="admonition-title">Added in version 1.3.3</p>
9100
+ <details class="version-added">
9101
+ <summary>Added in version 1.3.3</summary>
8779
9102
  <p>Entire Job execution testing was only introduced in 1.3.3 and newer.
8780
9103
  However the import paths used in the examples requires 1.5.2 and newer.</p>
8781
- </div>
9104
+ </details>
8782
9105
  <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>
8783
9106
  <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>
8784
9107
  <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>
@@ -8804,9 +9127,9 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
8804
9127
  <p>For more advanced examples refer to the Nautobot source code, specifically <code>nautobot/extras/tests/test_jobs.py</code>.</p>
8805
9128
  </div>
8806
9129
  <h2 id="debugging-job-performance">Debugging job performance<a class="headerlink" href="#debugging-job-performance" title="Permanent link">&para;</a></h2>
8807
- <div class="admonition version-added">
8808
- <p class="admonition-title">Added in version 1.5.17</p>
8809
- </div>
9130
+ <details class="version-added">
9131
+ <summary>Added in version 1.5.17</summary>
9132
+ </details>
8810
9133
  <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>
8811
9134
  <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>
8812
9135
  <div class="admonition note">
@@ -8832,7 +9155,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
8832
9155
  <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>
8833
9156
  <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">django.contrib.contenttypes.models</span> <span class="kn">import</span> <span class="n">ContentType</span>
8834
9157
  <a id="__codelineno-24-2" name="__codelineno-24-2" href="#__codelineno-24-2"></a>
8835
- <a id="__codelineno-24-3" name="__codelineno-24-3" href="#__codelineno-24-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>
9158
+ <a id="__codelineno-24-3" name="__codelineno-24-3" href="#__codelineno-24-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>
8836
9159
  <a id="__codelineno-24-4" name="__codelineno-24-4" href="#__codelineno-24-4"></a><span class="kn">from</span> <span class="nn">nautobot.dcim.models</span> <span class="kn">import</span> <span class="n">Location</span><span class="p">,</span> <span class="n">LocationType</span><span class="p">,</span> <span class="n">Device</span><span class="p">,</span> <span class="n">Manufacturer</span><span class="p">,</span> <span class="n">DeviceType</span>
8837
9160
  <a id="__codelineno-24-5" name="__codelineno-24-5" href="#__codelineno-24-5"></a><span class="kn">from</span> <span class="nn">nautobot.extras.models</span> <span class="kn">import</span> <span class="n">Status</span><span class="p">,</span> <span class="n">Role</span>
8838
9161
  <a id="__codelineno-24-6" name="__codelineno-24-6" href="#__codelineno-24-6"></a>
@@ -8885,10 +9208,13 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
8885
9208
  <a id="__codelineno-24-53" name="__codelineno-24-53" href="#__codelineno-24-53"></a> <span class="n">output</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">attrs</span><span class="p">))</span>
8886
9209
  <a id="__codelineno-24-54" name="__codelineno-24-54" href="#__codelineno-24-54"></a>
8887
9210
  <a id="__codelineno-24-55" name="__codelineno-24-55" href="#__codelineno-24-55"></a> <span class="k">return</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
9211
+ <a id="__codelineno-24-56" name="__codelineno-24-56" href="#__codelineno-24-56"></a>
9212
+ <a id="__codelineno-24-57" name="__codelineno-24-57" href="#__codelineno-24-57"></a>
9213
+ <a id="__codelineno-24-58" name="__codelineno-24-58" href="#__codelineno-24-58"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">NewBranch</span><span class="p">)</span>
8888
9214
  </code></pre></div>
8889
9215
  <h3 id="device-validation">Device validation<a class="headerlink" href="#device-validation" title="Permanent link">&para;</a></h3>
8890
- <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, nor does it implement a <code>run()</code> method.</p>
8891
- <div class="highlight"><pre><span></span><code><a id="__codelineno-25-1" name="__codelineno-25-1" href="#__codelineno-25-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span>
9216
+ <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>
9217
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-25-1" name="__codelineno-25-1" href="#__codelineno-25-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>
8892
9218
  <a id="__codelineno-25-2" name="__codelineno-25-2" href="#__codelineno-25-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>
8893
9219
  <a id="__codelineno-25-3" name="__codelineno-25-3" href="#__codelineno-25-3"></a><span class="kn">from</span> <span class="nn">nautobot.extras.models</span> <span class="kn">import</span> <span class="n">Status</span>
8894
9220
  <a id="__codelineno-25-4" name="__codelineno-25-4" href="#__codelineno-25-4"></a>
@@ -8907,42 +9233,37 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
8907
9233
  <a id="__codelineno-25-17" name="__codelineno-25-17" href="#__codelineno-25-17"></a> <span class="n">console_port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
8908
9234
  <a id="__codelineno-25-18" name="__codelineno-25-18" href="#__codelineno-25-18"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">console_port</span><span class="o">.</span><span class="n">device</span><span class="p">},</span>
8909
9235
  <a id="__codelineno-25-19" name="__codelineno-25-19" href="#__codelineno-25-19"></a> <span class="p">)</span>
8910
- <a id="__codelineno-25-20" name="__codelineno-25-20" href="#__codelineno-25-20"></a> <span class="k">elif</span> <span class="ow">not</span> <span class="n">console_port</span><span class="o">.</span><span class="n">connection_status</span><span class="p">:</span>
8911
- <a id="__codelineno-25-21" name="__codelineno-25-21" href="#__codelineno-25-21"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
8912
- <a id="__codelineno-25-22" name="__codelineno-25-22" href="#__codelineno-25-22"></a> <span class="s2">&quot;Console connection for </span><span class="si">%s</span><span class="s2"> marked as planned&quot;</span><span class="p">,</span>
9236
+ <a id="__codelineno-25-20" name="__codelineno-25-20" href="#__codelineno-25-20"></a> <span class="k">else</span><span class="p">:</span>
9237
+ <a id="__codelineno-25-21" name="__codelineno-25-21" href="#__codelineno-25-21"></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>
9238
+ <a id="__codelineno-25-22" name="__codelineno-25-22" href="#__codelineno-25-22"></a> <span class="s2">&quot;Console port </span><span class="si">%s</span><span class="s2"> has a connection defined&quot;</span><span class="p">,</span>
8913
9239
  <a id="__codelineno-25-23" name="__codelineno-25-23" href="#__codelineno-25-23"></a> <span class="n">console_port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
8914
9240
  <a id="__codelineno-25-24" name="__codelineno-25-24" href="#__codelineno-25-24"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">console_port</span><span class="o">.</span><span class="n">device</span><span class="p">},</span>
8915
9241
  <a id="__codelineno-25-25" name="__codelineno-25-25" href="#__codelineno-25-25"></a> <span class="p">)</span>
8916
- <a id="__codelineno-25-26" name="__codelineno-25-26" href="#__codelineno-25-26"></a> <span class="k">else</span><span class="p">:</span>
8917
- <a id="__codelineno-25-27" name="__codelineno-25-27" href="#__codelineno-25-27"></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>
8918
- <a id="__codelineno-25-28" name="__codelineno-25-28" href="#__codelineno-25-28"></a> <span class="s2">&quot;Console port </span><span class="si">%s</span><span class="s2"> has a connection defined&quot;</span><span class="p">,</span>
8919
- <a id="__codelineno-25-29" name="__codelineno-25-29" href="#__codelineno-25-29"></a> <span class="n">console_port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
8920
- <a id="__codelineno-25-30" name="__codelineno-25-30" href="#__codelineno-25-30"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">console_port</span><span class="o">.</span><span class="n">device</span><span class="p">},</span>
8921
- <a id="__codelineno-25-31" name="__codelineno-25-31" href="#__codelineno-25-31"></a> <span class="p">)</span>
8922
- <a id="__codelineno-25-32" name="__codelineno-25-32" href="#__codelineno-25-32"></a>
8923
- <a id="__codelineno-25-33" name="__codelineno-25-33" href="#__codelineno-25-33"></a> <span class="k">def</span> <span class="nf">test_power_connections</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
8924
- <a id="__codelineno-25-34" name="__codelineno-25-34" href="#__codelineno-25-34"></a> <span class="n">STATUS_ACTIVE</span> <span class="o">=</span> <span class="n">Status</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Active&#39;</span><span class="p">)</span>
8925
- <a id="__codelineno-25-35" name="__codelineno-25-35" href="#__codelineno-25-35"></a>
8926
- <a id="__codelineno-25-36" name="__codelineno-25-36" href="#__codelineno-25-36"></a> <span class="c1"># Check that every active device has at least two connected power supplies.</span>
8927
- <a id="__codelineno-25-37" name="__codelineno-25-37" href="#__codelineno-25-37"></a> <span class="k">for</span> <span class="n">device</span> <span class="ow">in</span> <span class="n">Device</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="n">STATUS_ACTIVE</span><span class="p">):</span>
8928
- <a id="__codelineno-25-38" name="__codelineno-25-38" href="#__codelineno-25-38"></a> <span class="n">connected_ports</span> <span class="o">=</span> <span class="mi">0</span>
8929
- <a id="__codelineno-25-39" name="__codelineno-25-39" href="#__codelineno-25-39"></a> <span class="k">for</span> <span class="n">power_port</span> <span class="ow">in</span> <span class="n">PowerPort</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">device</span><span class="o">=</span><span class="n">device</span><span class="p">):</span>
8930
- <a id="__codelineno-25-40" name="__codelineno-25-40" href="#__codelineno-25-40"></a> <span class="k">if</span> <span class="n">power_port</span><span class="o">.</span><span class="n">connected_endpoint</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
8931
- <a id="__codelineno-25-41" name="__codelineno-25-41" href="#__codelineno-25-41"></a> <span class="n">connected_ports</span> <span class="o">+=</span> <span class="mi">1</span>
8932
- <a id="__codelineno-25-42" name="__codelineno-25-42" href="#__codelineno-25-42"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">power_port</span><span class="o">.</span><span class="n">connection_status</span><span class="p">:</span>
8933
- <a id="__codelineno-25-43" name="__codelineno-25-43" href="#__codelineno-25-43"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
8934
- <a id="__codelineno-25-44" name="__codelineno-25-44" href="#__codelineno-25-44"></a> <span class="s2">&quot;Power connection for </span><span class="si">%s</span><span class="s2"> marked as planned&quot;</span><span class="p">,</span>
8935
- <a id="__codelineno-25-45" name="__codelineno-25-45" href="#__codelineno-25-45"></a> <span class="n">power_port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
8936
- <a id="__codelineno-25-46" name="__codelineno-25-46" href="#__codelineno-25-46"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">device</span><span class="p">},</span>
8937
- <a id="__codelineno-25-47" name="__codelineno-25-47" href="#__codelineno-25-47"></a> <span class="p">)</span>
8938
- <a id="__codelineno-25-48" name="__codelineno-25-48" href="#__codelineno-25-48"></a> <span class="k">if</span> <span class="n">connected_ports</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
8939
- <a id="__codelineno-25-49" name="__codelineno-25-49" href="#__codelineno-25-49"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
8940
- <a id="__codelineno-25-50" name="__codelineno-25-50" href="#__codelineno-25-50"></a> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> connected power supplies found (2 needed)&quot;</span><span class="p">,</span>
8941
- <a id="__codelineno-25-51" name="__codelineno-25-51" href="#__codelineno-25-51"></a> <span class="n">connected_ports</span><span class="p">,</span>
8942
- <a id="__codelineno-25-52" name="__codelineno-25-52" href="#__codelineno-25-52"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">device</span><span class="p">},</span>
8943
- <a id="__codelineno-25-53" name="__codelineno-25-53" href="#__codelineno-25-53"></a> <span class="p">)</span>
8944
- <a id="__codelineno-25-54" name="__codelineno-25-54" href="#__codelineno-25-54"></a> <span class="k">else</span><span class="p">:</span>
8945
- <a id="__codelineno-25-55" name="__codelineno-25-55" href="#__codelineno-25-55"></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;At least two connected power supplies found&quot;</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">device</span><span class="p">})</span>
9242
+ <a id="__codelineno-25-26" name="__codelineno-25-26" href="#__codelineno-25-26"></a>
9243
+ <a id="__codelineno-25-27" name="__codelineno-25-27" href="#__codelineno-25-27"></a> <span class="k">def</span> <span class="nf">test_power_connections</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
9244
+ <a id="__codelineno-25-28" name="__codelineno-25-28" href="#__codelineno-25-28"></a> <span class="n">STATUS_ACTIVE</span> <span class="o">=</span> <span class="n">Status</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Active&#39;</span><span class="p">)</span>
9245
+ <a id="__codelineno-25-29" name="__codelineno-25-29" href="#__codelineno-25-29"></a>
9246
+ <a id="__codelineno-25-30" name="__codelineno-25-30" href="#__codelineno-25-30"></a> <span class="c1"># Check that every active device has at least two connected power supplies.</span>
9247
+ <a id="__codelineno-25-31" name="__codelineno-25-31" href="#__codelineno-25-31"></a> <span class="k">for</span> <span class="n">device</span> <span class="ow">in</span> <span class="n">Device</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="n">STATUS_ACTIVE</span><span class="p">):</span>
9248
+ <a id="__codelineno-25-32" name="__codelineno-25-32" href="#__codelineno-25-32"></a> <span class="n">connected_ports</span> <span class="o">=</span> <span class="mi">0</span>
9249
+ <a id="__codelineno-25-33" name="__codelineno-25-33" href="#__codelineno-25-33"></a> <span class="k">for</span> <span class="n">power_port</span> <span class="ow">in</span> <span class="n">PowerPort</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">device</span><span class="o">=</span><span class="n">device</span><span class="p">):</span>
9250
+ <a id="__codelineno-25-34" name="__codelineno-25-34" href="#__codelineno-25-34"></a> <span class="k">if</span> <span class="n">power_port</span><span class="o">.</span><span class="n">connected_endpoint</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
9251
+ <a id="__codelineno-25-35" name="__codelineno-25-35" href="#__codelineno-25-35"></a> <span class="n">connected_ports</span> <span class="o">+=</span> <span class="mi">1</span>
9252
+ <a id="__codelineno-25-36" name="__codelineno-25-36" href="#__codelineno-25-36"></a> <span class="k">if</span> <span class="n">connected_ports</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
9253
+ <a id="__codelineno-25-37" name="__codelineno-25-37" href="#__codelineno-25-37"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
9254
+ <a id="__codelineno-25-38" name="__codelineno-25-38" href="#__codelineno-25-38"></a> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> connected power supplies found (2 needed)&quot;</span><span class="p">,</span>
9255
+ <a id="__codelineno-25-39" name="__codelineno-25-39" href="#__codelineno-25-39"></a> <span class="n">connected_ports</span><span class="p">,</span>
9256
+ <a id="__codelineno-25-40" name="__codelineno-25-40" href="#__codelineno-25-40"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">device</span><span class="p">},</span>
9257
+ <a id="__codelineno-25-41" name="__codelineno-25-41" href="#__codelineno-25-41"></a> <span class="p">)</span>
9258
+ <a id="__codelineno-25-42" name="__codelineno-25-42" href="#__codelineno-25-42"></a> <span class="k">else</span><span class="p">:</span>
9259
+ <a id="__codelineno-25-43" name="__codelineno-25-43" href="#__codelineno-25-43"></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;At least two connected power supplies found&quot;</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">device</span><span class="p">})</span>
9260
+ <a id="__codelineno-25-44" name="__codelineno-25-44" href="#__codelineno-25-44"></a>
9261
+ <a id="__codelineno-25-45" name="__codelineno-25-45" href="#__codelineno-25-45"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
9262
+ <a id="__codelineno-25-46" name="__codelineno-25-46" href="#__codelineno-25-46"></a> <span class="bp">self</span><span class="o">.</span><span class="n">test_console_connection</span><span class="p">()</span>
9263
+ <a id="__codelineno-25-47" name="__codelineno-25-47" href="#__codelineno-25-47"></a> <span class="bp">self</span><span class="o">.</span><span class="n">test_power_connections</span><span class="p">()</span>
9264
+ <a id="__codelineno-25-48" name="__codelineno-25-48" href="#__codelineno-25-48"></a>
9265
+ <a id="__codelineno-25-49" name="__codelineno-25-49" href="#__codelineno-25-49"></a>
9266
+ <a id="__codelineno-25-50" name="__codelineno-25-50" href="#__codelineno-25-50"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">DeviceConnectionsReport</span><span class="p">)</span>
8946
9267
  </code></pre></div>
8947
9268
  <h2 id="job-button-receivers">Job Button Receivers<a class="headerlink" href="#job-button-receivers" title="Permanent link">&para;</a></h2>
8948
9269
  <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>
@@ -8956,7 +9277,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
8956
9277
  <li><code>obj</code> - An instance of the object where the button was pressed</li>
8957
9278
  </ol>
8958
9279
  <h3 id="example-job-button-receiver">Example Job Button Receiver<a class="headerlink" href="#example-job-button-receiver" title="Permanent link">&para;</a></h3>
8959
- <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">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">JobButtonReceiver</span>
9280
+ <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">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">JobButtonReceiver</span><span class="p">,</span> <span class="n">register_jobs</span>
8960
9281
  <a id="__codelineno-26-2" name="__codelineno-26-2" href="#__codelineno-26-2"></a>
8961
9282
  <a id="__codelineno-26-3" name="__codelineno-26-3" href="#__codelineno-26-3"></a>
8962
9283
  <a id="__codelineno-26-4" name="__codelineno-26-4" href="#__codelineno-26-4"></a><span class="k">class</span> <span class="nc">ExampleSimpleJobButtonReceiver</span><span class="p">(</span><span class="n">JobButtonReceiver</span><span class="p">):</span>
@@ -8966,10 +9287,13 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
8966
9287
  <a id="__codelineno-26-8" name="__codelineno-26-8" href="#__codelineno-26-8"></a> <span class="k">def</span> <span class="nf">receive_job_button</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
8967
9288
  <a id="__codelineno-26-9" name="__codelineno-26-9" href="#__codelineno-26-9"></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;Running Job Button Receiver.&quot;</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">obj</span><span class="p">})</span>
8968
9289
  <a id="__codelineno-26-10" name="__codelineno-26-10" href="#__codelineno-26-10"></a> <span class="c1"># Add job logic here</span>
9290
+ <a id="__codelineno-26-11" name="__codelineno-26-11" href="#__codelineno-26-11"></a>
9291
+ <a id="__codelineno-26-12" name="__codelineno-26-12" href="#__codelineno-26-12"></a>
9292
+ <a id="__codelineno-26-13" name="__codelineno-26-13" href="#__codelineno-26-13"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">ExampleSimpleJobButtonReceiver</span><span class="p">)</span>
8969
9293
  </code></pre></div>
8970
9294
  <h3 id="job-buttons-for-multiple-types">Job Buttons for Multiple Types<a class="headerlink" href="#job-buttons-for-multiple-types" title="Permanent link">&para;</a></h3>
8971
9295
  <p>Since Job Buttons can be associated to multiple object types, it would be trivial to create a Job that can change what it runs based on the object type.</p>
8972
- <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">JobButtonReceiver</span>
9296
+ <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">JobButtonReceiver</span><span class="p">,</span> <span class="n">register_jobs</span>
8973
9297
  <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">Device</span><span class="p">,</span> <span class="n">Location</span>
8974
9298
  <a id="__codelineno-27-3" name="__codelineno-27-3" href="#__codelineno-27-3"></a>
8975
9299
  <a id="__codelineno-27-4" name="__codelineno-27-4" href="#__codelineno-27-4"></a>
@@ -9002,6 +9326,9 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
9002
9326
  <a id="__codelineno-27-31" name="__codelineno-27-31" href="#__codelineno-27-31"></a> <span class="k">else</span><span class="p">:</span>
9003
9327
  <a id="__codelineno-27-32" name="__codelineno-27-32" href="#__codelineno-27-32"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">&quot;Unable to run Job Button for type </span><span class="si">%s</span><span class="s2">.&quot;</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">obj</span><span class="p">})</span>
9004
9328
  <a id="__codelineno-27-33" name="__codelineno-27-33" href="#__codelineno-27-33"></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Job button called on unsupported object type.&quot;</span><span class="p">)</span>
9329
+ <a id="__codelineno-27-34" name="__codelineno-27-34" href="#__codelineno-27-34"></a>
9330
+ <a id="__codelineno-27-35" name="__codelineno-27-35" href="#__codelineno-27-35"></a>
9331
+ <a id="__codelineno-27-36" name="__codelineno-27-36" href="#__codelineno-27-36"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">ExampleComplexJobButtonReceiver</span><span class="p">)</span>
9005
9332
  </code></pre></div>
9006
9333
  <h2 id="job-hook-receivers">Job Hook Receivers<a class="headerlink" href="#job-hook-receivers" title="Permanent link">&para;</a></h2>
9007
9334
  <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>
@@ -9014,7 +9341,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
9014
9341
  <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>
9015
9342
  </div>
9016
9343
  <h3 id="example-job-hook-receiver">Example Job Hook Receiver<a class="headerlink" href="#example-job-hook-receiver" title="Permanent link">&para;</a></h3>
9017
- <div class="highlight"><pre><span></span><code><a id="__codelineno-28-1" name="__codelineno-28-1" href="#__codelineno-28-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">JobHookReceiver</span>
9344
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-28-1" name="__codelineno-28-1" href="#__codelineno-28-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>
9018
9345
  <a id="__codelineno-28-2" name="__codelineno-28-2" href="#__codelineno-28-2"></a><span class="kn">from</span> <span class="nn">nautobot.extras.choices</span> <span class="kn">import</span> <span class="n">ObjectChangeActionChoices</span>
9019
9346
  <a id="__codelineno-28-3" name="__codelineno-28-3" href="#__codelineno-28-3"></a>
9020
9347
  <a id="__codelineno-28-4" name="__codelineno-28-4" href="#__codelineno-28-4"></a>
@@ -9045,6 +9372,9 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
9045
9372
  <a id="__codelineno-28-29" name="__codelineno-28-29" href="#__codelineno-28-29"></a> <span class="k">def</span> <span class="nf">validate_serial</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">serial</span><span class="p">):</span>
9046
9373
  <a id="__codelineno-28-30" name="__codelineno-28-30" href="#__codelineno-28-30"></a> <span class="c1"># add business logic to validate serial</span>
9047
9374
  <a id="__codelineno-28-31" name="__codelineno-28-31" href="#__codelineno-28-31"></a> <span class="k">return</span> <span class="kc">False</span>
9375
+ <a id="__codelineno-28-32" name="__codelineno-28-32" href="#__codelineno-28-32"></a>
9376
+ <a id="__codelineno-28-33" name="__codelineno-28-33" href="#__codelineno-28-33"></a>
9377
+ <a id="__codelineno-28-34" name="__codelineno-28-34" href="#__codelineno-28-34"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">ExampleJobHookReceiver</span><span class="p">)</span>
9048
9378
  </code></pre></div>
9049
9379
  <h3 id="the-receive_job_hook-method">The <code>receive_job_hook()</code> Method<a class="headerlink" href="#the-receive_job_hook-method" title="Permanent link">&para;</a></h3>
9050
9380
  <p>All <code>JobHookReceiver</code> subclasses must implement a <code>receive_job_hook()</code> method. This method accepts three arguments:</p>
@@ -9070,6 +9400,8 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
9070
9400
  </div>
9071
9401
 
9072
9402
 
9403
+ <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var tab,labels=set.querySelector(".tabbed-labels");for(tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
9404
+
9073
9405
  <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
9074
9406
  </div>
9075
9407
 
@@ -9147,7 +9479,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
9147
9479
 
9148
9480
 
9149
9481
  <a href="https://blog.networktocode.com/blog/tags/nautobot" target="_blank" rel="noopener" title="Network to Code Blog" class="md-social__link">
9150
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M0 64c0-17.7 14.3-32 32-32 229.8 0 416 186.2 416 416 0 17.7-14.3 32-32 32s-32-14.3-32-32C384 253.6 226.4 96 32 96 14.3 96 0 81.7 0 64zm0 352a64 64 0 1 1 128 0 64 64 0 1 1-128 0zm32-256c159.1 0 288 128.9 288 288 0 17.7-14.3 32-32 32s-32-14.3-32-32c0-123.7-100.3-224-224-224-17.7 0-32-14.3-32-32s14.3-32 32-32z"/></svg>
9482
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M0 64c0-17.7 14.3-32 32-32 229.8 0 416 186.2 416 416 0 17.7-14.3 32-32 32s-32-14.3-32-32C384 253.6 226.4 96 32 96 14.3 96 0 81.7 0 64zm0 352a64 64 0 1 1 128 0 64 64 0 1 1-128 0zm32-256c159.1 0 288 128.9 288 288 0 17.7-14.3 32-32 32s-32-14.3-32-32c0-123.7-100.3-224-224-224-17.7 0-32-14.3-32-32s14.3-32 32-32z"/></svg>
9151
9483
  </a>
9152
9484
 
9153
9485
 
@@ -9155,7 +9487,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
9155
9487
 
9156
9488
 
9157
9489
  <a href="https://www.youtube.com/playlist?list=PLjA0bhxgryJ2Ts4GJMDA-tPzVWEncv4pb" target="_blank" rel="noopener" title="Nautobot Videos" class="md-social__link">
9158
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>
9490
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>
9159
9491
  </a>
9160
9492
 
9161
9493
 
@@ -9163,7 +9495,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
9163
9495
 
9164
9496
 
9165
9497
  <a href="https://www.networktocode.com/community/" target="_blank" rel="noopener" title="Network to Code Community" class="md-social__link">
9166
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M94.12 315.1c0 25.9-21.16 47.06-47.06 47.06S0 341 0 315.1c0-25.9 21.16-47.06 47.06-47.06h47.06v47.06zm23.72 0c0-25.9 21.16-47.06 47.06-47.06s47.06 21.16 47.06 47.06v117.84c0 25.9-21.16 47.06-47.06 47.06s-47.06-21.16-47.06-47.06V315.1zm47.06-188.98c-25.9 0-47.06-21.16-47.06-47.06S139 32 164.9 32s47.06 21.16 47.06 47.06v47.06H164.9zm0 23.72c25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06H47.06C21.16 243.96 0 222.8 0 196.9s21.16-47.06 47.06-47.06H164.9zm188.98 47.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06h-47.06V196.9zm-23.72 0c0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06V79.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06V196.9zM283.1 385.88c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06v-47.06h47.06zm0-23.72c-25.9 0-47.06-21.16-47.06-47.06 0-25.9 21.16-47.06 47.06-47.06h117.84c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06H283.1z"/></svg>
9498
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M94.12 315.1c0 25.9-21.16 47.06-47.06 47.06S0 341 0 315.1c0-25.9 21.16-47.06 47.06-47.06h47.06v47.06zm23.72 0c0-25.9 21.16-47.06 47.06-47.06s47.06 21.16 47.06 47.06v117.84c0 25.9-21.16 47.06-47.06 47.06s-47.06-21.16-47.06-47.06V315.1zm47.06-188.98c-25.9 0-47.06-21.16-47.06-47.06S139 32 164.9 32s47.06 21.16 47.06 47.06v47.06H164.9zm0 23.72c25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06H47.06C21.16 243.96 0 222.8 0 196.9s21.16-47.06 47.06-47.06H164.9zm188.98 47.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06h-47.06V196.9zm-23.72 0c0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06V79.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06V196.9zM283.1 385.88c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06v-47.06h47.06zm0-23.72c-25.9 0-47.06-21.16-47.06-47.06 0-25.9 21.16-47.06 47.06-47.06h117.84c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06H283.1z"/></svg>
9167
9499
  </a>
9168
9500
 
9169
9501
 
@@ -9171,7 +9503,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
9171
9503
 
9172
9504
 
9173
9505
  <a href="https://github.com/nautobot/nautobot" target="_blank" rel="noopener" title="GitHub Repo" class="md-social__link">
9174
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
9506
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
9175
9507
  </a>
9176
9508
 
9177
9509
 
@@ -9179,7 +9511,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
9179
9511
 
9180
9512
 
9181
9513
  <a href="https://twitter.com/networktocode" target="_blank" rel="noopener" title="Network to Code Twitter" class="md-social__link">
9182
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
9514
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
9183
9515
  </a>
9184
9516
 
9185
9517
  </div>
@@ -9194,10 +9526,10 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
9194
9526
  </div>
9195
9527
 
9196
9528
 
9197
- <script id="__config" type="application/json">{"base": "../..", "features": ["content.code.copy", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "../../assets/javascripts/workers/search.b8dbb3d2.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>
9529
+ <script id="__config" type="application/json">{"base": "../..", "features": ["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.b8dbb3d2.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>
9198
9530
 
9199
9531
 
9200
- <script src="../../assets/javascripts/bundle.bd41221c.min.js"></script>
9532
+ <script src="../../assets/javascripts/bundle.3220b9d7.min.js"></script>
9201
9533
 
9202
9534
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
9203
9535